如何从Bittrex调用该异步函数?WebSocket API升级求助
Hey there! I see you're transitioning from a scripted balance query to Bittrex's WebSocket API and got stuck on the signature and connection flow. Let's break this down step by step, starting with finishing that signature function and building out a complete working example.
First: Complete the Signature Function
You had the right start with the HMAC-SHA512 signature—here's the full implementation:
async def create_signature(api_secret, challenge): # Sign the server-provided challenge string with your API secret api_sign = hmac.new(api_secret.encode(), challenge.encode(), hashlib.sha512) return api_sign.hexdigest()
This takes the unique challenge Bittrex sends you and signs it, which proves you own the API key/secret pair.
Full Working Example with Key Concepts Explained
Here's a complete async script that handles connection, authentication, subscribing to balance updates, and parsing compressed messages:
from signalr_aio import Connection from base64 import b64decode from zlib import decompress, MAX_WBITS import hashlib import hmac import json import asyncio async def create_signature(api_secret, challenge): api_sign = hmac.new(api_secret.encode(), challenge.encode(), hashlib.sha512) return api_sign.hexdigest() async def main(): # Bittrex's official WebSocket SignalR endpoint ws_url = "wss://socket-v3.bittrex.com/signalr" connection = Connection(ws_url, session=None) # Register the "c3" hub—this is Bittrex's v3 API hub for real-time data c3_hub = connection.register_hub("c3") # Handle incoming update messages (this is where you'll get balance data) async def handle_updates(message): # Bittrex compresses all update payloads with zlib + base64 if message.get("M") == "update": compressed_payload = message["A"][0] # Decode base64, then decompress (MAX_WBITS |16 handles gzip-formatted compression) decompressed_data = decompress(b64decode(compressed_payload), MAX_WBITS | 16) parsed_data = json.loads(decompressed_data.decode()) # Filter for balance-specific updates if parsed_data["type"] == "balance": print("\n--- Current Balance Update ---") for balance in parsed_data["data"]: print(f"Asset: {balance['currencySymbol']}") print(f" Available: {balance['available']}") print(f" Total: {balance['total']}\n") # Attach the update handler to the hub c3_hub.on("update", handle_updates) # Handle the authentication challenge from Bittrex async def handle_challenge(message): challenge_str = message["A"][0] # Replace these with your actual Bittrex API credentials YOUR_API_KEY = "your-bittrex-api-key-here" YOUR_API_SECRET = "your-bittrex-api-secret-here" # Generate the required signature auth_signature = await create_signature(YOUR_API_SECRET, challenge_str) # Send authentication to the hub await c3_hub.invoke("authenticate", YOUR_API_KEY, auth_signature) print("Successfully authenticated with Bittrex WebSocket API!") # Attach the challenge handler c3_hub.on("challenge", handle_challenge) # Start the WebSocket connection await connection.start() # Subscribe to the "balance" channel to receive balance updates await c3_hub.invoke("subscribe", ["balance"]) # Keep the connection running (prevent script from exiting) while True: await asyncio.sleep(1) if __name__ == "__main__": event_loop = asyncio.get_event_loop() try: event_loop.run_until_complete(main()) except KeyboardInterrupt: print("\nConnection closed manually.")
Key Concepts You Might Have Missed
Let's clarify the parts that often trip people up:
- SignalR Hubs: Bittrex uses SignalR (a real-time communication framework) instead of raw WebSockets. The
c3hub is the official entry point for their v3 API—you can't connect to the right data without registering it. - Challenge Authentication: Bittrex doesn't let you send credentials directly. Instead, it sends a unique challenge string, you sign it with your secret, and send back the signature. This prevents replay attacks.
- Message Compression: All real-time updates are compressed to save bandwidth. You must decode the base64 string first, then decompress it with zlib (the
MAX_WBITS |16flag handles the gzip header Bittrex uses). - Subscriptions: You only get data for channels you explicitly subscribe to. For balances, we use the
balancechannel—other common channels areorder(for your order updates) andmarket(for market price data).
Important Notes
- Permissions: Make sure your Bittrex API key has read-only access (or full access if you need it) for balance data. You can set this when creating the key in your Bittrex account settings.
- Dependencies: Install the required library with
pip install signalr-aio. - Error Handling: Add try/except blocks around connection starts, invoke calls, and message parsing to handle disconnections or malformed data (critical for production use).
内容的提问来源于stack exchange,提问作者user9375283

