-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathstream_grpc.py
More file actions
158 lines (116 loc) · 3.78 KB
/
stream_grpc.py
File metadata and controls
158 lines (116 loc) · 3.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#!/usr/bin/env python3
"""
gRPC Streaming Example - High-Performance Real-Time Data
Stream trades, orders, L2 book, L4 book, and blocks via gRPC.
gRPC provides lower latency than WebSocket for high-frequency trading.
The SDK:
- Connects to port 10000 automatically
- Passes token via x-token header
- Handles reconnection with exponential backoff
- Manages keepalive pings
Requirements:
pip install hyperliquid-sdk[grpc]
Usage:
export ENDPOINT="https://your-endpoint.example.com/TOKEN"
python stream_grpc.py
"""
import os
import signal
import sys
import time
from datetime import datetime
from hyperliquid_sdk import HyperliquidSDK
ENDPOINT = os.environ.get("ENDPOINT") or os.environ.get("QUICKNODE_ENDPOINT")
if not ENDPOINT:
print("gRPC Streaming Example")
print("=" * 60)
print()
print("Usage:")
print(" export ENDPOINT='https://your-endpoint.example.com/TOKEN'")
print(" python stream_grpc.py")
sys.exit(1)
def timestamp():
return datetime.now().isoformat()[11:23]
def main():
print("=" * 60)
print("gRPC Streaming Examples")
print("=" * 60)
# Example 1: Stream Trades
print("\nExample 1: Streaming Trades")
print("-" * 60)
trade_count = [0]
# Create SDK client
sdk = HyperliquidSDK(ENDPOINT)
grpc = sdk.grpc
def on_connect():
print("[CONNECTED]")
def on_error(err):
print(f"[ERROR] {err}")
def on_trade(data):
trade_count[0] += 1
coin = data.get("coin", "?")
px = float(data.get("px", "0"))
sz = data.get("sz", "?")
side = "BUY " if data.get("side") == "B" else "SELL"
print(f"[{timestamp()}] {side} {sz} {coin} @ ${px:,.2f}")
grpc.on_connect = on_connect
grpc.on_error = on_error
grpc.trades(["BTC", "ETH"], on_trade)
print("Subscribing to BTC and ETH trades...")
# Handle Ctrl+C gracefully
def signal_handler(sig, frame):
print("\nShutting down gracefully...")
grpc.stop()
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
grpc.start()
# Wait for trades or timeout
start = time.time()
while trade_count[0] < 10 and time.time() - start < 30:
time.sleep(0.1)
print(f"\nReceived {trade_count[0]} trades.")
grpc.stop()
# Example 2: Stream L2 Book
print("\nExample 2: Streaming L2 Order Book")
print("-" * 60)
l2_count = [0]
sdk2 = HyperliquidSDK(ENDPOINT)
grpc2 = sdk2.grpc()
def on_l2_book(data):
l2_count[0] += 1
bids = data.get("bids", [])
asks = data.get("asks", [])
if bids and asks:
best_bid = float(bids[0][0]) if isinstance(bids[0], list) else float(bids[0].get("price", 0))
best_ask = float(asks[0][0]) if isinstance(asks[0], list) else float(asks[0].get("price", 0))
spread = best_ask - best_bid
print(f"[{timestamp()}] ETH: bid=${best_bid:,.2f} ask=${best_ask:,.2f} spread=${spread:.2f}")
grpc2.l2_book("ETH", on_l2_book, n_levels=10)
grpc2.start()
start = time.time()
while l2_count[0] < 5 and time.time() - start < 15:
time.sleep(0.1)
print(f"\nReceived {l2_count[0]} L2 updates.")
grpc2.stop()
# Example 3: Stream Blocks
print("\nExample 3: Streaming Blocks")
print("-" * 60)
block_count = [0]
sdk3 = HyperliquidSDK(ENDPOINT)
grpc3 = sdk3.grpc()
def on_block(data):
block_count[0] += 1
bn = data.get("block_number", "?")
print(f"[{timestamp()}] Block #{bn}")
grpc3.blocks(on_block)
grpc3.start()
start = time.time()
while block_count[0] < 5 and time.time() - start < 20:
time.sleep(0.1)
print(f"\nReceived {block_count[0]} blocks.")
grpc3.stop()
print()
print("=" * 60)
print("Done!")
if __name__ == "__main__":
main()