fix: HL testnet - add API wallet address to signed orders, 3-param constructor

This commit is contained in:
jackyu66git
2026-05-04 15:39:31 +08:00
parent 30436bbe75
commit c5c4c7394f
3 changed files with 17 additions and 4 deletions
+3 -1
View File
@@ -56,7 +56,8 @@ type Config struct {
// HyperLiquid API // HyperLiquid API
HLPrivateKey string // ed25519 private key hex HLPrivateKey string // ed25519 private key hex
HLAddress string // wallet address HLAddress string // main account address
HLAPIAddress string // API wallet address (signer, auto-derived if empty)
} }
// jsonConfig maps config.json fields (non-secret defaults checked into git). // jsonConfig maps config.json fields (non-secret defaults checked into git).
@@ -157,6 +158,7 @@ func LoadConfig() *Config {
HLPrivateKey: getEnv("HL_PRIVATE_KEY", ""), HLPrivateKey: getEnv("HL_PRIVATE_KEY", ""),
HLAddress: getEnv("HL_ADDRESS", ""), HLAddress: getEnv("HL_ADDRESS", ""),
HLAPIAddress: getEnv("HL_API_ADDRESS", ""),
} }
} }
+13 -2
View File
@@ -39,6 +39,7 @@ type HLSignedAction struct {
Action HLOrderAction `json:"action"` Action HLOrderAction `json:"action"`
Nonce int64 `json:"nonce"` Nonce int64 `json:"nonce"`
Signature string `json:"signature"` Signature string `json:"signature"`
Address string `json:"address"` // API wallet address (signer)
VaultAddress string `json:"vaultAddress,omitempty"` VaultAddress string `json:"vaultAddress,omitempty"`
} }
@@ -51,12 +52,13 @@ type HLOrderResponse struct {
type HyperLiquidTrade struct { type HyperLiquidTrade struct {
PrivateKey ed25519.PrivateKey PrivateKey ed25519.PrivateKey
Address string Address string
APIAddress string // API wallet address (signer), derived from private key
client *http.Client client *http.Client
lastNonce int64 lastNonce int64
nonceMu sync.Mutex // protect lastNonce++ (Issue #4) nonceMu sync.Mutex // protect lastNonce++ (Issue #4)
} }
func NewHyperLiquidTrade(privateKeyHex, address string) (*HyperLiquidTrade, error) { func NewHyperLiquidTrade(privateKeyHex, mainAddress, apiAddress string) (*HyperLiquidTrade, error) {
if privateKeyHex == "" { if privateKeyHex == "" {
return &HyperLiquidTrade{client: &http.Client{Timeout: 10 * time.Second}}, nil return &HyperLiquidTrade{client: &http.Client{Timeout: 10 * time.Second}}, nil
} }
@@ -81,9 +83,17 @@ func NewHyperLiquidTrade(privateKeyHex, address string) (*HyperLiquidTrade, erro
return nil, fmt.Errorf("invalid private key length: %d (expected 32 or %d)", len(keyBytes), ed25519.PrivateKeySize) return nil, fmt.Errorf("invalid private key length: %d (expected 32 or %d)", len(keyBytes), ed25519.PrivateKeySize)
} }
// If apiAddress not provided, derive from private key
if apiAddress == "" {
privKey := ed25519.PrivateKey(keyBytes)
pubKey := privKey.Public().(ed25519.PublicKey)
apiAddress = "0x" + hex.EncodeToString(pubKey)
}
return &HyperLiquidTrade{ return &HyperLiquidTrade{
PrivateKey: ed25519.PrivateKey(keyBytes), PrivateKey: ed25519.PrivateKey(keyBytes),
Address: address, Address: mainAddress,
APIAddress: apiAddress,
client: &http.Client{Timeout: 10 * time.Second}, client: &http.Client{Timeout: 10 * time.Second},
}, nil }, nil
} }
@@ -130,6 +140,7 @@ func (h *HyperLiquidTrade) PlaceMarketOrder(coin, side, sz string) (string, erro
Action: action, Action: action,
Nonce: nonce, Nonce: nonce,
Signature: sig, Signature: sig,
Address: h.APIAddress,
} }
bodyJSON, _ := json.Marshal(signed) bodyJSON, _ := json.Marshal(signed)
+1 -1
View File
@@ -191,7 +191,7 @@ func NewTrader(cfg *Config, database *db.DB) *Trader {
if cfg.BitgetAPIKey != "" { if cfg.BitgetAPIKey != "" {
bt = exchange.NewBitgetTrade(cfg.BitgetAPIKey, cfg.BitgetAPISecret, cfg.BitgetPassphrase) bt = exchange.NewBitgetTrade(cfg.BitgetAPIKey, cfg.BitgetAPISecret, cfg.BitgetPassphrase)
} }
hl, _ := exchange.NewHyperLiquidTrade(cfg.HLPrivateKey, cfg.HLAddress) hl, _ := exchange.NewHyperLiquidTrade(cfg.HLPrivateKey, cfg.HLAddress, cfg.HLAPIAddress)
t := &Trader{ t := &Trader{
cfg: cfg, cfg: cfg,