From 3c698e3fc55d71f9733f842831bfe179174875f6 Mon Sep 17 00:00:00 2001 From: shinchan-zhai Date: Mon, 23 Mar 2026 10:56:54 +0800 Subject: [PATCH] perf: reuse shared HTTP client in Hyperliquid trader Previously each direct API call (orders, sync, account) created a new http.Client, preventing TCP/TLS connection reuse. Now all calls share a single client on the HyperliquidTrader struct (30s timeout). --- trader/hyperliquid/trader.go | 4 ++++ trader/hyperliquid/trader_account.go | 4 ++-- trader/hyperliquid/trader_orders.go | 8 ++++---- trader/hyperliquid/trader_sync.go | 3 +-- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/trader/hyperliquid/trader.go b/trader/hyperliquid/trader.go index 2339a229..eb6c4f9c 100644 --- a/trader/hyperliquid/trader.go +++ b/trader/hyperliquid/trader.go @@ -4,10 +4,12 @@ import ( "context" "crypto/ecdsa" "fmt" + "net/http" "nofx/logger" "strconv" "strings" "sync" + "time" "github.com/ethereum/go-ethereum/crypto" "github.com/sonirico/go-hyperliquid" @@ -17,6 +19,7 @@ import ( type HyperliquidTrader struct { exchange *hyperliquid.Exchange ctx context.Context + httpClient *http.Client // Shared HTTP client for direct API calls (connection reuse) walletAddr string meta *hyperliquid.Meta // Cache meta information (including precision) metaMutex sync.RWMutex // Protect concurrent access to meta field @@ -220,6 +223,7 @@ func NewHyperliquidTrader(privateKeyHex string, walletAddr string, testnet bool, return &HyperliquidTrader{ exchange: exchange, ctx: ctx, + httpClient: &http.Client{Timeout: 30 * time.Second}, walletAddr: walletAddr, meta: meta, isCrossMargin: true, // Use cross margin mode by default diff --git a/trader/hyperliquid/trader_account.go b/trader/hyperliquid/trader_account.go index f733728f..92eb1f88 100644 --- a/trader/hyperliquid/trader_account.go +++ b/trader/hyperliquid/trader_account.go @@ -217,7 +217,7 @@ func (t *HyperliquidTrader) getXYZDexBalance() (accountValue float64, unrealized } req.Header.Set("Content-Type", "application/json") - client := &http.Client{Timeout: 30 * time.Second} + client := t.httpClient resp, err := client.Do(req) if err != nil { return 0, 0, nil, fmt.Errorf("failed to execute request: %w", err) @@ -308,7 +308,7 @@ func (t *HyperliquidTrader) getXyzMarketPrice(coin string) (float64, error) { } req.Header.Set("Content-Type", "application/json") - client := &http.Client{Timeout: 30 * time.Second} + client := t.httpClient resp, err := client.Do(req) if err != nil { return 0, fmt.Errorf("failed to execute request: %w", err) diff --git a/trader/hyperliquid/trader_orders.go b/trader/hyperliquid/trader_orders.go index 1e35e711..4792c0b4 100644 --- a/trader/hyperliquid/trader_orders.go +++ b/trader/hyperliquid/trader_orders.go @@ -445,7 +445,7 @@ func (t *HyperliquidTrader) cancelXyzOrders(coin string) error { } req.Header.Set("Content-Type", "application/json") - client := &http.Client{Timeout: 30 * time.Second} + client := t.httpClient resp, err := client.Do(req) if err != nil { return fmt.Errorf("failed to execute request: %w", err) @@ -538,7 +538,7 @@ func (t *HyperliquidTrader) cancelXyzOrder(oid int64) error { } req.Header.Set("Content-Type", "application/json") - client := &http.Client{Timeout: 30 * time.Second} + client := t.httpClient resp, err := client.Do(req) if err != nil { return fmt.Errorf("request failed: %w", err) @@ -679,7 +679,7 @@ func (t *HyperliquidTrader) placeXyzOrder(coin string, isBuy bool, size float64, } req.Header.Set("Content-Type", "application/json") - client := &http.Client{Timeout: 30 * time.Second} + client := t.httpClient resp, err := client.Do(req) if err != nil { return fmt.Errorf("request failed: %w", err) @@ -843,7 +843,7 @@ func (t *HyperliquidTrader) placeXyzTriggerOrder(coin string, isBuy bool, size f } req.Header.Set("Content-Type", "application/json") - client := &http.Client{Timeout: 30 * time.Second} + client := t.httpClient resp, err := client.Do(req) if err != nil { return fmt.Errorf("request failed: %w", err) diff --git a/trader/hyperliquid/trader_sync.go b/trader/hyperliquid/trader_sync.go index 2fdb6dc6..cb1c7c5b 100644 --- a/trader/hyperliquid/trader_sync.go +++ b/trader/hyperliquid/trader_sync.go @@ -8,7 +8,6 @@ import ( "net/http" "nofx/logger" "strings" - "time" ) // refreshMetaIfNeeded refreshes meta information when invalid (triggered when Asset ID is 0) @@ -67,7 +66,7 @@ func (t *HyperliquidTrader) fetchXyzMeta() error { } req.Header.Set("Content-Type", "application/json") - client := &http.Client{Timeout: 30 * time.Second} + client := t.httpClient resp, err := client.Do(req) if err != nil { return fmt.Errorf("failed to execute request: %w", err)