alphasec-py 0.1.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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Alphasec
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,96 @@
1
+ Metadata-Version: 2.4
2
+ Name: alphasec-py
3
+ Version: 0.1.0
4
+ Summary: trading sdk for alphasec orderbook dex
5
+ License-Expression: MIT
6
+ License-File: LICENSE
7
+ Author: Alphasec
8
+ Author-email: dev@alphasec.trade
9
+ Requires-Python: >=3.9,<4
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.9
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
17
+ Requires-Dist: eth-account (>=0.10.0,<0.14.0)
18
+ Requires-Dist: eth-utils (>=2.1.0,<6.0.0)
19
+ Requires-Dist: httpx (>=0.27.0,<1.0.0)
20
+ Requires-Dist: msgpack (>=1.0.5,<2.0.0)
21
+ Requires-Dist: pydantic (>=2.6.0,<3.0.0)
22
+ Requires-Dist: requests (>=2.31.0,<3.0.0)
23
+ Requires-Dist: web3 (>=7.13.0,<8.0.0)
24
+ Requires-Dist: websocket-client (>=1.5.1,<2.0.0)
25
+ Requires-Dist: websockets (>=13.0,<16.0)
26
+ Description-Content-Type: text/markdown
27
+
28
+ # Alphasec Python SDK
29
+
30
+ A trading SDK for the Alphasec orderbook DEX.
31
+
32
+ [![PyPI version](https://badge.fury.io/py/alphasec.svg)](https://badge.fury.io/py/alphasec)
33
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
34
+
35
+
36
+ ## 🚀 Quick Start
37
+
38
+ ### Install (Not yet deployed)
39
+ ```bash
40
+ pip install alphasec
41
+ ```
42
+
43
+ ### Configure (required for examples)
44
+ ```bash
45
+ cd examples
46
+ cp config/config.json.example config/config.json
47
+ # Then edit config.json and fill your values
48
+ ```
49
+
50
+ ### Minimal config.json
51
+ ```json
52
+ {
53
+ "network": "kairos",
54
+ "api_url": "https://api.alphasec.trade",
55
+ "l1_address": "0x...your_L1_address",
56
+ "l1_wallet": "0x...your_L1_private_key",
57
+ "l2_wallet": "0x...your_L2_private_key",
58
+ "session_enabled": false
59
+ }
60
+ ```
61
+
62
+ ### Run an example
63
+ ```bash
64
+ python examples/market_data/basic_tickers.py
65
+ ```
66
+
67
+
68
+ ## 🌐 Network Information
69
+
70
+ ### Kairos Testnet
71
+ - **API URL**: `https://api-testnet.alphasec.trade`
72
+ - **Websocket URL**: `wss://api-testnet.alphasec.trade/ws`
73
+ - **Network**: `kairos`
74
+ - **L1 Chain ID**: 1001 (Kaia Kairos)
75
+ - **L2 Chain ID**: 41001 (AlphaSec L2)
76
+
77
+ ### Mainnet
78
+ - **API URL**: `https://api.alphasec.trade`
79
+ - **Websocket URL**: `wss://api.alphasec.trade/ws`
80
+ - **Network**: `mainnet`
81
+ - **L1 Chain ID**: 8217 (Kaia Mainnet)
82
+ - **L2 Chain ID**: 48217 (AlphaSec L2)
83
+
84
+ ## 🔐 Security
85
+
86
+ ⚠️ **Important Security Notes:**
87
+
88
+ - Never commit private keys to version control
89
+ - Use environment variables or secure key management
90
+ - Always test on kairos testnet before mainnet
91
+ - Verify transaction details before signing
92
+ - Blockchain transactions are irreversible
93
+
94
+ ## ⚠️ Disclaimer
95
+
96
+ This SDK is provided as-is. Trading cryptocurrencies involves substantial risk and may result in significant losses. Always do your own research and never invest more than you can afford to lose. The developers are not responsible for any trading losses incurred while using this SDK.
@@ -0,0 +1,69 @@
1
+ # Alphasec Python SDK
2
+
3
+ A trading SDK for the Alphasec orderbook DEX.
4
+
5
+ [![PyPI version](https://badge.fury.io/py/alphasec.svg)](https://badge.fury.io/py/alphasec)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+
9
+ ## 🚀 Quick Start
10
+
11
+ ### Install (Not yet deployed)
12
+ ```bash
13
+ pip install alphasec
14
+ ```
15
+
16
+ ### Configure (required for examples)
17
+ ```bash
18
+ cd examples
19
+ cp config/config.json.example config/config.json
20
+ # Then edit config.json and fill your values
21
+ ```
22
+
23
+ ### Minimal config.json
24
+ ```json
25
+ {
26
+ "network": "kairos",
27
+ "api_url": "https://api.alphasec.trade",
28
+ "l1_address": "0x...your_L1_address",
29
+ "l1_wallet": "0x...your_L1_private_key",
30
+ "l2_wallet": "0x...your_L2_private_key",
31
+ "session_enabled": false
32
+ }
33
+ ```
34
+
35
+ ### Run an example
36
+ ```bash
37
+ python examples/market_data/basic_tickers.py
38
+ ```
39
+
40
+
41
+ ## 🌐 Network Information
42
+
43
+ ### Kairos Testnet
44
+ - **API URL**: `https://api-testnet.alphasec.trade`
45
+ - **Websocket URL**: `wss://api-testnet.alphasec.trade/ws`
46
+ - **Network**: `kairos`
47
+ - **L1 Chain ID**: 1001 (Kaia Kairos)
48
+ - **L2 Chain ID**: 41001 (AlphaSec L2)
49
+
50
+ ### Mainnet
51
+ - **API URL**: `https://api.alphasec.trade`
52
+ - **Websocket URL**: `wss://api.alphasec.trade/ws`
53
+ - **Network**: `mainnet`
54
+ - **L1 Chain ID**: 8217 (Kaia Mainnet)
55
+ - **L2 Chain ID**: 48217 (AlphaSec L2)
56
+
57
+ ## 🔐 Security
58
+
59
+ ⚠️ **Important Security Notes:**
60
+
61
+ - Never commit private keys to version control
62
+ - Use environment variables or secure key management
63
+ - Always test on kairos testnet before mainnet
64
+ - Verify transaction details before signing
65
+ - Blockchain transactions are irreversible
66
+
67
+ ## ⚠️ Disclaimer
68
+
69
+ This SDK is provided as-is. Trading cryptocurrencies involves substantial risk and may result in significant losses. Always do your own research and never invest more than you can afford to lose. The developers are not responsible for any trading losses incurred while using this SDK.
@@ -0,0 +1,10 @@
1
+ from .exceptions import AlphasecAPIError
2
+ from .transaction.utils import load_config
3
+ from .transaction.sign import AlphasecSigner
4
+ from .agent import Agent
5
+ from .async_agent import AsyncAgent
6
+ from .api.api import API
7
+ from .api.async_api import AsyncAPI
8
+ from .websocket.ws import WebsocketManager
9
+ from .websocket.async_ws import AsyncWebsocketManager
10
+ from .perp import decode_perp_event, PerpEvent, PerpAgent, AsyncPerpAgent
@@ -0,0 +1,191 @@
1
+ from typing import Any, Callable, Optional
2
+
3
+ from alphasec.api.api import API
4
+ from alphasec.websocket.ws import WebsocketManager
5
+ from alphasec.transaction.sign import AlphasecSigner
6
+ from alphasec.api.utils import market_to_market_id
7
+ from alphasec.perp.agent import PerpAgent
8
+
9
+ import logging
10
+ # logging.basicConfig(level=logging.DEBUG)
11
+
12
+ class Agent:
13
+ def __init__(self, base_url: str, signer: Optional[AlphasecSigner] = None, timeout: Optional[int] = None):
14
+ self.api = API(base_url, timeout=timeout, signer=signer)
15
+ self.ws = WebsocketManager(base_url)
16
+ self.perp = PerpAgent(self)
17
+
18
+ # WebSocket lifecycle
19
+ def start(self) -> None:
20
+ self.ws.start()
21
+
22
+ def stop(self) -> None:
23
+ self.ws.stop()
24
+
25
+ # WebSocket subscriptions
26
+ def subscribe(self, channel: str, callback: Callable[[Any], None], timeout: Optional[int] = None) -> int:
27
+ """
28
+ Subscribe to WebSocket channels with user-friendly channel format.
29
+
30
+ Parameters
31
+ ----------
32
+ channel : str
33
+ Channel in format 'type@target':
34
+ - 'trade@KAIA/USDT' for trade data
35
+ - 'ticker@BTC/USDT' for ticker data
36
+ - 'depth@ETH/USDT' for order book
37
+ - 'userEvent@0x123...' for user events
38
+ callback : Callable
39
+ Function to handle received messages
40
+ timeout : int, optional
41
+ Timeout in seconds
42
+
43
+ Returns
44
+ -------
45
+ int
46
+ Subscription ID for later unsubscribing
47
+
48
+ Examples
49
+ --------
50
+ agent.subscribe('trade@KAIA/USDT', print_trades)
51
+ agent.subscribe('userEvent@0x123...', print_events)
52
+ """
53
+ if '@' not in channel:
54
+ raise ValueError(f"Channel format should be 'type@target', got: {channel}")
55
+
56
+ channel_type, target = channel.split('@', 1)
57
+
58
+ if channel_type in ['trade', 'ticker', 'depth']:
59
+ # Convert market name to market_id (lazy-load token metadata first)
60
+ self.api._ensure_initialized()
61
+ market_id = market_to_market_id(target, self.api.symbol_token_id_map)
62
+ actual_channel = f"{channel_type}@{market_id}"
63
+ elif channel_type == 'userEvent':
64
+ # Use address directly
65
+ actual_channel = f"{channel_type}@{target}"
66
+ else:
67
+ raise ValueError(f"Unsupported channel type: {channel_type}. Use 'trade', 'ticker', 'depth', or 'userEvent'")
68
+
69
+ return self.ws.subscribe(actual_channel, callback, timeout=timeout)
70
+
71
+ def unsubscribe(self, channel: str, subscription_id: int, timeout: Optional[int] = None) -> bool:
72
+ """
73
+ Unsubscribe from WebSocket channels with user-friendly channel format.
74
+
75
+ Parameters
76
+ ----------
77
+ channel : str
78
+ Channel in format 'type@target' (same as used in subscribe)
79
+ subscription_id : int
80
+ ID returned from subscribe()
81
+ timeout : int, optional
82
+ Timeout in seconds
83
+
84
+ Examples
85
+ --------
86
+ agent.unsubscribe('trade@KAIA/USDT', sub_id)
87
+ agent.unsubscribe('userEvent@0x123...', sub_id)
88
+ """
89
+ if '@' not in channel:
90
+ raise ValueError(f"Channel format should be 'type@target', got: {channel}")
91
+
92
+ channel_type, target = channel.split('@', 1)
93
+
94
+ if channel_type in ['trade', 'ticker', 'depth']:
95
+ # Convert market name to market_id (lazy-load token metadata first)
96
+ self.api._ensure_initialized()
97
+ market_id = market_to_market_id(target, self.api.symbol_token_id_map)
98
+ actual_channel = f"{channel_type}@{market_id}"
99
+ elif channel_type == 'userEvent':
100
+ # Use address directly
101
+ actual_channel = f"{channel_type}@{target}"
102
+ else:
103
+ raise ValueError(f"Unsupported channel type: {channel_type}. Use 'trade', 'ticker', 'depth', or 'userEvent'")
104
+
105
+ return self.ws.unsubscribe(actual_channel, subscription_id, timeout=timeout)
106
+
107
+ # API helpers (commonly used)
108
+ def order(self, market: str, side: int, price: float, quantity: float, order_type: int, order_mode: int, tp_limit: Optional[float] = None, sl_trigger: Optional[float] = None, sl_limit: Optional[float] = None) -> dict:
109
+ return self.api.order(market, side, price, quantity, order_type, order_mode, tp_limit, sl_trigger, sl_limit)
110
+
111
+ def cancel(self, order_id: str) -> dict:
112
+ return self.api.cancel(order_id)
113
+
114
+ def cancel_all(self) -> dict:
115
+ return self.api.cancel_all()
116
+
117
+ def modify(self, order_id: str, new_price: Optional[float] = None, new_qty: Optional[float] = None, order_mode: Optional[int] = None) -> dict:
118
+ return self.api.modify(order_id, new_price, new_qty, order_mode)
119
+
120
+ def value_transfer(self, to: str, value: float) -> dict:
121
+ return self.api.value_transfer(to, value)
122
+
123
+ def token_transfer(self, to: str, value: float, token: str) -> dict:
124
+ return self.api.token_transfer(to, value, token)
125
+
126
+ def withdraw(self, token: str, value: float) -> dict:
127
+ return self.api.withdraw_to_kaia(token, value)
128
+
129
+ def deposit(self, token: str, value: float) -> dict:
130
+ return self.api.deposit_to_alphasec(token, value)
131
+
132
+ # State accessors
133
+ @property
134
+ def l1_address(self):
135
+ return self.api.signer.l1_address if self.api.signer else None
136
+
137
+ def is_session_enabled(self) -> bool:
138
+ return bool(self.api.signer and self.api.signer.session_enabled)
139
+
140
+ # Market data helpers
141
+ def get_depth(self, market: str, limit: int = 100) -> dict:
142
+ return self.api.get_depth(market, limit)
143
+
144
+ def get_ticker(self, market: str) -> dict:
145
+ return self.api.get_ticker(market)
146
+
147
+ def get_tickers(self) -> list[dict]:
148
+ return self.api.get_tickers()
149
+
150
+ def get_market_list(self) -> list[dict]:
151
+ return self.api.get_market_list()
152
+
153
+ def get_trades(self, market: str, limit: int = 100) -> list[dict]:
154
+ return self.api.get_trades(market, limit)
155
+
156
+ def get_tokens(self) -> list[dict]:
157
+ return self.api.get_tokens()
158
+
159
+ # Order history helpers
160
+ def get_open_orders(self, addr: str, market: str, limit: int = 100, from_msec: Optional[int] = None, end_msec: Optional[int] = None) -> list[dict]:
161
+ return self.api.get_open_orders(addr, market, limit, from_msec, end_msec)
162
+
163
+ def get_filled_canceled_orders(self, addr: str, market: str, limit: int = 100, from_msec: Optional[int] = None, end_msec: Optional[int] = None) -> list[dict]:
164
+ return self.api.get_filled_canceled_orders(addr, market, limit, from_msec, end_msec)
165
+
166
+ def get_order_by_id(self, order_id: str) -> dict:
167
+ return self.api.get_order_by_id(order_id)
168
+
169
+ # Wallet/session helpers
170
+ def get_balance(self, addr: str) -> dict:
171
+ return self.api.get_balance(addr)
172
+
173
+ def get_sessions(self, addr: str) -> list[dict]:
174
+ return self.api.get_sessions(addr)
175
+
176
+ def get_transfer_history(self, addr: str, token_id: Optional[int] = None, from_msec: Optional[int] = None, to_msec: Optional[int] = None, limit: int = 100) -> list[dict]:
177
+ return self.api.get_transfer_history(addr, token_id, from_msec, to_msec, limit)
178
+
179
+ # Session management
180
+ def create_session(self, session_id: str, session_wallet, expiry: int, nonce: int) -> dict:
181
+ return self.api.create_session(session_id, session_wallet, expiry, nonce)
182
+
183
+ def update_session(self, session_id: str, session_wallet, expiry: int, nonce: int) -> dict:
184
+ return self.api.update_session(session_id, session_wallet, expiry, nonce)
185
+
186
+ def delete_session(self, session_wallet) -> dict:
187
+ return self.api.delete_session(session_wallet)
188
+
189
+ # Additional trading helpers
190
+ def stop_order(self, market: str, stop_price: int, price: int, quantity: int, side: int, order_type: int, order_mode: int) -> dict:
191
+ return self.api.stop_order(market, stop_price, price, quantity, side, order_type, order_mode)
@@ -0,0 +1,25 @@
1
+ from .constants import (
2
+ BUY,
3
+ SELL,
4
+ LIMIT,
5
+ MARKET,
6
+ BASE_MODE,
7
+ QUOTE_MODE,
8
+ MAINNET_URL,
9
+ KAIROS_URL,
10
+ ALPHASEC_MAINNET_URL,
11
+ ALPHASEC_KAIROS_URL,
12
+ )
13
+
14
+ __all__ = [
15
+ "BUY",
16
+ "SELL",
17
+ "LIMIT",
18
+ "MARKET",
19
+ "BASE_MODE",
20
+ "QUOTE_MODE",
21
+ "MAINNET_URL",
22
+ "KAIROS_URL",
23
+ "ALPHASEC_MAINNET_URL",
24
+ "ALPHASEC_KAIROS_URL",
25
+ ]