StreamTpslUpdates gRPC 메서드
이 방식은 데이터 사용량을 기준으로 0.0165 MB당 10 API 크레딧으로 과금된다는 점에 유의하시기 바랍니다.
매개변수
동전
반복되는 문자열
로딩 중...
반품
스트림
stream<TpslUpdatesUpdate>
로딩 중...
시간
uint64
로딩 중...
높이
uint64
로딩 중...
스냅샷
bool
로딩 중...
diffs
array<TpslOrderDiff>
로딩 중...
요청
1// StreamTpslUpdates Example - Stream TP/SL trigger-order updates via gRPC2패키지 main34import (5"문맥"6"깃발"7"fmt"8"io"9"로그"10"수학"11"문자열"12"시간"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.초28)2930func streamTpslUpdates(coins []string) 오류 {31fmt.PrintlnPrintln문자열.반복("=", 60))32fmt.Printf("%s에 대한 TP/SL 업데이트 스트리밍\n", strings.Join(동전, ", "))33fmt.PrintlnPrintln ("자동 재연결: true")34fmt.PrintlnPrintln문자열.반복("=", 60) + "\n")3536retryCount := 03738for retryCount < maxRetries {39creds := 인증 정보.NewClientTLSFromCert(nil, "")40conn, err := grpc.Dial(grpcEndpoint,41grpc.WithTransportCredentials(creds),42grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(100*1024*1024)))43만약 err != nil {44return fmt.Errorf("연결 실패: %w", err)45}4647클라이언트 := pb.NewOrderBookStreamingClient)(conn)48ctx := 메타데이터.AppendToOutgoingContext(컨텍스트.배경(), "x-token", authToken)4950request := &pb.TpslUpdatesRequest{51동전: 동전,52}5354if retryCount > 0 {55fmt.Printf("\n🔄 재연결 중 (시도 %d/%d)...\n", retryCount+1, maxRetries)56} else {57fmt.Printf("%s에 연결 중...\n", printf("%s에 연결 중...\n",)58}5960스트림, err := client.StreamTpslUpdates(ctx, request)61만약 err != nil {62conn.닫기()63return fmt.Errorf("스트림 시작에 실패했습니다: %w", err)64}6566msgCount := 067shouldRetry := false6869~을 위해 {70업데이트, 오류 := 스트림.Recv()71만약 err == io.EOF {72중단73}74만약 err != nil {75st, 알겠습니다 := 상태.FromError(err)76만약 ok && st.코드() == 코드.DataLoss {77fmt.Printf("\n⚠️ 서버 재초기화됨: %s\n", st.메시지())78retryCount++79if retryCount < maxRetries {80지연 := 기본지연 * time.Duration(수학.Pow(2, float64(retryCount-1)))81fmt.Printf("⏳ 재연결하기 전 %v 동안 대기 중...\n", delay)82시간.수면(지연)83shouldRetry = true84중단85} else {86fmt.Printf("\n❌ 최대 재시도 횟수(%d)에 도달했습니다. 중단합니다.\n", maxRetries)87conn.닫기()88return nil89}90}91conn.닫기()92return fmt.Errorf("스트림 오류: %w", err)93}9495msgCount++96if msgCount == 1 {97fmt.Println("✓ 첫 번째 TP/SL 업데이트 수신!\n")98retryCount = 0 // 성공 시 재설정99}100101// Display update102fmt.PrintlnPrintln ("\n" + strings.반복("─", 60))103snapshotLabel := ""104만약 업데이트.스냅샷 {105스냅샷 레이블 = " | SNAPSHOT"106}107fmt.Printf("블록: %d | 시간: %d%s | 차이점: %d\n", update.높이, 업데이트.시간, 스냅샷 레이블, len(update.차이점))108fmt.PrintlnPrintln문자열.반복("─", 60))109110for _, diff := range update.Diffs {111side := "ASK"112만약 diff.측면 == "B" {113측면 = "BID"114}115sz := diff.Sz116만약 diff.IsPositionTpsl {117sz = "position-sized"118}119120전환 diff.DiffType {121사례 pb.TpslDiffType_TPSL_DIFF_TYPE_ADD:122fmt.Printf(" ADD %s oid: %d | %s | %s sz: %s\n", diff.Coin, diff.Oid, diff.OrderType, side, sz)123fmt.Printf(" 트리거: %s | 제한 픽셀: %s | 축소 전용: %t\n", diff.트리거 조건, diff.LimitPx, diff.ReduceOnly)124사례 pb.TpslDiffType_TPSL_DIFF_TYPE_REMOVE:125fmt.Printf(" %s 제거: %d | %s | 사유: %s\n", diff.코인, diff.Oid, diff.OrderType, diff.이유)126}127}128129fmt.Printf("\n 수신된 메시지: %d\n", msgCount)130}131132conn.닫기()133134만약 !shouldRetry {135중단136}137}138139return nil140}141142func main() {143coinsFlag := flag.String("coins", "ETH", "스트리밍할 코인 심볼을 쉼표로 구분하여 입력하세요 (예: ETH,BTC)")144145깃발.구문 분석()146147동전 := 문자열.Split(*coinsFlag, ",")148149fmt.PrintlnPrintln ("\n" + strings.반복("=", 60))150fmt.Println("Hyperliquid StreamTpslUpdates 예제")151fmt.Printf("엔드포인트: %s\n", grpcEndpoint)152fmt.PrintlnPrintln문자열.반복("=", 60))153154if err := streamTpslUpdates(coins); err != nil {155로그.치명적(err)156}157}158
1// StreamTpslUpdates Example - Stream TP/SL trigger-order updates via gRPC2패키지 main34import (5"문맥"6"깃발"7"fmt"8"io"9"로그"10"수학"11"문자열"12"시간"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.초28)2930func streamTpslUpdates(coins []string) 오류 {31fmt.PrintlnPrintln문자열.반복("=", 60))32fmt.Printf("%s에 대한 TP/SL 업데이트 스트리밍\n", strings.Join(동전, ", "))33fmt.PrintlnPrintln ("자동 재연결: true")34fmt.PrintlnPrintln문자열.반복("=", 60) + "\n")3536retryCount := 03738for retryCount < maxRetries {39creds := 인증 정보.NewClientTLSFromCert(nil, "")40conn, err := grpc.Dial(grpcEndpoint,41grpc.WithTransportCredentials(creds),42grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(100*1024*1024)))43만약 err != nil {44return fmt.Errorf("연결 실패: %w", err)45}4647클라이언트 := pb.NewOrderBookStreamingClient)(conn)48ctx := 메타데이터.AppendToOutgoingContext(컨텍스트.배경(), "x-token", authToken)4950request := &pb.TpslUpdatesRequest{51동전: 동전,52}5354if retryCount > 0 {55fmt.Printf("\n🔄 재연결 중 (시도 %d/%d)...\n", retryCount+1, maxRetries)56} else {57fmt.Printf("%s에 연결 중...\n", printf("%s에 연결 중...\n",)58}5960스트림, err := client.StreamTpslUpdates(ctx, request)61만약 err != nil {62conn.닫기()63return fmt.Errorf("스트림 시작에 실패했습니다: %w", err)64}6566msgCount := 067shouldRetry := false6869~을 위해 {70업데이트, 오류 := 스트림.Recv()71만약 err == io.EOF {72중단73}74만약 err != nil {75st, 알겠습니다 := 상태.FromError(err)76만약 ok && st.코드() == 코드.DataLoss {77fmt.Printf("\n⚠️ 서버 재초기화됨: %s\n", st.메시지())78retryCount++79if retryCount < maxRetries {80지연 := 기본지연 * time.Duration(수학.Pow(2, float64(retryCount-1)))81fmt.Printf("⏳ 재연결하기 전 %v 동안 대기 중...\n", delay)82시간.수면(지연)83shouldRetry = true84중단85} else {86fmt.Printf("\n❌ 최대 재시도 횟수(%d)에 도달했습니다. 중단합니다.\n", maxRetries)87conn.닫기()88return nil89}90}91conn.닫기()92return fmt.Errorf("스트림 오류: %w", err)93}9495msgCount++96if msgCount == 1 {97fmt.Println("✓ 첫 번째 TP/SL 업데이트 수신!\n")98retryCount = 0 // 성공 시 재설정99}100101// Display update102fmt.PrintlnPrintln ("\n" + strings.반복("─", 60))103snapshotLabel := ""104만약 업데이트.스냅샷 {105스냅샷 레이블 = " | SNAPSHOT"106}107fmt.Printf("블록: %d | 시간: %d%s | 차이점: %d\n", update.높이, 업데이트.시간, 스냅샷 레이블, len(update.차이점))108fmt.PrintlnPrintln문자열.반복("─", 60))109110for _, diff := range update.Diffs {111side := "ASK"112만약 diff.측면 == "B" {113측면 = "BID"114}115sz := diff.Sz116만약 diff.IsPositionTpsl {117sz = "position-sized"118}119120전환 diff.DiffType {121사례 pb.TpslDiffType_TPSL_DIFF_TYPE_ADD:122fmt.Printf(" ADD %s oid: %d | %s | %s sz: %s\n", diff.Coin, diff.Oid, diff.OrderType, side, sz)123fmt.Printf(" 트리거: %s | 제한 픽셀: %s | 축소 전용: %t\n", diff.트리거 조건, diff.LimitPx, diff.ReduceOnly)124사례 pb.TpslDiffType_TPSL_DIFF_TYPE_REMOVE:125fmt.Printf(" %s 제거: %d | %s | 사유: %s\n", diff.코인, diff.Oid, diff.OrderType, diff.이유)126}127}128129fmt.Printf("\n 수신된 메시지: %d\n", msgCount)130}131132conn.닫기()133134만약 !shouldRetry {135중단136}137}138139return nil140}141142func main() {143coinsFlag := flag.String("coins", "ETH", "스트리밍할 코인 심볼을 쉼표로 구분하여 입력하세요 (예: ETH,BTC)")144145깃발.구문 분석()146147동전 := 문자열.Split(*coinsFlag, ",")148149fmt.PrintlnPrintln ("\n" + strings.반복("=", 60))150fmt.Println("Hyperliquid StreamTpslUpdates 예제")151fmt.Printf("엔드포인트: %s\n", grpcEndpoint)152fmt.PrintlnPrintln문자열.반복("=", 60))153154if err := streamTpslUpdates(coins); err != nil {155로그.치명적(err)156}157}158
1// StreamTpslUpdates Example - Stream TP/SL trigger-order updates 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 패키지 정의 = protoLoader.loadSync(PROTO_PATH, {11keepCase: true,12longs: String,13열거형: String,14기본값: true,15oneofs: true16});17const proto = grpc.loadPackageDefinition(packageDefinition).hyperliquid;1819함수 createClient() {20돌아가기 new proto.OrderBookStreaming((21GRPC_ENDPOINT,22grpc.인증 정보.createSsl(),23{ 'grpc.max_receive_message_length': 100 * 1024 * 1024 }24);25}2627// Stream TP/SL trigger-order updates28async 함수 streamTpslUpdates(코인, autoReconnect = true, retryCount = 0) {29콘솔.log('='.반복(60));30console.log(`Streaming TP/SL Updates for ${coins.length > 0 ? coins.join(', ') : 'all perp coins'}`);31console.log(`Auto-reconnect: ${autoReconnect}`);32콘솔.log('='.반복(60) + '\n');3334const maxRetries = 10;35const baseDelay = 2000;3637while (retryCount < maxRetries) {38const client = createClient();39const 메타데이터 = new grpc.메타데이터();40메타데이터.추가('x-token', AUTH_TOKEN);4142const request = {43동전: 동전44};4546시도해 보세요 {47만약 (retryCount > 0) {48console.log(`\n🔄 Reconnecting (attempt ${retryCount + 1}/${maxRetries})...`);49} else {50console.log(`Connecting to ${GRPC_ENDPOINT}...`);51}5253let msgCount = 0;54const 호출 = 클라이언트.StreamTpslUpdates(요청, 메타데이터);5556호출.on('data', (업데이트) => {57msgCount++;5859만약 (msgCount === 1) {60콘솔.log('✓ 첫 번째 TP/SL 업데이트 수신!\n');61retryCount = 0; // 성공 시 재설정62}6364콘솔.log('\n' + '─'.반복(60));65console.log(`Block: ${update.height} | Time: ${update.time}${update.snapshot ? ' | SNAPSHOT' : ''} | Diffs: ${(update.diffs || []).length}`);66콘솔.log('─'.반복(60));6768(업데이트.차이점 || []).forEach(diff => {69const side = diff.side === 'B' ? 'BID' : 'ASK';70const sz = diff.is_position_tpsl ? 'position-sized' : diff.sz;7172만약 (diff.diff_type === 'TPSL_DIFF_TYPE_ADD') {73console.log(` ADD ${diff.coin} oid: ${diff.oid} | ${diff.order_type} | ${side} sz: ${sz}`);74console.log(` trigger: ${diff.trigger_condition} | limit px: ${diff.limit_px} | reduce-only: ${diff.reduce_only}`);75} else if (diff.diff_type === 'TPSL_DIFF_TYPE_REMOVE') {76console.log(` REMOVE ${diff.coin} oid: ${diff.oid} | ${diff.order_type} | reason: ${diff.reason}`);77}78});7980console.log(`\n Messages received: ${msgCount}`);81});8283호출.on('error', (err) => {84만약 (err.코드 === grpc.상태.DATA_LOSS && autoReconnect) {85console.log(`\n⚠️ Server reinitialized: ${err.message}`);86retryCount++;87if (retryCount < maxRetries) {88const delay = baseDelay * Math.pow(2, retryCount - 1);89console.log(`⏳ Waiting ${delay / 1000}s before reconnecting...`);90setTimeout(() => streamTpslUpdates(코인, autoReconnect, retryCount), delay);91} else {92console.log(`\n❌ Max retries (${maxRetries}) reached. Giving up.`);93}94} else {95콘솔.오류('\ngRPC 오류:', err.code, '-', err.메시지);96}97});9899호출.on('end', () => {100콘솔.log('\n스트림 종료됨');101});102103// Wait for stream to complete104기다리다 새로운 약속((결심) => {105호출.on('end', 해결);106호출.on('error', 해결);107});108109break; // 성공 시 재시도 루프 종료110111} catch (err) {112콘솔.오류('오류:', err.message);113break;114}115}116}117118// Parse command line args119const args = process.argv.slice(2);120const 동전 = (args.find(a => a.startsWith('--coins='))?.split('=')[1] || 'ETH').분할(',');121122콘솔.log('\n' + '='.반복(60));123콘솔.log('Hyperliquid StreamTpslUpdates 예제');124console.log(`Endpoint: ${GRPC_ENDPOINT}`);125콘솔.log('='.반복(60));126127streamTpslUpdates(코인);128
1// StreamTpslUpdates Example - Stream TP/SL trigger-order updates 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 패키지 정의 = protoLoader.loadSync(PROTO_PATH, {11keepCase: true,12longs: String,13열거형: String,14기본값: true,15oneofs: true16});17const proto = grpc.loadPackageDefinition(packageDefinition).hyperliquid;1819함수 createClient() {20돌아가기 new proto.OrderBookStreaming((21GRPC_ENDPOINT,22grpc.인증 정보.createSsl(),23{ 'grpc.max_receive_message_length': 100 * 1024 * 1024 }24);25}2627// Stream TP/SL trigger-order updates28async 함수 streamTpslUpdates(코인, autoReconnect = true, retryCount = 0) {29콘솔.log('='.반복(60));30console.log(`Streaming TP/SL Updates for ${coins.length > 0 ? coins.join(', ') : 'all perp coins'}`);31console.log(`Auto-reconnect: ${autoReconnect}`);32콘솔.log('='.반복(60) + '\n');3334const maxRetries = 10;35const baseDelay = 2000;3637while (retryCount < maxRetries) {38const client = createClient();39const 메타데이터 = new grpc.메타데이터();40메타데이터.추가('x-token', AUTH_TOKEN);4142const request = {43동전: 동전44};4546시도해 보세요 {47만약 (retryCount > 0) {48console.log(`\n🔄 Reconnecting (attempt ${retryCount + 1}/${maxRetries})...`);49} else {50console.log(`Connecting to ${GRPC_ENDPOINT}...`);51}5253let msgCount = 0;54const 호출 = 클라이언트.StreamTpslUpdates(요청, 메타데이터);5556호출.on('data', (업데이트) => {57msgCount++;5859만약 (msgCount === 1) {60콘솔.log('✓ 첫 번째 TP/SL 업데이트 수신!\n');61retryCount = 0; // 성공 시 재설정62}6364콘솔.log('\n' + '─'.반복(60));65console.log(`Block: ${update.height} | Time: ${update.time}${update.snapshot ? ' | SNAPSHOT' : ''} | Diffs: ${(update.diffs || []).length}`);66콘솔.log('─'.반복(60));6768(업데이트.차이점 || []).forEach(diff => {69const side = diff.side === 'B' ? 'BID' : 'ASK';70const sz = diff.is_position_tpsl ? 'position-sized' : diff.sz;7172만약 (diff.diff_type === 'TPSL_DIFF_TYPE_ADD') {73console.log(` ADD ${diff.coin} oid: ${diff.oid} | ${diff.order_type} | ${side} sz: ${sz}`);74console.log(` trigger: ${diff.trigger_condition} | limit px: ${diff.limit_px} | reduce-only: ${diff.reduce_only}`);75} else if (diff.diff_type === 'TPSL_DIFF_TYPE_REMOVE') {76console.log(` REMOVE ${diff.coin} oid: ${diff.oid} | ${diff.order_type} | reason: ${diff.reason}`);77}78});7980console.log(`\n Messages received: ${msgCount}`);81});8283호출.on('error', (err) => {84만약 (err.코드 === grpc.상태.DATA_LOSS && autoReconnect) {85console.log(`\n⚠️ Server reinitialized: ${err.message}`);86retryCount++;87if (retryCount < maxRetries) {88const delay = baseDelay * Math.pow(2, retryCount - 1);89console.log(`⏳ Waiting ${delay / 1000}s before reconnecting...`);90setTimeout(() => streamTpslUpdates(코인, autoReconnect, retryCount), delay);91} else {92console.log(`\n❌ Max retries (${maxRetries}) reached. Giving up.`);93}94} else {95콘솔.오류('\ngRPC 오류:', err.code, '-', err.메시지);96}97});9899호출.on('end', () => {100콘솔.log('\n스트림 종료됨');101});102103// Wait for stream to complete104기다리다 새로운 약속((결심) => {105호출.on('end', 해결);106호출.on('error', 해결);107});108109break; // 성공 시 재시도 루프 종료110111} catch (err) {112콘솔.오류('오류:', err.message);113break;114}115}116}117118// Parse command line args119const args = process.argv.slice(2);120const 동전 = (args.find(a => a.startsWith('--coins='))?.split('=')[1] || 'ETH').분할(',');121122콘솔.log('\n' + '='.반복(60));123콘솔.log('Hyperliquid StreamTpslUpdates 예제');124console.log(`Endpoint: ${GRPC_ENDPOINT}`);125콘솔.log('='.반복(60));126127streamTpslUpdates(코인);128
1#!/usr/bin/env python32"""3StreamTpslUpdates 예제 - gRPC를 통한 스트림 TP/SL 트리거 순서 업데이트45설정:6pip install grpcio grpcio-tools protobuf zstandard7python -m grpc_tools.protoc -I../../proto --python_out=. --grpc_python_out=. ../../proto/orderbook.proto89사용법:10python stream_tpsl_example.py --coins ETH,BTC11"""1213import grpc14import sys15import 시간16import argparse1718시도해 보세요:19import orderbook_pb2 다음과 같이 pb20import orderbook_pb2_grpc 다음과 같이 pb_grpc21except ImportError:22인쇄("오류: Proto 파일이 생성되지 않았습니다. 다음을 실행하십시오:")23인쇄(" python -m grpc_tools.protoc -I../../proto --python_out=. --grpc_python_out=. ../../proto/orderbook.proto")24sys.exit(1)2526# 구성27GRPC_ENDPOINT = "your-endpoint.hype-mainnet.quiknode.pro:10000"28AUTH_TOKEN = "your-auth-token"293031def stream_tpsl_updates(coins: list, auto_reconnect: bool = True):32"""33하나 이상의 코인에 대한 TP/SL 발동 순서 업데이트를 스트리밍합니다.3435인수:36코인: 스트리밍할 코인의 심볼(예: ["ETH", "BTC"]). 빈 목록은 모든 영구 코인을 의미합니다.37auto_reconnect: DATA_LOSS 오류 발생 시 자동 재연결 (기본값: True)38"""39인쇄(f"\n{'='*60}")40인쇄(f"다음에 대한 TP/SL 업데이트 스트리밍 {', '.join(코인) if 코인 else '모든 퍼프 코인'}")41print(f"Auto-reconnect: {auto_reconnect}")42인쇄(f"{'='*60}\n")4344retry_count = 045max_retries = 1046base_delay = 24748while retry_count < max_retries:49채널 = grpc.secure_channel(50GRPC_ENDPOINT,51grpc.ssl_channel_credentials(),52옵션=[53('grpc.max_receive_message_length', 100 * 1024 * 1024),54('grpc.keepalive_time_ms', 30000),55]56)57스텁 = pb_grpc.OrderBookStreamingStub(채널)5859# 빌드 요청60요청 = pb.TpslUpdatesRequest(코인=coins)6162msg_count = 06364시도해 보세요:65if retry_count > 0:66인쇄(f"\n🔄 다시 연결 중 (시도 중 {재시도 횟수 + 1}/{최대 재시도 횟수})...")67else:68인쇄(f"연결 중 {GRPC_ENDPOINT}...")6970~을 위해 업데이트 in 스텁.StreamTpslUpdates(요청, 메타데이터=[('x-token', AUTH_TOKEN)]):71msg_count += 17273if msg_count == 1:74인쇄(f"✓ 첫 번째 TP/SL 업데이트 수신!\n")75retry_count = 0 # 연결에 성공하면 재시도 횟수를 초기화합니다7677# 업데이트 내용 표시78인쇄(f"\n{'─'*60}")79snapshot_label = " | SNAPSHOT" if update.스냅샷 else ""80print(f"Block: {update.height} | Time: {update.time}{snapshot_label} | Diffs: {len(update.diffs)}")81인쇄(f"{'─'*60}")8283~을 위해 diff in update.diffs:84측면 = "BID" if diff.side == "B" else "ASK"85sz = "position-sized" if diff.is_position_tpsl else diff.sz8687만약 diff.diff_type == pb.TPSL_DIFF_TYPE_ADD:88print(f" ADD {diff.coin} oid: {diff.oid} | {diff.order_type} | {side} sz: {sz}")89print(f" trigger: {diff.trigger_condition} | limit px: {diff.limit_px} | reduce-only: {diff.reduce_only}")90elif diff.diff_type == pb.TPSL_DIFF_TYPE_REMOVE:91print(f" REMOVE {diff.coin} oid: {diff.oid} | {diff.order_type} | reason: {diff.reason}")9293print(f"\n Messages received: {msg_count}")9495단, grpc.RpcError 를 e:96만약 e.코드() == grpc.StatusCode.DATA_LOSS 및 auto_reconnect:97print(f"\n⚠️ Server reinitialized: {e.details()}")98retry_count += 199if retry_count < max_retries:100지연 = 기본_지연 * (2 ** (retry_count - 1)) # 지수적 백오프101인쇄(f"⏳ 대기 중 {지연}초 후 재연결됩니다...")102시간.sleep(지연)103채널.닫기()104계속105else:106인쇄(f"\n❌ 최대 재시도 횟수 ({max_retries})에 도달했습니다. 중단합니다.")107중단108else:109print(f"\ngRPC error: {e.code()} - {e.details()}")110중단111단, KeyboardInterrupt:112인쇄("\nTP/SL 스트림 중지 중...")113중단114드디어:115채널.닫기()116117# 오류 없이 여기까지 도달했다면, 재시도 루프를 종료한다118중단119120121def main():122파서 = argparse.ArgumentParser(설명='gRPC를 통한 Stream Hyperliquid TP/SL 트리거 순서 업데이트')123파서.add_argument('--coins', 기본값='ETH', 도움말='스트리밍할 코인 심볼을 쉼표로 구분하여 입력하세요 (예: ETH,BTC)')124125args = parser.parse_args()126동전 = [c.strip() for c in args.coins.split(',') if c.strip()]127128인쇄(f"\n{'='*60}")129인쇄("Hyperliquid StreamTpslUpdates 예제")130print(f"Endpoint: {GRPC_ENDPOINT}")131인쇄(f"{'='*60}")132133시도해 보세요:134stream_tpsl_updates(코인)135단, 예외 ~처럼 e:136print(f"\nError: {e}")137import 트레이스백138트레이스백.print_exc()139sys.exit(1)140141142if __name__ == "__main__":143main()144
1#!/usr/bin/env python32"""3StreamTpslUpdates 예제 - gRPC를 통한 스트림 TP/SL 트리거 순서 업데이트45설정:6pip install grpcio grpcio-tools protobuf zstandard7python -m grpc_tools.protoc -I../../proto --python_out=. --grpc_python_out=. ../../proto/orderbook.proto89사용법:10python stream_tpsl_example.py --coins ETH,BTC11"""1213import grpc14import sys15import 시간16import argparse1718시도해 보세요:19import orderbook_pb2 다음과 같이 pb20import orderbook_pb2_grpc 다음과 같이 pb_grpc21except ImportError:22인쇄("오류: Proto 파일이 생성되지 않았습니다. 다음을 실행하십시오:")23인쇄(" python -m grpc_tools.protoc -I../../proto --python_out=. --grpc_python_out=. ../../proto/orderbook.proto")24sys.exit(1)2526# 구성27GRPC_ENDPOINT = "your-endpoint.hype-mainnet.quiknode.pro:10000"28AUTH_TOKEN = "your-auth-token"293031def stream_tpsl_updates(coins: list, auto_reconnect: bool = True):32"""33하나 이상의 코인에 대한 TP/SL 발동 순서 업데이트를 스트리밍합니다.3435인수:36코인: 스트리밍할 코인의 심볼(예: ["ETH", "BTC"]). 빈 목록은 모든 영구 코인을 의미합니다.37auto_reconnect: DATA_LOSS 오류 발생 시 자동 재연결 (기본값: True)38"""39인쇄(f"\n{'='*60}")40인쇄(f"다음에 대한 TP/SL 업데이트 스트리밍 {', '.join(코인) if 코인 else '모든 퍼프 코인'}")41print(f"Auto-reconnect: {auto_reconnect}")42인쇄(f"{'='*60}\n")4344retry_count = 045max_retries = 1046base_delay = 24748while retry_count < max_retries:49채널 = grpc.secure_channel(50GRPC_ENDPOINT,51grpc.ssl_channel_credentials(),52옵션=[53('grpc.max_receive_message_length', 100 * 1024 * 1024),54('grpc.keepalive_time_ms', 30000),55]56)57스텁 = pb_grpc.OrderBookStreamingStub(채널)5859# 빌드 요청60요청 = pb.TpslUpdatesRequest(코인=coins)6162msg_count = 06364시도해 보세요:65if retry_count > 0:66인쇄(f"\n🔄 다시 연결 중 (시도 중 {재시도 횟수 + 1}/{최대 재시도 횟수})...")67else:68인쇄(f"연결 중 {GRPC_ENDPOINT}...")6970~을 위해 업데이트 in 스텁.StreamTpslUpdates(요청, 메타데이터=[('x-token', AUTH_TOKEN)]):71msg_count += 17273if msg_count == 1:74인쇄(f"✓ 첫 번째 TP/SL 업데이트 수신!\n")75retry_count = 0 # 연결에 성공하면 재시도 횟수를 초기화합니다7677# 업데이트 내용 표시78인쇄(f"\n{'─'*60}")79snapshot_label = " | SNAPSHOT" if update.스냅샷 else ""80print(f"Block: {update.height} | Time: {update.time}{snapshot_label} | Diffs: {len(update.diffs)}")81인쇄(f"{'─'*60}")8283~을 위해 diff in update.diffs:84측면 = "BID" if diff.side == "B" else "ASK"85sz = "position-sized" if diff.is_position_tpsl else diff.sz8687만약 diff.diff_type == pb.TPSL_DIFF_TYPE_ADD:88print(f" ADD {diff.coin} oid: {diff.oid} | {diff.order_type} | {side} sz: {sz}")89print(f" trigger: {diff.trigger_condition} | limit px: {diff.limit_px} | reduce-only: {diff.reduce_only}")90elif diff.diff_type == pb.TPSL_DIFF_TYPE_REMOVE:91print(f" REMOVE {diff.coin} oid: {diff.oid} | {diff.order_type} | reason: {diff.reason}")9293print(f"\n Messages received: {msg_count}")9495단, grpc.RpcError 를 e:96만약 e.코드() == grpc.StatusCode.DATA_LOSS 및 auto_reconnect:97print(f"\n⚠️ Server reinitialized: {e.details()}")98retry_count += 199if retry_count < max_retries:100지연 = 기본_지연 * (2 ** (retry_count - 1)) # 지수적 백오프101인쇄(f"⏳ 대기 중 {지연}초 후 재연결됩니다...")102시간.sleep(지연)103채널.닫기()104계속105else:106인쇄(f"\n❌ 최대 재시도 횟수 ({max_retries})에 도달했습니다. 중단합니다.")107중단108else:109print(f"\ngRPC error: {e.code()} - {e.details()}")110중단111단, KeyboardInterrupt:112인쇄("\nTP/SL 스트림 중지 중...")113중단114드디어:115채널.닫기()116117# 오류 없이 여기까지 도달했다면, 재시도 루프를 종료한다118중단119120121def main():122파서 = argparse.ArgumentParser(설명='gRPC를 통한 Stream Hyperliquid TP/SL 트리거 순서 업데이트')123파서.add_argument('--coins', 기본값='ETH', 도움말='스트리밍할 코인 심볼을 쉼표로 구분하여 입력하세요 (예: ETH,BTC)')124125args = parser.parse_args()126동전 = [c.strip() for c in args.coins.split(',') if c.strip()]127128인쇄(f"\n{'='*60}")129인쇄("Hyperliquid StreamTpslUpdates 예제")130print(f"Endpoint: {GRPC_ENDPOINT}")131인쇄(f"{'='*60}")132133시도해 보세요:134stream_tpsl_updates(코인)135단, 예외 ~처럼 e:136print(f"\nError: {e}")137import 트레이스백138트레이스백.print_exc()139sys.exit(1)140141142if __name__ == "__main__":143main()144