dnse-sdk-openapi 0.0.1__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.
Files changed (50) hide show
  1. broker-api/get_list_care_by.py +22 -0
  2. dnse/__init__.py +4 -0
  3. dnse/client.py +408 -0
  4. dnse/common.py +103 -0
  5. dnse_sdk_openapi-0.0.1.dist-info/METADATA +120 -0
  6. dnse_sdk_openapi-0.0.1.dist-info/RECORD +50 -0
  7. dnse_sdk_openapi-0.0.1.dist-info/WHEEL +5 -0
  8. dnse_sdk_openapi-0.0.1.dist-info/top_level.txt +5 -0
  9. marketdata-api/get_instruments.py +22 -0
  10. marketdata-api/get_latest_trade.py +22 -0
  11. marketdata-api/get_ohlc.py +31 -0
  12. marketdata-api/get_security_definition.py +22 -0
  13. marketdata-api/get_trades.py +22 -0
  14. marketdata-api/get_working_dates.py +22 -0
  15. trading-api/cancel_order.py +29 -0
  16. trading-api/close_position.py +27 -0
  17. trading-api/create_trading_token.py +26 -0
  18. trading-api/get_accounts.py +22 -0
  19. trading-api/get_balances.py +22 -0
  20. trading-api/get_close_price.py +22 -0
  21. trading-api/get_execution_detail.py +28 -0
  22. trading-api/get_loan_packages.py +27 -0
  23. trading-api/get_order_detail.py +28 -0
  24. trading-api/get_order_history.py +30 -0
  25. trading-api/get_orders.py +27 -0
  26. trading-api/get_position_by_id.py +26 -0
  27. trading-api/get_positions.py +26 -0
  28. trading-api/get_ppse.py +29 -0
  29. trading-api/post_order.py +38 -0
  30. trading-api/put_order.py +35 -0
  31. trading-api/send_email_otp.py +22 -0
  32. websocket-marketdata/expected_price.py +53 -0
  33. websocket-marketdata/foreign_investor.py +51 -0
  34. websocket-marketdata/market_index.py +52 -0
  35. websocket-marketdata/ohlc.py +55 -0
  36. websocket-marketdata/ohlc_closed.py +55 -0
  37. websocket-marketdata/order.py +51 -0
  38. websocket-marketdata/quote.py +50 -0
  39. websocket-marketdata/sec_def.py +52 -0
  40. websocket-marketdata/trade.py +52 -0
  41. websocket-marketdata/trade_extra.py +51 -0
  42. websocket-marketdata/trading_websocket/__init__.py +33 -0
  43. websocket-marketdata/trading_websocket/_version.py +3 -0
  44. websocket-marketdata/trading_websocket/auth.py +59 -0
  45. websocket-marketdata/trading_websocket/client.py +790 -0
  46. websocket-marketdata/trading_websocket/connection.py +151 -0
  47. websocket-marketdata/trading_websocket/encoding.py +78 -0
  48. websocket-marketdata/trading_websocket/exceptions.py +38 -0
  49. websocket-marketdata/trading_websocket/models.py +525 -0
  50. websocket-marketdata/trading_websocket/py.typed +0 -0
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env python3
2
+ import os
3
+ import sys
4
+
5
+ sys.path.append(os.path.dirname(os.path.dirname(__file__)))
6
+
7
+ from dnse import DNSEClient
8
+
9
+
10
+ def main():
11
+ client = DNSEClient(
12
+ api_key="replace-with-api-key",
13
+ api_secret="replace-with-api-secret",
14
+ base_url="https://openapi.dnse.com.vn",
15
+ )
16
+
17
+ status, body = client.send_email_otp(dry_run=False)
18
+ print(status, body)
19
+
20
+
21
+ if __name__ == "__main__":
22
+ main()
@@ -0,0 +1,53 @@
1
+ """
2
+ Market data subscription example.
3
+
4
+ Demonstrates:
5
+ - Subscribing to expected price updates
6
+
7
+ This example shows how to receive real-time market data for multiple symbols.
8
+ """
9
+
10
+ import asyncio
11
+ from datetime import datetime
12
+
13
+ from trading_websocket import TradingClient
14
+ from trading_websocket.models import ExpectedPrice
15
+
16
+
17
+ async def main():
18
+ # Initialize client
19
+ encoding = "msgpack" # json or msgpack
20
+ client = TradingClient(
21
+ api_key="api-key",
22
+ api_secret="api-secret",
23
+ base_url="wss://ws-openapi.dnse.com.vn",
24
+ encoding=encoding,
25
+ )
26
+
27
+ def handle_expected_price(expected_price: ExpectedPrice):
28
+ received_at = datetime.fromtimestamp(expected_price.receivedAt).strftime("%H:%M:%S.%f")[:-3] if expected_price.receivedAt else "N/A"
29
+ print(f"[{received_at}] EXPECTED PRICE: {expected_price}")
30
+
31
+ # Connect to gateway
32
+ print("Connecting to WebSocket gateway...")
33
+ await client.connect()
34
+ print(f"Connected! Session ID: {client._session_id}\n")
35
+
36
+ print("Subscribing to expected price for SSI and 41I1G4000...")
37
+ await client.subscribe_expected_price(["SSI", "41I1G4000"],
38
+ on_expected_price=handle_expected_price, encoding=encoding, board_id="G1")
39
+
40
+ print("\nReceiving market data (will run for 1 hour)...\n")
41
+
42
+ # Run for 1H to collect data
43
+ # In a real application, you might run indefinitely or until a specific condition
44
+ await asyncio.sleep(60 * 60 * 8)
45
+
46
+ # Disconnect gracefully
47
+ print("\n\nDisconnecting...")
48
+ await client.disconnect()
49
+ print("Disconnected!")
50
+
51
+
52
+ if __name__ == "__main__":
53
+ asyncio.run(main())
@@ -0,0 +1,51 @@
1
+ """
2
+ Demonstrates:
3
+ - Subscribing to foreigner trading
4
+
5
+ This example shows how to receive real-time foreigner trading data
6
+ """
7
+
8
+ import asyncio
9
+ from datetime import datetime
10
+
11
+ from trading_websocket import TradingClient
12
+ from trading_websocket.models import ForeignInvestor
13
+
14
+
15
+ async def main():
16
+ # Initialize client
17
+ encoding = "json" # json or msgpack
18
+ client = TradingClient(
19
+ api_key="api-key",
20
+ api_secret="api-secret",
21
+ base_url="wss://ws-openapi.dnse.com.vn",
22
+ encoding=encoding,
23
+ )
24
+
25
+ def handle_foreign_trading(data: ForeignInvestor):
26
+ received_at = datetime.fromtimestamp(data.receivedAt).strftime("%H:%M:%S.%f")[:-3] if data.receivedAt else "N/A"
27
+ print(f"[{received_at}] Foreign trading: {data}")
28
+
29
+ # Connect to gateway
30
+ print("Connecting to WebSocket gateway...")
31
+ await client.connect()
32
+ print(f"Connected! Session ID: {client._session_id}\n")
33
+
34
+ print("Subscribing to foreigner trading...")
35
+ await client.subscribe_foreign_trading(["HPG", "FPT"], board_id="G1", on_trade=handle_foreign_trading,
36
+ encoding=encoding)
37
+
38
+ print("\nReceiving foreigner trading data (will run for 8 hour)...\n")
39
+
40
+ # Run for 8H to collect data
41
+ # In a real application, you might run indefinitely or until a specific condition
42
+ await asyncio.sleep(60 * 60 * 8)
43
+
44
+ # Disconnect gracefully
45
+ print("\n\nDisconnecting...")
46
+ await client.disconnect()
47
+ print("Disconnected!")
48
+
49
+
50
+ if __name__ == "__main__":
51
+ asyncio.run(main())
@@ -0,0 +1,52 @@
1
+ """
2
+ Market index subscription example.
3
+
4
+ Demonstrates:
5
+ - Subscribing to market index
6
+
7
+ This example shows how to receive real-time market index
8
+ """
9
+
10
+ import asyncio
11
+
12
+ from trading_websocket import TradingClient
13
+ from trading_websocket.models import MarketIndex
14
+ from datetime import datetime
15
+
16
+
17
+ async def main():
18
+ # Initialize client
19
+ encoding = "msgpack" # json or msgpack
20
+ client = TradingClient(
21
+ api_key="api-key",
22
+ api_secret="api-secret",
23
+ base_url="wss://ws-openapi.dnse.com.vn",
24
+ encoding=encoding,
25
+ )
26
+
27
+ def handle_market_index(data: MarketIndex):
28
+ received_at = datetime.fromtimestamp(data.receivedAt).strftime("%H:%M:%S.%f")[:-3] if data.receivedAt else "N/A"
29
+ print(f"[{received_at}] Market index: {data}")
30
+
31
+ # Connect to gateway
32
+ print("Connecting to WebSocket gateway...")
33
+ await client.connect()
34
+ print(f"Connected! Session ID: {client._session_id}\n")
35
+
36
+ print("Subscribing to market index...")
37
+ await client.subscribe_market_index(market_index='HNX', on_market_index=handle_market_index, encoding=encoding)
38
+
39
+ print("\nReceiving market index (will run for 1 hour)...\n")
40
+
41
+ # Run for 1H to collect data
42
+ # In a real application, you might run indefinitely or until a specific condition
43
+ await asyncio.sleep(8 * 60 * 60)
44
+
45
+ # Disconnect gracefully
46
+ print("\n\nDisconnecting...")
47
+ await client.disconnect()
48
+ print("Disconnected!")
49
+
50
+
51
+ if __name__ == "__main__":
52
+ asyncio.run(main())
@@ -0,0 +1,55 @@
1
+ """
2
+ Market data subscription example.
3
+
4
+ Demonstrates:
5
+ - Subscribing to OHLCV updates
6
+
7
+ This example shows how to receive real-time market data for multiple symbols.
8
+ """
9
+
10
+ import asyncio
11
+ from datetime import datetime
12
+
13
+ from trading_websocket import TradingClient
14
+ from trading_websocket.models import Ohlc
15
+
16
+
17
+ async def main():
18
+ # Initialize client
19
+ encoding = "msgpack" # json or msgpack
20
+ client = TradingClient(
21
+ api_key="api-key",
22
+ api_secret="api-secret",
23
+ base_url="wss://ws-openapi.dnse.com.vn",
24
+ encoding=encoding,
25
+ )
26
+
27
+ def handle_ohlc(ohlc: Ohlc):
28
+ received_at = datetime.fromtimestamp(ohlc.receivedAt).strftime("%H:%M:%S.%f")[:-3] if ohlc.receivedAt else "N/A"
29
+ print(f"[{received_at}] OHLC: {ohlc}")
30
+
31
+ # Connect to gateway
32
+ print("Connecting to WebSocket gateway...")
33
+ await client.connect()
34
+ print(f"Connected! Session ID: {client._session_id}\n")
35
+
36
+ print("Subscribing to ohlc for SSI, VN30F1M and VN30...")
37
+ # internal 1 3 5 15 30 1H 1D 1W
38
+ await client.subscribe_ohlc(["SSI", "VN30F1M", "VN30"], resolution="1", on_ohlc=handle_ohlc, encoding=encoding)
39
+
40
+ # Subscribe to 1-minute OHLC
41
+
42
+ print("\nReceiving market data (will run for 1 hour)...\n")
43
+
44
+ # Run for 8H to collect data
45
+ # In a real application, you might run indefinitely or until a specific condition
46
+ await asyncio.sleep(8 * 60 * 60)
47
+
48
+ # Disconnect gracefully
49
+ print("\n\nDisconnecting...")
50
+ await client.disconnect()
51
+ print("Disconnected!")
52
+
53
+
54
+ if __name__ == "__main__":
55
+ asyncio.run(main())
@@ -0,0 +1,55 @@
1
+ """
2
+ Market data subscription example.
3
+
4
+ Demonstrates:
5
+ - Subscribing to OHLCV updates
6
+
7
+ This example shows how to receive real-time market data for multiple symbols.
8
+ """
9
+
10
+ import asyncio
11
+ from datetime import datetime
12
+
13
+ from trading_websocket import TradingClient
14
+ from trading_websocket.models import Ohlc
15
+
16
+
17
+ async def main():
18
+ # Initialize client
19
+ encoding = "msgpack" # json or msgpack
20
+ client = TradingClient(
21
+ api_key="api-key",
22
+ api_secret="api-secret",
23
+ base_url="wss://ws-openapi.dnse.com.vn",
24
+ encoding=encoding,
25
+ )
26
+
27
+ def handle_ohlc(ohlc: Ohlc):
28
+ received_at = datetime.fromtimestamp(ohlc.receivedAt).strftime("%H:%M:%S.%f")[:-3] if ohlc.receivedAt else "N/A"
29
+ print(f"[{received_at}] OHLC: {ohlc}")
30
+
31
+ # Connect to gateway
32
+ print("Connecting to WebSocket gateway...")
33
+ await client.connect()
34
+ print(f"Connected! Session ID: {client._session_id}\n")
35
+
36
+ print("Subscribing to ohlc closed for SSI, VN30F1M and VN30...")
37
+ # internal 1 3 5 15 30 1H 1D 1W
38
+ await client.subscribe_ohlc_closed(["SSI", "VN30F1M", "VN30"], resolution="1", on_ohlc=handle_ohlc, encoding=encoding)
39
+
40
+ # Subscribe to 1-minute OHLC
41
+
42
+ print("\nReceiving market data (will run for 1 hour)...\n")
43
+
44
+ # Run for 8H to collect data
45
+ # In a real application, you might run indefinitely or until a specific condition
46
+ await asyncio.sleep(8 * 60 * 60)
47
+
48
+ # Disconnect gracefully
49
+ print("\n\nDisconnecting...")
50
+ await client.disconnect()
51
+ print("Disconnected!")
52
+
53
+
54
+ if __name__ == "__main__":
55
+ asyncio.run(main())
@@ -0,0 +1,51 @@
1
+ """
2
+ Order event subscription example.
3
+
4
+ This example shows how to receive real-time order event for stock and derivative orders
5
+ """
6
+
7
+ import asyncio
8
+ from datetime import datetime
9
+
10
+ from trading_websocket import TradingClient
11
+ from trading_websocket.models import Order
12
+
13
+
14
+ async def main():
15
+ # Initialize client
16
+ encoding = "json" # json or msgpack
17
+ client = TradingClient(
18
+ api_key="api-key",
19
+ api_secret="api-secret",
20
+ base_url="wss://ws-openapi.dnse.com.vn",
21
+ encoding=encoding,
22
+ )
23
+
24
+ def handle_order(data: Order):
25
+ received_at = datetime.fromtimestamp(data.receivedAt).strftime("%H:%M:%S.%f")[:-3] if data.receivedAt else "N/A"
26
+ print(f"[{received_at}] Order: {data}")
27
+
28
+ # Connect to gateway
29
+ print("Connecting to WebSocket gateway...")
30
+ await client.connect()
31
+ print(f"Connected! Session ID: {client._session_id}\n")
32
+
33
+ print("Subscribing to order event")
34
+ # market_type: DERIVATIVE | STOCK
35
+ await client.subscribe_order_event(market_type="STOCK",
36
+ on_order_event=handle_order, encoding=encoding)
37
+
38
+ print("\nReceiving order event (will run for 1 hour)...\n")
39
+
40
+ # Run for 8H to collect data
41
+ # In a real application, you might run indefinitely or until a specific condition
42
+ await asyncio.sleep(8 * 60 * 60)
43
+
44
+ # Disconnect gracefully
45
+ print("\n\nDisconnecting...")
46
+ await client.disconnect()
47
+ print("Disconnected!")
48
+
49
+
50
+ if __name__ == "__main__":
51
+ asyncio.run(main())
@@ -0,0 +1,50 @@
1
+ """
2
+ Demonstrates:
3
+ - Subscribing to quote (BBO) updates
4
+
5
+ This example shows how to receive real-time quote data for multiple symbols.
6
+ """
7
+
8
+ import asyncio
9
+ from datetime import datetime
10
+
11
+ from trading_websocket import TradingClient
12
+ from trading_websocket.models import Quote
13
+
14
+
15
+ async def main():
16
+ # Initialize client
17
+ encoding = "msgpack" # json or msgpack
18
+ client = TradingClient(
19
+ api_key="api-key",
20
+ api_secret="api-secret",
21
+ base_url="wss://ws-openapi.dnse.com.vn",
22
+ encoding=encoding,
23
+ )
24
+
25
+ def handle_quote(quote: Quote):
26
+ received_at = datetime.fromtimestamp(quote.receivedAt).strftime("%H:%M:%S.%f")[:-3] if quote.receivedAt else "N/A"
27
+ print(f"[{received_at}] QUOTE: {quote}")
28
+
29
+ # Connect to gateway
30
+ print("Connecting to WebSocket gateway...")
31
+ await client.connect()
32
+ print(f"Connected! Session ID: {client._session_id}\n")
33
+
34
+ print("Subscribing to quotes for SSI and 41I1G4000...")
35
+ await client.subscribe_quotes(["SSI", "41I1G4000"], on_quote=handle_quote, encoding=encoding, board_id="G1")
36
+
37
+ print("\nReceiving market data (will run for 1 hour)...\n")
38
+
39
+ # Run for 8H to collect data
40
+ # In a real application, you might run indefinitely or until a specific condition
41
+ await asyncio.sleep(8 * 60 * 60)
42
+
43
+ # Disconnect gracefully
44
+ print("\n\nDisconnecting...")
45
+ await client.disconnect()
46
+ print("Disconnected!")
47
+
48
+
49
+ if __name__ == "__main__":
50
+ asyncio.run(main())
@@ -0,0 +1,52 @@
1
+ """
2
+ Market data subscription example.
3
+
4
+ Demonstrates:
5
+ - Subscribing to security definition updates
6
+
7
+ This example shows how to receive real-time market data for multiple symbols.
8
+ """
9
+
10
+ import asyncio
11
+ from datetime import datetime
12
+
13
+ from trading_websocket import TradingClient
14
+ from trading_websocket.models import SecurityDefinition
15
+
16
+
17
+ async def main():
18
+ # Initialize client
19
+ encoding = "msgpack" # json or msgpack
20
+ client = TradingClient(
21
+ api_key="api-key",
22
+ api_secret="api-secret",
23
+ base_url="wss://ws-openapi.dnse.com.vn",
24
+ encoding=encoding,
25
+ )
26
+
27
+ def handle_security_definition(sec_def: SecurityDefinition):
28
+ received_at = datetime.fromtimestamp(sec_def.receivedAt).strftime("%H:%M:%S.%f")[:-3] if sec_def.receivedAt else "N/A"
29
+ print(f"[{received_at}] SECURITY DEFINITION: {sec_def}")
30
+
31
+ # Connect to gateway
32
+ print("Connecting to WebSocket gateway...")
33
+ await client.connect()
34
+ print(f"Connected! Session ID: {client._session_id}\n")
35
+
36
+ print("Subscribing to security definition for SSI and 41I1G2000...")
37
+ await client.subscribe_sec_def(["SSI", "41I1G2000"], on_sec_def=handle_security_definition, encoding=encoding, board_id="G1")
38
+
39
+ print("\nReceiving market data (will run for 1 hour)...\n")
40
+
41
+ # Run for 1H to collect data
42
+ # In a real application, you might run indefinitely or until a specific condition
43
+ await asyncio.sleep(8 * 60 * 60)
44
+
45
+ # Disconnect gracefully
46
+ print("\n\nDisconnecting...")
47
+ await client.disconnect()
48
+ print("Disconnected!")
49
+
50
+
51
+ if __name__ == "__main__":
52
+ asyncio.run(main())
@@ -0,0 +1,52 @@
1
+ """
2
+ Market data subscription example.
3
+
4
+ Demonstrates:
5
+ - Subscribing to trade updates
6
+
7
+ This example shows how to receive real-time market data for multiple symbols.
8
+ """
9
+
10
+ import asyncio
11
+ from datetime import datetime
12
+
13
+ from trading_websocket import TradingClient
14
+ from trading_websocket.models import Trade
15
+
16
+
17
+ async def main():
18
+ # Initialize client
19
+ encoding = "msgpack" # json or msgpack
20
+ client = TradingClient(
21
+ api_key="api-key",
22
+ api_secret="api-secret",
23
+ base_url="wss://ws-openapi.dnse.com.vn",
24
+ encoding=encoding,
25
+ )
26
+
27
+ def handle_trade(trade: Trade):
28
+ received_at = datetime.fromtimestamp(trade.receivedAt).strftime("%H:%M:%S.%f")[:-3] if trade.receivedAt else "N/A"
29
+ print(f"[{received_at}] TRADE: {trade}")
30
+
31
+ # Connect to gateway
32
+ print("Connecting to WebSocket gateway...")
33
+ await client.connect()
34
+ print(f"Connected! Session ID: {client._session_id}\n")
35
+
36
+ print("Subscribing to trades for SSI and 41I1G4000...")
37
+ await client.subscribe_trades(["SSI", "41I1G4000"], on_trade=handle_trade, encoding=encoding, board_id="G1")
38
+
39
+ print("\nReceiving market data (will run for 1 hour)...\n")
40
+
41
+ # Run for 8H to collect data
42
+ # In a real application, you might run indefinitely or until a specific condition
43
+ await asyncio.sleep(8 * 60 * 60)
44
+
45
+ # Disconnect gracefully
46
+ print("\n\nDisconnecting...")
47
+ await client.disconnect()
48
+ print("Disconnected!")
49
+
50
+
51
+ if __name__ == "__main__":
52
+ asyncio.run(main())
@@ -0,0 +1,51 @@
1
+ """
2
+ Market data subscription example.
3
+
4
+ Demonstrates:
5
+ - Subscribing to trade extra updates
6
+
7
+ This example shows how to receive real-time market data for multiple symbols.
8
+ """
9
+
10
+ import asyncio
11
+ from datetime import datetime
12
+ from trading_websocket import TradingClient
13
+ import trading_websocket.models
14
+
15
+
16
+ async def main():
17
+ # Initialize client
18
+ encoding = "msgpack" # json or msgpack
19
+ client = TradingClient(
20
+ api_key="api-key",
21
+ api_secret="api-secret",
22
+ base_url="wss://ws-openapi.dnse.com.vn",
23
+ encoding=encoding,
24
+ )
25
+
26
+ def handle_trade_extra(trade: trading_websocket.models.TradeExtra):
27
+ received_at = datetime.fromtimestamp(trade.receivedAt).strftime("%H:%M:%S.%f")[:-3] if trade.receivedAt else "N/A"
28
+ print(f"[{received_at}] TRADE EXTRA: {trade}")
29
+
30
+ # Connect to gateway
31
+ print("Connecting to WebSocket gateway...")
32
+ await client.connect()
33
+ print(f"Connected! Session ID: {client._session_id}\n")
34
+
35
+ print("Subscribing to trade extra for SSI and 41I1G4000...")
36
+ await client.subscribe_trade_extra(["SSI", "41I1G4000"], on_trade_extra=handle_trade_extra, encoding=encoding, board_id="G1")
37
+
38
+ print("\nReceiving market data (will run for 1 hour)...\n")
39
+
40
+ # Run for 8H to collect data
41
+ # In a real application, you might run indefinitely or until a specific condition
42
+ await asyncio.sleep(8 * 60 * 60)
43
+
44
+ # Disconnect gracefully
45
+ print("\n\nDisconnecting...")
46
+ await client.disconnect()
47
+ print("Disconnected!")
48
+
49
+
50
+ if __name__ == "__main__":
51
+ asyncio.run(main())
@@ -0,0 +1,33 @@
1
+ """Trading WebSocket SDK for Python.
2
+
3
+ Async Python client for real-time trading data via WebSocket.
4
+ """
5
+
6
+ from .client import TradingClient
7
+ from .models import Trade, Quote, Ohlc, Order, Position, AccountUpdate
8
+ from .exceptions import (
9
+ TradingWebSocketError,
10
+ ConnectionError,
11
+ ConnectionClosed,
12
+ AuthenticationError,
13
+ SubscriptionError,
14
+ EncodingError,
15
+ )
16
+
17
+ __version__ = "1.0.0"
18
+
19
+ __all__ = [
20
+ "TradingClient",
21
+ "Trade",
22
+ "Quote",
23
+ "Ohlc",
24
+ "Order",
25
+ "Position",
26
+ "AccountUpdate",
27
+ "TradingWebSocketError",
28
+ "ConnectionError",
29
+ "ConnectionClosed",
30
+ "AuthenticationError",
31
+ "SubscriptionError",
32
+ "EncodingError",
33
+ ]
@@ -0,0 +1,3 @@
1
+ """Version information for trading_websocket package."""
2
+
3
+ __version__ = "1.0.0"
@@ -0,0 +1,59 @@
1
+ import hmac
2
+ import hashlib
3
+ import time
4
+ from typing import Dict, Any
5
+
6
+
7
+ class AuthManager:
8
+ """
9
+ HMAC-SHA256 authentication manager.
10
+
11
+ Handles signature generation and nonce creation for WebSocket authentication.
12
+ """
13
+
14
+ def __init__(self, api_key: str, api_secret: str):
15
+ """
16
+ Initialize auth manager.
17
+
18
+ Args:
19
+ api_key: API key
20
+ api_secret: API secret for HMAC signature
21
+ """
22
+ self.api_key = api_key
23
+ self.api_secret = api_secret
24
+
25
+ def create_auth_message(self) -> Dict[str, Any]:
26
+ timestamp = int(time.time()) # second
27
+ nonce = str(int(time.time() * 1000000)) # microseconds for uniqueness
28
+
29
+ signature = self.compute_signature(timestamp, nonce)
30
+
31
+ return {
32
+ "action": "auth",
33
+ "api_key": self.api_key,
34
+ "signature": signature,
35
+ "timestamp": timestamp,
36
+ "nonce": nonce
37
+ }
38
+
39
+ def compute_signature(self, timestamp: int, nonce: str) -> str:
40
+ """
41
+ Compute HMAC-SHA256 signature.
42
+
43
+ Args:
44
+ timestamp: Unix timestamp in second
45
+ nonce: Unique nonce string
46
+
47
+ Returns:
48
+ Hex-encoded HMAC signature
49
+ """
50
+ # Message format: {api_key}:{timestamp}:{nonce}
51
+ message = f"{self.api_key}:{timestamp}:{nonce}"
52
+
53
+ signature = hmac.new(
54
+ self.api_secret.encode('utf-8'),
55
+ message.encode('utf-8'),
56
+ hashlib.sha256
57
+ ).hexdigest()
58
+
59
+ return signature