StreamBboBook gRPC Method
Please note that this method is metered based on data consumption at 0.0165 MB = 10 API credits.
Parámetros
coins
repeated string
Cargando...
Devoluciones
stream
stream<BboBookUpdate>
Cargando...
moneda
cadena
Cargando...
tiempo
uint64
Cargando...
block_number
uint64
Cargando...
bid
L2Level
Cargando...
ask
L2Level
Cargando...
Solicitud
1// StreamBboBook Example - Stream top-of-book best bid/ask changes via gRPC2package main34import (5«contexto»6"flag"7«fmt»8"io"9«registro»10"math"11"strings"12«tiempo»1314"google.golang.org/grpc"15"google.golang.org/grpc/codes"16"google.golang.org/grpc/credentials"17"google.golang.org/grpc/metadata"18"google.golang.org/grpc/status"1920pb "hyperliquid-orderbook-example/proto"21)2223const (24grpcEndpoint = "your-endpoint.hype-mainnet.quiknode.pro:10000"25authToken = "your-auth-token"26maxRetries = 1027baseDelay = 2 * time.Second28)2930func streamBboBook(coins []string) error {31fmt.Println(strings.Repeat("=", 60))32fmt.Printf("Streaming BBO Book for %s\n", strings.Join(coins, ", "))33fmt.Println("Auto-reconnect: true")34fmt.Println(strings.Repeat("=", 60) + "\n")3536retryCount := 03738for retryCount < maxRetries {39creds := credentials.NewClientTLSFromCert(nil, "")40conn, err := grpc.Dial(grpcEndpoint,41grpc.WithTransportCredentials(creds),42grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(100*1024*1024)))43if err != nil {44return fmt.Errorf("failed to connect: %w", err)45}4647client := pb.NewOrderBookStreamingClient(conn)48ctx := metadata.AppendToOutgoingContext(context.Background(), "x-token", authToken)4950request := &pb.BboBookRequest{51Coins: coins,52}5354if retryCount > 0 {55fmt.Printf("\n🔄 Reconnecting (attempt %d/%d)...\n", retryCount+1, maxRetries)56} else {57fmt.Printf("Connecting to %s...\n", grpcEndpoint)58}5960stream, err := client.StreamBboBook(ctx, request)61if err != nil {62conn.Close()63return fmt.Errorf("failed to start stream: %w", err)64}6566msgCount := 067shouldRetry := false6869for {70update, err := stream.Recv()71if err == io.EOF {72break73}74if err != nil {75st, ok := status.FromError(err)76if ok && st.Code() == codes.DataLoss {77fmt.Printf("\n⚠️ Server reinitialized: %s\n", st.Message())78retryCount++79if retryCount < maxRetries {80delay := baseDelay * time.Duration(math.Pow(2, float64(retryCount-1)))81fmt.Printf("⏳ Waiting %v before reconnecting...\n", delay)82time.Sleep(delay)83shouldRetry = true84break85} else {86fmt.Printf("\n❌ Max retries (%d) reached. Giving up.\n", maxRetries)87conn.Close()88return nil89}90}91conn.Close()92return fmt.Errorf("stream error: %w", err)93}9495msgCount++96if msgCount == 1 {97fmt.Println("✓ First BBO update received!\n")98retryCount = 0 // Reset on success99}100101// Display BBO update102fmt.Println("\n" + strings.Repeat("─", 60))103fmt.Printf("Block: %d | Time: %d | Coin: %s\n", update.BlockNumber, update.Time, update.Coin)104fmt.Println(strings.Repeat("─", 60))105106// Display best ask107if update.Ask != nil {108fmt.Printf(" BEST ASK: %12s | %12s | (%d orders)\n", update.Ask.Px, update.Ask.Sz, update.Ask.N)109} else {110fmt.Println(" BEST ASK: (none)")111}112113// Display best bid114if update.Bid != nil {115fmt.Printf(" BEST BID: %12s | %12s | (%d orders)\n", update.Bid.Px, update.Bid.Sz, update.Bid.N)116} else {117fmt.Println(" BEST BID: (none)")118}119120// Display spread121if update.Bid != nil && update.Ask != nil {122fmt.Printf(" SPREAD: (best bid: %s, best ask: %s)\n", update.Bid.Px, update.Ask.Px)123}124125fmt.Printf("\n Messages received: %d\n", msgCount)126}127128conn.Close()129130if !shouldRetry {131break132}133}134135return nil136}137138func main() {139coinsFlag := flag.String("coins", "BTC", "Comma-separated coin symbols to stream (e.g., BTC,ETH)")140141flag.Parse()142143coins := strings.Split(*coinsFlag, ",")144145fmt.Println("\n" + strings.Repeat("=", 60))146fmt.Println("Hyperliquid StreamBboBook Example")147fmt.Printf("Endpoint: %s\n", grpcEndpoint)148fmt.Println(strings.Repeat("=", 60))149150if err := streamBboBook(coins); err != nil {151registro.Fatal(err)152}153}154
1// StreamBboBook Example - Stream top-of-book best bid/ask changes via gRPC2package main34import (5«contexto»6"flag"7«fmt»8"io"9«registro»10"math"11"strings"12«tiempo»1314"google.golang.org/grpc"15"google.golang.org/grpc/codes"16"google.golang.org/grpc/credentials"17"google.golang.org/grpc/metadata"18"google.golang.org/grpc/status"1920pb "hyperliquid-orderbook-example/proto"21)2223const (24grpcEndpoint = "your-endpoint.hype-mainnet.quiknode.pro:10000"25authToken = "your-auth-token"26maxRetries = 1027baseDelay = 2 * time.Second28)2930func streamBboBook(coins []string) error {31fmt.Println(strings.Repeat("=", 60))32fmt.Printf("Streaming BBO Book for %s\n", strings.Join(coins, ", "))33fmt.Println("Auto-reconnect: true")34fmt.Println(strings.Repeat("=", 60) + "\n")3536retryCount := 03738for retryCount < maxRetries {39creds := credentials.NewClientTLSFromCert(nil, "")40conn, err := grpc.Dial(grpcEndpoint,41grpc.WithTransportCredentials(creds),42grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(100*1024*1024)))43if err != nil {44return fmt.Errorf("failed to connect: %w", err)45}4647client := pb.NewOrderBookStreamingClient(conn)48ctx := metadata.AppendToOutgoingContext(context.Background(), "x-token", authToken)4950request := &pb.BboBookRequest{51Coins: coins,52}5354if retryCount > 0 {55fmt.Printf("\n🔄 Reconnecting (attempt %d/%d)...\n", retryCount+1, maxRetries)56} else {57fmt.Printf("Connecting to %s...\n", grpcEndpoint)58}5960stream, err := client.StreamBboBook(ctx, request)61if err != nil {62conn.Close()63return fmt.Errorf("failed to start stream: %w", err)64}6566msgCount := 067shouldRetry := false6869for {70update, err := stream.Recv()71if err == io.EOF {72break73}74if err != nil {75st, ok := status.FromError(err)76if ok && st.Code() == codes.DataLoss {77fmt.Printf("\n⚠️ Server reinitialized: %s\n", st.Message())78retryCount++79if retryCount < maxRetries {80delay := baseDelay * time.Duration(math.Pow(2, float64(retryCount-1)))81fmt.Printf("⏳ Waiting %v before reconnecting...\n", delay)82time.Sleep(delay)83shouldRetry = true84break85} else {86fmt.Printf("\n❌ Max retries (%d) reached. Giving up.\n", maxRetries)87conn.Close()88return nil89}90}91conn.Close()92return fmt.Errorf("stream error: %w", err)93}9495msgCount++96if msgCount == 1 {97fmt.Println("✓ First BBO update received!\n")98retryCount = 0 // Reset on success99}100101// Display BBO update102fmt.Println("\n" + strings.Repeat("─", 60))103fmt.Printf("Block: %d | Time: %d | Coin: %s\n", update.BlockNumber, update.Time, update.Coin)104fmt.Println(strings.Repeat("─", 60))105106// Display best ask107if update.Ask != nil {108fmt.Printf(" BEST ASK: %12s | %12s | (%d orders)\n", update.Ask.Px, update.Ask.Sz, update.Ask.N)109} else {110fmt.Println(" BEST ASK: (none)")111}112113// Display best bid114if update.Bid != nil {115fmt.Printf(" BEST BID: %12s | %12s | (%d orders)\n", update.Bid.Px, update.Bid.Sz, update.Bid.N)116} else {117fmt.Println(" BEST BID: (none)")118}119120// Display spread121if update.Bid != nil && update.Ask != nil {122fmt.Printf(" SPREAD: (best bid: %s, best ask: %s)\n", update.Bid.Px, update.Ask.Px)123}124125fmt.Printf("\n Messages received: %d\n", msgCount)126}127128conn.Close()129130if !shouldRetry {131break132}133}134135return nil136}137138func main() {139coinsFlag := flag.String("coins", "BTC", "Comma-separated coin symbols to stream (e.g., BTC,ETH)")140141flag.Parse()142143coins := strings.Split(*coinsFlag, ",")144145fmt.Println("\n" + strings.Repeat("=", 60))146fmt.Println("Hyperliquid StreamBboBook Example")147fmt.Printf("Endpoint: %s\n", grpcEndpoint)148fmt.Println(strings.Repeat("=", 60))149150if err := streamBboBook(coins); err != nil {151registro.Fatal(err)152}153}154
1// StreamBboBook Example - Stream top-of-book best bid/ask changes via gRPC2const grpc = require('@grpc/grpc-js');3const protoLoader = require('@grpc/proto-loader');4const path = require('path');56const GRPC_ENDPOINT = 'your-endpoint.hype-mainnet.quiknode.pro:10000';7const AUTH_TOKEN = 'your-auth-token';8const PROTO_PATH = path.join(__dirname, 'proto', 'orderbook.proto');910const packageDefinition = protoLoader.loadSync(PROTO_PATH, {11keepCase: true,12longs: String,13enums: String,14defaults: true,15oneofs: true16});17const proto = grpc.loadPackageDefinition(packageDefinition).hyperliquid;1819function createClient() {20return new proto.OrderBookStreaming(21GRPC_ENDPOINT,22grpc.credentials.createSsl(),23{ 'grpc.max_receive_message_length': 100 * 1024 * 1024 }24);25}2627// Stream best bid/offer updates28async function streamBboBook(coins, autoReconnect = true, retryCount = 0) {29console.log('='.repeat(60));30console.log(`Streaming BBO Book for ${coins.length > 0 ? coins.join(', ') : 'all coins'}`);31console.log(`Auto-reconnect: ${autoReconnect}`);32console.log('='.repeat(60) + '\n');3334const maxRetries = 10;35const baseDelay = 2000;3637while (retryCount < maxRetries) {38const client = createClient();39const metadata = new grpc.Metadata();40metadata.add('x-token', AUTH_TOKEN);4142const request = {43coins: coins44};4546prueba {47if (retryCount > 0) {48console.log(`\n🔄 Reconnecting (attempt ${retryCount + 1}/${maxRetries})...`);49} else {50console.log(`Connecting to ${GRPC_ENDPOINT}...`);51}5253let msgCount = 0;54const call = client.StreamBboBook(request, metadata);5556call.on('data', (update) => {57msgCount++;5859if (msgCount === 1) {60console.log('✓ First BBO update received!\n');61retryCount = 0; // Reset on success62}6364console.log('\n' + '─'.repeat(60));65console.log(`Block: ${update.block_number} | Time: ${update.time} | Coin: ${update.coin}`);66console.log('─'.repeat(60));6768// Display best ask69if (update.ask) {70console.log(` BEST ASK: ${update.ask.px.padStart(12)} | ${update.ask.sz.padStart(12)} | (${update.ask.n} orders)`);71} else {72console.log(' BEST ASK: (none)');73}7475// Display best bid76if (update.bid) {77console.log(` BEST BID: ${update.bid.px.padStart(12)} | ${update.bid.sz.padStart(12)} | (${update.bid.n} orders)`);78} else {79console.log(' BEST BID: (none)');80}8182// Display spread83if (update.bid && update.ask) {84const bestBid = parseFloat(update.bid.px);85const bestAsk = parseFloat(update.ask.px);86const spread = bestAsk - bestBid;87const spreadBps = (spread / bestBid) * 10000;88console.log(` SPREAD: ${spread.toFixed(2)} (${spreadBps.toFixed(2)} bps)`);89}9091console.log(`\n Messages received: ${msgCount}`);92});9394call.on('error', (err) => {95if (err.code === grpc.status.DATA_LOSS && autoReconnect) {96console.log(`\n⚠️ Server reinitialized: ${err.message}`);97retryCount++;98if (retryCount < maxRetries) {99const delay = baseDelay * Math.pow(2, retryCount - 1);100console.log(`⏳ Waiting ${delay / 1000}s before reconnecting...`);101setTimeout(() => streamBboBook(coins, autoReconnect, retryCount), delay);102} else {103console.log(`\n❌ Max retries (${maxRetries}) reached. Giving up.`);104}105} else {106console.error('\ngRPC error:', err.code, '-', err.message);107}108});109110call.on('end', () => {111console.log('\nStream ended');112});113114// Wait for stream to complete115await new Promise((resolve) => {116call.on('end', resolve);117call.on('error', resolve);118});119120break; // Exit retry loop on success121122} catch (err) {123console.error('Error:', err.message);124break;125}126}127}128129// Parse command line args130const args = process.argv.slice(2);131const coins = (args.find(a => a.startsWith('--coins='))?.split('=')[1] || 'BTC').split(',');132133console.log('\n' + '='.repeat(60));134console.log('Hyperliquid StreamBboBook Example');135console.log(`Endpoint: ${GRPC_ENDPOINT}`);136console.log('='.repeat(60));137138streamBboBook(coins);139
1// StreamBboBook Example - Stream top-of-book best bid/ask changes via gRPC2const grpc = require('@grpc/grpc-js');3const protoLoader = require('@grpc/proto-loader');4const path = require('path');56const GRPC_ENDPOINT = 'your-endpoint.hype-mainnet.quiknode.pro:10000';7const AUTH_TOKEN = 'your-auth-token';8const PROTO_PATH = path.join(__dirname, 'proto', 'orderbook.proto');910const packageDefinition = protoLoader.loadSync(PROTO_PATH, {11keepCase: true,12longs: String,13enums: String,14defaults: true,15oneofs: true16});17const proto = grpc.loadPackageDefinition(packageDefinition).hyperliquid;1819function createClient() {20return new proto.OrderBookStreaming(21GRPC_ENDPOINT,22grpc.credentials.createSsl(),23{ 'grpc.max_receive_message_length': 100 * 1024 * 1024 }24);25}2627// Stream best bid/offer updates28async function streamBboBook(coins, autoReconnect = true, retryCount = 0) {29console.log('='.repeat(60));30console.log(`Streaming BBO Book for ${coins.length > 0 ? coins.join(', ') : 'all coins'}`);31console.log(`Auto-reconnect: ${autoReconnect}`);32console.log('='.repeat(60) + '\n');3334const maxRetries = 10;35const baseDelay = 2000;3637while (retryCount < maxRetries) {38const client = createClient();39const metadata = new grpc.Metadata();40metadata.add('x-token', AUTH_TOKEN);4142const request = {43coins: coins44};4546prueba {47if (retryCount > 0) {48console.log(`\n🔄 Reconnecting (attempt ${retryCount + 1}/${maxRetries})...`);49} else {50console.log(`Connecting to ${GRPC_ENDPOINT}...`);51}5253let msgCount = 0;54const call = client.StreamBboBook(request, metadata);5556call.on('data', (update) => {57msgCount++;5859if (msgCount === 1) {60console.log('✓ First BBO update received!\n');61retryCount = 0; // Reset on success62}6364console.log('\n' + '─'.repeat(60));65console.log(`Block: ${update.block_number} | Time: ${update.time} | Coin: ${update.coin}`);66console.log('─'.repeat(60));6768// Display best ask69if (update.ask) {70console.log(` BEST ASK: ${update.ask.px.padStart(12)} | ${update.ask.sz.padStart(12)} | (${update.ask.n} orders)`);71} else {72console.log(' BEST ASK: (none)');73}7475// Display best bid76if (update.bid) {77console.log(` BEST BID: ${update.bid.px.padStart(12)} | ${update.bid.sz.padStart(12)} | (${update.bid.n} orders)`);78} else {79console.log(' BEST BID: (none)');80}8182// Display spread83if (update.bid && update.ask) {84const bestBid = parseFloat(update.bid.px);85const bestAsk = parseFloat(update.ask.px);86const spread = bestAsk - bestBid;87const spreadBps = (spread / bestBid) * 10000;88console.log(` SPREAD: ${spread.toFixed(2)} (${spreadBps.toFixed(2)} bps)`);89}9091console.log(`\n Messages received: ${msgCount}`);92});9394call.on('error', (err) => {95if (err.code === grpc.status.DATA_LOSS && autoReconnect) {96console.log(`\n⚠️ Server reinitialized: ${err.message}`);97retryCount++;98if (retryCount < maxRetries) {99const delay = baseDelay * Math.pow(2, retryCount - 1);100console.log(`⏳ Waiting ${delay / 1000}s before reconnecting...`);101setTimeout(() => streamBboBook(coins, autoReconnect, retryCount), delay);102} else {103console.log(`\n❌ Max retries (${maxRetries}) reached. Giving up.`);104}105} else {106console.error('\ngRPC error:', err.code, '-', err.message);107}108});109110call.on('end', () => {111console.log('\nStream ended');112});113114// Wait for stream to complete115await new Promise((resolve) => {116call.on('end', resolve);117call.on('error', resolve);118});119120break; // Exit retry loop on success121122} catch (err) {123console.error('Error:', err.message);124break;125}126}127}128129// Parse command line args130const args = process.argv.slice(2);131const coins = (args.find(a => a.startsWith('--coins='))?.split('=')[1] || 'BTC').split(',');132133console.log('\n' + '='.repeat(60));134console.log('Hyperliquid StreamBboBook Example');135console.log(`Endpoint: ${GRPC_ENDPOINT}`);136console.log('='.repeat(60));137138streamBboBook(coins);139
1#!/usr/bin/env python32"""3StreamBboBook Example - Stream top-of-book best bid/ask changes via gRPC45Setup:6pip install grpcio grpcio-tools protobuf zstandard7python -m grpc_tools.protoc -I../../proto --python_out=. --grpc_python_out=. ../../proto/orderbook.proto89Usage:10python stream_bbo_example.py --coins BTC,ETH11"""1213import grpc14import sys15import time16import argparse1718try:19import orderbook_pb2 as pb20import orderbook_pb2_grpc as pb_grpc21except ImportError:22print("Error: Proto files not generated. Run:")23print(" python -m grpc_tools.protoc -I../../proto --python_out=. --grpc_python_out=. ../../proto/orderbook.proto")24sys.exit(1)2526# Configuration27GRPC_ENDPOINT = "your-endpoint.hype-mainnet.quiknode.pro:10000"28AUTH_TOKEN = "your-auth-token"293031def stream_bbo_book(coins: list, auto_reconnect: bool = True):32"""33Stream best bid/offer (top-of-book) updates for one or more coins.3435Args:36coins: Symbols to stream (e.g., ["BTC", "ETH"]). Empty list means all coins37auto_reconnect: Auto-reconnect on DATA_LOSS errors (default True)38"""39print(f"\n{'='*60}")40print(f"Streaming BBO Book for {', '.join(coins) if coins else 'all coins'}")41print(f"Auto-reconnect: {auto_reconnect}")42print(f"{'='*60}\n")4344retry_count = 045max_retries = 1046base_delay = 24748while retry_count < max_retries:49channel = grpc.secure_channel(50GRPC_ENDPOINT,51grpc.ssl_channel_credentials(),52options=[53('grpc.max_receive_message_length', 100 * 1024 * 1024),54('grpc.keepalive_time_ms', 30000),55]56)57stub = pb_grpc.OrderBookStreamingStub(channel)5859# Build request60request = pb.BboBookRequest(coins=coins)6162msg_count = 06364try:65if retry_count > 0:66print(f"\n🔄 Reconnecting (attempt {retry_count + 1}/{max_retries})...")67else:68print(f"Connecting to {GRPC_ENDPOINT}...")6970for update in stub.StreamBboBook(request, metadata=[('x-token', AUTH_TOKEN)]):71msg_count += 17273if msg_count == 1:74print(f"✓ First BBO update received!\n")75retry_count = 0 # Reset retry count on successful connection7677# Display the BBO update78print(f"\n{'─'*60}")79print(f"Block: {update.block_number} | Time: {update.time} | Coin: {update.coin}")80print(f"{'─'*60}")8182# Show best ask83if update.HasField('ask'):84print(f" BEST ASK: {update.ask.px:>12} | {update.ask.sz:>12} | ({update.ask.n} orders)")85else:86print(" BEST ASK: (none)")8788# Show best bid89if update.HasField('bid'):90print(f" BEST BID: {update.bid.px:>12} | {update.bid.sz:>12} | ({update.bid.n} orders)")91else:92print(" BEST BID: (none)")9394# Show spread95if update.HasField('bid') and update.HasField('ask'):96best_bid = float(update.bid.px)97best_ask = float(update.ask.px)98spread = best_ask - best_bid99spread_bps = (spread / best_bid) * 10000 if best_bid > 0 else 0100print(f" SPREAD: {spread:.2f} ({spread_bps:.2f} bps)")101102print(f"\n Messages received: {msg_count}")103104except grpc.RpcError as e:105if e.code() == grpc.StatusCode.DATA_LOSS and auto_reconnect:106print(f"\n⚠️ Server reinitialized: {e.details()}")107retry_count += 1108if retry_count < max_retries:109delay = base_delay * (2 ** (retry_count - 1)) # Exponential backoff110print(f"⏳ Waiting {delay}s before reconnecting...")111time.sleep(delay)112channel.close()113continue114else:115print(f"\n❌ Max retries ({max_retries}) reached. Giving up.")116break117else:118print(f"\ngRPC error: {e.code()} - {e.details()}")119break120except KeyboardInterrupt:121print("\nStopping BBO stream...")122break123finally:124channel.close()125126# If we get here without error, break the retry loop127break128129130def main():131parser = argparse.ArgumentParser(description='Stream Hyperliquid best bid/offer data via gRPC')132parser.add_argument('--coins', default='BTC', help='Comma-separated coin symbols to stream (e.g., BTC,ETH)')133134args = parser.parse_args()135coins = [c.strip() for c in args.coins.split(',') if c.strip()]136137print(f"\n{'='*60}")138print("Hyperliquid StreamBboBook Example")139print(f"Endpoint: {GRPC_ENDPOINT}")140print(f"{'='*60}")141142try:143stream_bbo_book(coins)144except Exception as e:145print(f"\nError: {e}")146import traceback147traceback.print_exc()148sys.exit(1)149150151if __name__ == "__main__":152main()153
1#!/usr/bin/env python32"""3StreamBboBook Example - Stream top-of-book best bid/ask changes via gRPC45Setup:6pip install grpcio grpcio-tools protobuf zstandard7python -m grpc_tools.protoc -I../../proto --python_out=. --grpc_python_out=. ../../proto/orderbook.proto89Usage:10python stream_bbo_example.py --coins BTC,ETH11"""1213import grpc14import sys15import time16import argparse1718try:19import orderbook_pb2 as pb20import orderbook_pb2_grpc as pb_grpc21except ImportError:22print("Error: Proto files not generated. Run:")23print(" python -m grpc_tools.protoc -I../../proto --python_out=. --grpc_python_out=. ../../proto/orderbook.proto")24sys.exit(1)2526# Configuration27GRPC_ENDPOINT = "your-endpoint.hype-mainnet.quiknode.pro:10000"28AUTH_TOKEN = "your-auth-token"293031def stream_bbo_book(coins: list, auto_reconnect: bool = True):32"""33Stream best bid/offer (top-of-book) updates for one or more coins.3435Args:36coins: Symbols to stream (e.g., ["BTC", "ETH"]). Empty list means all coins37auto_reconnect: Auto-reconnect on DATA_LOSS errors (default True)38"""39print(f"\n{'='*60}")40print(f"Streaming BBO Book for {', '.join(coins) if coins else 'all coins'}")41print(f"Auto-reconnect: {auto_reconnect}")42print(f"{'='*60}\n")4344retry_count = 045max_retries = 1046base_delay = 24748while retry_count < max_retries:49channel = grpc.secure_channel(50GRPC_ENDPOINT,51grpc.ssl_channel_credentials(),52options=[53('grpc.max_receive_message_length', 100 * 1024 * 1024),54('grpc.keepalive_time_ms', 30000),55]56)57stub = pb_grpc.OrderBookStreamingStub(channel)5859# Build request60request = pb.BboBookRequest(coins=coins)6162msg_count = 06364try:65if retry_count > 0:66print(f"\n🔄 Reconnecting (attempt {retry_count + 1}/{max_retries})...")67else:68print(f"Connecting to {GRPC_ENDPOINT}...")6970for update in stub.StreamBboBook(request, metadata=[('x-token', AUTH_TOKEN)]):71msg_count += 17273if msg_count == 1:74print(f"✓ First BBO update received!\n")75retry_count = 0 # Reset retry count on successful connection7677# Display the BBO update78print(f"\n{'─'*60}")79print(f"Block: {update.block_number} | Time: {update.time} | Coin: {update.coin}")80print(f"{'─'*60}")8182# Show best ask83if update.HasField('ask'):84print(f" BEST ASK: {update.ask.px:>12} | {update.ask.sz:>12} | ({update.ask.n} orders)")85else:86print(" BEST ASK: (none)")8788# Show best bid89if update.HasField('bid'):90print(f" BEST BID: {update.bid.px:>12} | {update.bid.sz:>12} | ({update.bid.n} orders)")91else:92print(" BEST BID: (none)")9394# Show spread95if update.HasField('bid') and update.HasField('ask'):96best_bid = float(update.bid.px)97best_ask = float(update.ask.px)98spread = best_ask - best_bid99spread_bps = (spread / best_bid) * 10000 if best_bid > 0 else 0100print(f" SPREAD: {spread:.2f} ({spread_bps:.2f} bps)")101102print(f"\n Messages received: {msg_count}")103104except grpc.RpcError as e:105if e.code() == grpc.StatusCode.DATA_LOSS and auto_reconnect:106print(f"\n⚠️ Server reinitialized: {e.details()}")107retry_count += 1108if retry_count < max_retries:109delay = base_delay * (2 ** (retry_count - 1)) # Exponential backoff110print(f"⏳ Waiting {delay}s before reconnecting...")111time.sleep(delay)112channel.close()113continue114else:115print(f"\n❌ Max retries ({max_retries}) reached. Giving up.")116break117else:118print(f"\ngRPC error: {e.code()} - {e.details()}")119break120except KeyboardInterrupt:121print("\nStopping BBO stream...")122break123finally:124channel.close()125126# If we get here without error, break the retry loop127break128129130def main():131parser = argparse.ArgumentParser(description='Stream Hyperliquid best bid/offer data via gRPC')132parser.add_argument('--coins', default='BTC', help='Comma-separated coin symbols to stream (e.g., BTC,ETH)')133134args = parser.parse_args()135coins = [c.strip() for c in args.coins.split(',') if c.strip()]136137print(f"\n{'='*60}")138print("Hyperliquid StreamBboBook Example")139print(f"Endpoint: {GRPC_ENDPOINT}")140print(f"{'='*60}")141142try:143stream_bbo_book(coins)144except Exception as e:145print(f"\nError: {e}")146import traceback147traceback.print_exc()148sys.exit(1)149150151if __name__ == "__main__":152main()153
¿Aún no tienes una cuenta?
Crea tu punto de conexión de Quicknode en cuestión de segundos y empieza a desarrollar
Empieza gratis