alphasec-py 0.1.0__py3-none-any.whl

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.
alphasec/__init__.py ADDED
@@ -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
alphasec/agent.py ADDED
@@ -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
+ ]