tanya/okx/publicApiService.go
zhangkun9038@dingtalk.com f0814c40bc up
2025-03-10 20:41:28 +08:00

184 lines
4.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package okx
import (
"bytes"
"encoding/json"
"fmt"
"github.com/google/go-querystring/query" // 用于将 struct 转为 URL 参数需要安装go get github.com/google/go-querystring
"io"
"net/http"
"net/url"
"time"
)
type OkxPublicDataService struct {
BaseURL string
client *http.Client
}
// NewOkxPublicDataService 创建服务实例
func NewOkxPublicDataService() *OkxPublicDataService {
return &OkxPublicDataService{
BaseURL: "https://aws.okx.com/api/v5",
client: &http.Client{
Timeout: 10 * time.Second, // 设置10秒超时
},
}
}
// GetInstruments 获取交易对信息
func (s *OkxPublicDataService) GetInstruments(params InstrumentsRequest) ([]Instrument, error) {
u, err := url.Parse(s.BaseURL + "/public/instruments")
if err != nil {
return nil, err
}
// 将 struct 转为查询参数
q, err := query.Values(params)
if err != nil {
return nil, err
}
u.RawQuery = q.Encode()
resp, err := s.client.Get(u.String())
if err != nil {
return nil, err
}
defer resp.Body.Close()
var apiResp ApiResponse
apiResp.Data = new([]Instrument) // 预分配 Data 字段为 Instrument 切片
if err := json.NewDecoder(resp.Body).Decode(&apiResp); err != nil {
return nil, err
}
if apiResp.Code != "0" {
return nil, fmt.Errorf("API error: code=%s, msg=%s, request_url=%s", apiResp.Code, apiResp.Msg, u.String())
}
// 进行类型断言并检查长度
switch data := apiResp.Data.(type) {
case []Instrument:
if len(data) == 0 {
return nil, fmt.Errorf("no data returned from API")
}
case [][]string:
if len(data) == 0 {
return nil, fmt.Errorf("no data returned from API")
}
case []*Ticker:
if len(data) == 0 {
return nil, fmt.Errorf("no data returned from API")
}
default:
return nil, fmt.Errorf("unexpected data type from API: %T", apiResp.Data)
}
return *apiResp.Data.(*[]Instrument), nil
}
// GetCandles 获取K线数据
func (s *OkxPublicDataService) GetCandles(params CandlesRequest) ([]*Candle, error) {
u, err := url.Parse(s.BaseURL + "/market/candles")
if err != nil {
return nil, err
}
// 将 struct 转为查询参数
q, err := query.Values(params)
if err != nil {
return nil, err
}
u.RawQuery = q.Encode()
// 添加调试日志
fmt.Printf("Making request to: %s\n", u.String())
resp, err := http.Get(u.String())
if err != nil {
return nil, err
}
defer resp.Body.Close()
// 记录响应状态
fmt.Printf("Response Status: %s\n", resp.Status)
// 读取并记录响应体
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
fmt.Printf("Response Body: %s\n", string(body))
// 重新设置resp.Body以便后续解码
resp.Body = io.NopCloser(bytes.NewBuffer(body))
var apiResp struct {
Code string `json:"code"`
Msg string `json:"msg"`
Data [][]string `json:"data"` // K线数据是二维数组
}
if err := json.NewDecoder(resp.Body).Decode(&apiResp); err != nil {
return nil, err
}
if apiResp.Code != "0" {
return nil, fmt.Errorf("API error: %s", apiResp.Msg)
}
// 将二维数组转为 Candle 切片
candles := make([]*Candle, len(apiResp.Data))
for i, item := range apiResp.Data {
candles[i] = &Candle{
Timestamp: item[0],
Open: item[1],
High: item[2],
Low: item[3],
Close: item[4],
Volume: item[5],
VolumeCcy: item[6],
}
}
return candles, nil
} // GetTicker 获取单个交易对的 ticker 数据
func (s *OkxPublicDataService) GetTicker(params TickerRequest) (*Ticker, error) {
u, err := url.Parse(s.BaseURL + "/market/ticker")
if err != nil {
return nil, err
}
// 将 struct 转为查询参数
q, err := query.Values(params)
if err != nil {
return nil, err
}
u.RawQuery = q.Encode()
resp, err := http.Get(u.String())
if err != nil {
return nil, err
}
defer resp.Body.Close()
var apiResp struct {
Code string `json:"code"`
Msg string `json:"msg"`
Data []*Ticker `json:"data"` // 返回的是指针数组
}
if err := json.NewDecoder(resp.Body).Decode(&apiResp); err != nil {
return nil, err
}
if apiResp.Code != "0" {
return nil, fmt.Errorf("API error: %s", apiResp.Msg)
}
if len(apiResp.Data) == 0 {
return nil, fmt.Errorf("no ticker data returned")
}
// 返回第一个 ticker通常只返回一个
return apiResp.Data[0], nil
}