Skip to content

Commit

Permalink
feat: htx spot apis
Browse files Browse the repository at this point in the history
  • Loading branch information
linstohu committed Dec 20, 2023
1 parent 88cb5d3 commit ca6e25d
Show file tree
Hide file tree
Showing 14 changed files with 570 additions and 44 deletions.
56 changes: 56 additions & 0 deletions htx/spot/rest/basic.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* 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/spot/rest/types"
"github.com/linstohu/nexapi/htx/utils"
)

func (scli *SpotClient) GetSymbols(ctx context.Context, param types.GetSymbolsParam) (*types.GetSymbolsResp, error) {
req := utils.HTTPRequest{
BaseURL: scli.cli.GetBaseURL(),
Path: "/v2/settings/common/symbols",
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.GetSymbolsResp
if err := resp.ReadJsonBody(&ret); err != nil {
return nil, errors.New(resp.Error())
}

return &ret, nil
}
78 changes: 69 additions & 9 deletions htx/spot/rest/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ type SpotClientCfg struct {
Logger *slog.Logger

BaseURL string `validate:"required"`
Key string `validate:"required"`
Secret string `validate:"required"`
SignVersion string `validate:"required"`
Key string
Secret string
SignVersion string
}

func NewSpotClient(cfg *SpotClientCfg) (*SpotClient, error) {
Expand All @@ -60,7 +60,7 @@ func NewSpotClient(cfg *SpotClientCfg) (*SpotClient, error) {
BaseURL: cfg.BaseURL,
Key: cfg.Key,
Secret: cfg.Secret,
SignVersion: cfg.SignVersion,
SignVersion: utils.ApiKeyVersionV2,
})
if err != nil {
return nil, err
Expand All @@ -73,6 +73,10 @@ func NewSpotClient(cfg *SpotClientCfg) (*SpotClient, error) {
}

func (scli *SpotClient) GetAccountInfo(ctx context.Context) (*types.GetAccountInfoResponse, error) {
if err := scli.cli.CheckAuth(); err != nil {
return nil, err
}

req := utils.HTTPRequest{
BaseURL: scli.cli.GetBaseURL(),
Path: "/v1/account/accounts",
Expand All @@ -88,12 +92,67 @@ func (scli *SpotClient) GetAccountInfo(ctx context.Context) (*types.GetAccountIn
}

{
values, err := scli.cli.GenSignatureValues(req)
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.GetAccountInfoResponse
if err := resp.ReadJsonBody(&ret); err != nil {
return nil, errors.New(resp.Error())
}

return &ret, nil
}

func (scli *SpotClient) GetAccountValuation(ctx context.Context, param types.GetAccountValuationParam) (*types.GetAccountValuationResp, 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: "/v2/account/valuation",
Method: http.MethodGet,
}

{
headers, err := scli.cli.GetHeaders()
if err != nil {
return nil, err
}
req.Headers = headers
}

{
query := types.GetAccountValuationParams{
GetAccountValuationParam: param,
DefaultAuthParam: scli.cli.GenAuthParams(),
}

signStr, err := scli.cli.NormalizeRequestContent(req, values)
signStr, err := scli.cli.NormalizeRequestContent(req, query)
if err != nil {
return nil, err
}
Expand All @@ -103,16 +162,17 @@ func (scli *SpotClient) GetAccountInfo(ctx context.Context) (*types.GetAccountIn
return nil, err
}

values.Add("Signature", h)
req.Query = values
query.DefaultAuthParam.Signature = h

req.Query = query
}

resp, err := scli.cli.SendHTTPRequest(ctx, req)
if err != nil {
return nil, err
}

var ret types.GetAccountInfoResponse
var ret types.GetAccountValuationResp
if err := resp.ReadJsonBody(&ret); err != nil {
return nil, errors.New(resp.Error())
}
Expand Down
43 changes: 43 additions & 0 deletions htx/spot/rest/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"os"
"testing"

"github.com/linstohu/nexapi/htx/spot/rest/types"
"github.com/linstohu/nexapi/htx/utils"
"github.com/stretchr/testify/assert"
)
Expand All @@ -42,10 +43,52 @@ func testNewSpotClient(t *testing.T) *SpotClient {
return cli
}

func TestGetSymbols(t *testing.T) {
cli := testNewSpotClient(t)

_, err := cli.GetSymbols(context.TODO(), types.GetSymbolsParam{})

assert.Nil(t, err)
}

func TestGetMergedMarketTicker(t *testing.T) {
cli := testNewSpotClient(t)

_, err := cli.GetMergedMarketTicker(context.TODO(), types.GetMergedMarketTickerParam{
Symbol: "btcusdt",
})

assert.Nil(t, err)
}

func TestGetAccountInfo(t *testing.T) {
cli := testNewSpotClient(t)

_, err := cli.GetAccountInfo(context.TODO())

assert.Nil(t, err)
}

func TestGetAccountValuation(t *testing.T) {
cli := testNewSpotClient(t)

_, err := cli.GetAccountValuation(context.TODO(),
types.GetAccountValuationParam{},
)

assert.Nil(t, err)
}

func TestNewOrder(t *testing.T) {
cli := testNewSpotClient(t)

_, err := cli.NewOrder(context.TODO(), types.NewOrderParam{
AccountID: "",
Symbol: "usdcusdt",
Type: "buy-limit",
Amount: "12",
Price: "0.9",
})

assert.Nil(t, err)
}
61 changes: 61 additions & 0 deletions htx/spot/rest/market.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* 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/spot/rest/types"
"github.com/linstohu/nexapi/htx/utils"
)

func (scli *SpotClient) GetMergedMarketTicker(ctx context.Context, param types.GetMergedMarketTickerParam) (*types.GetMergedMarketTickerResp, error) {
err := scli.validate.Struct(param)
if err != nil {
return nil, err
}

req := utils.HTTPRequest{
BaseURL: scli.cli.GetBaseURL(),
Path: "/market/detail/merged",
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.GetMergedMarketTickerResp
if err := resp.ReadJsonBody(&ret); err != nil {
return nil, errors.New(resp.Error())
}

return &ret, nil
}
83 changes: 83 additions & 0 deletions htx/spot/rest/trading.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* 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/spot/rest/types"
"github.com/linstohu/nexapi/htx/utils"
)

func (scli *SpotClient) NewOrder(ctx context.Context, param types.NewOrderParam) (*types.NewOrderResp, 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/place",
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.NewOrderResp
if err := resp.ReadJsonBody(&ret); err != nil {
return nil, errors.New(resp.Error())
}

return &ret, nil
}
Loading

0 comments on commit ca6e25d

Please sign in to comment.