From 0de84407d13f40cf463625aebb505c7f5d8b00d2 Mon Sep 17 00:00:00 2001 From: thanhpp Date: Tue, 9 Apr 2024 16:09:53 +0700 Subject: [PATCH] =?UTF-8?q?feat:=20=E2=9C=A8=20saving:=20GetFlexibleProduc?= =?UTF-8?q?tPosition=20and=20GetLockedProductPosition?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: thanhpp --- v2/client.go | 8 ++ v2/savings_service.go | 165 +++++++++++++++++++++++++++++++++++++ v2/savings_service_test.go | 147 +++++++++++++++++++++++++++++++++ 3 files changed, 320 insertions(+) diff --git a/v2/client.go b/v2/client.go index 384cd46e..84022387 100644 --- a/v2/client.go +++ b/v2/client.go @@ -569,6 +569,14 @@ func (c *Client) NewSavingFixedProjectPositionsService() *SavingFixedProjectPosi return &SavingFixedProjectPositionsService{c: c} } +func (c *Client) NewGetFlexibleProductPosition() *GetFlexibleProductPositionService { + return &GetFlexibleProductPositionService{c: c} +} + +func (c *Client) NewGetLockedProductPosition() *GetLockedProductPositionService { + return &GetLockedProductPositionService{c: c} +} + // NewListSavingsFlexibleProductsService get flexible products list (Savings) func (c *Client) NewListSavingsFlexibleProductsService() *ListSavingsFlexibleProductsService { return &ListSavingsFlexibleProductsService{c: c} diff --git a/v2/savings_service.go b/v2/savings_service.go index 3dbe0126..1849306a 100644 --- a/v2/savings_service.go +++ b/v2/savings_service.go @@ -423,3 +423,168 @@ type SavingFixedProjectPosition struct { Status string `json:"status"` ProjectType string `json:"type"` } + +// GetFlexibleProductPositionService: https://binance-docs.github.io/apidocs/spot/en/#get-flexible-product-position-user_data +type GetFlexibleProductPositionService struct { + c *Client + productId string + current int64 + size int64 +} + +func (s *GetFlexibleProductPositionService) ProductId(productId string) *GetFlexibleProductPositionService { + s.productId = productId + return s +} + +// Currently querying the page. Start from 1. Default:1 +func (s *GetFlexibleProductPositionService) Current(current int64) *GetFlexibleProductPositionService { + s.current = current + return s +} + +// Default:10, Max:100 +func (s *GetFlexibleProductPositionService) Size(size int64) *GetFlexibleProductPositionService { + s.size = size + return s +} + +func (s *GetFlexibleProductPositionService) Do(ctx context.Context, opts ...RequestOption) (GetFlexibleProductPositionResponse, error) { + r := &request{ + method: http.MethodGet, + endpoint: "/sapi/v1/simple-earn/flexible/position", + secType: secTypeSigned, + } + m := params{} + if s.productId != "" { + m["productId"] = s.productId + } + if s.current != 0 { + m["current"] = s.current + } + if s.size != 0 { + m["size"] = s.size + } + r.setParams(m) + data, err := s.c.callAPI(ctx, r, opts...) + if err != nil { + return GetFlexibleProductPositionResponse{}, err + } + var res GetFlexibleProductPositionResponse + if err = json.Unmarshal(data, &res); err != nil { + return GetFlexibleProductPositionResponse{}, err + } + return res, nil +} + +type GetFlexibleProductPositionResponse struct { + Rows []FlexibleProductPosition `json:"rows,omitempty"` + Total int `json:"total,omitempty"` +} + +type FlexibleProductPosition struct { + TotalAmount string `json:"totalAmount,omitempty"` + TierAnnualPercentageRate map[string]float64 `json:"tierAnnualPercentageRate,omitempty"` + LatestAnnualPercentageRate string `json:"latestAnnualPercentageRate,omitempty"` + YesterdayAirdropPercentageRate string `json:"yesterdayAirdropPercentageRate,omitempty"` + Asset string `json:"asset,omitempty"` + AirDropAsset string `json:"airDropAsset,omitempty"` + CanRedeem bool `json:"canRedeem,omitempty"` + CollateralAmount string `json:"collateralAmount,omitempty"` + ProductID string `json:"productId,omitempty"` + YesterdayRealTimeRewards string `json:"yesterdayRealTimeRewards,omitempty"` + CumulativeBonusRewards string `json:"cumulativeBonusRewards,omitempty"` + CumulativeRealTimeRewards string `json:"cumulativeRealTimeRewards,omitempty"` + CumulativeTotalRewards string `json:"cumulativeTotalRewards,omitempty"` + AutoSubscribe bool `json:"autoSubscribe,omitempty"` +} + +// https://binance-docs.github.io/apidocs/spot/en/#get-locked-product-position-user_data +type GetLockedProductPositionService struct { + c *Client + asset string + positionId string + productId string + current int64 + size int64 +} + +func (s *GetLockedProductPositionService) Asset(asset string) *GetLockedProductPositionService { + s.asset = asset + return s +} + +func (s *GetLockedProductPositionService) PositionID(positionId string) *GetLockedProductPositionService { + s.positionId = positionId + return s +} + +func (s *GetLockedProductPositionService) ProductId(productId string) *GetLockedProductPositionService { + s.productId = productId + return s +} + +// Currently querying the page. Start from 1. Default:1 +func (s *GetLockedProductPositionService) Current(current int64) *GetLockedProductPositionService { + s.current = current + return s +} + +// Default:10, Max:100 +func (s *GetLockedProductPositionService) Size(size int64) *GetLockedProductPositionService { + s.size = size + return s +} + +func (s *GetLockedProductPositionService) Do(ctx context.Context, opts ...RequestOption) (GetLockedProductPositionResponse, error) { + r := &request{ + method: http.MethodGet, + endpoint: "/sapi/v1/simple-earn/locked/position", + secType: secTypeSigned, + } + m := params{} + if s.asset != "" { + m["asset"] = s.asset + } + if s.positionId != "" { + m["positionId"] = s.positionId + } + if s.productId != "" { + m["productId"] = s.productId + } + if s.current != 0 { + m["current"] = s.current + } + if s.size != 0 { + m["size"] = s.size + } + r.setParams(m) + data, err := s.c.callAPI(ctx, r, opts...) + if err != nil { + return GetLockedProductPositionResponse{}, err + } + var res GetLockedProductPositionResponse + if err = json.Unmarshal(data, &res); err != nil { + return GetLockedProductPositionResponse{}, err + } + return res, nil +} + +type GetLockedProductPositionResponse struct { + Rows []LockedProductPosition `json:"rows,omitempty"` + Total int `json:"total,omitempty"` +} +type LockedProductPosition struct { + PositionID string `json:"positionId,omitempty"` + ProjectID string `json:"projectId,omitempty"` + Asset string `json:"asset,omitempty"` + Amount string `json:"amount,omitempty"` + PurchaseTime string `json:"purchaseTime,omitempty"` + Duration string `json:"duration,omitempty"` + AccrualDays string `json:"accrualDays,omitempty"` + RewardAsset string `json:"rewardAsset,omitempty"` + Apy string `json:"APY,omitempty"` + IsRenewable bool `json:"isRenewable,omitempty"` + IsAutoRenew bool `json:"isAutoRenew,omitempty"` + RedeemDate string `json:"redeemDate,omitempty"` +} diff --git a/v2/savings_service_test.go b/v2/savings_service_test.go index 669c390c..22e1eb95 100644 --- a/v2/savings_service_test.go +++ b/v2/savings_service_test.go @@ -396,3 +396,150 @@ func (s *savingsServiceTestSuite) assertSavingFixedProjectPositionsService(e, a r.Equal(e.Status, a.Status, "Status") r.Equal(e.ProjectType, a.ProjectType, "ProjectType") } + +func (s *savingsServiceTestSuite) TestGetFlexibleProductPositionService() { + data := []byte(`{ + "rows":[ + { + "totalAmount": "75.46000000", + "tierAnnualPercentageRate": { + "0-5BTC": 0.05, + "5-10BTC": 0.03 + }, + "latestAnnualPercentageRate": "0.02599895", + "yesterdayAirdropPercentageRate": "0.02599895", + "asset": "USDT", + "airDropAsset": "BETH", + "canRedeem": true, + "collateralAmount": "232.23123213", + "productId": "USDT001", + "yesterdayRealTimeRewards": "0.10293829", + "cumulativeBonusRewards": "0.22759183", + "cumulativeRealTimeRewards": "0.22759183", + "cumulativeTotalRewards": "0.45459183", + "autoSubscribe": true + } + ], + "total": 1 + }`) + + s.mockDo(data, nil) + defer s.assertDo() + s.assertReq(func(r *request) { + e := newSignedRequest().setParams(params{}) + s.assertRequestEqual(e, r) + }) + + positionsList, err := s.client.NewGetFlexibleProductPosition(). + Do(newContext()) + r := s.r() + r.NoError(err) + + r.Len(positionsList.Rows, 1) + s.assertFlexibleProductPosition(&FlexibleProductPosition{ + TotalAmount: "75.46000000", + TierAnnualPercentageRate: map[string]float64{ + "0-5BTC": 0.05, + "5-10BTC": 0.03, + }, + LatestAnnualPercentageRate: "0.02599895", + YesterdayAirdropPercentageRate: "0.02599895", + Asset: "USDT", + AirDropAsset: "BETH", + CanRedeem: true, + CollateralAmount: "232.23123213", + ProductID: "USDT001", + YesterdayRealTimeRewards: "0.10293829", + CumulativeBonusRewards: "0.22759183", + CumulativeRealTimeRewards: "0.22759183", + CumulativeTotalRewards: "0.45459183", + AutoSubscribe: true, + }, &positionsList.Rows[0]) +} + +func (s *savingsServiceTestSuite) assertFlexibleProductPosition(e, a *FlexibleProductPosition) { + r := s.r() + r.Equal(e.TotalAmount, a.TotalAmount, "TotalAmount") + r.Equal(e.TierAnnualPercentageRate, a.TierAnnualPercentageRate, "TierAnnualPercentageRate") + r.Equal(e.LatestAnnualPercentageRate, a.LatestAnnualPercentageRate, "LatestAnnualPercentageRate") + r.Equal(e.YesterdayAirdropPercentageRate, a.YesterdayAirdropPercentageRate, "YesterdayAirdropPercentageRate") + r.Equal(e.Asset, a.Asset, "Asset") + r.Equal(e.AirDropAsset, a.AirDropAsset, "AirDropAsset") + r.Equal(e.CanRedeem, a.CanRedeem, "CanRedeem") + r.Equal(e.CollateralAmount, a.CollateralAmount, "CollateralAmount") + r.Equal(e.ProductID, a.ProductID, "ProductID") + r.Equal(e.YesterdayRealTimeRewards, a.YesterdayRealTimeRewards, "YesterdayRealTimeRewards") + r.Equal(e.CumulativeBonusRewards, a.CumulativeBonusRewards, "CumulativeBonusRewards") + r.Equal(e.CumulativeRealTimeRewards, a.CumulativeRealTimeRewards, "CumulativeRealTimeRewards") + r.Equal(e.CumulativeTotalRewards, a.CumulativeTotalRewards, "CumulativeTotalRewards") + r.Equal(e.AutoSubscribe, a.AutoSubscribe, "AutoSubscribe") +} + +func (s *savingsServiceTestSuite) TestGetLockedProductPositionService() { + data := []byte(`{ + "rows":[ + { + "positionId": "123123", + "projectId": "Axs*90", + "asset": "AXS", + "amount": "122.09202928", + "purchaseTime": "1646182276000", + "duration": "60", + "accrualDays": "4", + "rewardAsset": "AXS", + "APY": "0.23", + "isRenewable": true, + "isAutoRenew": true, + "redeemDate": "1732182276000" + } + ], + "total": 1 + }`) + + s.mockDo(data, nil) + defer s.assertDo() + s.assertReq(func(r *request) { + e := newSignedRequest().setParams(params{ + "asset": "AXS", + }) + s.assertRequestEqual(e, r) + }) + + positionsList, err := s.client.NewGetLockedProductPosition(). + Asset("AXS"). + Do(newContext()) + r := s.r() + r.NoError(err) + + r.Len(positionsList.Rows, 1) + s.assertLockedProductPosition(&LockedProductPosition{ + PositionID: "123123", + ProjectID: "Axs*90", + Asset: "AXS", + Amount: "122.09202928", + PurchaseTime: "1646182276000", + Duration: "60", + AccrualDays: "4", + RewardAsset: "AXS", + Apy: "0.23", + IsRenewable: true, + IsAutoRenew: true, + RedeemDate: "1732182276000", + }, &positionsList.Rows[0]) +} + +func (s *savingsServiceTestSuite) assertLockedProductPosition(e, a *LockedProductPosition) { + r := s.r() + r.Equal(e.PositionID, a.PositionID, "PositionID") + r.Equal(e.ProjectID, a.ProjectID, "ProjectID") + r.Equal(e.Asset, a.Asset, "Asset") + r.Equal(e.Amount, a.Amount, "Amount") + r.Equal(e.PurchaseTime, a.PurchaseTime, "PurchaseTime") + r.Equal(e.Duration, a.Duration, "Duration") + r.Equal(e.AccrualDays, a.AccrualDays, "AccrualDays") + r.Equal(e.RewardAsset, a.RewardAsset, "RewardAsset") + r.Equal(e.Apy, a.Apy, "Apy") + r.Equal(e.IsRenewable, a.IsRenewable, "IsRenewable") + r.Equal(e.IsAutoRenew, a.IsAutoRenew, "IsAutoRenew") + r.Equal(e.RedeemDate, a.RedeemDate, "RedeemDate") +}