From 524f084d39e83f56adee6aa8d83d2a19f057fb1a Mon Sep 17 00:00:00 2001 From: linstohu Date: Wed, 27 Dec 2023 23:33:08 +0800 Subject: [PATCH] feat: add some htx apis --- htx/spot/rest/basic.go | 113 +++++++ htx/spot/rest/client_test.go | 40 +++ htx/spot/rest/trading.go | 231 +++++++++++++ htx/spot/rest/types/basic.go | 40 +++ htx/spot/rest/types/kline.go | 25 ++ htx/spot/rest/types/market.go | 64 ++++ htx/spot/rest/types/trading.go | 106 ++++++ htx/usdm/rest/account.go | 168 ++++++++++ htx/usdm/rest/basic.go | 144 ++++++++ htx/usdm/rest/client_test.go | 111 +++++++ htx/usdm/rest/trading.go | 587 +++++++++++++++++++++++++++++++++ htx/usdm/rest/types/account.go | 143 ++++++++ htx/usdm/rest/types/basic.go | 76 +++++ htx/usdm/rest/types/kline.go | 26 ++ htx/usdm/rest/types/trading.go | 270 +++++++++++++++ 15 files changed, 2144 insertions(+) create mode 100644 htx/usdm/rest/trading.go create mode 100644 htx/usdm/rest/types/trading.go diff --git a/htx/spot/rest/basic.go b/htx/spot/rest/basic.go index bec7f6e..2b4b858 100644 --- a/htx/spot/rest/basic.go +++ b/htx/spot/rest/basic.go @@ -54,3 +54,116 @@ func (scli *SpotClient) GetSymbols(ctx context.Context, param types.GetSymbolsPa return &ret, nil } + +func (scli *SpotClient) GetSymbolInfo(ctx context.Context) (*types.GetSymbolInfoResp, error) { + req := utils.HTTPRequest{ + BaseURL: scli.cli.GetBaseURL(), + Path: "/v1/settings/common/market-symbols", + Method: http.MethodGet, + } + + { + headers, err := scli.cli.GetHeaders() + if err != nil { + return nil, err + } + req.Headers = headers + } + + resp, err := scli.cli.SendHTTPRequest(ctx, req) + if err != nil { + return nil, err + } + + var ret types.GetSymbolInfoResp + if err := resp.ReadJsonBody(&ret); err != nil { + return nil, errors.New(resp.Error()) + } + + return &ret, nil +} + +func (scli *SpotClient) GetMarketDepth(ctx context.Context, param types.GetMarketDepthParam) (*types.GetMarketDepthResp, error) { + req := utils.HTTPRequest{ + BaseURL: scli.cli.GetBaseURL(), + Path: "/market/depth", + Method: http.MethodGet, + Query: param, + } + + { + headers, err := scli.cli.GetHeaders() + if err != nil { + return nil, err + } + req.Headers = headers + } + + resp, err := scli.cli.SendHTTPRequest(ctx, req) + if err != nil { + return nil, err + } + var ret types.GetMarketDepthResp + if err := resp.ReadJsonBody(&ret); err != nil { + return nil, errors.New(err.Error()) + } + + return &ret, nil +} + +func (scli *SpotClient) GetKline(ctx context.Context, param types.GetKlineParam) (*types.GetKlineResp, error) { + req := utils.HTTPRequest{ + BaseURL: scli.cli.GetBaseURL(), + Path: "/market/history/kline", + Method: http.MethodGet, + Query: param, + } + + { + headers, err := scli.cli.GetHeaders() + if err != nil { + return nil, err + } + req.Headers = headers + } + + resp, err := scli.cli.SendHTTPRequest(ctx, req) + if err != nil { + return nil, err + } + + var ret types.GetKlineResp + if err := resp.ReadJsonBody(&ret); err != nil { + return nil, errors.New(resp.Error()) + } + + return &ret, nil +} + +func (scli *SpotClient) GetAllMarketTickers(ctx context.Context) (*types.GetMarketTickersResp, error) { + req := utils.HTTPRequest{ + BaseURL: scli.cli.GetBaseURL(), + Path: "/market/tickers", + Method: http.MethodGet, + } + + { + headers, err := scli.cli.GetHeaders() + if err != nil { + return nil, err + } + req.Headers = headers + } + + resp, err := scli.cli.SendHTTPRequest(ctx, req) + if err != nil { + return nil, err + } + + var ret types.GetMarketTickersResp + if err := resp.ReadJsonBody(&ret); err != nil { + return nil, errors.New(resp.Error()) + } + + return &ret, nil +} diff --git a/htx/spot/rest/client_test.go b/htx/spot/rest/client_test.go index db07815..1708581 100644 --- a/htx/spot/rest/client_test.go +++ b/htx/spot/rest/client_test.go @@ -91,3 +91,43 @@ func TestNewOrder(t *testing.T) { assert.Nil(t, err) } + +func TestCancelOrder(t *testing.T) { + cli := testNewSpotClient(t) + + _, err := cli.CancelOrder(context.TODO(), types.CancelOrderParams{ + OrderID: "", + }) + + assert.Nil(t, err) +} + +func TestGetOpenOrders(t *testing.T) { + cli := testNewSpotClient(t) + + _, err := cli.GetOpenOrders(context.TODO(), types.GetOpenOrdersParam{ + AccountID: "", + }) + + assert.Nil(t, err) +} + +func TestCancelOrders(t *testing.T) { + cli := testNewSpotClient(t) + + _, err := cli.CancelOrders(context.TODO(), types.CancelOrdersParam{ + AccountID: "", + }) + + assert.Nil(t, err) +} + +func TestSearchMatchResults(t *testing.T) { + cli := testNewSpotClient(t) + + _, err := cli.SearchMatchResults(context.TODO(), types.SearchMatchResultsParam{ + Symbol: "usdcusdt", + }) + + assert.Nil(t, err) +} diff --git a/htx/spot/rest/trading.go b/htx/spot/rest/trading.go index ef0c59c..f506917 100644 --- a/htx/spot/rest/trading.go +++ b/htx/spot/rest/trading.go @@ -20,6 +20,7 @@ package rest import ( "context" "errors" + "fmt" "net/http" "github.com/linstohu/nexapi/htx/spot/rest/types" @@ -81,3 +82,233 @@ func (scli *SpotClient) NewOrder(ctx context.Context, param types.NewOrderParam) return &ret, nil } + +func (scli *SpotClient) CancelOrder(ctx context.Context, param types.CancelOrderParams) (*types.CancelOrderResp, error) { + if err := scli.cli.CheckAuth(); err != nil { + return nil, err + } + + err := scli.validate.Struct(param) + if err != nil { + return nil, err + } + + req := utils.HTTPRequest{ + BaseURL: scli.cli.GetBaseURL(), + Path: fmt.Sprintf("/v1/order/orders/%s/submitcancel", param.OrderID), + Method: http.MethodPost, + Body: types.CancelOrderParam{ + Symbol: param.Symbol, + }, + } + + { + headers, err := scli.cli.GetHeaders() + if err != nil { + return nil, err + } + req.Headers = headers + } + + { + query := scli.cli.GenAuthParams() + + signStr, err := scli.cli.NormalizeRequestContent(req, query) + if err != nil { + return nil, err + } + + h := scli.cli.Sign([]byte(signStr)) + if err != nil { + return nil, err + } + + query.Signature = h + + req.Query = query + } + + resp, err := scli.cli.SendHTTPRequest(ctx, req) + if err != nil { + return nil, err + } + + var ret types.CancelOrderResp + if err := resp.ReadJsonBody(&ret); err != nil { + return nil, errors.New(resp.Error()) + } + + return &ret, nil +} + +func (scli *SpotClient) GetOpenOrders(ctx context.Context, param types.GetOpenOrdersParam) (*types.GetOpenOrdersResp, error) { + if err := scli.cli.CheckAuth(); err != nil { + return nil, err + } + + err := scli.validate.Struct(param) + if err != nil { + return nil, err + } + + req := utils.HTTPRequest{ + BaseURL: scli.cli.GetBaseURL(), + Path: "/v1/order/openOrders", + Method: http.MethodGet, + } + + { + headers, err := scli.cli.GetHeaders() + if err != nil { + return nil, err + } + req.Headers = headers + } + + { + query := types.GetOpenOrdersParams{ + GetOpenOrdersParam: param, + DefaultAuthParam: scli.cli.GenAuthParams(), + } + + signStr, err := scli.cli.NormalizeRequestContent(req, query) + if err != nil { + return nil, err + } + + h := scli.cli.Sign([]byte(signStr)) + if err != nil { + return nil, err + } + + query.Signature = h + + req.Query = query + } + + resp, err := scli.cli.SendHTTPRequest(ctx, req) + if err != nil { + return nil, err + } + + var ret types.GetOpenOrdersResp + if err := resp.ReadJsonBody(&ret); err != nil { + return nil, errors.New(resp.Error()) + } + + return &ret, nil +} + +func (scli *SpotClient) CancelOrders(ctx context.Context, param types.CancelOrdersParam) (*types.CancelOrdersResp, error) { + if err := scli.cli.CheckAuth(); err != nil { + return nil, err + } + + err := scli.validate.Struct(param) + if err != nil { + return nil, err + } + + req := utils.HTTPRequest{ + BaseURL: scli.cli.GetBaseURL(), + Path: "/v1/order/orders/batchCancelOpenOrders", + Method: http.MethodPost, + Body: param, + } + + { + headers, err := scli.cli.GetHeaders() + if err != nil { + return nil, err + } + req.Headers = headers + } + + { + query := scli.cli.GenAuthParams() + + signStr, err := scli.cli.NormalizeRequestContent(req, query) + if err != nil { + return nil, err + } + + h := scli.cli.Sign([]byte(signStr)) + if err != nil { + return nil, err + } + + query.Signature = h + + req.Query = query + } + + resp, err := scli.cli.SendHTTPRequest(ctx, req) + if err != nil { + return nil, err + } + + var ret types.CancelOrdersResp + if err := resp.ReadJsonBody(&ret); err != nil { + return nil, errors.New(resp.Error()) + } + + return &ret, nil +} + +func (scli *SpotClient) SearchMatchResults(ctx context.Context, param types.SearchMatchResultsParam) (*types.SearchMatchResultsResp, error) { + if err := scli.cli.CheckAuth(); err != nil { + return nil, err + } + + err := scli.validate.Struct(param) + if err != nil { + return nil, err + } + + req := utils.HTTPRequest{ + BaseURL: scli.cli.GetBaseURL(), + Path: "/v1/order/matchresults", + Method: http.MethodGet, + } + + { + headers, err := scli.cli.GetHeaders() + if err != nil { + return nil, err + } + req.Headers = headers + } + + { + query := types.SearchMatchResultsParams{ + SearchMatchResultsParam: param, + DefaultAuthParam: scli.cli.GenAuthParams(), + } + + signStr, err := scli.cli.NormalizeRequestContent(req, query) + if err != nil { + return nil, err + } + + h := scli.cli.Sign([]byte(signStr)) + if err != nil { + return nil, err + } + + query.Signature = h + + req.Query = query + } + + resp, err := scli.cli.SendHTTPRequest(ctx, req) + if err != nil { + return nil, err + } + + var ret types.SearchMatchResultsResp + if err := resp.ReadJsonBody(&ret); err != nil { + return nil, errors.New(resp.Error()) + } + + return &ret, nil +} diff --git a/htx/spot/rest/types/basic.go b/htx/spot/rest/types/basic.go index bc00298..003daf3 100644 --- a/htx/spot/rest/types/basic.go +++ b/htx/spot/rest/types/basic.go @@ -59,3 +59,43 @@ type Symbol struct { Elr any `json:"elr,omitempty"` P any `json:"p,omitempty"` } + +type GetSymbolInfoResp struct { + htxutils.V1Response + Ts string `json:"ts"` + Data []SymbolInfo `json:"data,omitempty"` +} + +type SymbolInfo struct { + Symbol string `json:"symbol"` + State string `json:"state"` + Bc string `json:"bc"` + Qc string `json:"qc"` + Pp int `json:"pp"` + Ap int `json:"ap"` + Sp string `json:"sp"` + Vp int `json:"vp"` + Minoa float64 `json:"minoa"` + Maxoa float64 `json:"maxoa"` + Minov float64 `json:"minov"` + Lominoa float64 `json:"lominoa"` + Lomaxoa float64 `json:"lomaxoa"` + Lomaxba float64 `json:"lomaxba"` + Lomaxsa float64 `json:"lomaxsa"` + Smminoa float64 `json:"smminoa"` + Blmlt float64 `json:"blmlt"` + Slmgt float64 `json:"slmgt"` + Smmaxoa float64 `json:"smmaxoa"` + Bmmaxov float64 `json:"bmmaxov"` + Msormlt float64 `json:"msormlt"` + Mbormlt float64 `json:"mbormlt"` + Maxov float64 `json:"maxov"` + U string `json:"u"` + Mfr float64 `json:"mfr"` + Ct string `json:"ct"` + Rt string `json:"rt"` + Rthr float64 `json:"rthr"` + In float64 `json:"in"` + At string `json:"at"` + Tags string `json:"tags"` +} diff --git a/htx/spot/rest/types/kline.go b/htx/spot/rest/types/kline.go index 8af22e1..b92ed1d 100644 --- a/htx/spot/rest/types/kline.go +++ b/htx/spot/rest/types/kline.go @@ -17,6 +17,8 @@ package types +import htxutils "github.com/linstohu/nexapi/htx/utils" + type KlineInterval string var ( @@ -31,3 +33,26 @@ var ( Week1 KlineInterval = "1week" Year1 KlineInterval = "1year" ) + +type GetKlineParam struct { + Symbol string `url:"symbol" validate:"required"` + Period KlineInterval `url:"period" validate:"required"` + Size int64 `url:"size,omitempty" validate:"omitempty"` +} + +type GetKlineResp struct { + htxutils.V1Response + Ts int64 `json:"ts"` + Data []Kline `json:"data,omitempty"` +} + +type Kline struct { + ID int64 `json:"id"` + Open float64 `json:"open"` + Close float64 `json:"close"` + Low float64 `json:"low"` + High float64 `json:"high"` + Amount float64 `json:"amount"` + Vol float64 `json:"vol"` + Count int `json:"count"` +} diff --git a/htx/spot/rest/types/market.go b/htx/spot/rest/types/market.go index 7796fc3..3fdd6c9 100644 --- a/htx/spot/rest/types/market.go +++ b/htx/spot/rest/types/market.go @@ -44,3 +44,67 @@ type Tick struct { Bid []float64 `json:"bid,omitempty"` Ask []float64 `json:"ask,omitempty"` } + +type GetMarketDepthParam struct { + Symbol string `url:"symbol" validate:"required"` + Depth int `url:"depth,omitempty" validate:"omitempty"` + Type string `url:"type" validate:"required"` +} + +type GetMarketDepthResp struct { + htxutils.V1Response + Ts int64 `json:"ts"` + Tick MarketDepth `json:"tick,omitempty"` +} + +type MarketDepth struct { + Ts int64 `json:"ts,omitempty"` + Version int64 `json:"version,omitempty"` + Bids [][]float64 `json:"bids,omitempty"` + Asks [][]float64 `json:"asks,omitempty"` +} + +type GetMarketTickerParam struct { + Symbol string `url:"symbol" validate:"required"` +} + +type GetMarketTickerResp struct { + htxutils.V1Response + Ts int64 `json:"ts"` + Tick MarketTickerMerged `json:"tick,omitempty"` +} + +type MarketTickerMerged struct { + ID int64 `json:"id"` + Version int64 `json:"version"` + Open float64 `json:"open"` + Close float64 `json:"close"` + Low float64 `json:"low"` + High float64 `json:"high"` + Amount float64 `json:"amount"` + Vol float64 `json:"vol"` + Count int `json:"count"` + Bid []float64 `json:"bid"` + Ask []float64 `json:"ask"` +} + +type GetMarketTickersResp struct { + htxutils.V1Response + Ts int64 `json:"ts"` + Data []MarketTicker `json:"data,omitempty"` +} + +type MarketTicker struct { + Symbol string `json:"symbol"` // 交易对,例如 btcusdt, ethbtc + Open float64 `json:"open"` // 开盘价(以新加坡时间自然日计) + High float64 `json:"high"` // 最高价(以新加坡时间自然日计) + Low float64 `json:"low"` // 最低价(以新加坡时间自然日计) + Close float64 `json:"close"` // 最新价(以新加坡时间自然日计) + Amount float64 `json:"amount"` // 以基础币种计量的交易量(以滚动24小时计) + Vol float64 `json:"vol"` // 以报价币种计量的交易量(以滚动24小时计) + Count int `json:"count"` // 交易笔数(以滚动24小时计) + Bid float64 `json:"bid"` // 买一价 + BidSize float64 `json:"bidSize"` // 买一量 + Ask float64 `json:"ask"` // 卖一价 + AskSize float64 `json:"askSize"` // 卖一量 +} diff --git a/htx/spot/rest/types/trading.go b/htx/spot/rest/types/trading.go index 8d66f3f..d432e26 100644 --- a/htx/spot/rest/types/trading.go +++ b/htx/spot/rest/types/trading.go @@ -38,3 +38,109 @@ type NewOrderResp struct { htxutils.V1Response Data string `json:"data,omitempty"` } + +type CancelOrderParams struct { + OrderID string `json:"order-id" validate:"required"` + Symbol string `json:"symbol,omitempty" validate:"omitempty"` +} + +type CancelOrderParam struct { + Symbol string `json:"symbol,omitempty" validate:"omitempty"` +} + +type CancelOrderResp struct { + htxutils.V1Response + Data string `json:"data,omitempty"` +} + +type GetOpenOrdersParam struct { + AccountID string `url:"account-id,omitempty" validate:"omitempty"` + Symbol string `url:"symbol,omitempty" validate:"omitempty"` + Side string `url:"side,omitempty" validate:"omitempty"` + Types string `url:"types,omitempty" validate:"omitempty"` + From string `url:"from,omitempty" validate:"omitempty"` + Direct string `url:"direct,omitempty" validate:"omitempty"` + Size string `url:"size,omitempty" validate:"omitempty"` +} + +type GetOpenOrdersParams struct { + GetOpenOrdersParam + htxutils.DefaultAuthParam +} + +type GetOpenOrdersResp struct { + htxutils.V1Response + Data []OpenOrder `json:"data,omitempty"` +} + +type OpenOrder struct { + Symbol string `json:"symbol,omitempty"` + Source string `json:"source,omitempty"` + Price string `json:"price,omitempty"` + CreatedAt int64 `json:"created-at,omitempty"` + Amount string `json:"amount,omitempty"` + AccountID int `json:"account-id,omitempty"` + FilledCashAmount string `json:"filled-cash-amount,omitempty"` + ClientOrderID string `json:"client-order-id,omitempty"` + FilledAmount string `json:"filled-amount,omitempty"` + FilledFees string `json:"filled-fees,omitempty"` + ID int64 `json:"id,omitempty"` + State string `json:"state,omitempty"` + Type string `json:"type,omitempty"` +} + +type CancelOrdersParam struct { + AccountID string `json:"account-id,omitempty" validate:"omitempty"` + Symbol string `json:"symbol,omitempty" validate:"omitempty"` + Types string `json:"types,omitempty" validate:"omitempty"` + Side string `json:"side,omitempty" validate:"omitempty"` + Size int `json:"size,omitempty" validate:"omitempty"` +} + +type CancelOrdersResp struct { + htxutils.V1Response + Data struct { + SuccessCount int `json:"success-count,omitempty"` + FailedCount int `json:"failed-count,omitempty"` + NextID int64 `json:"next-id,omitempty"` + } `json:"data,omitempty"` +} + +type SearchMatchResultsParams struct { + SearchMatchResultsParam + htxutils.DefaultAuthParam +} + +type SearchMatchResultsParam struct { + Symbol string `url:"symbol" validate:"required"` + Types string `url:"types,omitempty" validate:"omitempty"` + StartTime int64 `url:"start-time,omitempty" validate:"omitempty"` + EndTime int64 `url:"end-time,omitempty" validate:"omitempty"` + From string `url:"from,omitempty" validate:"omitempty"` + Direct string `url:"direct,omitempty" validate:"omitempty"` + Size string `url:"size,omitempty" validate:"omitempty"` +} + +type SearchMatchResultsResp struct { + htxutils.V1Response + Data []MatchResult `json:"data,omitempty"` +} + +type MatchResult struct { + Symbol string `json:"symbol,omitempty"` + FeeCurrency string `json:"fee-currency,omitempty"` + Source string `json:"source,omitempty"` + Price string `json:"price,omitempty"` + CreatedAt int64 `json:"created-at,omitempty"` + Role string `json:"role,omitempty"` + OrderID int64 `json:"order-id,omitempty"` + MatchID int64 `json:"match-id,omitempty"` + TradeID int64 `json:"trade-id,omitempty"` + FilledAmount string `json:"filled-amount,omitempty"` + FilledFees string `json:"filled-fees,omitempty"` + FilledPoints string `json:"filled-points,omitempty"` + FeeDeductCurrency string `json:"fee-deduct-currency,omitempty"` + FeeDeductState string `json:"fee-deduct-state,omitempty"` + ID int64 `json:"id,omitempty"` + Type string `json:"type,omitempty"` +} diff --git a/htx/usdm/rest/account.go b/htx/usdm/rest/account.go index 3af4e9e..adc5b99 100644 --- a/htx/usdm/rest/account.go +++ b/htx/usdm/rest/account.go @@ -81,3 +81,171 @@ func (ucli *UsdmClient) GetAssetValuation(ctx context.Context, param types.GetAs return &ret, nil } + +func (ucli *UsdmClient) GetIsolatedAccounts(ctx context.Context, param types.GetIsolatedAccountsParam) (*types.GetIsolatedAccountsResp, error) { + if err := ucli.cli.CheckAuth(); err != nil { + return nil, err + } + + err := ucli.validate.Struct(param) + if err != nil { + return nil, err + } + + req := utils.HTTPRequest{ + BaseURL: ucli.cli.GetBaseURL(), + Path: "/linear-swap-api/v1/swap_account_info", + Method: http.MethodPost, + Body: param, + } + + { + headers, err := ucli.cli.GetHeaders() + if err != nil { + return nil, err + } + req.Headers = headers + } + + { + query := ucli.cli.GenAuthParams() + + signStr, err := ucli.cli.NormalizeRequestContent(req, query) + if err != nil { + return nil, err + } + + h := ucli.cli.Sign([]byte(signStr)) + if err != nil { + return nil, err + } + + query.Signature = h + + req.Query = query + } + + resp, err := ucli.cli.SendHTTPRequest(ctx, req) + if err != nil { + return nil, err + } + + var ret types.GetIsolatedAccountsResp + if err := resp.ReadJsonBody(&ret); err != nil { + return nil, errors.New(resp.Error()) + } + + return &ret, nil +} + +func (ucli *UsdmClient) GetCrossAccounts(ctx context.Context, param types.GetCrossAccountsParam) (*types.GetCrossAccountsResp, error) { + if err := ucli.cli.CheckAuth(); err != nil { + return nil, err + } + + err := ucli.validate.Struct(param) + if err != nil { + return nil, err + } + + req := utils.HTTPRequest{ + BaseURL: ucli.cli.GetBaseURL(), + Path: "/linear-swap-api/v1/swap_cross_account_info", + Method: http.MethodPost, + Body: param, + } + + { + headers, err := ucli.cli.GetHeaders() + if err != nil { + return nil, err + } + req.Headers = headers + } + + { + query := ucli.cli.GenAuthParams() + + signStr, err := ucli.cli.NormalizeRequestContent(req, query) + if err != nil { + return nil, err + } + + h := ucli.cli.Sign([]byte(signStr)) + if err != nil { + return nil, err + } + + query.Signature = h + + req.Query = query + } + + resp, err := ucli.cli.SendHTTPRequest(ctx, req) + if err != nil { + return nil, err + } + + var ret types.GetCrossAccountsResp + if err := resp.ReadJsonBody(&ret); err != nil { + return nil, errors.New(resp.Error()) + } + + return &ret, nil +} + +func (ucli *UsdmClient) GetUnifiedAccounts(ctx context.Context, param types.GetUnifiedAccountsParam) (*types.GetUnifiedAccountsResp, error) { + if err := ucli.cli.CheckAuth(); err != nil { + return nil, err + } + + err := ucli.validate.Struct(param) + if err != nil { + return nil, err + } + + req := utils.HTTPRequest{ + BaseURL: ucli.cli.GetBaseURL(), + Path: "/linear-swap-api/v3/unified_account_info", + Method: http.MethodGet, + Body: param, + } + + { + headers, err := ucli.cli.GetHeaders() + if err != nil { + return nil, err + } + req.Headers = headers + } + + { + query := ucli.cli.GenAuthParams() + + signStr, err := ucli.cli.NormalizeRequestContent(req, query) + if err != nil { + return nil, err + } + + h := ucli.cli.Sign([]byte(signStr)) + if err != nil { + return nil, err + } + + query.Signature = h + + req.Query = query + } + + resp, err := ucli.cli.SendHTTPRequest(ctx, req) + if err != nil { + return nil, err + } + + var ret types.GetUnifiedAccountsResp + if err := resp.ReadJsonBody(&ret); err != nil { + return nil, errors.New(resp.Error()) + } + + return &ret, nil +} diff --git a/htx/usdm/rest/basic.go b/htx/usdm/rest/basic.go index 8fdaca0..db06f2f 100644 --- a/htx/usdm/rest/basic.go +++ b/htx/usdm/rest/basic.go @@ -54,3 +54,147 @@ func (ucli *UsdmClient) GetContractInfo(ctx context.Context, param types.GetCont return &ret, nil } + +func (ucli *UsdmClient) GetFundingRate(ctx context.Context) (*types.GetFundingRateResp, error) { + req := utils.HTTPRequest{ + BaseURL: ucli.cli.GetBaseURL(), + Path: "/linear-swap-api/v1/swap_batch_funding_rate", + Method: http.MethodGet, + } + + { + headers, err := ucli.cli.GetHeaders() + if err != nil { + return nil, err + } + req.Headers = headers + } + + resp, err := ucli.cli.SendHTTPRequest(ctx, req) + if err != nil { + return nil, err + } + + var ret types.GetFundingRateResp + if err := resp.ReadJsonBody(&ret); err != nil { + return nil, errors.New(resp.Error()) + } + + return &ret, nil +} + +func (ucli *UsdmClient) GetMarketDepth(ctx context.Context, param types.GetMarketDepthParam) (*types.GetMarketDepthResp, error) { + req := utils.HTTPRequest{ + BaseURL: ucli.cli.GetBaseURL(), + Path: "/linear-swap-ex/market/depth", + Method: http.MethodGet, + Query: param, + } + + { + headers, err := ucli.cli.GetHeaders() + if err != nil { + return nil, err + } + req.Headers = headers + } + + resp, err := ucli.cli.SendHTTPRequest(ctx, req) + if err != nil { + return nil, err + } + + var ret types.GetMarketDepthResp + if err := resp.ReadJsonBody(&ret); err != nil { + return nil, errors.New(resp.Error()) + } + + return &ret, nil +} + +func (ucli *UsdmClient) GetKline(ctx context.Context, param types.GetKlineParam) (*types.GetKlineResp, error) { + req := utils.HTTPRequest{ + BaseURL: ucli.cli.GetBaseURL(), + Path: "/linear-swap-ex/market/history/kline", + Method: http.MethodGet, + Query: param, + } + + { + headers, err := ucli.cli.GetHeaders() + if err != nil { + return nil, err + } + req.Headers = headers + } + + resp, err := ucli.cli.SendHTTPRequest(ctx, req) + if err != nil { + return nil, err + } + + var ret types.GetKlineResp + if err := resp.ReadJsonBody(&ret); err != nil { + return nil, errors.New(resp.Error()) + } + + return &ret, nil +} + +func (ucli *UsdmClient) GetMarketTicker(ctx context.Context, param types.GetMarketTickerParam) (*types.GetMarketTickerResp, error) { + req := utils.HTTPRequest{ + BaseURL: ucli.cli.GetBaseURL(), + Path: "/linear-swap-ex/market/detail/merged", + Method: http.MethodGet, + Query: param, + } + + { + headers, err := ucli.cli.GetHeaders() + if err != nil { + return nil, err + } + req.Headers = headers + } + + resp, err := ucli.cli.SendHTTPRequest(ctx, req) + if err != nil { + return nil, err + } + + var ret types.GetMarketTickerResp + if err := resp.ReadJsonBody(&ret); err != nil { + return nil, errors.New(resp.Error()) + } + + return &ret, nil +} + +func (ucli *UsdmClient) GetMarketTickers(ctx context.Context, param types.GetMarketTickersParam) (*types.GetMarketTickersResp, error) { + req := utils.HTTPRequest{ + BaseURL: ucli.cli.GetBaseURL(), + Path: "/v2/linear-swap-ex/market/detail/batch_merged", + Method: http.MethodGet, + Query: param, + } + + { + headers, err := ucli.cli.GetHeaders() + if err != nil { + return nil, err + } + req.Headers = headers + } + + resp, err := ucli.cli.SendHTTPRequest(ctx, req) + if err != nil { + return nil, err + } + + var ret types.GetMarketTickersResp + if err := resp.ReadJsonBody(&ret); err != nil { + return nil, errors.New(resp.Error()) + } + + return &ret, nil +} diff --git a/htx/usdm/rest/client_test.go b/htx/usdm/rest/client_test.go index 1a0d6e2..4ce6e81 100644 --- a/htx/usdm/rest/client_test.go +++ b/htx/usdm/rest/client_test.go @@ -59,3 +59,114 @@ func TestGetAssetValuation(t *testing.T) { assert.Nil(t, err) } + +func TestPlaceIsolatedOrder(t *testing.T) { + cli := testNewUsdmClient(t) + + _, err := cli.PlaceIsolatedOrder(context.TODO(), types.PlaceIsolatedOrderParam{ + ContractCode: "XRP-USDT", + Price: 0.5, + Volume: 1, + Direction: "buy", + LeverRate: 1, + OrderPriceType: "limit", + }) + + assert.Nil(t, err) +} + +func TestPlaceCrossOrder(t *testing.T) { + cli := testNewUsdmClient(t) + + _, err := cli.PlaceCrossOrder(context.TODO(), types.PlaceCrossOrderParam{ + ContractCode: "XRP-USDT", + Price: 0.5, + Volume: 1, + Direction: "buy", + LeverRate: 1, + OrderPriceType: "limit", + }) + + assert.Nil(t, err) +} + +func TestCancelIsolatedOrder(t *testing.T) { + cli := testNewUsdmClient(t) + + _, err := cli.CancelIsolatedOrder(context.TODO(), types.CancelIsolatedOrderParam{ + OrderID: "", + ContractCode: "XRP-USDT", + }) + + assert.Nil(t, err) +} + +func TestCancelCrossOrder(t *testing.T) { + cli := testNewUsdmClient(t) + + _, err := cli.CancelCrossOrder(context.TODO(), types.CancelCrossOrderParam{ + OrderID: "", + }) + + assert.Nil(t, err) +} + +func TestCancelAllIsolatedOrders(t *testing.T) { + cli := testNewUsdmClient(t) + + _, err := cli.CancelAllIsolatedOrders(context.TODO(), types.CancelAllIsolatedOrdersParam{ + ContractCode: "XRP-USDT", + }) + + assert.Nil(t, err) +} + +func TestCancelAllCrossOrders(t *testing.T) { + cli := testNewUsdmClient(t) + + _, err := cli.CancelAllCrossOrders(context.TODO(), types.CancelAllCrossOrdersParam{ + ContractCode: "XRP-USDT", + }) + + assert.Nil(t, err) +} + +func TestGetIsolatedOpenOrders(t *testing.T) { + cli := testNewUsdmClient(t) + + _, err := cli.GetIsolatedOpenOrders(context.TODO(), types.GetIsolatedOpenOrdersParam{ + ContractCode: "XRP-USDT", + }) + + assert.Nil(t, err) +} + +func TestGetCrossOpenOrders(t *testing.T) { + cli := testNewUsdmClient(t) + + _, err := cli.GetCrossOpenOrders(context.TODO(), types.GetCrossOpenOrdersParam{ + ContractCode: "XRP-USDT", + }) + + assert.Nil(t, err) +} + +func TestGetIsolatedHistoryMatchResults(t *testing.T) { + cli := testNewUsdmClient(t) + + _, err := cli.GetIsolatedHistoryMatchResults(context.TODO(), types.GetIsolatedHistoryMatchResultsParam{ + TradeType: 0, + }) + + assert.Nil(t, err) +} + +func TestGetCrossHistoryMatchResults(t *testing.T) { + cli := testNewUsdmClient(t) + + _, err := cli.GetCrossHistoryMatchResults(context.TODO(), types.GetCrossHistoryMatchResultsParam{ + Contract: "XRP-USDT", + }) + + assert.Nil(t, err) +} diff --git a/htx/usdm/rest/trading.go b/htx/usdm/rest/trading.go new file mode 100644 index 0000000..7c93433 --- /dev/null +++ b/htx/usdm/rest/trading.go @@ -0,0 +1,587 @@ +/* + * Copyright (c) 2023, LinstoHu + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package rest + +import ( + "context" + "errors" + "net/http" + + "github.com/linstohu/nexapi/htx/usdm/rest/types" + "github.com/linstohu/nexapi/htx/utils" +) + +func (ucli *UsdmClient) PlaceIsolatedOrder(ctx context.Context, param types.PlaceIsolatedOrderParam) (*types.PlaceOrderResp, error) { + if err := ucli.cli.CheckAuth(); err != nil { + return nil, err + } + + err := ucli.validate.Struct(param) + if err != nil { + return nil, err + } + + req := utils.HTTPRequest{ + BaseURL: ucli.cli.GetBaseURL(), + Path: "/linear-swap-api/v1/swap_order", + Method: http.MethodPost, + Body: param, + } + + { + headers, err := ucli.cli.GetHeaders() + if err != nil { + return nil, err + } + req.Headers = headers + } + + { + query := ucli.cli.GenAuthParams() + + signStr, err := ucli.cli.NormalizeRequestContent(req, query) + if err != nil { + return nil, err + } + + h := ucli.cli.Sign([]byte(signStr)) + if err != nil { + return nil, err + } + + query.Signature = h + + req.Query = query + } + + resp, err := ucli.cli.SendHTTPRequest(ctx, req) + if err != nil { + return nil, err + } + + var ret types.PlaceOrderResp + if err := resp.ReadJsonBody(&ret); err != nil { + return nil, errors.New(resp.Error()) + } + + return &ret, nil +} + +func (ucli *UsdmClient) PlaceCrossOrder(ctx context.Context, param types.PlaceCrossOrderParam) (*types.PlaceOrderResp, error) { + if err := ucli.cli.CheckAuth(); err != nil { + return nil, err + } + + err := ucli.validate.Struct(param) + if err != nil { + return nil, err + } + + req := utils.HTTPRequest{ + BaseURL: ucli.cli.GetBaseURL(), + Path: "/linear-swap-api/v1/swap_cross_order", + Method: http.MethodPost, + Body: param, + } + + { + headers, err := ucli.cli.GetHeaders() + if err != nil { + return nil, err + } + req.Headers = headers + } + + { + query := ucli.cli.GenAuthParams() + + signStr, err := ucli.cli.NormalizeRequestContent(req, query) + if err != nil { + return nil, err + } + + h := ucli.cli.Sign([]byte(signStr)) + if err != nil { + return nil, err + } + + query.Signature = h + + req.Query = query + } + + resp, err := ucli.cli.SendHTTPRequest(ctx, req) + if err != nil { + return nil, err + } + + var ret types.PlaceOrderResp + if err := resp.ReadJsonBody(&ret); err != nil { + return nil, errors.New(resp.Error()) + } + + return &ret, nil +} + +func (ucli *UsdmClient) CancelIsolatedOrder(ctx context.Context, param types.CancelIsolatedOrderParam) (*types.CancelOrderResp, error) { + if err := ucli.cli.CheckAuth(); err != nil { + return nil, err + } + + err := ucli.validate.Struct(param) + if err != nil { + return nil, err + } + + req := utils.HTTPRequest{ + BaseURL: ucli.cli.GetBaseURL(), + Path: "/linear-swap-api/v1/swap_cancel", + Method: http.MethodPost, + Body: param, + } + + { + headers, err := ucli.cli.GetHeaders() + if err != nil { + return nil, err + } + req.Headers = headers + } + + { + query := ucli.cli.GenAuthParams() + + signStr, err := ucli.cli.NormalizeRequestContent(req, query) + if err != nil { + return nil, err + } + + h := ucli.cli.Sign([]byte(signStr)) + if err != nil { + return nil, err + } + + query.Signature = h + + req.Query = query + } + + resp, err := ucli.cli.SendHTTPRequest(ctx, req) + if err != nil { + return nil, err + } + + var ret types.CancelOrderResp + if err := resp.ReadJsonBody(&ret); err != nil { + return nil, errors.New(resp.Error()) + } + + return &ret, nil +} + +func (ucli *UsdmClient) CancelCrossOrder(ctx context.Context, param types.CancelCrossOrderParam) (*types.CancelOrderResp, error) { + if err := ucli.cli.CheckAuth(); err != nil { + return nil, err + } + + err := ucli.validate.Struct(param) + if err != nil { + return nil, err + } + + req := utils.HTTPRequest{ + BaseURL: ucli.cli.GetBaseURL(), + Path: "/linear-swap-api/v1/swap_cross_cancel", + Method: http.MethodPost, + Body: param, + } + + { + headers, err := ucli.cli.GetHeaders() + if err != nil { + return nil, err + } + req.Headers = headers + } + + { + query := ucli.cli.GenAuthParams() + + signStr, err := ucli.cli.NormalizeRequestContent(req, query) + if err != nil { + return nil, err + } + + h := ucli.cli.Sign([]byte(signStr)) + if err != nil { + return nil, err + } + + query.Signature = h + + req.Query = query + } + + resp, err := ucli.cli.SendHTTPRequest(ctx, req) + if err != nil { + return nil, err + } + + var ret types.CancelOrderResp + if err := resp.ReadJsonBody(&ret); err != nil { + return nil, errors.New(resp.Error()) + } + + return &ret, nil +} + +func (ucli *UsdmClient) CancelAllIsolatedOrders(ctx context.Context, param types.CancelAllIsolatedOrdersParam) (*types.CancelOrderResp, error) { + if err := ucli.cli.CheckAuth(); err != nil { + return nil, err + } + + err := ucli.validate.Struct(param) + if err != nil { + return nil, err + } + + req := utils.HTTPRequest{ + BaseURL: ucli.cli.GetBaseURL(), + Path: "/linear-swap-api/v1/swap_cancelall", + Method: http.MethodPost, + Body: param, + } + + { + headers, err := ucli.cli.GetHeaders() + if err != nil { + return nil, err + } + req.Headers = headers + } + + { + query := ucli.cli.GenAuthParams() + + signStr, err := ucli.cli.NormalizeRequestContent(req, query) + if err != nil { + return nil, err + } + + h := ucli.cli.Sign([]byte(signStr)) + if err != nil { + return nil, err + } + + query.Signature = h + + req.Query = query + } + + resp, err := ucli.cli.SendHTTPRequest(ctx, req) + if err != nil { + return nil, err + } + + var ret types.CancelOrderResp + if err := resp.ReadJsonBody(&ret); err != nil { + return nil, errors.New(resp.Error()) + } + + return &ret, nil +} + +func (ucli *UsdmClient) CancelAllCrossOrders(ctx context.Context, param types.CancelAllCrossOrdersParam) (*types.CancelOrderResp, error) { + if err := ucli.cli.CheckAuth(); err != nil { + return nil, err + } + + err := ucli.validate.Struct(param) + if err != nil { + return nil, err + } + + req := utils.HTTPRequest{ + BaseURL: ucli.cli.GetBaseURL(), + Path: "/linear-swap-api/v1/swap_cross_cancelall", + Method: http.MethodPost, + Body: param, + } + + { + headers, err := ucli.cli.GetHeaders() + if err != nil { + return nil, err + } + req.Headers = headers + } + + { + query := ucli.cli.GenAuthParams() + + signStr, err := ucli.cli.NormalizeRequestContent(req, query) + if err != nil { + return nil, err + } + + h := ucli.cli.Sign([]byte(signStr)) + if err != nil { + return nil, err + } + + query.Signature = h + + req.Query = query + } + + resp, err := ucli.cli.SendHTTPRequest(ctx, req) + if err != nil { + return nil, err + } + + var ret types.CancelOrderResp + if err := resp.ReadJsonBody(&ret); err != nil { + return nil, errors.New(resp.Error()) + } + + return &ret, nil +} + +func (ucli *UsdmClient) GetIsolatedOpenOrders(ctx context.Context, param types.GetIsolatedOpenOrdersParam) (*types.GetIsolatedOpenOrdersResp, error) { + if err := ucli.cli.CheckAuth(); err != nil { + return nil, err + } + + err := ucli.validate.Struct(param) + if err != nil { + return nil, err + } + + req := utils.HTTPRequest{ + BaseURL: ucli.cli.GetBaseURL(), + Path: "/linear-swap-api/v1/swap_openorders", + Method: http.MethodPost, + Body: param, + } + + { + headers, err := ucli.cli.GetHeaders() + if err != nil { + return nil, err + } + req.Headers = headers + } + + { + query := ucli.cli.GenAuthParams() + + signStr, err := ucli.cli.NormalizeRequestContent(req, query) + if err != nil { + return nil, err + } + + h := ucli.cli.Sign([]byte(signStr)) + if err != nil { + return nil, err + } + + query.Signature = h + + req.Query = query + } + + resp, err := ucli.cli.SendHTTPRequest(ctx, req) + if err != nil { + return nil, err + } + + var ret types.GetIsolatedOpenOrdersResp + if err := resp.ReadJsonBody(&ret); err != nil { + return nil, errors.New(resp.Error()) + } + + return &ret, nil +} + +func (ucli *UsdmClient) GetCrossOpenOrders(ctx context.Context, param types.GetCrossOpenOrdersParam) (*types.GetCrossOpenOrdersResp, error) { + if err := ucli.cli.CheckAuth(); err != nil { + return nil, err + } + + err := ucli.validate.Struct(param) + if err != nil { + return nil, err + } + + req := utils.HTTPRequest{ + BaseURL: ucli.cli.GetBaseURL(), + Path: "/linear-swap-api/v1/swap_cross_openorders", + Method: http.MethodPost, + Body: param, + } + + { + headers, err := ucli.cli.GetHeaders() + if err != nil { + return nil, err + } + req.Headers = headers + } + + { + query := ucli.cli.GenAuthParams() + + signStr, err := ucli.cli.NormalizeRequestContent(req, query) + if err != nil { + return nil, err + } + + h := ucli.cli.Sign([]byte(signStr)) + if err != nil { + return nil, err + } + + query.Signature = h + + req.Query = query + } + + resp, err := ucli.cli.SendHTTPRequest(ctx, req) + if err != nil { + return nil, err + } + + var ret types.GetCrossOpenOrdersResp + if err := resp.ReadJsonBody(&ret); err != nil { + return nil, errors.New(resp.Error()) + } + + return &ret, nil +} + +func (ucli *UsdmClient) GetIsolatedHistoryMatchResults(ctx context.Context, param types.GetIsolatedHistoryMatchResultsParam) (*types.HistoryMatchResultsResp, error) { + if err := ucli.cli.CheckAuth(); err != nil { + return nil, err + } + + err := ucli.validate.Struct(param) + if err != nil { + return nil, err + } + + req := utils.HTTPRequest{ + BaseURL: ucli.cli.GetBaseURL(), + Path: "/linear-swap-api/v3/swap_matchresults", + Method: http.MethodPost, + Body: param, + } + + { + headers, err := ucli.cli.GetHeaders() + if err != nil { + return nil, err + } + req.Headers = headers + } + + { + query := ucli.cli.GenAuthParams() + + signStr, err := ucli.cli.NormalizeRequestContent(req, query) + if err != nil { + return nil, err + } + + h := ucli.cli.Sign([]byte(signStr)) + if err != nil { + return nil, err + } + + query.Signature = h + + req.Query = query + } + + resp, err := ucli.cli.SendHTTPRequest(ctx, req) + if err != nil { + return nil, err + } + + var ret types.HistoryMatchResultsResp + if err := resp.ReadJsonBody(&ret); err != nil { + return nil, errors.New(resp.Error()) + } + + return &ret, nil +} + +func (ucli *UsdmClient) GetCrossHistoryMatchResults(ctx context.Context, param types.GetCrossHistoryMatchResultsParam) (*types.HistoryMatchResultsResp, error) { + if err := ucli.cli.CheckAuth(); err != nil { + return nil, err + } + + err := ucli.validate.Struct(param) + if err != nil { + return nil, err + } + + req := utils.HTTPRequest{ + BaseURL: ucli.cli.GetBaseURL(), + Path: "/linear-swap-api/v3/swap_cross_matchresults", + Method: http.MethodPost, + Body: param, + } + + { + headers, err := ucli.cli.GetHeaders() + if err != nil { + return nil, err + } + req.Headers = headers + } + + { + query := ucli.cli.GenAuthParams() + + signStr, err := ucli.cli.NormalizeRequestContent(req, query) + if err != nil { + return nil, err + } + + h := ucli.cli.Sign([]byte(signStr)) + if err != nil { + return nil, err + } + + query.Signature = h + + req.Query = query + } + + resp, err := ucli.cli.SendHTTPRequest(ctx, req) + if err != nil { + return nil, err + } + + var ret types.HistoryMatchResultsResp + if err := resp.ReadJsonBody(&ret); err != nil { + return nil, errors.New(resp.Error()) + } + + return &ret, nil +} diff --git a/htx/usdm/rest/types/account.go b/htx/usdm/rest/types/account.go index 6ceec60..a0b566b 100644 --- a/htx/usdm/rest/types/account.go +++ b/htx/usdm/rest/types/account.go @@ -17,6 +17,10 @@ package types +import ( + htxutils "github.com/linstohu/nexapi/htx/utils" +) + type GetAssetValuationParam struct { ValuationAsset string `json:"valuation_asset,omitempty" validate:"omitempty"` } @@ -30,3 +34,142 @@ type AssetValuation struct { ValuationAsset string `json:"valuation_asset"` Balance string `json:"balance"` } + +type GetIsolatedAccountsParam struct { + ContractCode string `json:"contract_code,omitempty" validate:"omitempty"` +} + +type GetIsolatedAccountsResp struct { + DefaultResponse + Data []IsolatedAccount `json:"data"` +} + +type IsolatedAccount struct { + Symbol string `json:"symbol,omitempty"` + MarginBalance float64 `json:"margin_balance,omitempty"` + MarginPosition float64 `json:"margin_position,omitempty"` + MarginFrozen float64 `json:"margin_frozen,omitempty"` + MarginAvailable float64 `json:"margin_available,omitempty"` + ProfitReal float64 `json:"profit_real,omitempty"` + ProfitUnreal float64 `json:"profit_unreal,omitempty"` + RiskRate float64 `json:"risk_rate,omitempty"` + NewRiskRate string `json:"new_risk_rate,omitempty"` + TradePartition string `json:"trade_partition,omitempty"` + WithdrawAvailable float64 `json:"withdraw_available,omitempty"` + LiquidationPrice float64 `json:"liquidation_price,omitempty"` + LeverRate float64 `json:"lever_rate,omitempty"` + AdjustFactor float64 `json:"adjust_factor,omitempty"` + MarginStatic float64 `json:"margin_static,omitempty"` + ContractCode string `json:"contract_code,omitempty"` + MarginAsset string `json:"margin_asset,omitempty"` + MarginMode string `json:"margin_mode,omitempty"` + MarginAccount string `json:"margin_account,omitempty"` + PositionMode string `json:"position_mode,omitempty"` +} + +type GetCrossAccountsParam struct { + MarginAccount string `json:"margin_account,omitempty" validate:"omitempty"` +} + +type GetCrossAccountsResp struct { + DefaultResponse + Data []CrossAccount `json:"data"` +} + +type CrossAccount struct { + FuturesContractDetail []FuturesContractDetail `json:"futures_contract_detail,omitempty"` + MarginMode string `json:"margin_mode,omitempty"` + MarginAccount string `json:"margin_account,omitempty"` + MarginAsset string `json:"margin_asset,omitempty"` + MarginBalance float64 `json:"margin_balance,omitempty"` + MarginStatic float64 `json:"margin_static,omitempty"` + MarginPosition float64 `json:"margin_position,omitempty"` + MarginFrozen float64 `json:"margin_frozen,omitempty"` + ProfitUnreal float64 `json:"profit_unreal,omitempty"` + WithdrawAvailable float64 `json:"withdraw_available,omitempty"` + RiskRate float64 `json:"risk_rate,omitempty"` + MoneyIn string `json:"money_in,omitempty"` + MoneyOut string `json:"money_out,omitempty"` + NewRiskRate string `json:"new_risk_rate,omitempty"` + PositionMode string `json:"position_mode,omitempty"` + ContractDetail []ContractDetail `json:"contract_detail,omitempty"` +} + +type FuturesContractDetail struct { + Symbol string `json:"symbol,omitempty"` + ContractCode string `json:"contract_code,omitempty"` + MarginPosition float64 `json:"margin_position,omitempty"` + MarginFrozen float64 `json:"margin_frozen,omitempty"` + MarginAvailable float64 `json:"margin_available,omitempty"` + ProfitUnreal float64 `json:"profit_unreal,omitempty"` + LiquidationPrice float64 `json:"liquidation_price,omitempty"` + LeverRate float64 `json:"lever_rate,omitempty"` + AdjustFactor float64 `json:"adjust_factor,omitempty"` + ContractType string `json:"contract_type,omitempty"` + CrossMaxAvailable string `json:"cross_max_available,omitempty"` + TradePartition string `json:"trade_partition,omitempty"` + Pair string `json:"pair,omitempty"` + BusinessType string `json:"business_type,omitempty"` +} + +type ContractDetail struct { + Symbol string `json:"symbol,omitempty"` + ContractCode string `json:"contract_code,omitempty"` + MarginPosition float64 `json:"margin_position,omitempty"` + MarginFrozen float64 `json:"margin_frozen,omitempty"` + MarginAvailable float64 `json:"margin_available,omitempty"` + ProfitUnreal float64 `json:"profit_unreal,omitempty"` + LiquidationPrice float64 `json:"liquidation_price,omitempty"` + LeverRate float64 `json:"lever_rate,omitempty"` + AdjustFactor float64 `json:"adjust_factor,omitempty"` + ContractType string `json:"contract_type,omitempty"` + CrossMaxAvailable string `json:"cross_max_available,omitempty"` + TradePartition string `json:"trade_partition,omitempty"` + Pair string `json:"pair,omitempty"` + BusinessType string `json:"business_type,omitempty"` +} + +type GetUnifiedAccountsParam struct { + ContractCode string `json:"contract_code,omitempty" validate:"omitempty"` +} + +type GetUnifiedAccountsResp struct { + htxutils.V2Response + Data []UnifiedAccount `json:"data"` +} + +type CrossFuture struct { + BusinessType string `json:"business_type,omitempty"` + ContractCode string `json:"contract_code,omitempty"` + ContractType string `json:"contract_type,omitempty"` + CrossMaxAvailable float64 `json:"cross_max_available,omitempty"` + LeverRate float64 `json:"lever_rate,omitempty"` + MarginAvailable float64 `json:"margin_available,omitempty"` + MarginMode string `json:"margin_mode,omitempty"` + Symbol string `json:"symbol,omitempty"` +} + +type CrossSwap struct { + BusinessType string `json:"business_type,omitempty"` + ContractCode string `json:"contract_code,omitempty"` + ContractType string `json:"contract_type,omitempty"` + CrossMaxAvailable float64 `json:"cross_max_available,omitempty"` + LeverRate float64 `json:"lever_rate,omitempty"` + MarginAvailable float64 `json:"margin_available,omitempty"` + MarginMode string `json:"margin_mode,omitempty"` + Symbol string `json:"symbol,omitempty"` +} + +type UnifiedAccount struct { + CrossMarginStatic float64 `json:"cross_margin_static,omitempty"` + CrossProfitUnreal float64 `json:"cross_profit_unreal,omitempty"` + CrossRiskRate float64 `json:"cross_risk_rate,omitempty"` + MarginAsset string `json:"margin_asset,omitempty"` + MarginBalance float64 `json:"margin_balance,omitempty"` + MarginFrozen float64 `json:"margin_frozen,omitempty"` + MarginStatic float64 `json:"margin_static,omitempty"` + UserID float64 `json:"userId,omitempty"` + WithdrawAvailable float64 `json:"withdraw_available,omitempty"` + CrossFuture []CrossFuture `json:"cross_future,omitempty"` + CrossSwap []CrossSwap `json:"cross_swap,omitempty"` +} diff --git a/htx/usdm/rest/types/basic.go b/htx/usdm/rest/types/basic.go index c6d2615..64ffee4 100644 --- a/htx/usdm/rest/types/basic.go +++ b/htx/usdm/rest/types/basic.go @@ -17,6 +17,10 @@ package types +import ( + htxutils "github.com/linstohu/nexapi/htx/utils" +) + type GetContractInfoParam struct { ContractCode string `url:"contract_code,omitempty" validate:"omitempty"` SupportMarginMode string `url:"support_margin_mode,omitempty" validate:"omitempty"` @@ -45,3 +49,75 @@ type ContractInfo struct { Pair string `json:"pair,omitempty"` ContractType string `json:"contract_type,omitempty"` } + +type GetFundingRateResp struct { + DefaultResponse + Data []FundingRate `json:"data,omitempty"` +} + +type FundingRate struct { + EstimatedRate string `json:"estimated_rate"` + FundingRate string `json:"funding_rate"` + ContractCode string `json:"contract_code"` + Symbol string `json:"symbol"` + FeeAsset string `json:"fee_asset"` + FundingTime string `json:"funding_time"` + NextFundingTime string `json:"next_funding_time"` +} + +type GetMarketDepthParam struct { + ContractCode string `url:"contract_code,omitempty" validate:"omitempty"` + Type string `url:"type" validate:"required"` +} + +type GetMarketDepthResp struct { + htxutils.V1Response + Ts int64 `json:"ts"` + Tick MarketDepth `json:"tick,omitempty"` +} + +type MarketDepth struct { + Ch string `json:"ch,omitempty"` + Ts int64 `json:"ts,omitempty"` + Version int64 `json:"version,omitempty"` + Bids [][]float64 `json:"bids,omitempty"` + Asks [][]float64 `json:"asks,omitempty"` +} + +type GetMarketTickerParam struct { + ContractCode string `url:"contract_code" validate:"required"` +} + +type GetMarketTickerResp struct { + htxutils.V1Response + Ts int64 `json:"ts"` + Tick MarketTicker `json:"tick,omitempty"` +} + +type GetMarketTickersParam struct { + ContractCode string `url:"contract_code,omitempty" validate:"omitempty"` + BusinessType string `url:"business_type,omitempty" validate:"omitempty"` +} + +type GetMarketTickersResp struct { + htxutils.V1Response + Ts int64 `json:"ts"` + Ticks []MarketTicker `json:"ticks,omitempty"` +} + +type MarketTicker struct { + ID int `json:"id"` + Ts int64 `json:"ts"` + Ask []float64 `json:"ask"` + Bid []float64 `json:"bid"` + BusinessType string `json:"business_type"` + ContractCode string `json:"contract_code"` + Open string `json:"open"` + Close string `json:"close"` + Low string `json:"low"` + High string `json:"high"` + Amount string `json:"amount"` + Count int `json:"count"` + Vol string `json:"vol"` + NumberOf string `json:"number_of"` +} diff --git a/htx/usdm/rest/types/kline.go b/htx/usdm/rest/types/kline.go index be8fa41..48f4fac 100644 --- a/htx/usdm/rest/types/kline.go +++ b/htx/usdm/rest/types/kline.go @@ -17,6 +17,8 @@ package types +import htxutils "github.com/linstohu/nexapi/htx/utils" + type KlineInterval string var ( @@ -29,3 +31,27 @@ var ( Day1 KlineInterval = "1day" Month1 KlineInterval = "1mon" ) + +type GetKlineParam struct { + Symbol string `url:"contract_code" validate:"required"` + Period KlineInterval `url:"period" validate:"required"` + Size int64 `url:"size,omitempty" validate:"omitempty"` +} + +type GetKlineResp struct { + htxutils.V1Response + Ts int64 `json:"ts"` + Data []Kline `json:"data,omitempty"` +} + +type Kline struct { + ID int64 `json:"id"` + Count int `json:"count"` + Amount float64 `json:"amount"` + Close float64 `json:"close"` + High float64 `json:"high"` + Low float64 `json:"low"` + Open float64 `json:"open"` + TradeTurnover float64 `json:"trade_turnover"` + Vol float64 `json:"vol"` +} diff --git a/htx/usdm/rest/types/trading.go b/htx/usdm/rest/types/trading.go new file mode 100644 index 0000000..d5d2450 --- /dev/null +++ b/htx/usdm/rest/types/trading.go @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2023, LinstoHu + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package types + +type PlaceIsolatedOrderParam struct { + ContractCode string `json:"contract_code" validate:"required"` + ReduceOnly int `json:"reduce_only,omitempty" validate:"omitempty"` + ClientOrderID int64 `json:"client_order_id,omitempty" validate:"omitempty"` + Price float64 `json:"price,omitempty" validate:"omitempty"` + Volume int64 `json:"volume" validate:"required"` + Direction string `json:"direction" validate:"required"` + Offset string `json:"offset,omitempty" validate:"omitempty"` + LeverRate int `json:"lever_rate" validate:"required"` + OrderPriceType string `json:"order_price_type" validate:"required"` + TpTriggerPrice float64 `json:"tp_trigger_price,omitempty" validate:"omitempty"` + TpOrderPrice float64 `json:"tp_order_price,omitempty" validate:"omitempty"` + TpOrderPriceType string `json:"tp_order_price_type,omitempty" validate:"omitempty"` + SlTriggerPrice float64 `json:"sl_trigger_price,omitempty" validate:"omitempty"` + SlOrderPrice float64 `json:"sl_order_price,omitempty" validate:"omitempty"` + SlOrderPriceType string `json:"sl_order_price_type,omitempty" validate:"omitempty"` +} + +type PlaceOrderResp struct { + DefaultResponse + Data struct { + OrderID int64 `json:"order_id,omitempty"` + ClientOrderID int64 `json:"client_order_id,omitempty"` + OrderIDStr string `json:"order_id_str,omitempty"` + } `json:"data"` +} + +type PlaceCrossOrderParam struct { + ContractCode string `json:"contract_code" validate:"required"` + Pair string `json:"pair,omitempty" validate:"omitempty"` + ContractType string `json:"contract_type,omitempty" validate:"omitempty"` + ReduceOnly int `json:"reduce_only,omitempty" validate:"omitempty"` + ClientOrderID int64 `json:"client_order_id,omitempty" validate:"omitempty"` + Price float64 `json:"price,omitempty" validate:"omitempty"` + Volume int64 `json:"volume" validate:"required"` + Direction string `json:"direction" validate:"required"` + Offset string `json:"offset,omitempty" validate:"omitempty"` + LeverRate int `json:"lever_rate" validate:"required"` + OrderPriceType string `json:"order_price_type" validate:"required"` + TpTriggerPrice float64 `json:"tp_trigger_price,omitempty" validate:"omitempty"` + TpOrderPrice float64 `json:"tp_order_price,omitempty" validate:"omitempty"` + TpOrderPriceType string `json:"tp_order_price_type,omitempty" validate:"omitempty"` + SlTriggerPrice float64 `json:"sl_trigger_price,omitempty" validate:"omitempty"` + SlOrderPrice float64 `json:"sl_order_price,omitempty" validate:"omitempty"` + SlOrderPriceType string `json:"sl_order_price_type,omitempty" validate:"omitempty"` +} + +type CancelIsolatedOrderParam struct { + OrderID string `json:"order_id,omitempty" validate:"omitempty"` + ClientOrderID string `json:"client_order_id,omitempty" validate:"omitempty"` + ContractCode string `json:"contract_code" validate:"required"` +} + +type CancelOrderResp struct { + DefaultResponse + Data struct { + Errors []struct { + OrderID string `json:"order_id,omitempty"` + ErrCode int `json:"err_code,omitempty"` + ErrMsg string `json:"err_msg,omitempty"` + } `json:"errors,omitempty"` + Successes string `json:"successes,omitempty"` + } `json:"data"` +} + +type CancelCrossOrderParam struct { + OrderID string `json:"order_id,omitempty" validate:"omitempty"` + ClientOrderID string `json:"client_order_id,omitempty" validate:"omitempty"` + ContractCode string `json:"contract_code,omitempty" validate:"omitempty"` + Pair string `json:"pair,omitempty" validate:"omitempty"` + ContractType string `json:"contract_type,omitempty" validate:"omitempty"` +} + +type CancelAllIsolatedOrdersParam struct { + ContractCode string `json:"contract_code" validate:"required"` + Direction string `json:"direction,omitempty" validate:"omitempty"` + Offset string `json:"offset,omitempty" validate:"omitempty"` +} + +type CancelAllCrossOrdersParam struct { + ContractCode string `json:"contract_code,omitempty" validate:"omitempty"` + Pair string `json:"pair,omitempty" validate:"omitempty"` + ContractType string `json:"contract_type,omitempty" validate:"omitempty"` + Direction string `json:"direction,omitempty" validate:"omitempty"` + Offset string `json:"offset,omitempty" validate:"omitempty"` +} + +type GetIsolatedOpenOrdersParam struct { + ContractCode string `json:"contract_code" validate:"required"` + PageIndex int `json:"page_index,omitempty" validate:"omitempty"` + PageSize int `json:"page_size,omitempty" validate:"omitempty"` + SortBy string `json:"sort_by,omitempty" validate:"omitempty"` + TradeType int `json:"trade_type,omitempty" validate:"omitempty"` +} + +type GetIsolatedOpenOrdersResp struct { + DefaultResponse + Data IsolatedOpenOrders `json:"data"` +} + +type IsolatedOrder struct { + Symbol string `json:"symbol,omitempty"` + ContractCode string `json:"contract_code,omitempty"` + Volume float64 `json:"volume,omitempty"` + Price float64 `json:"price,omitempty"` + OrderPriceType string `json:"order_price_type,omitempty"` + OrderType int `json:"order_type,omitempty"` + Direction string `json:"direction,omitempty"` + Offset string `json:"offset,omitempty"` + LeverRate int `json:"lever_rate,omitempty"` + OrderID int64 `json:"order_id,omitempty"` + ClientOrderID int64 `json:"client_order_id,omitempty"` + CreatedAt int64 `json:"created_at,omitempty"` + TradeVolume float64 `json:"trade_volume,omitempty"` + TradeTurnover float64 `json:"trade_turnover,omitempty"` + Fee float64 `json:"fee,omitempty"` + TradeAvgPrice float64 `json:"trade_avg_price,omitempty"` + MarginFrozen float64 `json:"margin_frozen,omitempty"` + Profit float64 `json:"profit,omitempty"` + Status int `json:"status,omitempty"` + OrderSource string `json:"order_source,omitempty"` + OrderIDStr string `json:"order_id_str,omitempty"` + FeeAsset string `json:"fee_asset,omitempty"` + LiquidationType string `json:"liquidation_type,omitempty"` + CanceledAt int64 `json:"canceled_at,omitempty"` + MarginAsset string `json:"margin_asset,omitempty"` + MarginMode string `json:"margin_mode,omitempty"` + MarginAccount string `json:"margin_account,omitempty"` + IsTpsl int `json:"is_tpsl,omitempty"` + UpdateTime int64 `json:"update_time,omitempty"` + RealProfit float64 `json:"real_profit,omitempty"` + ReduceOnly int `json:"reduce_only,omitempty"` +} + +type IsolatedOpenOrders struct { + Orders []IsolatedOrder `json:"orders,omitempty"` + TotalPage int `json:"total_page,omitempty"` + CurrentPage int `json:"current_page,omitempty"` + TotalSize int `json:"total_size,omitempty"` +} + +type GetCrossOpenOrdersParam struct { + ContractCode string `json:"contract_code,omitempty" validate:"omitempty"` + Pair string `json:"pair,omitempty" validate:"omitempty"` + PageIndex int `json:"page_index,omitempty" validate:"omitempty"` + PageSize int `json:"page_size,omitempty" validate:"omitempty"` + SortBy string `json:"sort_by,omitempty" validate:"omitempty"` + TradeType int `json:"trade_type,omitempty" validate:"omitempty"` +} + +type GetCrossOpenOrdersResp struct { + DefaultResponse + Data CrossOpenOrders `json:"data"` +} + +type CrossOpenOrders struct { + Orders []CrossOpenOrder `json:"orders,omitempty"` + TotalPage int `json:"total_page,omitempty"` + CurrentPage int `json:"current_page,omitempty"` + TotalSize int `json:"total_size,omitempty"` +} + +type CrossOpenOrder struct { + UpdateTime int64 `json:"update_time,omitempty"` + BusinessType string `json:"business_type,omitempty"` + ContractType string `json:"contract_type,omitempty"` + Pair string `json:"pair,omitempty"` + Symbol string `json:"symbol,omitempty"` + ContractCode string `json:"contract_code,omitempty"` + Volume float64 `json:"volume,omitempty"` + Price float64 `json:"price,omitempty"` + OrderPriceType string `json:"order_price_type,omitempty"` + OrderType int `json:"order_type,omitempty"` + Direction string `json:"direction,omitempty"` + Offset string `json:"offset,omitempty"` + LeverRate int `json:"lever_rate,omitempty"` + OrderID int64 `json:"order_id,omitempty"` + ClientOrderID int64 `json:"client_order_id,omitempty"` + CreatedAt int64 `json:"created_at,omitempty"` + TradeVolume float64 `json:"trade_volume,omitempty"` + TradeTurnover float64 `json:"trade_turnover,omitempty"` + Fee float64 `json:"fee,omitempty"` + TradeAvgPrice float64 `json:"trade_avg_price,omitempty"` + MarginFrozen float64 `json:"margin_frozen,omitempty"` + Profit float64 `json:"profit,omitempty"` + Status int `json:"status,omitempty"` + OrderSource string `json:"order_source,omitempty"` + OrderIDStr string `json:"order_id_str,omitempty"` + FeeAsset string `json:"fee_asset,omitempty"` + LiquidationType string `json:"liquidation_type,omitempty"` + CanceledAt int64 `json:"canceled_at,omitempty"` + MarginAsset string `json:"margin_asset,omitempty"` + MarginAccount string `json:"margin_account,omitempty"` + MarginMode string `json:"margin_mode,omitempty"` + IsTpsl int `json:"is_tpsl,omitempty"` + RealProfit string `json:"real_profit,omitempty"` + ReduceOnly int `json:"reduce_only,omitempty"` +} + +type GetIsolatedHistoryMatchResultsParam struct { + Contract string `json:"contract,omitempty" validate:"omitempty"` + Pair string `json:"pair,omitempty" validate:"omitempty"` + TradeType int `json:"trade_type" validate:"required"` + StartTime int64 `json:"start_time,omitempty"` + EndTime int64 `json:"end_time,omitempty"` + Direct string `json:"direct,omitempty" validate:"omitempty"` + FromID int64 `json:"from_id,omitempty"` +} + +type GetCrossHistoryMatchResultsParam struct { + Contract string `json:"contract" validate:"required"` + Pair string `json:"pair,omitempty" validate:"omitempty"` + TradeType int `json:"trade_type" validate:"required"` + StartTime int64 `json:"start_time,omitempty"` + EndTime int64 `json:"end_time,omitempty"` + Direct string `json:"direct,omitempty" validate:"omitempty"` + FromID int64 `json:"from_id,omitempty"` +} + +type HistoryMatchResultsResp struct { + DefaultResponse + Data []HistoryMatchResult `json:"data"` +} + +type HistoryMatchResult struct { + ID string `json:"id,omitempty"` + QueryID int64 `json:"query_id,omitempty"` + MatchID int64 `json:"match_id,omitempty"` + OrderID int64 `json:"order_id,omitempty"` + OrderIDStr string `json:"order_id_str,omitempty"` + Symbol string `json:"symbol,omitempty"` + ContractCode string `json:"contract_code,omitempty"` + MarginMode string `json:"margin_mode,omitempty"` + MarginAccount string `json:"margin_account,omitempty"` + Direction string `json:"direction,omitempty"` + Offset string `json:"offset,omitempty"` + TradeVolume float64 `json:"trade_volume,omitempty"` + TradePrice float64 `json:"trade_price,omitempty"` + TradeTurnover float64 `json:"trade_turnover,omitempty"` + CreateDate int64 `json:"create_date,omitempty"` + OffsetProfitloss float64 `json:"offset_profitloss,omitempty"` + RealProfit float64 `json:"real_profit,omitempty"` + TradeFee float64 `json:"trade_fee,omitempty"` + Role string `json:"role,omitempty"` + FeeAsset string `json:"fee_asset,omitempty"` + OrderSource string `json:"order_source,omitempty"` + ContractType string `json:"contract_type,omitempty"` + Pair string `json:"pair,omitempty"` + BusinessType string `json:"business_type,omitempty"` + ReduceOnly int `json:"reduce_only,omitempty"` +}