From 19fd19ce867992faeba7189b48b0cd9546ca6c37 Mon Sep 17 00:00:00 2001 From: linstohu Date: Thu, 21 Dec 2023 01:07:40 +0800 Subject: [PATCH] feat: htx usdm apis --- htx/spot/rest/account.go | 135 +++++++++++++++++++++++++++++++++ htx/spot/rest/client.go | 118 +--------------------------- htx/spot/rest/client_test.go | 2 +- htx/spot/rest/types/account.go | 1 + htx/usdm/rest/account.go | 83 ++++++++++++++++++++ htx/usdm/rest/basic.go | 56 ++++++++++++++ htx/usdm/rest/client.go | 50 ++++++++++++ htx/usdm/rest/client_test.go | 61 +++++++++++++++ htx/usdm/rest/types/account.go | 32 ++++++++ htx/usdm/rest/types/basic.go | 47 ++++++++++++ htx/usdm/rest/types/types.go | 23 ++++++ htx/utils/vars.go | 7 +- 12 files changed, 497 insertions(+), 118 deletions(-) create mode 100644 htx/spot/rest/account.go create mode 100644 htx/usdm/rest/account.go create mode 100644 htx/usdm/rest/basic.go create mode 100644 htx/usdm/rest/client_test.go create mode 100644 htx/usdm/rest/types/account.go create mode 100644 htx/usdm/rest/types/basic.go create mode 100644 htx/usdm/rest/types/types.go diff --git a/htx/spot/rest/account.go b/htx/spot/rest/account.go new file mode 100644 index 0000000..c8deb68 --- /dev/null +++ b/htx/spot/rest/account.go @@ -0,0 +1,135 @@ +/* + * 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) 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", + Method: http.MethodGet, + } + + { + 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.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, query) + if err != nil { + return nil, err + } + + h := scli.cli.Sign([]byte(signStr)) + if err != nil { + return nil, err + } + + query.DefaultAuthParam.Signature = h + + req.Query = query + } + + resp, err := scli.cli.SendHTTPRequest(ctx, req) + if err != nil { + return nil, err + } + + var ret types.GetAccountValuationResp + if err := resp.ReadJsonBody(&ret); err != nil { + return nil, errors.New(resp.Error()) + } + + return &ret, nil +} diff --git a/htx/spot/rest/client.go b/htx/spot/rest/client.go index bc729fb..a57c21f 100644 --- a/htx/spot/rest/client.go +++ b/htx/spot/rest/client.go @@ -18,13 +18,9 @@ package rest import ( - "context" - "errors" "log/slog" - "net/http" "github.com/go-playground/validator" - "github.com/linstohu/nexapi/htx/spot/rest/types" "github.com/linstohu/nexapi/htx/utils" ) @@ -40,9 +36,9 @@ type SpotClientCfg struct { // Logger Logger *slog.Logger - BaseURL string `validate:"required"` - Key string - Secret string + BaseURL string `validate:"required"` + Key string + Secret string } func NewSpotClient(cfg *SpotClientCfg) (*SpotClient, error) { @@ -70,111 +66,3 @@ func NewSpotClient(cfg *SpotClientCfg) (*SpotClient, error) { validate: validator, }, nil } - -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", - Method: http.MethodGet, - } - - { - 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.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, query) - if err != nil { - return nil, err - } - - h := scli.cli.Sign([]byte(signStr)) - if err != nil { - return nil, err - } - - query.DefaultAuthParam.Signature = h - - req.Query = query - } - - resp, err := scli.cli.SendHTTPRequest(ctx, req) - if err != nil { - return nil, err - } - - var ret types.GetAccountValuationResp - 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 7fa64cd..db07815 100644 --- a/htx/spot/rest/client_test.go +++ b/htx/spot/rest/client_test.go @@ -29,7 +29,7 @@ import ( func testNewSpotClient(t *testing.T) *SpotClient { cli, err := NewSpotClient(&SpotClientCfg{ - BaseURL: utils.ProdAWSBaseURL, + BaseURL: utils.SpotAWSBaseURL, Key: os.Getenv("HTX_KEY"), Secret: os.Getenv("HTX_SECRET"), Debug: true, diff --git a/htx/spot/rest/types/account.go b/htx/spot/rest/types/account.go index a155830..ee02040 100644 --- a/htx/spot/rest/types/account.go +++ b/htx/spot/rest/types/account.go @@ -25,6 +25,7 @@ type GetAccountInfoResponse struct { Status string `json:"status"` Data []AccountInfo `json:"data"` } + type AccountInfo struct { Id int64 `json:"id"` Type string `json:"type"` diff --git a/htx/usdm/rest/account.go b/htx/usdm/rest/account.go new file mode 100644 index 0000000..3af4e9e --- /dev/null +++ b/htx/usdm/rest/account.go @@ -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/usdm/rest/types" + "github.com/linstohu/nexapi/htx/utils" +) + +func (ucli *UsdmClient) GetAssetValuation(ctx context.Context, param types.GetAssetValuationParam) (*types.GetAssetValuationResp, 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_balance_valuation", + 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.GetAssetValuationResp + 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 new file mode 100644 index 0000000..8fdaca0 --- /dev/null +++ b/htx/usdm/rest/basic.go @@ -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/usdm/rest/types" + "github.com/linstohu/nexapi/htx/utils" +) + +func (ucli *UsdmClient) GetContractInfo(ctx context.Context, param types.GetContractInfoParam) (*types.GetContractInfoResp, error) { + req := utils.HTTPRequest{ + BaseURL: ucli.cli.GetBaseURL(), + Path: "/linear-swap-api/v1/swap_contract_info", + 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.GetContractInfoResp + if err := resp.ReadJsonBody(&ret); err != nil { + return nil, errors.New(resp.Error()) + } + + return &ret, nil +} diff --git a/htx/usdm/rest/client.go b/htx/usdm/rest/client.go index 3c71972..abc3985 100644 --- a/htx/usdm/rest/client.go +++ b/htx/usdm/rest/client.go @@ -16,3 +16,53 @@ */ package rest + +import ( + "log/slog" + + "github.com/go-playground/validator" + "github.com/linstohu/nexapi/htx/utils" +) + +type UsdmClient struct { + cli *utils.HTXClient + + // validate struct fields + validate *validator.Validate +} + +type UsdmClientCfg struct { + Debug bool + // Logger + Logger *slog.Logger + + BaseURL string `validate:"required"` + Key string + Secret string +} + +func NewUsdmClient(cfg *UsdmClientCfg) (*UsdmClient, error) { + validator := validator.New() + + err := validator.Struct(cfg) + if err != nil { + return nil, err + } + + cli, err := utils.NewHTXRestClient(&utils.HTXClientCfg{ + Debug: cfg.Debug, + Logger: cfg.Logger, + BaseURL: cfg.BaseURL, + Key: cfg.Key, + Secret: cfg.Secret, + SignVersion: utils.ApiKeyVersionV2, + }) + if err != nil { + return nil, err + } + + return &UsdmClient{ + cli: cli, + validate: validator, + }, nil +} diff --git a/htx/usdm/rest/client_test.go b/htx/usdm/rest/client_test.go new file mode 100644 index 0000000..1a0d6e2 --- /dev/null +++ b/htx/usdm/rest/client_test.go @@ -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" + "os" + "testing" + + "github.com/linstohu/nexapi/htx/usdm/rest/types" + "github.com/linstohu/nexapi/htx/utils" + "github.com/stretchr/testify/assert" +) + +func testNewUsdmClient(t *testing.T) *UsdmClient { + cli, err := NewUsdmClient(&UsdmClientCfg{ + BaseURL: utils.UsdmBaseURL, + Key: os.Getenv("HTX_KEY"), + Secret: os.Getenv("HTX_SECRET"), + Debug: true, + }) + + if err != nil { + t.Fatalf("Could not create htx client, %s", err) + } + + return cli +} + +func TestGetContractInfo(t *testing.T) { + cli := testNewUsdmClient(t) + + _, err := cli.GetContractInfo(context.TODO(), types.GetContractInfoParam{}) + + assert.Nil(t, err) +} + +func TestGetAssetValuation(t *testing.T) { + cli := testNewUsdmClient(t) + + _, err := cli.GetAssetValuation(context.TODO(), types.GetAssetValuationParam{ + ValuationAsset: "USDT", + }) + + assert.Nil(t, err) +} diff --git a/htx/usdm/rest/types/account.go b/htx/usdm/rest/types/account.go new file mode 100644 index 0000000..6ceec60 --- /dev/null +++ b/htx/usdm/rest/types/account.go @@ -0,0 +1,32 @@ +/* + * 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 GetAssetValuationParam struct { + ValuationAsset string `json:"valuation_asset,omitempty" validate:"omitempty"` +} + +type GetAssetValuationResp struct { + DefaultResponse + Data []AssetValuation `json:"data"` +} + +type AssetValuation struct { + ValuationAsset string `json:"valuation_asset"` + Balance string `json:"balance"` +} diff --git a/htx/usdm/rest/types/basic.go b/htx/usdm/rest/types/basic.go new file mode 100644 index 0000000..c6d2615 --- /dev/null +++ b/htx/usdm/rest/types/basic.go @@ -0,0 +1,47 @@ +/* + * 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 GetContractInfoParam struct { + ContractCode string `url:"contract_code,omitempty" validate:"omitempty"` + SupportMarginMode string `url:"support_margin_mode,omitempty" validate:"omitempty"` + Pair string `url:"pair,omitempty" validate:"omitempty"` + ContractType string `url:"contract_type,omitempty" validate:"omitempty"` + BusinessType string `url:"business_type,omitempty" validate:"omitempty"` +} + +type GetContractInfoResp struct { + DefaultResponse + Data []ContractInfo `json:"data"` +} + +type ContractInfo struct { + Symbol string `json:"symbol,omitempty"` + ContractCode string `json:"contract_code,omitempty"` + ContractSize float64 `json:"contract_size,omitempty"` + PriceTick float64 `json:"price_tick,omitempty"` + DeliveryDate string `json:"delivery_date,omitempty"` + DeliveryTime string `json:"delivery_time,omitempty"` + CreateDate string `json:"create_date,omitempty"` + ContractStatus int `json:"contract_status,omitempty"` + SettlementDate string `json:"settlement_date,omitempty"` + SupportMarginMode string `json:"support_margin_mode,omitempty"` + BusinessType string `json:"business_type,omitempty"` + Pair string `json:"pair,omitempty"` + ContractType string `json:"contract_type,omitempty"` +} diff --git a/htx/usdm/rest/types/types.go b/htx/usdm/rest/types/types.go new file mode 100644 index 0000000..488496e --- /dev/null +++ b/htx/usdm/rest/types/types.go @@ -0,0 +1,23 @@ +/* + * 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 DefaultResponse struct { + Status string `json:"status"` + Ts int64 `json:"ts"` +} diff --git a/htx/utils/vars.go b/htx/utils/vars.go index 122020a..793c43f 100644 --- a/htx/utils/vars.go +++ b/htx/utils/vars.go @@ -18,8 +18,11 @@ package utils var ( - ProdBaseURL = "https://api.huobi.pro" - ProdAWSBaseURL = "https://api-aws.huobi.pro" + SpotBaseURL = "https://api.huobi.pro" + SpotAWSBaseURL = "https://api-aws.huobi.pro" + + UsdmBaseURL = "https://api.hbdm.com" + UsdmAWSBaseURL = "https://api.hbdm.vn" ) var NIL = ""