From e41c66fb9a2f863bd0e02e4d020e2565259e940e Mon Sep 17 00:00:00 2001 From: alplabin <122352306+alplabin@users.noreply.github.com> Date: Wed, 20 Nov 2024 15:43:42 +0900 Subject: [PATCH] Release v0.8.0 --- CHANGELOG.md | 39 + account.go | 58 +- account_test.go | 60 +- client.go | 56 +- .../MarginAccountAdjustCrossMaxLeverage.go | 29 + .../MarginAccountNewOTO.go | 31 + .../MarginAccountNewOTOCO.go | 31 + .../MarginIsolatedCapitalFlow.go | 28 + .../MarginManualLiquidation.go | 29 + .../QueryLiabilityCoinLeverageBracket.go | 28 + .../QueryMarginAvailableInventory.go | 29 + examples/market/TickerPrice/TickerPrice.go | 3 +- .../AccountInfo.go} | 11 +- .../DepositAddressList.go} | 12 +- .../GetSymbolsDelistSchedule.go | 28 + .../UserDelegationHistory.go | 29 + margin.go | 1184 +++++++++++++++-- margin_test.go | 427 +++++- market.go | 63 +- subaccount.go | 16 +- subaccount_test.go | 56 +- wallet.go | 403 ++++-- wallet_test.go | 334 +++-- websocket_api.go | 2 +- websocket_api_account.go | 2 +- 25 files changed, 2503 insertions(+), 485 deletions(-) create mode 100644 examples/margin/MarginAccountAdjustCrossMaxLeverage/MarginAccountAdjustCrossMaxLeverage.go create mode 100644 examples/margin/MarginAccountNewOTO/MarginAccountNewOTO.go create mode 100644 examples/margin/MarginAccountNewOTOCO/MarginAccountNewOTOCO.go create mode 100644 examples/margin/MarginIsolatedCapitalFlow/MarginIsolatedCapitalFlow.go create mode 100644 examples/margin/MarginManualLiquidation/MarginManualLiquidation.go create mode 100644 examples/margin/QueryLiabilityCoinLeverageBracket/QueryLiabilityCoinLeverageBracket.go create mode 100644 examples/margin/QueryMarginAvailableInventory/QueryMarginAvailableInventory.go rename examples/wallet/{AutoConvertStableCoin/AutoConvertStableCoin.go => AccountInfo/AccountInfo.go} (53%) rename examples/wallet/{BUSDConvert/BUSDConvert.go => DepositAddressList/DepositAddressList.go} (52%) create mode 100644 examples/wallet/GetSymbolsDelistSchedule/GetSymbolsDelistSchedule.go create mode 100644 examples/wallet/UserDelegationHistory/UserDelegationHistory.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 78b00aeb..09cc64bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,45 @@ ## v0.8.0 - 2024-11-20 +### Added +- Added `Wallet` Endpoints: + - `GET /sapi/v1/account/info` - Fetch account info detail + - `GET /sapi/v1/asset/custody/transfer-history` - Query user delegation history + - `GET /sapi/v1/asset/wallet/balance` - Query user wallet balance + - `GET /sapi/v1/capital/deposit/address/list` - Fetch deposit address list with network + - `GET /sapi/v1/spot/delist-schedule` - Query spot delist schedule + +- Added `Margin` Endpoints: + - `GET /sapi/v1/margin/available-inventory` + - `GET /sapi/v1/margin/capital-flow` + - `GET /sapi/v1/margin/leverageBracket` + - `POST /sapi/v1/margin/manual-liquidation` + - `POST /sapi/v1/margin/max-leverage` + - `POST /sapi/v1/margin/order/oto` + - `POST /sapi/v1/margin/order/otoco` + +### Fixed +- Fixed `TestConnectivityResponse.RateLimits` type - updated to array +- Fixed `NewTickerPriceService.Do` unmarshaling issue +- Fixed `SystemStatusResponse` type +- Fixed variable named `CumulativeQuoteQty` to `CummulativeQuoteQty` +- Fixed `SubAccountTransferHistoryService` response type +- Fixed field `Fills` type in `CancelReplaceResponse` + +### Updated +- Added the parameters `symbol`, `symbols`, `permissions` , `showPermissionSets` and `symbolStatus` to endpoint `GET /api/v3/exchangeInfo` +- Added parameter `accountType` to endpoint `POST /sapi/v1/asset/dust-btc` +- Added response fields `Created`, `CollateralMarginLevel`, `TotalCollateralValueInUSDT`, `TransferInEnabled`, `TransferOutEnabled` and `AccountType` to endpoint `GET /sapi/v1/margin/account` +- Added response fields `EnableFixApiTrade`, `EnableFixReadOnly` and `EnablePortfolioMarginTrading` to endpoint `GET /sapi/v1/account/apiRestrictions` +- Updated `SymbolInfo` and `SymbolFilter` types +- Removed response field `resetAddressStatus` and added fields `contractAddressUrl` and `contractAddress` from endpoint `GET /sapi/v1/capital/config/getall` + + +### Removed +- Removed `Wallet` endpoints: + - `GET /sapi/v1/capital/contract/convertible-coins` + - `POST /sapi/v1/asset/convert-transfer` + ## v0.7.0 - 2024-08-23 ### Added diff --git a/account.go b/account.go index 156df3af..189e908f 100644 --- a/account.go +++ b/account.go @@ -396,7 +396,7 @@ type CreateOrderResponseRESULT struct { Price string `json:"price"` OrigQty string `json:"origQty"` ExecutedQty string `json:"executedQty"` - CumulativeQuoteQty string `json:"cummulativeQuoteQty"` + CummulativeQuoteQty string `json:"cummulativeQuoteQty"` Status string `json:"status"` TimeInForce string `json:"timeInForce"` Type string `json:"type"` @@ -423,7 +423,7 @@ type CreateOrderResponseFULL struct { Price string `json:"price"` OrigQty string `json:"origQty"` ExecutedQty string `json:"executedQty"` - CumulativeQuoteQty string `json:"cummulativeQuoteQty"` + CummulativeQuoteQty string `json:"cummulativeQuoteQty"` Status string `json:"status"` TimeInForce string `json:"timeInForce"` Type string `json:"type"` @@ -569,7 +569,7 @@ type CancelOrderResponse struct { Price string `json:"price"` OrigQty string `json:"origQty"` ExecutedQty string `json:"executedQty"` - CumulativeQuoteQty string `json:"cumulativeQuoteQty"` + CummulativeQuoteQty string `json:"cummulativeQuoteQty"` Status string `json:"status"` TimeInForce string `json:"timeInForce"` Type string `json:"type"` @@ -651,7 +651,7 @@ type GetOrderResponse struct { Price string `json:"price"` OrigQty string `json:"origQty"` ExecutedQty string `json:"executedQty"` - CumulativeQuoteQty string `json:"cumulativeQuoteQty"` + CummulativeQuoteQty string `json:"cummulativeQuoteQty"` Status string `json:"status"` TimeInForce string `json:"timeInForce"` Type string `json:"type"` @@ -904,7 +904,7 @@ type CancelReplaceResponse struct { Price string `json:"price,omitempty"` OrigQty string `json:"origQty,omitempty"` ExecutedQty string `json:"executedQty,omitempty"` - CumulativeQuoteQty string `json:"cumulativeQuoteQty,omitempty"` + CummulativeQuoteQty string `json:"cummulativeQuoteQty,omitempty"` Status string `json:"status,omitempty"` TimeInForce string `json:"timeInForce,omitempty"` Type string `json:"type,omitempty"` @@ -912,23 +912,29 @@ type CancelReplaceResponse struct { SelfTradePreventionMode string `json:"selfTradePreventionMode,omitempty"` } `json:"cancelResponse,omitempty"` NewOrderResponse *struct { - Code int64 `json:"code,omitempty"` - Msg string `json:"msg,omitempty"` - Symbol string `json:"symbol,omitempty"` - OrderId int64 `json:"orderId,omitempty"` - OrderListId int64 `json:"orderListId,omitempty"` - ClientOrderId string `json:"clientOrderId,omitempty"` - TransactTime uint64 `json:"transactTime,omitempty"` - Price string `json:"price,omitempty"` - OrigQty string `json:"origQty,omitempty"` - ExecutedQty string `json:"executedQty,omitempty"` - CumulativeQuoteQty string `json:"cumulativeQuoteQty,omitempty"` - Status string `json:"status,omitempty"` - TimeInForce string `json:"timeInForce,omitempty"` - Type string `json:"type,omitempty"` - Side string `json:"side,omitempty"` - Fills []string `json:"fills,omitempty"` - SelfTradePreventionMode string `json:"selfTradePreventionMode,omitempty"` + Code int64 `json:"code,omitempty"` + Msg string `json:"msg,omitempty"` + Symbol string `json:"symbol,omitempty"` + OrderId int64 `json:"orderId,omitempty"` + OrderListId int64 `json:"orderListId,omitempty"` + ClientOrderId string `json:"clientOrderId,omitempty"` + TransactTime uint64 `json:"transactTime,omitempty"` + Price string `json:"price,omitempty"` + OrigQty string `json:"origQty,omitempty"` + ExecutedQty string `json:"executedQty,omitempty"` + CummulativeQuoteQty string `json:"cummulativeQuoteQty,omitempty"` + Status string `json:"status,omitempty"` + TimeInForce string `json:"timeInForce,omitempty"` + Type string `json:"type,omitempty"` + Side string `json:"side,omitempty"` + Fills []struct { + Price string `json:"price"` + Qty string `json:"qty"` + Commission string `json:"commission"` + CommissionAsset string `json:"commissionAsset"` + TradeId int64 `json:"tradeId"` + } `json:"fills,omitempty"` + SelfTradePreventionMode string `json:"selfTradePreventionMode,omitempty"` } `json:"newOrderResponse,omitempty"` Data *struct { CancelResult string `json:"cancelResult,omitempty"` @@ -944,7 +950,7 @@ type CancelReplaceResponse struct { Price string `json:"price,omitempty"` OrigQty string `json:"origQty,omitempty"` ExecutedQty string `json:"executedQty,omitempty"` - CumulativeQuoteQty string `json:"cumulativeQuoteQty,omitempty"` + CummulativeQuoteQty string `json:"cummulativeQuoteQty,omitempty"` Status string `json:"status,omitempty"` TimeInForce string `json:"timeInForce,omitempty"` Type string `json:"type,omitempty"` @@ -962,7 +968,7 @@ type CancelReplaceResponse struct { Price string `json:"price,omitempty"` OrigQty string `json:"origQty,omitempty"` ExecutedQty string `json:"executedQty,omitempty"` - CumulativeQuoteQty string `json:"cumulativeQuoteQty,omitempty"` + CummulativeQuoteQty string `json:"cummulativeQuoteQty,omitempty"` Status string `json:"status,omitempty"` TimeInForce string `json:"timeInForce,omitempty"` Type string `json:"type,omitempty"` @@ -1017,7 +1023,7 @@ type NewOpenOrdersResponse struct { Price string `json:"price"` OrigQty string `json:"origQty"` ExecutedQty string `json:"executedQty"` - CumulativeQuoteQty string `json:"cumulativeQuoteQty"` + CummulativeQuoteQty string `json:"cummulativeQuoteQty"` Status string `json:"status"` TimeInForce string `json:"timeInForce"` Type string `json:"type"` @@ -1124,7 +1130,7 @@ type NewAllOrdersResponse struct { Price string `json:"price"` OrigQty string `json:"origQty"` ExecutedQty string `json:"executedQty"` - CumulativeQuoteQty string `json:"cumulativeQuoteQty"` + CummulativeQuoteQty string `json:"cummulativeQuoteQty"` Status string `json:"status"` TimeInForce string `json:"timeInForce"` Type string `json:"type"` diff --git a/account_test.go b/account_test.go index 0b66e128..e2826064 100644 --- a/account_test.go +++ b/account_test.go @@ -237,7 +237,7 @@ func (s *accountTestSuite) TestNewOrder() { Price: "0.00000000", OrigQty: "10.00000000", ExecutedQty: "10.00000000", - CumulativeQuoteQty: "10.00000000", + CummulativeQuoteQty: "10.00000000", Status: "FILLED", TimeInForce: "GTC", Type: "MARKET", @@ -259,7 +259,7 @@ func (s *baseTestSuite) assertCreateOrderResponseEqual(e, a *CreateOrderResponse r.Equal(e.Price, a.Price, "Price") r.Equal(e.OrigQty, a.OrigQty, "OrigQty") r.Equal(e.ExecutedQty, a.ExecutedQty, "ExecutedQty") - r.Equal(e.CumulativeQuoteQty, a.CumulativeQuoteQty, "CumulativeQuoteQty") + r.Equal(e.CummulativeQuoteQty, a.CummulativeQuoteQty, "CummulativeQuoteQty") r.Equal(e.Status, a.Status, "Status") r.Equal(e.TimeInForce, a.TimeInForce, "TimeInForce") r.Equal(e.Type, a.Type, "Type") @@ -278,7 +278,7 @@ func (s *accountTestSuite) TestCancelOrder() { "price": "0.001", "origQty": "1.00000000", "executedQty": "0.00000000", - "cumulativeQuoteQty": "0.00000000", + "cummulativeQuoteQty": "0.00000000", "status": "CANCELED", "timeInForce": "GTC", "type": "LIMIT", @@ -309,7 +309,7 @@ func (s *accountTestSuite) TestCancelOrder() { Price: "0.001", OrigQty: "1.00000000", ExecutedQty: "0.00000000", - CumulativeQuoteQty: "0.00000000", + CummulativeQuoteQty: "0.00000000", Status: "CANCELED", TimeInForce: "GTC", Type: "LIMIT", @@ -329,7 +329,7 @@ func (s *accountTestSuite) assertCancelOrderEqual(e, a *CancelOrderResponse) { r.Equal(e.Price, a.Price, "Price") r.Equal(e.OrigQty, a.OrigQty, "OrigQty") r.Equal(e.ExecutedQty, a.ExecutedQty, "ExecutedQty") - r.Equal(e.CumulativeQuoteQty, a.CumulativeQuoteQty, "CumulativeQuoteQty") + r.Equal(e.CummulativeQuoteQty, a.CummulativeQuoteQty, "CummulativeQuoteQty") r.Equal(e.Status, a.Status, "Status") r.Equal(e.TimeInForce, a.TimeInForce, "TimeInForce") r.Equal(e.Type, a.Type, "Type") @@ -398,7 +398,7 @@ func (s *accountTestSuite) TestGetOrder() { "price": "100.00", "origQty": "10.00", "executedQty": "0.00", - "cumulativeQuoteQty": "0.00", + "cummulativeQuoteQty": "0.00", "status": "NEW", "timeInForce": "GTC", "type": "LIMIT", @@ -418,24 +418,24 @@ func (s *accountTestSuite) TestGetOrder() { s.r().NoError(err) s.assertGetOrderResponseEqual(&GetOrderResponse{ - Symbol: "BTCUSDT", - OrderId: 12345, - OrderListId: -1, - ClientOrderId: "abcde12345", - Price: "100.00", - OrigQty: "10.00", - ExecutedQty: "0.00", - CumulativeQuoteQty: "0.00", - Status: "NEW", - TimeInForce: "GTC", - Type: "LIMIT", - Side: "BUY", - StopPrice: "0.00", - IcebergQty: "0.00", - Time: 1499827319559, - UpdateTime: 1499827319559, - IsWorking: true, - OrigQuoteOrderQty: "0.000000", + Symbol: "BTCUSDT", + OrderId: 12345, + OrderListId: -1, + ClientOrderId: "abcde12345", + Price: "100.00", + OrigQty: "10.00", + ExecutedQty: "0.00", + CummulativeQuoteQty: "0.00", + Status: "NEW", + TimeInForce: "GTC", + Type: "LIMIT", + Side: "BUY", + StopPrice: "0.00", + IcebergQty: "0.00", + Time: 1499827319559, + UpdateTime: 1499827319559, + IsWorking: true, + OrigQuoteOrderQty: "0.000000", }, res) } @@ -658,7 +658,7 @@ func (s *accountTestSuite) TestGetAllOrders() { "price": "25000.00000000", "origQty": "1.00000000", "executedQty": "0.00000000", - "cumulativeQuoteQty": "0.00000000", + "cummulativeQuoteQty": "0.00000000", "status": "NEW", "timeInForce": "GTC", "type": "LIMIT", @@ -697,7 +697,7 @@ func (s *accountTestSuite) TestGetAllOrders() { s.Equal("25000.00000000", resp[0].Price) s.Equal("1.00000000", resp[0].OrigQty) s.Equal("0.00000000", resp[0].ExecutedQty) - s.Equal("0.00000000", resp[0].CumulativeQuoteQty) + s.Equal("0.00000000", resp[0].CummulativeQuoteQty) s.Equal("NEW", resp[0].Status) s.Equal("GTC", resp[0].TimeInForce) s.Equal("LIMIT", resp[0].Type) @@ -725,7 +725,7 @@ func (s *accountTestSuite) TestCancelOpenOrders() { "price": "0.00000000", "origQty": "1.00000000", "executedQty": "0.00000000", - "cumulativeQuoteQty": "0.00000000", + "cummulativeQuoteQty": "0.00000000", "status": "CANCELED", "timeInForce": "GTC", "type": "LIMIT", @@ -741,7 +741,7 @@ func (s *accountTestSuite) TestCancelOpenOrders() { "price": "0.00000000", "origQty": "2.00000000", "executedQty": "0.00000000", - "cumulativeQuoteQty": "0.00000000", + "cummulativeQuoteQty": "0.00000000", "status": "CANCELED", "timeInForce": "GTC", "type": "LIMIT", @@ -767,7 +767,7 @@ func (s *accountTestSuite) TestCancelOpenOrders() { s.Equal("0.00000000", res[0].Price) s.Equal("1.00000000", res[0].OrigQty) s.Equal("0.00000000", res[0].ExecutedQty) - s.Equal("0.00000000", res[0].CumulativeQuoteQty) + s.Equal("0.00000000", res[0].CummulativeQuoteQty) s.Equal("CANCELED", res[0].Status) s.Equal("GTC", res[0].TimeInForce) s.Equal("LIMIT", res[0].Type) @@ -782,7 +782,7 @@ func (s *accountTestSuite) TestCancelOpenOrders() { s.Equal("0.00000000", res[1].Price) s.Equal("2.00000000", res[1].OrigQty) s.Equal("0.00000000", res[1].ExecutedQty) - s.Equal("0.00000000", res[1].CumulativeQuoteQty) + s.Equal("0.00000000", res[1].CummulativeQuoteQty) s.Equal("CANCELED", res[1].Status) s.Equal("GTC", res[1].TimeInForce) s.Equal("LIMIT", res[1].Type) diff --git a/client.go b/client.go index 403b692e..f24d8e72 100644 --- a/client.go +++ b/client.go @@ -337,6 +337,14 @@ func (c *Client) NewQueryMarginPriceIndexService() *QueryMarginPriceIndexService return &QueryMarginPriceIndexService{c: c} } +func (c *Client) NewQueryMarginAvailableInventoryService() *QueryMarginAvailableInventoryService { + return &QueryMarginAvailableInventoryService{c: c} +} + +func (c *Client) NewQueryLiabilityCoinLeverageBracketService() *QueryLiabilityCoinLeverageBracketService { + return &QueryLiabilityCoinLeverageBracketService{c: c} +} + func (c *Client) NewMarginAccountNewOrderService() *MarginAccountNewOrderService { return &MarginAccountNewOrderService{c: c} } @@ -409,6 +417,10 @@ func (c *Client) NewMarginAccountQueryMaxTransferOutAmountService() *MarginAccou return &MarginAccountQueryMaxTransferOutAmountService{c: c} } +func (c *Client) NewMarginAccountAdjustCrossMaxLeverageService() *MarginAccountAdjustCrossMaxLeverageService { + return &MarginAccountAdjustCrossMaxLeverageService{c: c} +} + func (c *Client) NewMarginAccountSummaryService() *MarginAccountSummaryService { return &MarginAccountSummaryService{c: c} } @@ -437,6 +449,10 @@ func (c *Client) NewMarginToggleBnbBurnService() *MarginToggleBnbBurnService { return &MarginToggleBnbBurnService{c: c} } +func (c *Client) NewMarginIsolatedCapitalFlowService() *MarginIsolatedCapitalFlowService { + return &MarginIsolatedCapitalFlowService{c: c} +} + func (c *Client) NewMarginBnbBurnStatusService() *MarginBnbBurnStatusService { return &MarginBnbBurnStatusService{c: c} } @@ -469,6 +485,18 @@ func (c *Client) NewMarginSmallLiabilityExchangeCoinListService() *MarginSmallLi return &MarginSmallLiabilityExchangeCoinListService{c: c} } +func (c *Client) NewMarginManualLiquidationService() *MarginManualLiquidationService { + return &MarginManualLiquidationService{c: c} +} + +func (c *Client) NewMarginAccountNewOTOService() *MarginAccountNewOTOService { + return &MarginAccountNewOTOService{c: c} +} + +func (c *Client) NewMarginAccountNewOTOCOService() *MarginAccountNewOTOCOService { + return &MarginAccountNewOTOCOService{c: c} +} + func (c *Client) NewMarginSmallLiabilityExchangeService() *MarginSmallLiabilityExchangeService { return &MarginSmallLiabilityExchangeService{c: c} } @@ -655,6 +683,10 @@ func (c *Client) NewGetSystemStatusService() *GetSystemStatusService { return &GetSystemStatusService{c: c} } +func (c *Client) NewGetSymbolsDelistScheduleService() *GetSymbolsDelistScheduleService { + return &GetSymbolsDelistScheduleService{c: c} +} + func (c *Client) NewGetAllCoinsInfoService() *GetAllCoinsInfoService { return &GetAllCoinsInfoService{c: c} } @@ -687,6 +719,10 @@ func (c *Client) NewDepositAddressService() *DepositAddressService { return &DepositAddressService{c: c} } +func (c *Client) NewDepositAddressListService() *DepositAddressListService { + return &DepositAddressListService{c: c} +} + func (c *Client) NewAccountStatusService() *AccountStatusService { return &AccountStatusService{c: c} } @@ -715,6 +751,10 @@ func (c *Client) NewAssetDetailV2Service() *AssetDetailV2Service { return &AssetDetailV2Service{c: c} } +func (c *Client) NewWalletBalanceService() *WalletBalanceService { + return &WalletBalanceService{c: c} +} + func (c *Client) NewTradeFeeService() *TradeFeeService { return &TradeFeeService{c: c} } @@ -735,10 +775,6 @@ func (c *Client) NewUserAssetService() *UserAssetService { return &UserAssetService{c: c} } -func (c *Client) NewBUSDConvertService() *BUSDConvertService { - return &BUSDConvertService{c: c} -} - func (c *Client) NewBUSDConvertHistoryService() *BUSDConvertHistoryService { return &BUSDConvertHistoryService{c: c} } @@ -747,16 +783,16 @@ func (c *Client) NewCloudMiningPaymentHistoryService() *CloudMiningPaymentHistor return &CloudMiningPaymentHistoryService{c: c} } -func (c *Client) NewAPIKeyPermissionService() *APIKeyPermissionService { - return &APIKeyPermissionService{c: c} +func (c *Client) NewUserDelegationHistoryService() *UserDelegationHistoryService { + return &UserDelegationHistoryService{c: c} } -func (c *Client) NewAutoConvertStableCoinService() *AutoConvertStableCoinService { - return &AutoConvertStableCoinService{c: c} +func (c *Client) NewAccountInfoService() *AccountInfoService { + return &AccountInfoService{c: c} } -func (c *Client) NewWalletBalanceService() *WalletBalanceService { - return &WalletBalanceService{c: c} +func (c *Client) NewAPIKeyPermissionService() *APIKeyPermissionService { + return &APIKeyPermissionService{c: c} } // User Data Streams: diff --git a/examples/margin/MarginAccountAdjustCrossMaxLeverage/MarginAccountAdjustCrossMaxLeverage.go b/examples/margin/MarginAccountAdjustCrossMaxLeverage/MarginAccountAdjustCrossMaxLeverage.go new file mode 100644 index 00000000..346cf044 --- /dev/null +++ b/examples/margin/MarginAccountAdjustCrossMaxLeverage/MarginAccountAdjustCrossMaxLeverage.go @@ -0,0 +1,29 @@ +package main + +import ( + "context" + "fmt" + + binance_connector "github.com/binance/binance-connector-go" +) + +func main() { + MarginAccountAdjustCrossMaxLeverage() +} + +func MarginAccountAdjustCrossMaxLeverage() { + apiKey := "your api key" + secretKey := "your secret key" + baseURL := "https://api.binance.com" + + client := binance_connector.NewClient(apiKey, secretKey, baseURL) + + // MarginAccountAdjustCrossMaxLeverageService - /sapi/v1/margin/max-leverage + marginAccountAdjustCrossMaxLeverage, err := client.NewMarginAccountAdjustCrossMaxLeverageService(). + MaxLeverage(5).Do(context.Background()) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(binance_connector.PrettyPrint(marginAccountAdjustCrossMaxLeverage)) +} diff --git a/examples/margin/MarginAccountNewOTO/MarginAccountNewOTO.go b/examples/margin/MarginAccountNewOTO/MarginAccountNewOTO.go new file mode 100644 index 00000000..c2638138 --- /dev/null +++ b/examples/margin/MarginAccountNewOTO/MarginAccountNewOTO.go @@ -0,0 +1,31 @@ +package main + +import ( + "context" + "fmt" + + binance_connector "github.com/binance/binance-connector-go" +) + +func main() { + MarginAccountNewOTO() +} + +func MarginAccountNewOTO() { + apiKey := "your api key" + secretKey := "your secret key" + baseURL := "https://api.binance.com" + + client := binance_connector.NewClient(apiKey, secretKey, baseURL) + + // MarginAccountNewOTOService - /sapi/v1/margin/order/oto + marginAccountNewOTO, err := client.NewMarginAccountNewOTOService(). + Symbol("BNBUSDT").WorkingType("LIMIT").WorkingSide("BUY").WorkingPrice(600).WorkingQuantity(1). + PendingType("LIMIT").PendingSide("BUY").PendingQuantity(1).WorkingTimeInForce("GTC"). + PendingPrice(595).PendingTimeInForce("GTC").WorkingIcebergQty(0.1).Do(context.Background()) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(binance_connector.PrettyPrint(marginAccountNewOTO)) +} diff --git a/examples/margin/MarginAccountNewOTOCO/MarginAccountNewOTOCO.go b/examples/margin/MarginAccountNewOTOCO/MarginAccountNewOTOCO.go new file mode 100644 index 00000000..9b113cce --- /dev/null +++ b/examples/margin/MarginAccountNewOTOCO/MarginAccountNewOTOCO.go @@ -0,0 +1,31 @@ +package main + +import ( + "context" + "fmt" + + binance_connector "github.com/binance/binance-connector-go" +) + +func main() { + MarginAccountNewOTOCO() +} + +func MarginAccountNewOTOCO() { + apiKey := "your api key" + secretKey := "your secret key" + baseURL := "https://api.binance.com" + + client := binance_connector.NewClient(apiKey, secretKey, baseURL) + + // MarginAccountNewOTOCOService - /sapi/v1/margin/order/otoco + marginAccountNewOTOCO, err := client.NewMarginAccountNewOTOCOService(). + Symbol("BNBUSDT").WorkingType("LIMIT").WorkingSide("BUY").WorkingPrice(600).WorkingQuantity(1). + PendingSide("BUY").PendingQuantity(1).PendingAboveType("LIMIT_MAKER").WorkingTimeInForce("GTC"). + PendingAbovePrice(605).PendingBelowType("LIMIT_MAKER").PendingBelowPrice(595).WorkingIcebergQty(0.1).Do(context.Background()) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(binance_connector.PrettyPrint(marginAccountNewOTOCO)) +} diff --git a/examples/margin/MarginIsolatedCapitalFlow/MarginIsolatedCapitalFlow.go b/examples/margin/MarginIsolatedCapitalFlow/MarginIsolatedCapitalFlow.go new file mode 100644 index 00000000..9f5d70ee --- /dev/null +++ b/examples/margin/MarginIsolatedCapitalFlow/MarginIsolatedCapitalFlow.go @@ -0,0 +1,28 @@ +package main + +import ( + "context" + "fmt" + + binance_connector "github.com/binance/binance-connector-go" +) + +func main() { + MarginIsolatedCapitalFlow() +} + +func MarginIsolatedCapitalFlow() { + apiKey := "your api key" + secretKey := "your secret key" + baseURL := "https://api.binance.com" + + client := binance_connector.NewClient(apiKey, secretKey, baseURL) + + // MarginIsolatedCapitalFlowService - /sapi/v1/margin/capital-flow + marginIsolatedCapitalFlow, err := client.NewMarginIsolatedCapitalFlowService().Do(context.Background()) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(binance_connector.PrettyPrint(marginIsolatedCapitalFlow)) +} diff --git a/examples/margin/MarginManualLiquidation/MarginManualLiquidation.go b/examples/margin/MarginManualLiquidation/MarginManualLiquidation.go new file mode 100644 index 00000000..4f042d3a --- /dev/null +++ b/examples/margin/MarginManualLiquidation/MarginManualLiquidation.go @@ -0,0 +1,29 @@ +package main + +import ( + "context" + "fmt" + + binance_connector "github.com/binance/binance-connector-go" +) + +func main() { + MarginManualLiquidation() +} + +func MarginManualLiquidation() { + apiKey := "your api key" + secretKey := "your secret key" + baseURL := "https://api.binance.com" + + client := binance_connector.NewClient(apiKey, secretKey, baseURL) + + // MarginManualLiquidationService - /sapi/v1/margin/manual-liquidation + marginManualLiquidation, err := client.NewMarginManualLiquidationService(). + MarginType("MARGIN").Do(context.Background()) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(binance_connector.PrettyPrint(marginManualLiquidation)) +} diff --git a/examples/margin/QueryLiabilityCoinLeverageBracket/QueryLiabilityCoinLeverageBracket.go b/examples/margin/QueryLiabilityCoinLeverageBracket/QueryLiabilityCoinLeverageBracket.go new file mode 100644 index 00000000..d172351e --- /dev/null +++ b/examples/margin/QueryLiabilityCoinLeverageBracket/QueryLiabilityCoinLeverageBracket.go @@ -0,0 +1,28 @@ +package main + +import ( + "context" + "fmt" + + binance_connector "github.com/binance/binance-connector-go" +) + +func main() { + QueryLiabilityCoinLeverageBracket() +} + +func QueryLiabilityCoinLeverageBracket() { + apiKey := "your api key" + secretKey := "your secret key" + baseURL := "https://api.binance.com" + + client := binance_connector.NewClient(apiKey, secretKey, baseURL) + + // QueryLiabilityCoinLeverageBracketService - /sapi/v1/margin/leverageBracket + queryLiabilityCoinLeverageBracket, err := client.NewQueryLiabilityCoinLeverageBracketService().Do(context.Background()) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(binance_connector.PrettyPrint(queryLiabilityCoinLeverageBracket)) +} diff --git a/examples/margin/QueryMarginAvailableInventory/QueryMarginAvailableInventory.go b/examples/margin/QueryMarginAvailableInventory/QueryMarginAvailableInventory.go new file mode 100644 index 00000000..bc0a28d8 --- /dev/null +++ b/examples/margin/QueryMarginAvailableInventory/QueryMarginAvailableInventory.go @@ -0,0 +1,29 @@ +package main + +import ( + "context" + "fmt" + + binance_connector "github.com/binance/binance-connector-go" +) + +func main() { + QueryMarginAvailableInventory() +} + +func QueryMarginAvailableInventory() { + apiKey := "your api key" + secretKey := "your secret key" + baseURL := "https://api.binance.com" + + client := binance_connector.NewClient(apiKey, secretKey, baseURL) + + // QueryMarginAvailableInventoryService - /sapi/v1/margin/available-inventory + queryMarginAvailableInventory, err := client.NewQueryMarginAvailableInventoryService(). + MarginType("MARGIN").Do(context.Background()) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(binance_connector.PrettyPrint(queryMarginAvailableInventory)) +} diff --git a/examples/market/TickerPrice/TickerPrice.go b/examples/market/TickerPrice/TickerPrice.go index b25a944d..5aff10f7 100644 --- a/examples/market/TickerPrice/TickerPrice.go +++ b/examples/market/TickerPrice/TickerPrice.go @@ -17,8 +17,7 @@ func TickerPrice() { client := binance_connector.NewClient("", "", baseURL) // TickerPrice - tickerPrice, err := client.NewTickerPriceService(). - Symbol("BTCUSDT").Do(context.Background()) + tickerPrice, err := client.NewTickerPriceService().Do(context.Background()) if err != nil { fmt.Println(err) return diff --git a/examples/wallet/AutoConvertStableCoin/AutoConvertStableCoin.go b/examples/wallet/AccountInfo/AccountInfo.go similarity index 53% rename from examples/wallet/AutoConvertStableCoin/AutoConvertStableCoin.go rename to examples/wallet/AccountInfo/AccountInfo.go index 9abcc342..f12fe1c3 100644 --- a/examples/wallet/AutoConvertStableCoin/AutoConvertStableCoin.go +++ b/examples/wallet/AccountInfo/AccountInfo.go @@ -8,21 +8,22 @@ import ( ) func main() { - AutoConvertStableCoin() + AccountInfo() } -func AutoConvertStableCoin() { +func AccountInfo() { apiKey := "your api key" secretKey := "your secret key" baseURL := "https://api.binance.com" client := binance_connector.NewClient(apiKey, secretKey, baseURL) - // AutoConvertStableCoinService - /sapi/v1/capital/contract/convertible-coins - autoConvertStableCoin, err := client.NewAutoConvertStableCoinService().Do(context.Background()) + // AccountInfoService - /sapi/v1/account/apiTradingStatus + accountInfo, err := client.NewAccountInfoService(). + Do(context.Background()) if err != nil { fmt.Println(err) return } - fmt.Println(binance_connector.PrettyPrint(autoConvertStableCoin)) + fmt.Println(binance_connector.PrettyPrint(accountInfo)) } diff --git a/examples/wallet/BUSDConvert/BUSDConvert.go b/examples/wallet/DepositAddressList/DepositAddressList.go similarity index 52% rename from examples/wallet/BUSDConvert/BUSDConvert.go rename to examples/wallet/DepositAddressList/DepositAddressList.go index 8c73ad18..3a47ec23 100644 --- a/examples/wallet/BUSDConvert/BUSDConvert.go +++ b/examples/wallet/DepositAddressList/DepositAddressList.go @@ -8,22 +8,22 @@ import ( ) func main() { - BUSDConvert() + DepositAddressList() } -func BUSDConvert() { +func DepositAddressList() { apiKey := "your api key" secretKey := "your secret key" baseURL := "https://api.binance.com" client := binance_connector.NewClient(apiKey, secretKey, baseURL) - // BUSDConvertService - /sapi/v1/asset/convert-transfer - bUSDConvert, err := client.NewBUSDConvertService().ClientTranId("118263407119"). - Asset("BUSD").Amount(20.0).AccountType("MAIN").Do(context.Background()) + // DepositAddressListService - /sapi/v1/capital/deposit/address/list + depositAddressList, err := client.NewDepositAddressListService().Coin("BTC"). + Do(context.Background()) if err != nil { fmt.Println(err) return } - fmt.Println(binance_connector.PrettyPrint(bUSDConvert)) + fmt.Println(binance_connector.PrettyPrint(depositAddressList)) } diff --git a/examples/wallet/GetSymbolsDelistSchedule/GetSymbolsDelistSchedule.go b/examples/wallet/GetSymbolsDelistSchedule/GetSymbolsDelistSchedule.go new file mode 100644 index 00000000..3e2c6026 --- /dev/null +++ b/examples/wallet/GetSymbolsDelistSchedule/GetSymbolsDelistSchedule.go @@ -0,0 +1,28 @@ +package main + +import ( + "context" + "fmt" + + binance_connector "github.com/binance/binance-connector-go" +) + +func main() { + GetSymbolsDelistSchedule() +} + +func GetSymbolsDelistSchedule() { + apiKey := "your api key" + secretKey := "your secret key" + baseURL := "https://api.binance.com" + + client := binance_connector.NewClient(apiKey, secretKey, baseURL) + + // GetSymbolsDelistScheduleService - /sapi/v1/spot/delist-schedule + getSymbolsDelistSchedule, err := client.NewGetSymbolsDelistScheduleService().Do(context.Background()) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(binance_connector.PrettyPrint(getSymbolsDelistSchedule)) +} diff --git a/examples/wallet/UserDelegationHistory/UserDelegationHistory.go b/examples/wallet/UserDelegationHistory/UserDelegationHistory.go new file mode 100644 index 00000000..d380ef1a --- /dev/null +++ b/examples/wallet/UserDelegationHistory/UserDelegationHistory.go @@ -0,0 +1,29 @@ +package main + +import ( + "context" + "fmt" + + binance_connector "github.com/binance/binance-connector-go" +) + +func main() { + UserDelegationHistory() +} + +func UserDelegationHistory() { + apiKey := "your api key" + secretKey := "your secret key" + baseURL := "https://api.binance.com" + + client := binance_connector.NewClient(apiKey, secretKey, baseURL) + + // UserDelegationHistoryService - /sapi/v1/asset/custody/transfer-history + userDelegationHistory, err := client.NewUserDelegationHistoryService(). + Email("email@email.com").StartTime(1664442061000).EndTime(1664442078000).Do(context.Background()) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(binance_connector.PrettyPrint(userDelegationHistory)) +} diff --git a/margin.go b/margin.go index c6336346..6b024b25 100644 --- a/margin.go +++ b/margin.go @@ -132,6 +132,91 @@ type QueryMarginPriceIndexResponse struct { Symbol string `json:"symbol"` } +// Query Margin Available Inventory (USER_DATA) +const ( + queryMarginAvailableInventoryEndpoint = "/sapi/v1/margin/available-inventory" +) + +// QueryMarginAvailableInventoryService query margin available inventory +type QueryMarginAvailableInventoryService struct { + c *Client + marginType string +} + +// MarginType set marginType +func (s *QueryMarginAvailableInventoryService) MarginType(marginType string) *QueryMarginAvailableInventoryService { + s.marginType = marginType + return s +} + +// Do send request +func (s *QueryMarginAvailableInventoryService) Do(ctx context.Context, opts ...RequestOption) (res *QueryMarginAvailableInventoryResponse, err error) { + r := &request{ + method: http.MethodGet, + endpoint: queryMarginAvailableInventoryEndpoint, + secType: secTypeSigned, + } + r.setParam("type", s.marginType) + data, err := s.c.callAPI(ctx, r, opts...) + if err != nil { + return &QueryMarginAvailableInventoryResponse{}, err + } + res = new(QueryMarginAvailableInventoryResponse) + err = json.Unmarshal(data, res) + if err != nil { + return &QueryMarginAvailableInventoryResponse{}, err + } + return res, nil +} + +// QueryMarginAvailableInventoryResponse define query margin available inventory response +type QueryMarginAvailableInventoryResponse struct { + Assets map[string]string `json:"assets"` + UpdateTime int64 `json:"updateTime"` +} + +// Query Liability Coin Leverage Bracket in Cross Margin Pro Mode(MARKET_DATA) +const ( + queryLiabilityCoinLeverageBracketEndpoint = "/sapi/v1/margin/leverageBracket" +) + +// QueryLiabilityCoinLeverageBracketService query liability coin leverage bracket +type QueryLiabilityCoinLeverageBracketService struct { + c *Client +} + +// Do send request +func (s *QueryLiabilityCoinLeverageBracketService) Do(ctx context.Context, opts ...RequestOption) (res []*QueryLiabilityCoinLeverageBracketResponse, err error) { + r := &request{ + method: http.MethodGet, + endpoint: queryLiabilityCoinLeverageBracketEndpoint, + secType: secTypeAPIKey, + } + data, err := s.c.callAPI(ctx, r, opts...) + if err != nil { + return []*QueryLiabilityCoinLeverageBracketResponse{}, err + } + res = make([]*QueryLiabilityCoinLeverageBracketResponse, 0) + err = json.Unmarshal(data, &res) + if err != nil { + return []*QueryLiabilityCoinLeverageBracketResponse{}, err + } + return res, nil +} + +// QueryLiabilityCoinLeverageBracketResponse define query liability coin leverage bracket response +type QueryLiabilityCoinLeverageBracketResponse struct { + AssetNames []string `json:"assetNames"` + Rank int `json:"rank"` + Brackets []struct { + Leverage int `json:"leverage"` + MaxDebt float64 `json:"maxDebt"` + MaintenanceMarginRate float64 `json:"maintenanceMarginRate"` + InitialMarginRate float64 `json:"initialMarginRate"` + FastNum float64 `json:"fastNum"` + } `json:"brackets"` +} + // Margin Accouunt New Order (TRADE) API Endpoint const ( marginAccountNewOrderEndpoint = "/sapi/v1/margin/order" @@ -321,19 +406,19 @@ type MarginAccountNewOrderResponseACK struct { // Create MarginAccountNewOrderResponseRESULT type MarginAccountNewOrderResponseRESULT struct { - Symbol string `json:"symbol"` - OrderId int64 `json:"orderId"` - ClientOrderId string `json:"clientOrderId"` - TransactTime uint64 `json:"transactTime"` - Price string `json:"price"` - OrigQty string `json:"origQty"` - ExecutedQty string `json:"executedQty"` - CumulativeQuoteQty string `json:"cummulativeQuoteQty"` - Status string `json:"status"` - TimeInForce string `json:"timeInForce"` - Type string `json:"type"` - IsIsolated bool `json:"isIsolated"` - Side string `json:"side"` + Symbol string `json:"symbol"` + OrderId int64 `json:"orderId"` + ClientOrderId string `json:"clientOrderId"` + TransactTime uint64 `json:"transactTime"` + Price string `json:"price"` + OrigQty string `json:"origQty"` + ExecutedQty string `json:"executedQty"` + CummulativeQuoteQty string `json:"cummulativeQuoteQty"` + Status string `json:"status"` + TimeInForce string `json:"timeInForce"` + Type string `json:"type"` + IsIsolated bool `json:"isIsolated"` + Side string `json:"side"` } // Create MarginAccountNewOrderResponseFULL @@ -345,7 +430,7 @@ type MarginAccountNewOrderResponseFULL struct { Price string `json:"price"` OrigQty string `json:"origQty"` ExecutedQty string `json:"executedQty"` - CumulativeQuoteQty string `json:"cummulativeQuoteQty"` + CummulativeQuoteQty string `json:"cummulativeQuoteQty"` Status string `json:"status"` TimeInForce string `json:"timeInForce"` Type string `json:"type"` @@ -443,19 +528,19 @@ func (s *MarginAccountCancelOrderService) Do(ctx context.Context, opts ...Reques // MarginAccountCancelOrderResponse define margin account cancel order response type MarginAccountCancelOrderResponse struct { - Symbol string `json:"symbol"` - IsIsolated bool `json:"isIsolated"` - OrderId int `json:"orderId"` - OrigClientOrderId string `json:"origClientOrderId"` - ClientOrderId string `json:"clientOrderId"` - Price string `json:"price"` - OrigQty string `json:"origQty"` - ExecutedQty string `json:"executedQty"` - CumulativeQuoteQty string `json:"cumulativeQuoteQty"` - Status string `json:"status"` - TimeInForce string `json:"timeInForce"` - Type string `json:"type"` - Side string `json:"side"` + Symbol string `json:"symbol"` + IsIsolated bool `json:"isIsolated"` + OrderId int `json:"orderId"` + OrigClientOrderId string `json:"origClientOrderId"` + ClientOrderId string `json:"clientOrderId"` + Price string `json:"price"` + OrigQty string `json:"origQty"` + ExecutedQty string `json:"executedQty"` + CummulativeQuoteQty string `json:"cummulativeQuoteQty"` + Status string `json:"status"` + TimeInForce string `json:"timeInForce"` + Type string `json:"type"` + Side string `json:"side"` } // Margin Account Cancel All Orders (TRADE) API Endpoint @@ -510,20 +595,20 @@ func (s *MarginAccountCancelAllOrdersService) Do(ctx context.Context, opts ...Re // MarginAccountCancelAllOrdersResponse define margin account cancel all orders response type MarginAccountCancelAllOrdersResponse struct { - Symbol string `json:"symbol"` - IsIsolated bool `json:"isIsolated"` - OrigClientOrderId string `json:"origClientOrderId"` - OrderId int `json:"orderId"` - OrderListId int `json:"orderListId"` - ClientOrderId string `json:"clientOrderId"` - Price string `json:"price"` - OrigQty string `json:"origQty"` - ExecutedQty string `json:"executedQty"` - CumulativeQuoteQty string `json:"cumulativeQuoteQty"` - Status string `json:"status"` - TimeInForce string `json:"timeInForce"` - Type string `json:"type"` - Side string `json:"side"` + Symbol string `json:"symbol"` + IsIsolated bool `json:"isIsolated"` + OrigClientOrderId string `json:"origClientOrderId"` + OrderId int `json:"orderId"` + OrderListId int `json:"orderListId"` + ClientOrderId string `json:"clientOrderId"` + Price string `json:"price"` + OrigQty string `json:"origQty"` + ExecutedQty string `json:"executedQty"` + CummulativeQuoteQty string `json:"cummulativeQuoteQty"` + Status string `json:"status"` + TimeInForce string `json:"timeInForce"` + Type string `json:"type"` + Side string `json:"side"` } // Get Cross Margin Transfer History (USER_DATA) API Endpoint @@ -880,14 +965,19 @@ func (s *CrossMarginAccountDetailService) Do(ctx context.Context, opts ...Reques // CrossMarginAccountDetailResponse define cross margin account detail response type CrossMarginAccountDetailResponse struct { - BorrowEnabled bool `json:"borrowEnabled"` - MarginLevel string `json:"marginLevel"` - TotalAssetOfBtc string `json:"totalAssetOfBtc"` - TotalLiabilityOfBtc string `json:"totalLiabilityOfBtc"` - TotalNetAssetOfBtc string `json:"totalNetAssetOfBtc"` - TradeEnabled bool `json:"tradeEnabled"` - TransferEnabled bool `json:"transferEnabled"` - UserAssets []struct { + Created bool `json:"created"` + BorrowEnabled bool `json:"borrowEnabled"` + MarginLevel string `json:"marginLevel"` + CollateralMarginLevel string `json:"collateralMarginLevel"` + TotalAssetOfBtc string `json:"totalAssetOfBtc"` + TotalLiabilityOfBtc string `json:"totalLiabilityOfBtc"` + TotalNetAssetOfBtc string `json:"totalNetAssetOfBtc"` + TotalCollateralValueInUSDT string `json:"totalCollateralValueInUSDT"` + TradeEnabled bool `json:"tradeEnabled"` + TransferInEnabled bool `json:"transferInEnabled"` + TransferOutEnabled bool `json:"transferOutEnabled"` + AccountType string `json:"accountType"` + UserAssets []struct { Asset string `json:"asset"` Borrowed string `json:"borrowed"` Free string `json:"free"` @@ -969,23 +1059,23 @@ func (s *MarginAccountOrderService) Do(ctx context.Context, opts ...RequestOptio // MarginAccountOrderResponse define margin account order response type MarginAccountOrderResponse struct { - ClientOrderId string `json:"clientOrderId"` - CumulativeQuoteQty string `json:"cumulativeQuoteQty"` - ExecutedQty string `json:"executedQty"` - IcebergQty string `json:"icebergQty"` - IsWorking bool `json:"isWorking"` - OrderId int `json:"orderId"` - OrigQty string `json:"origQty"` - Price string `json:"price"` - Side string `json:"side"` - Status string `json:"status"` - StopPrice string `json:"stopPrice"` - Symbol string `json:"symbol"` - IsIsolated bool `json:"isIsolated"` - Time uint64 `json:"time"` - TimeInForce string `json:"timeInForce"` - OrderType string `json:"type"` - UpdateTime uint64 `json:"updateTime"` + ClientOrderId string `json:"clientOrderId"` + CummulativeQuoteQty string `json:"cummulativeQuoteQty"` + ExecutedQty string `json:"executedQty"` + IcebergQty string `json:"icebergQty"` + IsWorking bool `json:"isWorking"` + OrderId int `json:"orderId"` + OrigQty string `json:"origQty"` + Price string `json:"price"` + Side string `json:"side"` + Status string `json:"status"` + StopPrice string `json:"stopPrice"` + Symbol string `json:"symbol"` + IsIsolated bool `json:"isIsolated"` + Time uint64 `json:"time"` + TimeInForce string `json:"timeInForce"` + OrderType string `json:"type"` + UpdateTime uint64 `json:"updateTime"` } // Query Margin Account's Open Order (USER_DATA) API Endpoint @@ -1039,23 +1129,23 @@ func (s *MarginAccountOpenOrderService) Do(ctx context.Context, opts ...RequestO // MarginAccountOpenOrderResponse define margin account open order response type MarginAccountOpenOrderResponse struct { - ClientOrderId string `json:"clientOrderId"` - CumulativeQuoteQty string `json:"cumulativeQuoteQty"` - ExecutedQty string `json:"executedQty"` - IcebergQty string `json:"icebergQty"` - IsWorking bool `json:"isWorking"` - OrderId int `json:"orderId"` - OrigQty string `json:"origQty"` - Price string `json:"price"` - Side string `json:"side"` - Status string `json:"status"` - StopPrice string `json:"stopPrice"` - Symbol string `json:"symbol"` - IsIsolated bool `json:"isIsolated"` - Time uint64 `json:"time"` - TimeInForce string `json:"timeInForce"` - OrderType string `json:"type"` - UpdateTime uint64 `json:"updateTime"` + ClientOrderId string `json:"clientOrderId"` + CummulativeQuoteQty string `json:"cummulativeQuoteQty"` + ExecutedQty string `json:"executedQty"` + IcebergQty string `json:"icebergQty"` + IsWorking bool `json:"isWorking"` + OrderId int `json:"orderId"` + OrigQty string `json:"origQty"` + Price string `json:"price"` + Side string `json:"side"` + Status string `json:"status"` + StopPrice string `json:"stopPrice"` + Symbol string `json:"symbol"` + IsIsolated bool `json:"isIsolated"` + Time uint64 `json:"time"` + TimeInForce string `json:"timeInForce"` + OrderType string `json:"type"` + UpdateTime uint64 `json:"updateTime"` } // Query Margin Account's All Orders (USER_DATA) API Endpoint @@ -1150,23 +1240,23 @@ func (s *MarginAccountAllOrderService) Do(ctx context.Context, opts ...RequestOp // MarginAccountAllOrderResponse define margin account all order response type MarginAccountAllOrderResponse struct { - ClientOrderId string `json:"clientOrderId"` - CumulativeQuoteQty string `json:"cumulativeQuoteQty"` - ExecutedQty string `json:"executedQty"` - IcebergQty string `json:"icebergQty"` - IsWorking bool `json:"isWorking"` - OrderId int `json:"orderId"` - OrigQty string `json:"origQty"` - Price string `json:"price"` - Side string `json:"side"` - Status string `json:"status"` - StopPrice string `json:"stopPrice"` - Symbol string `json:"symbol"` - IsIsolated bool `json:"isIsolated"` - Time uint64 `json:"time"` - TimeInForce string `json:"timeInForce"` - OrderType string `json:"type"` - UpdateTime uint64 `json:"updateTime"` + ClientOrderId string `json:"clientOrderId"` + CummulativeQuoteQty string `json:"cummulativeQuoteQty"` + ExecutedQty string `json:"executedQty"` + IcebergQty string `json:"icebergQty"` + IsWorking bool `json:"isWorking"` + OrderId int `json:"orderId"` + OrigQty string `json:"origQty"` + Price string `json:"price"` + Side string `json:"side"` + Status string `json:"status"` + StopPrice string `json:"stopPrice"` + Symbol string `json:"symbol"` + IsIsolated bool `json:"isIsolated"` + Time uint64 `json:"time"` + TimeInForce string `json:"timeInForce"` + OrderType string `json:"type"` + UpdateTime uint64 `json:"updateTime"` } // Margin Account New OCO (TRADE) API Endpoint @@ -1358,20 +1448,20 @@ type MarginAccountNewOCOResponse struct { ClientOrderId string `json:"clientOrderId"` } `json:"orders"` OrderReports []struct { - Symbol string `json:"symbol"` - OrderId int `json:"orderId"` - OrderListId int `json:"orderListId"` - ClientOrderId string `json:"clientOrderId"` - TransactTime uint64 `json:"transactTime"` - Price string `json:"price"` - OrigQty string `json:"origQty"` - ExecutedQty string `json:"executedQty"` - CumulativeQuoteQty string `json:"cumulativeQuoteQty"` - Status string `json:"status"` - TimeInForce string `json:"timeInForce"` - OrderType string `json:"type"` - Side string `json:"side"` - StopPrice string `json:"stopPrice"` + Symbol string `json:"symbol"` + OrderId int `json:"orderId"` + OrderListId int `json:"orderListId"` + ClientOrderId string `json:"clientOrderId"` + TransactTime uint64 `json:"transactTime"` + Price string `json:"price"` + OrigQty string `json:"origQty"` + ExecutedQty string `json:"executedQty"` + CummulativeQuoteQty string `json:"cummulativeQuoteQty"` + Status string `json:"status"` + TimeInForce string `json:"timeInForce"` + OrderType string `json:"type"` + Side string `json:"side"` + StopPrice string `json:"stopPrice"` } `json:"orderReports"` } @@ -1470,20 +1560,20 @@ type MarginAccountCancelOCOResponse struct { ClientOrderId string `json:"clientOrderId"` } `json:"orders"` OrderReports []struct { - Symbol string `json:"symbol"` - OrigClientOrderId string `json:"origClientOrderId"` - OrderId int `json:"orderId"` - OrderListId int `json:"orderListId"` - ClientOrderId string `json:"clientOrderId"` - Price string `json:"price"` - OrigQty string `json:"origQty"` - ExecutedQty string `json:"executedQty"` - CumulativeQuoteQty string `json:"cumulativeQuoteQty"` - Status string `json:"status"` - TimeInForce string `json:"timeInForce"` - OrderType string `json:"type"` - Side string `json:"side"` - StopPrice string `json:"stopPrice"` + Symbol string `json:"symbol"` + OrigClientOrderId string `json:"origClientOrderId"` + OrderId int `json:"orderId"` + OrderListId int `json:"orderListId"` + ClientOrderId string `json:"clientOrderId"` + Price string `json:"price"` + OrigQty string `json:"origQty"` + ExecutedQty string `json:"executedQty"` + CummulativeQuoteQty string `json:"cummulativeQuoteQty"` + Status string `json:"status"` + TimeInForce string `json:"timeInForce"` + OrderType string `json:"type"` + Side string `json:"side"` + StopPrice string `json:"stopPrice"` } `json:"orderReports"` } @@ -1966,6 +2056,47 @@ type MarginAccountQueryMaxTransferOutAmountResponse struct { Amount string `json:"amount"` } +// Adjust cross margin max leverage (USER_DATA) +const ( + marginAccountAdjustCrossMaxLeverageEndpoint = "/sapi/v1/margin/max-leverage" +) + +type MarginAccountAdjustCrossMaxLeverageService struct { + c *Client + maxLeverage int32 +} + +// MaxLeverage set maxLeverage +func (s *MarginAccountAdjustCrossMaxLeverageService) MaxLeverage(maxLeverage int32) *MarginAccountAdjustCrossMaxLeverageService { + s.maxLeverage = maxLeverage + return s +} + +// Do send request +func (s *MarginAccountAdjustCrossMaxLeverageService) Do(ctx context.Context, opts ...RequestOption) (res *MarginAccountAdjustCrossMaxLeverageResponse, err error) { + r := &request{ + method: http.MethodPost, + endpoint: marginAccountAdjustCrossMaxLeverageEndpoint, + secType: secTypeSigned, + } + r.setParam("maxLeverage", s.maxLeverage) + data, err := s.c.callAPI(ctx, r, opts...) + if err != nil { + return &MarginAccountAdjustCrossMaxLeverageResponse{}, err + } + res = new(MarginAccountAdjustCrossMaxLeverageResponse) + err = json.Unmarshal(data, res) + if err != nil { + return &MarginAccountAdjustCrossMaxLeverageResponse{}, err + } + return res, nil +} + +// MarginAccountAdjustCrossMaxLeverageService response +type MarginAccountAdjustCrossMaxLeverageResponse struct { + Success bool `json:"success"` +} + // Get Summary of Margin account (USER_DATA) - GET /sapi/v1/margin/tradeCoeff (HMAC SHA256) const ( marginAccountSummaryEndpoint = "/sapi/v1/margin/tradeCoeff" @@ -2314,6 +2445,116 @@ type MarginToggleBnbBurnResponse struct { InterestBNBBurn bool `json:"interestBNBBurn"` } +// Query Cross Isolated Margin Capital Flow (USER_DATA) +const ( + marginIsolatedCapitalFlowEndpoint = "/sapi/v1/margin/capital-flow" +) + +type MarginIsolatedCapitalFlowService struct { + c *Client + asset *string + symbol *string + isolatedType *string + startTime *uint64 + endTime *uint64 + fromId *int + limit *int +} + +// Asset set asset +func (s *MarginIsolatedCapitalFlowService) Asset(asset string) *MarginIsolatedCapitalFlowService { + s.asset = &asset + return s +} + +// Symbol set symbol +func (s *MarginIsolatedCapitalFlowService) Symbol(symbol string) *MarginIsolatedCapitalFlowService { + s.symbol = &symbol + return s +} + +// IsolatedType set isolatedType +func (s *MarginIsolatedCapitalFlowService) IsolatedType(isolatedType string) *MarginIsolatedCapitalFlowService { + s.isolatedType = &isolatedType + return s +} + +// StartTime set startTime +func (s *MarginIsolatedCapitalFlowService) StartTime(startTime uint64) *MarginIsolatedCapitalFlowService { + s.startTime = &startTime + return s +} + +// EndTime set endTime +func (s *MarginIsolatedCapitalFlowService) EndTime(endTime uint64) *MarginIsolatedCapitalFlowService { + s.endTime = &endTime + return s +} + +// FromId set fromId +func (s *MarginIsolatedCapitalFlowService) FromId(fromId int) *MarginIsolatedCapitalFlowService { + s.fromId = &fromId + return s +} + +// Limit set limit +func (s *MarginIsolatedCapitalFlowService) Limit(limit int) *MarginIsolatedCapitalFlowService { + s.limit = &limit + return s +} + +// Do send request +func (s *MarginIsolatedCapitalFlowService) Do(ctx context.Context, opts ...RequestOption) (res []*MarginIsolatedCapitalFlowResponse, err error) { + r := &request{ + method: http.MethodGet, + endpoint: marginIsolatedCapitalFlowEndpoint, + secType: secTypeSigned, + } + m := params{} + if s.asset != nil { + m["asset"] = *s.asset + } + if s.symbol != nil { + m["symbol"] = *s.symbol + } + if s.isolatedType != nil { + m["isolatedType"] = *s.isolatedType + } + if s.startTime != nil { + m["startTime"] = *s.startTime + } + if s.endTime != nil { + m["endTime"] = *s.endTime + } + if s.fromId != nil { + m["fromId"] = *s.fromId + } + if s.limit != nil { + m["limit"] = *s.limit + } + data, err := s.c.callAPI(ctx, r, opts...) + if err != nil { + return []*MarginIsolatedCapitalFlowResponse{}, err + } + res = make([]*MarginIsolatedCapitalFlowResponse, 0) + err = json.Unmarshal(data, &res) + if err != nil { + return []*MarginIsolatedCapitalFlowResponse{}, err + } + return res, nil +} + +// MarginIsolatedCapitalFlowService response +type MarginIsolatedCapitalFlowResponse struct { + Id int `json:"id"` + TranId int `json:"tranId"` + Timestamp uint64 `json:"timestamp"` + Asset string `json:"asset"` + Symbol string `json:"symbol"` + Type string `json:"type"` + Amount string `json:"amount"` +} + // Get BNB Burn Status (USER_DATA) const ( marginBnbBurnStatusEndpoint = "/sapi/v1/bnbBurn" @@ -2759,6 +3000,693 @@ type MarginSmallLiabilityExchangeCoinListResponse struct { LiabilityOfBUSD string `json:"liabilityOfBUSD"` } +// Margin Manual Liquidation +const ( + marginManualLiquidationEndpoint = "/sapi/v1/margin/manual-liquidation" +) + +type MarginManualLiquidationService struct { + c *Client + marginType string + symbol *string +} + +// MarginType set marginType +func (s *MarginManualLiquidationService) MarginType(marginType string) *MarginManualLiquidationService { + s.marginType = marginType + return s +} + +// Symbol set symbol +func (s *MarginManualLiquidationService) Symbol(symbol string) *MarginManualLiquidationService { + s.symbol = &symbol + return s +} + +// Do send request +func (s *MarginManualLiquidationService) Do(ctx context.Context, opts ...RequestOption) (res []*MarginManualLiquidationResponse, err error) { + r := &request{ + method: http.MethodPost, + endpoint: marginManualLiquidationEndpoint, + secType: secTypeSigned, + } + m := params{ + "marginType": s.marginType, + } + if s.symbol != nil { + m["symbol"] = *s.symbol + } + r.setParams(m) + data, err := s.c.callAPI(ctx, r, opts...) + if err != nil { + return []*MarginManualLiquidationResponse{}, err + } + res = make([]*MarginManualLiquidationResponse, 0) + err = json.Unmarshal(data, &res) + if err != nil { + return []*MarginManualLiquidationResponse{}, err + } + return res, nil +} + +// MarginManualLiquidationService response +type MarginManualLiquidationResponse struct { + Asset string `json:"asset"` + Interest string `json:"interest"` + Principal string `json:"principal"` + LiabilityAsset string `json:"liabilityAsset"` + LiabilityQty float64 `json:"liabilityQty"` +} + +// Margin Account New OTO (TRADE) +const ( + marginAccountNewOTOEndpoint = "/sapi/v1/margin/order/oto" +) + +type MarginAccountNewOTOService struct { + c *Client + symbol string + workingType string + workingSide string + workingPrice float64 + workingQuantity float64 + pendingType string + pendingSide string + pendingQuantity float64 + isIsolated *string + listClientOrderId *string + newOrderRespType *string + sideEffectType *string + selfTradePreventionMode *string + autoRepayAtCancel *bool + workingClientOrderId *string + workingIcebergQty *float64 + workingTimeInForce *string + pendingClientOrderId *string + pendingPrice *float64 + pendingStopPrice *float64 + pendingTrailingDelta *float64 + pendingIcebergQty *float64 + pendingTimeInForce *string +} + +// Symbol set symbol +func (s *MarginAccountNewOTOService) Symbol(symbol string) *MarginAccountNewOTOService { + s.symbol = symbol + return s +} + +// WorkingType set workingType +func (s *MarginAccountNewOTOService) WorkingType(workingType string) *MarginAccountNewOTOService { + s.workingType = workingType + return s +} + +// WorkingSide set workingSide +func (s *MarginAccountNewOTOService) WorkingSide(workingSide string) *MarginAccountNewOTOService { + s.workingSide = workingSide + return s +} + +// WorkingPrice set workingPrice +func (s *MarginAccountNewOTOService) WorkingPrice(workingPrice float64) *MarginAccountNewOTOService { + s.workingPrice = workingPrice + return s +} + +// WorkingQuantity set workingQuantity +func (s *MarginAccountNewOTOService) WorkingQuantity(workingQuantity float64) *MarginAccountNewOTOService { + s.workingQuantity = workingQuantity + return s +} + +// PendingType set pendingType +func (s *MarginAccountNewOTOService) PendingType(pendingType string) *MarginAccountNewOTOService { + s.pendingType = pendingType + return s +} + +// PendingSide set pendingSide +func (s *MarginAccountNewOTOService) PendingSide(pendingSide string) *MarginAccountNewOTOService { + s.pendingSide = pendingSide + return s +} + +// PendingQuantity set pendingQuantity +func (s *MarginAccountNewOTOService) PendingQuantity(pendingQuantity float64) *MarginAccountNewOTOService { + s.pendingQuantity = pendingQuantity + return s +} + +// IsIsolated set isIsolated +func (s *MarginAccountNewOTOService) IsIsolated(isIsolated string) *MarginAccountNewOTOService { + s.isIsolated = &isIsolated + return s +} + +// ListClientOrderId set listClientOrderId +func (s *MarginAccountNewOTOService) ListClientOrderId(listClientOrderId string) *MarginAccountNewOTOService { + s.listClientOrderId = &listClientOrderId + return s +} + +// NewOrderRespType set newOrderRespType +func (s *MarginAccountNewOTOService) NewOrderRespType(newOrderRespType string) *MarginAccountNewOTOService { + s.newOrderRespType = &newOrderRespType + return s +} + +// SideEffectType set sideEffectType +func (s *MarginAccountNewOTOService) SideEffectType(sideEffectType string) *MarginAccountNewOTOService { + s.sideEffectType = &sideEffectType + return s +} + +// SelfTradePreventionMode set selfTradePreventionMode +func (s *MarginAccountNewOTOService) SelfTradePreventionMode(selfTradePreventionMode string) *MarginAccountNewOTOService { + s.selfTradePreventionMode = &selfTradePreventionMode + return s +} + +// AutoRepayAtCancel set autoRepayAtCancel +func (s *MarginAccountNewOTOService) AutoRepayAtCancel(autoRepayAtCancel bool) *MarginAccountNewOTOService { + s.autoRepayAtCancel = &autoRepayAtCancel + return s +} + +// WorkingClientOrderId set workingClientOrderId +func (s *MarginAccountNewOTOService) WorkingClientOrderId(workingClientOrderId string) *MarginAccountNewOTOService { + s.workingClientOrderId = &workingClientOrderId + return s +} + +// WorkingIcebergQty set workingIcebergQty +func (s *MarginAccountNewOTOService) WorkingIcebergQty(workingIcebergQty float64) *MarginAccountNewOTOService { + s.workingIcebergQty = &workingIcebergQty + return s +} + +// WorkingTimeInForce set workingTimeInForce +func (s *MarginAccountNewOTOService) WorkingTimeInForce(workingTimeInForce string) *MarginAccountNewOTOService { + s.workingTimeInForce = &workingTimeInForce + return s +} + +// PendingClientOrderId set pendingClientOrderId +func (s *MarginAccountNewOTOService) PendingClientOrderId(pendingClientOrderId string) *MarginAccountNewOTOService { + s.pendingClientOrderId = &pendingClientOrderId + return s +} + +// PendingPrice set pendingPrice +func (s *MarginAccountNewOTOService) PendingPrice(pendingPrice float64) *MarginAccountNewOTOService { + s.pendingPrice = &pendingPrice + return s +} + +// PendingStopPrice set pendingStopPrice +func (s *MarginAccountNewOTOService) PendingStopPrice(pendingStopPrice float64) *MarginAccountNewOTOService { + s.pendingStopPrice = &pendingStopPrice + return s +} + +// PendingTrailingDelta set pendingTrailingDelta +func (s *MarginAccountNewOTOService) PendingTrailingDelta(pendingTrailingDelta float64) *MarginAccountNewOTOService { + s.pendingTrailingDelta = &pendingTrailingDelta + return s +} + +// PendingIcebergQty set pendingIcebergQty +func (s *MarginAccountNewOTOService) PendingIcebergQty(pendingIcebergQty float64) *MarginAccountNewOTOService { + s.pendingIcebergQty = &pendingIcebergQty + return s +} + +// PendingTimeInForce set pendingTimeInForce +func (s *MarginAccountNewOTOService) PendingTimeInForce(pendingTimeInForce string) *MarginAccountNewOTOService { + s.pendingTimeInForce = &pendingTimeInForce + return s +} + +// Do send request +func (s *MarginAccountNewOTOService) Do(ctx context.Context, opts ...RequestOption) (res *MarginAccountNewOTOResponse, err error) { + r := &request{ + method: http.MethodPost, + endpoint: marginAccountNewOTOEndpoint, + secType: secTypeSigned, + } + m := params{ + "symbol": s.symbol, + "workingType": s.workingType, + "workingSide": s.workingSide, + "workingPrice": s.workingPrice, + "workingQuantity": s.workingQuantity, + "pendingType": s.pendingType, + "pendingSide": s.pendingSide, + "pendingQuantity": s.pendingQuantity, + } + if s.isIsolated != nil { + m["isIsolated"] = *s.isIsolated + } + if s.listClientOrderId != nil { + m["listClientOrderId"] = *s.listClientOrderId + } + if s.newOrderRespType != nil { + m["newOrderRespType"] = *s.newOrderRespType + } + if s.sideEffectType != nil { + m["sideEffectType"] = *s.sideEffectType + } + if s.selfTradePreventionMode != nil { + m["selfTradePreventionMode"] = *s.selfTradePreventionMode + } + if s.autoRepayAtCancel != nil { + m["autoRepayAtCancel"] = *s.autoRepayAtCancel + } + if s.workingClientOrderId != nil { + m["workingClientOrderId"] = *s.workingClientOrderId + } + if s.workingIcebergQty != nil { + m["workingIcebergQty"] = *s.workingIcebergQty + } + if s.workingTimeInForce != nil { + m["workingTimeInForce"] = *s.workingTimeInForce + } + if s.pendingClientOrderId != nil { + m["pendingClientOrderId"] = *s.pendingClientOrderId + } + if s.pendingPrice != nil { + m["pendingPrice"] = *s.pendingPrice + } + if s.pendingStopPrice != nil { + m["pendingStopPrice"] = *s.pendingStopPrice + } + if s.pendingTrailingDelta != nil { + m["pendingTrailingDelta"] = *s.pendingTrailingDelta + } + if s.pendingIcebergQty != nil { + m["pendingIcebergQty"] = *s.pendingIcebergQty + } + if s.pendingTimeInForce != nil { + m["pendingTimeInForce"] = *s.pendingTimeInForce + } + r.setParams(m) + data, err := s.c.callAPI(ctx, r, opts...) + if err != nil { + return &MarginAccountNewOTOResponse{}, err + } + res = new(MarginAccountNewOTOResponse) + err = json.Unmarshal(data, res) + if err != nil { + return &MarginAccountNewOTOResponse{}, err + } + return res, nil +} + +// MarginAccountNewOTOResponse represents the response from the MarginAccountNewOTOService +type MarginAccountNewOTOResponse struct { + OrderListId int64 `json:"orderListId"` + ContingencyType string `json:"contingencyType"` + ListStatusType string `json:"listStatusType"` + ListOrderStatus string `json:"listOrderStatus"` + ListClientOrderId string `json:"listClientOrderId"` + TransactionTime int64 `json:"transactionTime"` + Symbol string `json:"symbol"` + IsIsolated bool `json:"isIsolated"` + Orders []struct { + Symbol string `json:"symbol"` + OrderId int64 `json:"orderId"` + ClientOrderId string `json:"clientOrderId"` + } + OrderReports []struct { + Symbol string `json:"symbol"` + OrderId int64 `json:"orderId"` + OrderListId int64 `json:"orderListId"` + ClientOrderId string `json:"clientOrderId"` + TransactTime int64 `json:"transactTime"` + Price string `json:"price"` + OrigQty string `json:"origQty"` + ExecutedQty string `json:"executedQty"` + CummulativeQuoteQty string `json:"cummulativeQuoteQty"` + Status string `json:"status"` + TimeInForce string `json:"timeInForce"` + Type string `json:"type"` + Side string `json:"side"` + SelfTradePreventionMode string `json:"selfTradePreventionMode"` + } +} + +// Margin Account New OTOCO (TRADE) +const ( + marginAccountNewOTOCOEndpoint = "/sapi/v1/margin/order/otoco" +) + +type MarginAccountNewOTOCOService struct { + c *Client + symbol string + workingType string + workingSide string + workingPrice float64 + workingQuantity float64 + pendingSide string + pendingQuantity float64 + pendingAboveType string + isIsolated *string + sideEffectType *string + autoRepayAtCancel *bool + listClientOrderId *string + newOrderRespType *string + selfTradePreventionMode *string + workingClientOrderId *string + workingIcebergQty *float64 + workingTimeInForce *string + pendingAboveClientOrderId *string + pendingAbovePrice *float64 + pendingAboveStopPrice *float64 + pendingAboveTrailingDelta *float64 + pendingAboveIcebergQty *float64 + pendingAboveTimeInForce *string + pendingBelowType *string + pendingBelowClientOrderId *string + pendingBelowPrice *float64 + pendingBelowStopPrice *float64 + pendingBelowTrailingDelta *float64 + pendingBelowIcebergQty *float64 + pendingBelowTimeInForce *string +} + +// Symbol set symbol +func (s *MarginAccountNewOTOCOService) Symbol(symbol string) *MarginAccountNewOTOCOService { + s.symbol = symbol + return s +} + +// WorkingType set workingType +func (s *MarginAccountNewOTOCOService) WorkingType(workingType string) *MarginAccountNewOTOCOService { + s.workingType = workingType + return s +} + +// WorkingSide set workingSide +func (s *MarginAccountNewOTOCOService) WorkingSide(workingSide string) *MarginAccountNewOTOCOService { + s.workingSide = workingSide + return s +} + +// WorkingPrice set workingPrice +func (s *MarginAccountNewOTOCOService) WorkingPrice(workingPrice float64) *MarginAccountNewOTOCOService { + s.workingPrice = workingPrice + return s +} + +// WorkingQuantity set workingQuantity +func (s *MarginAccountNewOTOCOService) WorkingQuantity(workingQuantity float64) *MarginAccountNewOTOCOService { + s.workingQuantity = workingQuantity + return s +} + +// PendingSide set pendingSide +func (s *MarginAccountNewOTOCOService) PendingSide(pendingSide string) *MarginAccountNewOTOCOService { + s.pendingSide = pendingSide + return s +} + +// PendingQuantity set pendingQuantity +func (s *MarginAccountNewOTOCOService) PendingQuantity(pendingQuantity float64) *MarginAccountNewOTOCOService { + s.pendingQuantity = pendingQuantity + return s +} + +// PendingAboveType set pendingAboveType +func (s *MarginAccountNewOTOCOService) PendingAboveType(pendingAboveType string) *MarginAccountNewOTOCOService { + s.pendingAboveType = pendingAboveType + return s +} + +// IsIsolated set isIsolated +func (s *MarginAccountNewOTOCOService) IsIsolated(isIsolated string) *MarginAccountNewOTOCOService { + s.isIsolated = &isIsolated + return s +} + +// SideEffectType set sideEffectType +func (s *MarginAccountNewOTOCOService) SideEffectType(sideEffectType string) *MarginAccountNewOTOCOService { + s.sideEffectType = &sideEffectType + return s +} + +// AutoRepayAtCancel set autoRepayAtCancel +func (s *MarginAccountNewOTOCOService) AutoRepayAtCancel(autoRepayAtCancel bool) *MarginAccountNewOTOCOService { + s.autoRepayAtCancel = &autoRepayAtCancel + return s +} + +// ListClientOrderId set listClientOrderId +func (s *MarginAccountNewOTOCOService) ListClientOrderId(listClientOrderId string) *MarginAccountNewOTOCOService { + s.listClientOrderId = &listClientOrderId + return s +} + +// NewOrderRespType set newOrderRespType +func (s *MarginAccountNewOTOCOService) NewOrderRespType(newOrderRespType string) *MarginAccountNewOTOCOService { + s.newOrderRespType = &newOrderRespType + return s +} + +// SelfTradePreventionMode set selfTradePreventionMode +func (s *MarginAccountNewOTOCOService) SelfTradePreventionMode(selfTradePreventionMode string) *MarginAccountNewOTOCOService { + s.selfTradePreventionMode = &selfTradePreventionMode + return s +} + +// WorkingClientOrderId set workingClientOrderId +func (s *MarginAccountNewOTOCOService) WorkingClientOrderId(workingClientOrderId string) *MarginAccountNewOTOCOService { + s.workingClientOrderId = &workingClientOrderId + return s +} + +// WorkingIcebergQty set workingIcebergQty +func (s *MarginAccountNewOTOCOService) WorkingIcebergQty(workingIcebergQty float64) *MarginAccountNewOTOCOService { + s.workingIcebergQty = &workingIcebergQty + return s +} + +// WorkingTimeInForce set workingTimeInForce +func (s *MarginAccountNewOTOCOService) WorkingTimeInForce(workingTimeInForce string) *MarginAccountNewOTOCOService { + s.workingTimeInForce = &workingTimeInForce + return s +} + +// PendingAboveClientOrderId set pendingAboveClientOrderId +func (s *MarginAccountNewOTOCOService) PendingAboveClientOrderId(pendingAboveClientOrderId string) *MarginAccountNewOTOCOService { + s.pendingAboveClientOrderId = &pendingAboveClientOrderId + return s +} + +// PendingAbovePrice set pendingAbovePrice +func (s *MarginAccountNewOTOCOService) PendingAbovePrice(pendingAbovePrice float64) *MarginAccountNewOTOCOService { + s.pendingAbovePrice = &pendingAbovePrice + return s +} + +// PendingAboveStopPrice set pendingAboveStopPrice +func (s *MarginAccountNewOTOCOService) PendingAboveStopPrice(pendingAboveStopPrice float64) *MarginAccountNewOTOCOService { + s.pendingAboveStopPrice = &pendingAboveStopPrice + return s +} + +// PendingAboveTrailingDelta set pendingAboveTrailingDelta +func (s *MarginAccountNewOTOCOService) PendingAboveTrailingDelta(pendingAboveTrailingDelta float64) *MarginAccountNewOTOCOService { + s.pendingAboveTrailingDelta = &pendingAboveTrailingDelta + return s +} + +// PendingAboveIcebergQty set pendingAboveIcebergQty +func (s *MarginAccountNewOTOCOService) PendingAboveIcebergQty(pendingAboveIcebergQty float64) *MarginAccountNewOTOCOService { + s.pendingAboveIcebergQty = &pendingAboveIcebergQty + return s +} + +// PendingAboveTimeInForce set pendingAboveTimeInForce +func (s *MarginAccountNewOTOCOService) PendingAboveTimeInForce(pendingAboveTimeInForce string) *MarginAccountNewOTOCOService { + s.pendingAboveTimeInForce = &pendingAboveTimeInForce + return s +} + +// PendingBelowType set pendingBelowType +func (s *MarginAccountNewOTOCOService) PendingBelowType(pendingBelowType string) *MarginAccountNewOTOCOService { + s.pendingBelowType = &pendingBelowType + return s +} + +// PendingBelowClientOrderId set pendingBelowClientOrderId +func (s *MarginAccountNewOTOCOService) PendingBelowClientOrderId(pendingBelowClientOrderId string) *MarginAccountNewOTOCOService { + s.pendingBelowClientOrderId = &pendingBelowClientOrderId + return s +} + +// PendingBelowPrice set pendingBelowPrice +func (s *MarginAccountNewOTOCOService) PendingBelowPrice(pendingBelowPrice float64) *MarginAccountNewOTOCOService { + s.pendingBelowPrice = &pendingBelowPrice + return s +} + +// PendingBelowStopPrice set pendingBelowStopPrice +func (s *MarginAccountNewOTOCOService) PendingBelowStopPrice(pendingBelowStopPrice float64) *MarginAccountNewOTOCOService { + s.pendingBelowStopPrice = &pendingBelowStopPrice + return s +} + +// PendingBelowTrailingDelta set pendingBelowTrailingDelta +func (s *MarginAccountNewOTOCOService) PendingBelowTrailingDelta(pendingBelowTrailingDelta float64) *MarginAccountNewOTOCOService { + s.pendingBelowTrailingDelta = &pendingBelowTrailingDelta + return s +} + +// PendingBelowIcebergQty set pendingBelowIcebergQty +func (s *MarginAccountNewOTOCOService) PendingBelowIcebergQty(pendingBelowIcebergQty float64) *MarginAccountNewOTOCOService { + s.pendingBelowIcebergQty = &pendingBelowIcebergQty + return s +} + +// PendingBelowTimeInForce set pendingBelowTimeInForce +func (s *MarginAccountNewOTOCOService) PendingBelowTimeInForce(pendingBelowTimeInForce string) *MarginAccountNewOTOCOService { + s.pendingBelowTimeInForce = &pendingBelowTimeInForce + return s +} + +// Do send request +func (s *MarginAccountNewOTOCOService) Do(ctx context.Context, opts ...RequestOption) (res *MarginAccountNewOTOCOResponse, err error) { + r := &request{ + method: http.MethodPost, + endpoint: marginAccountNewOTOCOEndpoint, + secType: secTypeSigned, + } + + m := params{ + "symbol": s.symbol, + "workingType": s.workingType, + "workingSide": s.workingSide, + "workingPrice": s.workingPrice, + "workingQuantity": s.workingQuantity, + "pendingSide": s.pendingSide, + "pendingQuantity": s.pendingQuantity, + "pendingAboveType": s.pendingAboveType, + } + + if s.isIsolated != nil { + m["isIsolated"] = *s.isIsolated + } + if s.sideEffectType != nil { + m["sideEffectType"] = *s.sideEffectType + } + if s.autoRepayAtCancel != nil { + m["autoRepayAtCancel"] = *s.autoRepayAtCancel + } + if s.listClientOrderId != nil { + m["listClientOrderId"] = *s.listClientOrderId + } + if s.newOrderRespType != nil { + m["newOrderRespType"] = *s.newOrderRespType + } + if s.selfTradePreventionMode != nil { + m["selfTradePreventionMode"] = *s.selfTradePreventionMode + } + if s.workingClientOrderId != nil { + m["workingClientOrderId"] = *s.workingClientOrderId + } + if s.workingIcebergQty != nil { + m["workingIcebergQty"] = *s.workingIcebergQty + } + if s.workingTimeInForce != nil { + m["workingTimeInForce"] = *s.workingTimeInForce + } + if s.pendingAboveClientOrderId != nil { + m["pendingAboveClientOrderId"] = *s.pendingAboveClientOrderId + } + if s.pendingAbovePrice != nil { + m["pendingAbovePrice"] = *s.pendingAbovePrice + } + if s.pendingAboveStopPrice != nil { + m["pendingAboveStopPrice"] = *s.pendingAboveStopPrice + } + if s.pendingAboveTrailingDelta != nil { + m["pendingAboveTrailingDelta"] = *s.pendingAboveTrailingDelta + } + if s.pendingAboveIcebergQty != nil { + m["pendingAboveIcebergQty"] = *s.pendingAboveIcebergQty + } + if s.pendingAboveTimeInForce != nil { + m["pendingAboveTimeInForce"] = *s.pendingAboveTimeInForce + } + if s.pendingBelowType != nil { + m["pendingBelowType"] = *s.pendingBelowType + } + if s.pendingBelowClientOrderId != nil { + m["pendingBelowClientOrderId"] = *s.pendingBelowClientOrderId + } + if s.pendingBelowPrice != nil { + m["pendingBelowPrice"] = *s.pendingBelowPrice + } + if s.pendingBelowStopPrice != nil { + m["pendingBelowStopPrice"] = *s.pendingBelowStopPrice + } + if s.pendingBelowTrailingDelta != nil { + m["pendingBelowTrailingDelta"] = *s.pendingBelowTrailingDelta + } + if s.pendingBelowIcebergQty != nil { + m["pendingBelowIcebergQty"] = *s.pendingBelowIcebergQty + } + if s.pendingBelowTimeInForce != nil { + m["pendingBelowTimeInForce"] = *s.pendingBelowTimeInForce + } + r.setParams(m) + data, err := s.c.callAPI(ctx, r, opts...) + if err != nil { + return &MarginAccountNewOTOCOResponse{}, err + } + res = new(MarginAccountNewOTOCOResponse) + err = json.Unmarshal(data, res) + if err != nil { + return &MarginAccountNewOTOCOResponse{}, err + } + return res, nil +} + +// MarginAccountNewOTOCOResponse represents the response from the MarginAccountNewOTOCOService +type MarginAccountNewOTOCOResponse struct { + OrderListId int64 `json:"orderListId"` + ContingencyType string `json:"contingencyType"` + ListStatusType string `json:"listStatusType"` + ListOrderStatus string `json:"listOrderStatus"` + ListClientOrderId string `json:"listClientOrderId"` + TransactionTime int64 `json:"transactionTime"` + Symbol string `json:"symbol"` + IsIsolated bool `json:"isIsolated"` + Orders []struct { + Symbol string `json:"symbol"` + OrderId int64 `json:"orderId"` + ClientOrderId string `json:"clientOrderId"` + } + OrderReports []struct { + Symbol string `json:"symbol"` + OrderId int64 `json:"orderId"` + OrderListId int64 `json:"orderListId"` + ClientOrderId string `json:"clientOrderId"` + TransactTime int64 `json:"transactTime"` + Price string `json:"price"` + OrigQty string `json:"origQty"` + ExecutedQty string `json:"executedQty"` + CummulativeQuoteQty string `json:"cummulativeQuoteQty"` + Status string `json:"status"` + TimeInForce string `json:"timeInForce"` + Type string `json:"type"` + Side string `json:"side"` + StopPrice string `json:"stopPrice"` + SelfTradePreventionMode string `json:"selfTradePreventionMode"` + } +} + // Small Liability Exchange (MARGIN) const ( marginSmallLiabilityExchangeEndpoint = "/sapi/v1/margin/exchange-small-liability" diff --git a/margin_test.go b/margin_test.go index afdcb24f..7c714a72 100644 --- a/margin_test.go +++ b/margin_test.go @@ -71,6 +71,18 @@ func (s *marginTestSuite) assertMaxTransferableEqual(e, a *MarginAccountQueryMax s.r().Equal(e.Amount, a.Amount, "Amount") } +func (s *marginTestSuite) TestMarginAccountAdjustCrossMaxLeverage() { + data := []byte(`{ + "success": true + }`) + s.mockDo(data, nil) + defer s.assertDo() + + res, err := s.client.NewMarginAccountAdjustCrossMaxLeverageService().MaxLeverage(5).Do(context.Background()) + s.r().NoError(err) + s.True(res.Success) +} + func (s *marginTestSuite) TestGetMarginPriceIndex() { data := []byte(`{ "calcTime": 1562046418000, @@ -95,6 +107,83 @@ func (s *marginTestSuite) TestGetMarginPriceIndex() { s.assertMarginPriceIndexEqual(e, res) } +func (s *marginTestSuite) TestQueryMarginAvailableInventory() { + data := []byte(`{ + "assets": { + "MATIC": "100000000", + "STPT": "100000000", + "TVK": "100000000", + "SHIB": "97409653" + }, + "updateTime": 1699272487 + }`) + s.mockDo(data, nil) + defer s.assertDo() + + res, err := s.client.NewQueryMarginAvailableInventoryService().Do(context.Background()) + s.r().NoError(err) + s.Len(res.Assets, 4) + s.Equal("100000000", res.Assets["MATIC"]) + s.Equal("100000000", res.Assets["STPT"]) + s.Equal("100000000", res.Assets["TVK"]) + s.Equal("97409653", res.Assets["SHIB"]) + s.Equal(int64(1699272487), res.UpdateTime) +} + +func (s *marginTestSuite) TestQueryLiabilityCoinLeverageBracket() { + data := []byte(`[ + { + "assetNames":[ + "SHIB", + "FDUSD", + "BTC", + "ETH", + "USDC" + ], + "rank":1, + "brackets":[ + { + "leverage":10, + "maxDebt":1000000.00000000, + "maintenanceMarginRate":0.02000000, + "initialMarginRate":0.1112, + "fastNum":0 + }, + { + "leverage":3, + "maxDebt":4000000.00000000, + "maintenanceMarginRate":0.07000000, + "initialMarginRate":0.5000, + "fastNum":60000.0000000000000000 + } + ] + } + ]`) + s.mockDo(data, nil) + defer s.assertDo() + res, err := s.client.NewQueryLiabilityCoinLeverageBracketService().Do(context.Background()) + s.r().NoError(err) + s.Len(res, 1) + s.Len(res[0].Brackets, 2) + s.Equal(1, res[0].Rank) + s.Len(res[0].AssetNames, 5) + s.Equal("SHIB", res[0].AssetNames[0]) + s.Equal("FDUSD", res[0].AssetNames[1]) + s.Equal("BTC", res[0].AssetNames[2]) + s.Equal("ETH", res[0].AssetNames[3]) + s.Equal("USDC", res[0].AssetNames[4]) + s.Equal(10, res[0].Brackets[0].Leverage) + s.Equal(1000000.00000000, res[0].Brackets[0].MaxDebt) + s.Equal(0.02000000, res[0].Brackets[0].MaintenanceMarginRate) + s.Equal(0.1112, res[0].Brackets[0].InitialMarginRate) + s.Equal(0.0, res[0].Brackets[0].FastNum) + s.Equal(3, res[0].Brackets[1].Leverage) + s.Equal(4000000.00000000, res[0].Brackets[1].MaxDebt) + s.Equal(0.07000000, res[0].Brackets[1].MaintenanceMarginRate) + s.Equal(0.5000, res[0].Brackets[1].InitialMarginRate) + s.Equal(60000.0000000000000000, res[0].Brackets[1].FastNum) +} + func (s *marginTestSuite) assertMarginPriceIndexEqual(e, a *QueryMarginPriceIndexResponse) { r := s.r() r.Equal(e.CalcTime, a.CalcTime, "CalcTime") @@ -342,7 +431,7 @@ func (s *marginTestSuite) TestMarginAccountAllOrderService() { [ { "clientOrderId": "example-client-order-id", - "cumulativeQuoteQty": "100.00000000", + "cummulativeQuoteQty": "100.00000000", "executedQty": "1.00000000", "icebergQty": "0.00000000", "isWorking": false, @@ -375,7 +464,7 @@ func (s *marginTestSuite) TestMarginAccountAllOrderService() { s.r().NoError(err) s.Len(resp, 1) s.Equal("example-client-order-id", resp[0].ClientOrderId) - s.Equal("100.00000000", resp[0].CumulativeQuoteQty) + s.Equal("100.00000000", resp[0].CummulativeQuoteQty) s.Equal("1.00000000", resp[0].ExecutedQty) s.Equal("0.00000000", resp[0].IcebergQty) s.False(resp[0].IsWorking) @@ -392,7 +481,7 @@ func (s *marginTestSuite) TestMarginAccountAllOrderService() { } func (s *marginTestSuite) TestMarginAccountCancelAllOrders() { - data := []byte(`{"symbol":"BTCUSDT","isIsolated":false,"origClientOrderId":"a0e0a6f7-8b38-44d5-9dc5-87e3b9bd2d31","orderId":123456789,"orderListId":-1,"clientOrderId":"my_order_id","price":"10000.00000000","origQty":"1.00000000","executedQty":"0.00000000","cumulativeQuoteQty":"0.00000000","status":"CANCELED","timeInForce":"GTC","type":"LIMIT","side":"BUY"}`) + data := []byte(`{"symbol":"BTCUSDT","isIsolated":false,"origClientOrderId":"a0e0a6f7-8b38-44d5-9dc5-87e3b9bd2d31","orderId":123456789,"orderListId":-1,"clientOrderId":"my_order_id","price":"10000.00000000","origQty":"1.00000000","executedQty":"0.00000000","cummulativeQuoteQty":"0.00000000","status":"CANCELED","timeInForce":"GTC","type":"LIMIT","side":"BUY"}`) s.mockDo(data, nil) defer s.assertDo() @@ -412,7 +501,7 @@ func (s *marginTestSuite) TestMarginAccountCancelAllOrders() { s.Equal("10000.00000000", resp.Price) s.Equal("1.00000000", resp.OrigQty) s.Equal("0.00000000", resp.ExecutedQty) - s.Equal("0.00000000", resp.CumulativeQuoteQty) + s.Equal("0.00000000", resp.CummulativeQuoteQty) s.Equal("CANCELED", resp.Status) s.Equal("GTC", resp.TimeInForce) s.Equal("LIMIT", resp.Type) @@ -510,7 +599,7 @@ func (s *marginTestSuite) TestMarginAccountCancelOrder() { "price": "100.00000000", "origQty": "1.00000000", "executedQty": "0.00000000", - "cumulativeQuoteQty": "0.00000000", + "cummulativeQuoteQty": "0.00000000", "status": "CANCELED", "timeInForce": "GTC", "type": "LIMIT", @@ -536,7 +625,7 @@ func (s *marginTestSuite) TestMarginAccountCancelOrder() { s.Equal("100.00000000", resp.Price) s.Equal("1.00000000", resp.OrigQty) s.Equal("0.00000000", resp.ExecutedQty) - s.Equal("0.00000000", resp.CumulativeQuoteQty) + s.Equal("0.00000000", resp.CummulativeQuoteQty) s.Equal("CANCELED", resp.Status) s.Equal("GTC", resp.TimeInForce) s.Equal("LIMIT", resp.Type) @@ -646,7 +735,7 @@ func (s *marginTestSuite) TestMarginAccountNewOrder() { s.Equal("1.00000000", a.Price) s.Equal("10.00000000", a.OrigQty) s.Equal("10.00000000", a.ExecutedQty) - s.Equal("10.00000000", a.CumulativeQuoteQty) + s.Equal("10.00000000", a.CummulativeQuoteQty) s.Equal("FILLED", a.Status) s.Equal("GTC", a.TimeInForce) s.Equal("MARKET", a.Type) @@ -659,7 +748,7 @@ func (s *marginTestSuite) TestMarginAccountOpenOrder() { [ { "clientOrderId": "abc123", - "cumulativeQuoteQty": "1.00000000", + "cummulativeQuoteQty": "1.00000000", "executedQty": "1.00000000", "icebergQty": "0.00000000", "isWorking": false, @@ -690,7 +779,7 @@ func (s *marginTestSuite) TestMarginAccountOpenOrder() { s.r().NoError(err) s.Len(resp, 1) s.Equal("abc123", resp[0].ClientOrderId) - s.Equal("1.00000000", resp[0].CumulativeQuoteQty) + s.Equal("1.00000000", resp[0].CummulativeQuoteQty) s.Equal("1.00000000", resp[0].ExecutedQty) s.Equal("0.00000000", resp[0].IcebergQty) s.Equal(false, resp[0].IsWorking) @@ -712,7 +801,7 @@ func (s *marginTestSuite) TestMarginAccountOrder() { data := []byte(` { "clientOrderId": "myclientorderid", - "cumulativeQuoteQty": "1.00000000", + "cummulativeQuoteQty": "1.00000000", "executedQty": "1.00000000", "icebergQty": "0.00000000", "isWorking": false, @@ -743,7 +832,7 @@ func (s *marginTestSuite) TestMarginAccountOrder() { s.r().NoError(err) s.Equal("myclientorderid", resp.ClientOrderId) - s.Equal("1.00000000", resp.CumulativeQuoteQty) + s.Equal("1.00000000", resp.CummulativeQuoteQty) s.Equal("1.00000000", resp.ExecutedQty) s.Equal("0.00000000", resp.IcebergQty) s.False(resp.IsWorking) @@ -1323,6 +1412,294 @@ func (s *marginTestSuite) TestMarginSmallLiabilityExchangeCoinList() { s.Equal("0.00000000", resp[1].LiabilityOfBUSD) } +func (s *marginTestSuite) TestMarginManualLiquidation() { + data := []byte(`[ + { + "asset": "ETH", + "interest": "0.00083334", + "principal": "0.001", + "liabilityAsset": "USDT", + "liabilityQty": 0.3552 + } + ]`) + s.mockDo(data, nil) + defer s.assertDo() + + resp, err := s.client.NewMarginManualLiquidationService().MarginType("MARGIN").Do(context.Background()) + + s.r().NoError(err) + s.Len(resp, 1) + s.Equal("ETH", resp[0].Asset) + s.Equal("0.00083334", resp[0].Interest) + s.Equal("0.001", resp[0].Principal) + s.Equal("USDT", resp[0].LiabilityAsset) + s.Equal(0.3552, resp[0].LiabilityQty) +} + +func (s *marginTestSuite) TestMarginAccountNewOTO() { + data := []byte(`{ + "orderListId": 13551, + "contingencyType": "OTO", + "listStatusType": "EXEC_STARTED", + "listOrderStatus": "EXECUTING", + "listClientOrderId": "JDuOrsu0Ge8GTyvx8J7VTD", + "transactionTime": 1725521998054, + "symbol": "BTCUSDT", + "isIsolated": false, + "orders": [ + { + "symbol": "BTCUSDT", + "orderId": 29896699, + "clientOrderId": "y8RB6tQEMuHUXybqbtzTxk" + }, + { + "symbol": "BTCUSDT", + "orderId": 29896700, + "clientOrderId": "dKQEdh5HhXb7Lpp85jz1dQ" + } + ], + "orderReports": [ + { + "symbol": "BTCUSDT", + "orderId": 29896699, + "orderListId": 13551, + "clientOrderId": "y8RB6tQEMuHUXybqbtzTxk", + "transactTime": 1725521998054, + "price": "80000.00000000", + "origQty": "0.02000000", + "executedQty": "0", + "cummulativeQuoteQty": "0", + "status": "NEW", + "timeInForce": "GTC", + "type": "LIMIT", + "side": "SELL", + "selfTradePreventionMode": "NONE" + }, + { + "symbol": "BTCUSDT", + "orderId": 29896700, + "orderListId": 13551, + "clientOrderId": "dKQEdh5HhXb7Lpp85jz1dQ", + "transactTime": 1725521998054, + "price": "50000.00000000", + "origQty": "0.02000000", + "executedQty": "0", + "cummulativeQuoteQty": "0", + "status": "PENDING_NEW", + "timeInForce": "GTC", + "type": "LIMIT", + "side": "BUY", + "selfTradePreventionMode": "NONE" + } + ] + }`) + s.mockDo(data, nil) + defer s.assertDo() + + resp, err := s.client.NewMarginAccountNewOTOService(). + Symbol("BTCUSDT").WorkingType("LIMIT").WorkingSide("SELL").WorkingPrice(80000.0).WorkingQuantity(0.02). + PendingType("LIMIT").PendingSide("BUY").PendingQuantity(0.02).WorkingTimeInForce("GTC"). + PendingPrice(50000.0).PendingTimeInForce("GTC").Do(context.Background()) + + s.r().NoError(err) + s.Equal(int64(13551), resp.OrderListId) + s.Equal("OTO", resp.ContingencyType) + s.Equal("EXEC_STARTED", resp.ListStatusType) + s.Equal("EXECUTING", resp.ListOrderStatus) + s.Equal("JDuOrsu0Ge8GTyvx8J7VTD", resp.ListClientOrderId) + s.Equal(int64(1725521998054), resp.TransactionTime) + s.Equal("BTCUSDT", resp.Symbol) + s.False(resp.IsIsolated) + s.Len(resp.Orders, 2) + s.Equal("BTCUSDT", resp.Orders[0].Symbol) + s.Equal(int64(29896699), resp.Orders[0].OrderId) + s.Equal("y8RB6tQEMuHUXybqbtzTxk", resp.Orders[0].ClientOrderId) + s.Equal("BTCUSDT", resp.Orders[1].Symbol) + s.Equal(int64(29896700), resp.Orders[1].OrderId) + s.Equal("dKQEdh5HhXb7Lpp85jz1dQ", resp.Orders[1].ClientOrderId) + s.Len(resp.OrderReports, 2) + s.Equal("BTCUSDT", resp.OrderReports[0].Symbol) + s.Equal(int64(29896699), resp.OrderReports[0].OrderId) + s.Equal(int64(13551), resp.OrderReports[0].OrderListId) + s.Equal("y8RB6tQEMuHUXybqbtzTxk", resp.OrderReports[0].ClientOrderId) + s.Equal(int64(1725521998054), resp.OrderReports[0].TransactTime) + s.Equal("80000.00000000", resp.OrderReports[0].Price) + s.Equal("0.02000000", resp.OrderReports[0].OrigQty) + s.Equal("0", resp.OrderReports[0].ExecutedQty) + s.Equal("0", resp.OrderReports[0].CummulativeQuoteQty) + s.Equal("NEW", resp.OrderReports[0].Status) + s.Equal("GTC", resp.OrderReports[0].TimeInForce) + s.Equal("LIMIT", resp.OrderReports[0].Type) + s.Equal("SELL", resp.OrderReports[0].Side) + s.Equal("NONE", resp.OrderReports[0].SelfTradePreventionMode) + s.Equal("BTCUSDT", resp.OrderReports[1].Symbol) + s.Equal(int64(29896700), resp.OrderReports[1].OrderId) + s.Equal(int64(13551), resp.OrderReports[1].OrderListId) + s.Equal("dKQEdh5HhXb7Lpp85jz1dQ", resp.OrderReports[1].ClientOrderId) + s.Equal(int64(1725521998054), resp.OrderReports[1].TransactTime) + s.Equal("50000.00000000", resp.OrderReports[1].Price) + s.Equal("0.02000000", resp.OrderReports[1].OrigQty) + s.Equal("0", resp.OrderReports[1].ExecutedQty) + s.Equal("0", resp.OrderReports[1].CummulativeQuoteQty) + s.Equal("PENDING_NEW", resp.OrderReports[1].Status) + s.Equal("GTC", resp.OrderReports[1].TimeInForce) + s.Equal("LIMIT", resp.OrderReports[1].Type) + s.Equal("BUY", resp.OrderReports[1].Side) + s.Equal("NONE", resp.OrderReports[1].SelfTradePreventionMode) +} + +func (s *marginTestSuite) TestMarginAccountNewOTOCO() { + data := []byte(`{ + "orderListId": 13509, + "contingencyType": "OTO", + "listStatusType": "EXEC_STARTED", + "listOrderStatus": "EXECUTING", + "listClientOrderId": "u2AUo48LLef5qVenRtwJZy", + "transactionTime": 1725521881300, + "symbol": "BNBUSDT", + "isIsolated": false, + "orders": [ + { + "symbol": "BNBUSDT", + "orderId": 28282534, + "clientOrderId": "IfYDxvrZI4kiyqYpRH13iI" + }, + { + "symbol": "BNBUSDT", + "orderId": 28282535, + "clientOrderId": "0HCSsPRxVfW8BkTUy9z4np" + }, + { + "symbol": "BNBUSDT", + "orderId": 28282536, + "clientOrderId": "dypsgdxWnLY75kwT930cbD" + } + ], + "orderReports": [ + { + "symbol": "BNBUSDT", + "orderId": 28282534, + "orderListId": 13509, + "clientOrderId": "IfYDxvrZI4kiyqYpRH13iI", + "transactTime": 1725521881300, + "price": "300.00000000", + "origQty": "1.00000000", + "executedQty": "0", + "cummulativeQuoteQty": "0", + "status": "NEW", + "timeInForce": "GTC", + "type": "LIMIT", + "side": "BUY", + "selfTradePreventionMode": "NONE" + }, + { + "symbol": "BNBUSDT", + "orderId": 28282535, + "orderListId": 13509, + "clientOrderId": "0HCSsPRxVfW8BkTUy9z4np", + "transactTime": 1725521881300, + "price": "0E-8", + "origQty": "1.00000000", + "executedQty": "0", + "cummulativeQuoteQty": "0", + "status": "PENDING_NEW", + "timeInForce": "GTC", + "type": "STOP_LOSS", + "side": "SELL", + "stopPrice": "299.00000000", + "selfTradePreventionMode": "NONE" + }, + { + "symbol": "BNBUSDT", + "orderId": 28282536, + "orderListId": 13509, + "clientOrderId": "dypsgdxWnLY75kwT930cbD", + "transactTime": 1725521881300, + "price": "301.00000000", + "origQty": "1.00000000", + "executedQty": "0", + "cummulativeQuoteQty": "0", + "status": "PENDING_NEW", + "timeInForce": "GTC", + "type": "LIMIT_MAKER", + "side": "SELL", + "selfTradePreventionMode": "NONE" + } + ] + }`) + s.mockDo(data, nil) + defer s.assertDo() + + resp, err := s.client.NewMarginAccountNewOTOCOService(). + Symbol("BNBUSDT").WorkingType("LIMIT").WorkingSide("BUY").WorkingPrice(300).WorkingQuantity(1). + PendingSide("SELL").PendingQuantity(1).PendingAboveType("LIMIT_MAKER").WorkingTimeInForce("GTC"). + PendingAbovePrice(301.0).PendingBelowType("STOP_LOSS").PendingBelowPrice(299.0).Do(context.Background()) + + s.r().NoError(err) + s.Equal(int64(13509), resp.OrderListId) + s.Equal("OTO", resp.ContingencyType) + s.Equal("EXEC_STARTED", resp.ListStatusType) + s.Equal("EXECUTING", resp.ListOrderStatus) + s.Equal("u2AUo48LLef5qVenRtwJZy", resp.ListClientOrderId) + s.Equal(int64(1725521881300), resp.TransactionTime) + s.Equal("BNBUSDT", resp.Symbol) + s.False(resp.IsIsolated) + s.Len(resp.Orders, 3) + s.Equal("BNBUSDT", resp.Orders[0].Symbol) + s.Equal(int64(28282534), resp.Orders[0].OrderId) + s.Equal("IfYDxvrZI4kiyqYpRH13iI", resp.Orders[0].ClientOrderId) + s.Equal("BNBUSDT", resp.Orders[1].Symbol) + s.Equal(int64(28282535), resp.Orders[1].OrderId) + s.Equal("0HCSsPRxVfW8BkTUy9z4np", resp.Orders[1].ClientOrderId) + s.Equal("BNBUSDT", resp.Orders[2].Symbol) + s.Equal(int64(28282536), resp.Orders[2].OrderId) + s.Equal("dypsgdxWnLY75kwT930cbD", resp.Orders[2].ClientOrderId) + s.Len(resp.OrderReports, 3) + s.Equal("BNBUSDT", resp.OrderReports[0].Symbol) + s.Equal(int64(28282534), resp.OrderReports[0].OrderId) + s.Equal(int64(13509), resp.OrderReports[0].OrderListId) + s.Equal("IfYDxvrZI4kiyqYpRH13iI", resp.OrderReports[0].ClientOrderId) + s.Equal(int64(1725521881300), resp.OrderReports[0].TransactTime) + s.Equal("300.00000000", resp.OrderReports[0].Price) + s.Equal("1.00000000", resp.OrderReports[0].OrigQty) + s.Equal("0", resp.OrderReports[0].ExecutedQty) + s.Equal("0", resp.OrderReports[0].CummulativeQuoteQty) + s.Equal("NEW", resp.OrderReports[0].Status) + s.Equal("GTC", resp.OrderReports[0].TimeInForce) + s.Equal("LIMIT", resp.OrderReports[0].Type) + s.Equal("BUY", resp.OrderReports[0].Side) + s.Equal("NONE", resp.OrderReports[0].SelfTradePreventionMode) + s.Equal("BNBUSDT", resp.OrderReports[1].Symbol) + s.Equal(int64(28282535), resp.OrderReports[1].OrderId) + s.Equal(int64(13509), resp.OrderReports[1].OrderListId) + s.Equal("0HCSsPRxVfW8BkTUy9z4np", resp.OrderReports[1].ClientOrderId) + s.Equal(int64(1725521881300), resp.OrderReports[1].TransactTime) + s.Equal("0E-8", resp.OrderReports[1].Price) + s.Equal("1.00000000", resp.OrderReports[1].OrigQty) + s.Equal("0", resp.OrderReports[1].ExecutedQty) + s.Equal("0", resp.OrderReports[1].CummulativeQuoteQty) + s.Equal("PENDING_NEW", resp.OrderReports[1].Status) + s.Equal("GTC", resp.OrderReports[1].TimeInForce) + s.Equal("STOP_LOSS", resp.OrderReports[1].Type) + s.Equal("SELL", resp.OrderReports[1].Side) + s.Equal("NONE", resp.OrderReports[1].SelfTradePreventionMode) + s.Equal("299.00000000", resp.OrderReports[1].StopPrice) + s.Equal("BNBUSDT", resp.OrderReports[2].Symbol) + s.Equal(int64(28282536), resp.OrderReports[2].OrderId) + s.Equal(int64(13509), resp.OrderReports[2].OrderListId) + s.Equal("dypsgdxWnLY75kwT930cbD", resp.OrderReports[2].ClientOrderId) + s.Equal(int64(1725521881300), resp.OrderReports[2].TransactTime) + s.Equal("301.00000000", resp.OrderReports[2].Price) + s.Equal("1.00000000", resp.OrderReports[2].OrigQty) + s.Equal("0", resp.OrderReports[2].ExecutedQty) + s.Equal("0", resp.OrderReports[2].CummulativeQuoteQty) + s.Equal("PENDING_NEW", resp.OrderReports[2].Status) + s.Equal("GTC", resp.OrderReports[2].TimeInForce) + s.Equal("LIMIT_MAKER", resp.OrderReports[2].Type) + s.Equal("SELL", resp.OrderReports[2].Side) + s.Equal("NONE", resp.OrderReports[2].SelfTradePreventionMode) +} + func (s *marginTestSuite) TestMarginSmallLiabilityExchangeHistory() { data := []byte(`[ { @@ -1376,3 +1753,31 @@ func (s *marginTestSuite) TestMarginToggleBnbBurn() { s.Equal(true, resp.SpotBNBBurn) s.Equal(false, resp.InterestBNBBurn) } + +func (s *marginTestSuite) TestMarginIsolatedCapitalFlow() { + data := []byte(`[ + { + "id": 123456, + "tranId": 123123, + "timestamp": 1691116657000, + "asset": "USDT", + "symbol": "BTCUSDT", + "type": "BORROW", + "amount": "101" + } + ]`) + s.mockDo(data, nil) + defer s.assertDo() + + resp, err := s.client.NewMarginIsolatedCapitalFlowService().Do(context.Background()) + + s.r().NoError(err) + s.Len(resp, 1) + s.Equal(int(123456), resp[0].Id) + s.Equal(int(123123), resp[0].TranId) + s.Equal(uint64(1691116657000), resp[0].Timestamp) + s.Equal("USDT", resp[0].Asset) + s.Equal("BTCUSDT", resp[0].Symbol) + s.Equal("BORROW", resp[0].Type) + s.Equal("101", resp[0].Amount) +} diff --git a/market.go b/market.go index 4a611edc..322ba520 100644 --- a/market.go +++ b/market.go @@ -57,9 +57,12 @@ type ServerTimeResponse struct { // Binance Exchange Information endpoint (GET /api/v3/exchangeInfo) type ExchangeInfo struct { - c *Client - symbol *string - symbols *[]string + c *Client + symbol *string + symbols *[]string + permissions *string + showPermissionSets *bool + symbolStatus *string } // Symbol set symbol @@ -74,6 +77,24 @@ func (s *ExchangeInfo) Symbols(symbols []string) *ExchangeInfo { return s } +// Permissions set permissions +func (s *ExchangeInfo) Permissions(permissions string) *ExchangeInfo { + s.permissions = &permissions + return s +} + +// ShowPermissionSets set showPermissionSets +func (s *ExchangeInfo) ShowPermissionSets(showPermissionSets bool) *ExchangeInfo { + s.showPermissionSets = &showPermissionSets + return s +} + +// SymbolStatus set symbolStatus +func (s *ExchangeInfo) SymbolStatus(symbolStatus string) *ExchangeInfo { + s.symbolStatus = &symbolStatus + return s +} + // Send the request func (s *ExchangeInfo) Do(ctx context.Context, opts ...RequestOption) (res *ExchangeInfoResponse, err error) { r := &request{ @@ -87,6 +108,15 @@ func (s *ExchangeInfo) Do(ctx context.Context, opts ...RequestOption) (res *Exch if s.symbols != nil { r.setParam("symbols", *s.symbols) } + if s.permissions != nil { + r.setParam("permissions", *s.permissions) + } + if s.showPermissionSets != nil { + r.setParam("showPermissionSets", *s.showPermissionSets) + } + if s.symbolStatus != nil { + r.setParam("symbolStatus", *s.symbolStatus) + } data, err := s.c.callAPI(ctx, r, opts...) if err != nil { return nil, err @@ -130,9 +160,12 @@ type SymbolInfo struct { QuoteAsset string `json:"quoteAsset"` QuotePrecision int64 `json:"quotePrecision"` QuoteAssetPrecision int64 `json:"quoteAssetPrecision"` + BaseCommissionPrecision int64 `json:"baseCommissionPrecision"` + QuoteCommissionPrecision int64 `json:"quoteCommissionPrecision"` OrderTypes []string `json:"orderTypes"` IcebergAllowed bool `json:"icebergAllowed"` OcoAllowed bool `json:"ocoAllowed"` + OtoAllowed bool `json:"otoAllowed"` QuoteOrderQtyMarketAllowed bool `json:"quoteOrderQtyMarketAllowed"` AllowTrailingStop bool `json:"allowTrailingStop"` CancelReplaceAllowed bool `json:"cancelReplaceAllowed"` @@ -782,7 +815,7 @@ func (s *TickerPrice) Symbols(symbols []string) *TickerPrice { } // Send the request -func (s *TickerPrice) Do(ctx context.Context, opts ...RequestOption) (res *TickerPriceResponse, err error) { +func (s *TickerPrice) Do(ctx context.Context, opts ...RequestOption) (res []*TickerPriceResponse, err error) { r := &request{ method: http.MethodGet, endpoint: "/api/v3/ticker/price", @@ -798,10 +831,26 @@ func (s *TickerPrice) Do(ctx context.Context, opts ...RequestOption) (res *Ticke if err != nil { return nil, err } - res = new(TickerPriceResponse) - err = json.Unmarshal(data, res) + var raw json.RawMessage + err = json.Unmarshal(data, &raw) if err != nil { - return nil, err + return []*TickerPriceResponse{}, err + } + + if raw[0] == '[' { + res = make([]*TickerPriceResponse, 0) + err = json.Unmarshal(data, &res) + if err != nil { + return []*TickerPriceResponse{}, err + } + } else { + // The response is a single object, not an array, make sure to add it to the slice + singleRes := new(TickerPriceResponse) + err = json.Unmarshal(data, &singleRes) + if err != nil { + return []*TickerPriceResponse{}, err + } + res = append(res, singleRes) } return res, nil } diff --git a/subaccount.go b/subaccount.go index e838666b..08dd7e60 100644 --- a/subaccount.go +++ b/subaccount.go @@ -406,9 +406,11 @@ func (s *QuerySubAccountAssetsService) Do(ctx context.Context, opts ...RequestOp type QuerySubAccountAssetsResp struct { Balances []struct { - Asset string `json:"asset"` - Free string `json:"free"` - Locked string `json:"locked"` + Freeze string `json:"freeze"` + Withdrawing string `json:"withdrawing"` + Asset string `json:"asset"` + Free string `json:"free"` + Locked string `json:"locked"` } `json:"balances"` } @@ -2584,9 +2586,11 @@ func (s *QuerySubAccountAssetsForMasterAccountService) Do(ctx context.Context, o type QuerySubAccountAssetsForMasterAccountResp struct { Balances []struct { - Asset string `json:"asset"` - Free string `json:"free"` - Locked string `json:"locked"` + Freeze string `json:"freeze"` + Withdrawing string `json:"withdrawing"` + Asset string `json:"asset"` + Free string `json:"free"` + Locked string `json:"locked"` } `json:"balances"` } diff --git a/subaccount_test.go b/subaccount_test.go index 61ed51a6..0a222aab 100644 --- a/subaccount_test.go +++ b/subaccount_test.go @@ -1138,11 +1138,15 @@ func (s *subAccountTestSuite) TestQuerySubAccountAssets() { { "balances": [ { + "freeze":"0", + "withdrawing":"0", "asset": "BTC", "free": "0.1", "locked": "0.2" }, { + "freeze":"0", + "withdrawing":"0", "asset": "ETH", "free": "1.0", "locked": "2.0" @@ -1151,19 +1155,25 @@ func (s *subAccountTestSuite) TestQuerySubAccountAssets() { }`) expectedBalances := []struct { - Asset string - Free string - Locked string + Freeze string `json:"freeze"` + Withdrawing string `json:"withdrawing"` + Asset string `json:"asset"` + Free string `json:"free"` + Locked string `json:"locked"` }{ { - Asset: "BTC", - Free: "0.1", - Locked: "0.2", + Freeze: "0", + Withdrawing: "0", + Asset: "BTC", + Free: "0.1", + Locked: "0.2", }, { - Asset: "ETH", - Free: "1.0", - Locked: "2.0", + Freeze: "0", + Withdrawing: "0", + Asset: "ETH", + Free: "1.0", + Locked: "2.0", }, } @@ -1188,11 +1198,15 @@ func (s *subAccountTestSuite) TestQuerySubAccountAssetsForMasterAccount() { { "balances": [ { + "freeze":"0", + "withdrawing":"0", "asset": "BTC", "free": "0.005", "locked": "0.005" }, { + "freeze":"0", + "withdrawing":"0", "asset": "ETH", "free": "0.01", "locked": "0.01" @@ -1203,19 +1217,25 @@ func (s *subAccountTestSuite) TestQuerySubAccountAssetsForMasterAccount() { expectedResp := &QuerySubAccountAssetsForMasterAccountResp{ Balances: []struct { - Asset string `json:"asset"` - Free string `json:"free"` - Locked string `json:"locked"` + Freeze string `json:"freeze"` + Withdrawing string `json:"withdrawing"` + Asset string `json:"asset"` + Free string `json:"free"` + Locked string `json:"locked"` }{ { - Asset: "BTC", - Free: "0.005", - Locked: "0.005", + Freeze: "0", + Withdrawing: "0", + Asset: "BTC", + Free: "0.005", + Locked: "0.005", }, { - Asset: "ETH", - Free: "0.01", - Locked: "0.01", + Freeze: "0", + Withdrawing: "0", + Asset: "ETH", + Free: "0.01", + Locked: "0.01", }, }, } diff --git a/wallet.go b/wallet.go index dd31264a..01d21cd3 100644 --- a/wallet.go +++ b/wallet.go @@ -16,7 +16,7 @@ type GetSystemStatusService struct { c *Client } -func (s *GetSystemStatusService) Do(ctx context.Context, opts ...RequestOption) (*SystemStatusResponse, error) { +func (s *GetSystemStatusService) Do(ctx context.Context, opts ...RequestOption) (res *SystemStatusResponse, err error) { r := &request{ method: http.MethodGet, endpoint: systemStatusEndpoint, @@ -26,12 +26,12 @@ func (s *GetSystemStatusService) Do(ctx context.Context, opts ...RequestOption) if err != nil { return nil, err } - var res SystemStatusResponse + res = new(SystemStatusResponse) err = json.Unmarshal(data, &res) if err != nil { return nil, err } - return &res, nil + return res, nil } // SystemStatusResponse define response of GetSystemStatusService @@ -40,6 +40,40 @@ type SystemStatusResponse struct { Msg string `json:"msg"` } +// Get symbols delist schedule for spot (MARKET_DATA) +const ( + symbolsDelistScheduleEndpoint = "/sapi/v1/spot/delist-schedule" +) + +// GetSymbolsDelistScheduleService get symbols delist schedule +type GetSymbolsDelistScheduleService struct { + c *Client +} + +func (s *GetSymbolsDelistScheduleService) Do(ctx context.Context) (res []*SymbolsDelistScheduleResponse, err error) { + r := &request{ + method: http.MethodGet, + endpoint: symbolsDelistScheduleEndpoint, + secType: secTypeNone, + } + data, err := s.c.callAPI(ctx, r) + if err != nil { + return nil, err + } + res = make([]*SymbolsDelistScheduleResponse, 0) + err = json.Unmarshal(data, &res) + if err != nil { + return nil, err + } + return res, nil +} + +// SymbolsDelistScheduleResponse define response of GetSymbolsDelistScheduleService +type SymbolsDelistScheduleResponse struct { + DelistTime uint64 `json:"delistTime"` + Symbols []string `json:"symbols"` +} + // All Coins' Information (USER_DATA) const ( allCoinsInfoEndpoint = "/sapi/v1/capital/config/getall" @@ -89,7 +123,6 @@ type CoinInfo struct { MinConfirm int `json:"minConfirm"` Name string `json:"name"` Network string `json:"network"` - ResetAddressStatus bool `json:"resetAddressStatus"` SpecialTips string `json:"specialTips"` UnLockConfirm int `json:"unLockConfirm"` WithdrawDesc string `json:"withdrawDesc"` @@ -101,6 +134,8 @@ type CoinInfo struct { SameAddress bool `json:"sameAddress"` EstimatedArrivalTime uint64 `json:"estimatedArrivalTime"` Busy bool `json:"busy"` + ContractAddressUrl string `json:"contractAddressUrl"` + ContractAddress string `json:"contractAddress"` } `json:"networkList"` Storage string `json:"storage"` Trading bool `json:"trading"` @@ -617,6 +652,7 @@ type DepositAddressService struct { c *Client coin string network *string + amount *float64 } // Coin set coin @@ -631,6 +667,12 @@ func (s *DepositAddressService) Network(network string) *DepositAddressService { return s } +// Amount set amount +func (s *DepositAddressService) Amount(amount float64) *DepositAddressService { + s.amount = &amount + return s +} + func (s *DepositAddressService) Do(ctx context.Context) (res *DepositAddressResponse, err error) { r := &request{ method: http.MethodGet, @@ -641,6 +683,9 @@ func (s *DepositAddressService) Do(ctx context.Context) (res *DepositAddressResp if s.network != nil { r.setParam("network", *s.network) } + if s.amount != nil { + r.setParam("amount", s.amount) + } data, err := s.c.callAPI(ctx, r) if err != nil { return nil, err @@ -661,6 +706,60 @@ type DepositAddressResponse struct { Url string `json:"url"` } +// Fetch deposit address list with network (USER_DATA) +const ( + depositAddressListEndpoint = "/sapi/v1/capital/deposit/address/list" +) + +// DepositAddressListService deposit address list +type DepositAddressListService struct { + c *Client + coin string + network *string +} + +// Coin set coin +func (s *DepositAddressListService) Coin(coin string) *DepositAddressListService { + s.coin = coin + return s +} + +// Network set network +func (s *DepositAddressListService) Network(network string) *DepositAddressListService { + s.network = &network + return s +} + +func (s *DepositAddressListService) Do(ctx context.Context) (res []*DepositAddressListResponse, err error) { + r := &request{ + method: http.MethodGet, + endpoint: depositAddressListEndpoint, + secType: secTypeSigned, + } + r.setParam("coin", s.coin) + if s.network != nil { + r.setParam("network", *s.network) + } + data, err := s.c.callAPI(ctx, r) + if err != nil { + return nil, err + } + res = make([]*DepositAddressListResponse, 0) + err = json.Unmarshal(data, &res) + if err != nil { + return nil, err + } + return res, nil +} + +// DepositAddressListResponse define response of DepositAddressListService +type DepositAddressListResponse struct { + Coin string `json:"coin"` + Address string `json:"address"` + Tag string `json:"tag"` + IsDefault int32 `json:"isDefault"` +} + // Account Status (USER_DATA) const ( accountStatusEndpoint = "/sapi/v1/account/status" @@ -810,7 +909,14 @@ const ( // AssetDetailService asset detail type AssetDetailService struct { - c *Client + c *Client + accountType *string +} + +// AccountType set accountType +func (s *AssetDetailService) AccountType(accountType string) *AssetDetailService { + s.accountType = &accountType + return s } func (s *AssetDetailService) Do(ctx context.Context) (res *AssetDetailResponse, err error) { @@ -819,6 +925,9 @@ func (s *AssetDetailService) Do(ctx context.Context) (res *AssetDetailResponse, endpoint: assetDetailEndpoint, secType: secTypeSigned, } + if s.accountType != nil { + r.setParam("accountType", *s.accountType) + } data, err := s.c.callAPI(ctx, r) if err != nil { return nil, err @@ -1021,6 +1130,41 @@ func (s *AssetDetailV2Service) Do(ctx context.Context) (res *AssetDetailV2Respon return res, nil } +// Query User Wallet Balance +const ( + walletBalanceEndpoint = "/sapi/v1/asset/wallet/balance" +) + +// WalletBalanceService gets the user wallet balance. +type WalletBalanceService struct { + c *Client +} + +func (s *WalletBalanceService) Do(ctx context.Context) (res []*WalletBalanceResponse, err error) { + r := &request{ + method: http.MethodGet, + endpoint: walletBalanceEndpoint, + secType: secTypeSigned, + } + data, err := s.c.callAPI(ctx, r) + if err != nil { + return nil, err + } + res = make([]*WalletBalanceResponse, 0) + err = json.Unmarshal(data, &res) + if err != nil { + return nil, err + } + return res, nil +} + +// WalletBalanceResponse defines the response of WalletBalanceService +type WalletBalanceResponse struct { + Activate bool `json:"activate"` + Balance string `json:"balance"` + WalletName string `json:"walletName"` +} + // AssetDetailV2Response define response of AssetDetailV2Service type AssetDetailV2Response struct { AssetDetail struct { @@ -1380,82 +1524,6 @@ type UserAssetResponse struct { BtcValuation string `json:"btcValuation"` } -// BUSD Convert (TRADE) -const ( - bUSDConvertEndpoint = "/sapi/v1/asset/convert-transfer" -) - -// BUSDConvertService BUSD convert -type BUSDConvertService struct { - c *Client - clientTranId string - asset string - amount float64 - targetAsset string - accountType *string -} - -// ClientTranId set clientTranId -func (s *BUSDConvertService) ClientTranId(clientTranId string) *BUSDConvertService { - s.clientTranId = clientTranId - return s -} - -// Asset set asset -func (s *BUSDConvertService) Asset(asset string) *BUSDConvertService { - s.asset = asset - return s -} - -// Amount set amount -func (s *BUSDConvertService) Amount(amount float64) *BUSDConvertService { - s.amount = amount - return s -} - -// TargetAsset set targetAsset -func (s *BUSDConvertService) TargetAsset(targetAsset string) *BUSDConvertService { - s.targetAsset = targetAsset - return s -} - -// AccountType set accountType -func (s *BUSDConvertService) AccountType(accountType string) *BUSDConvertService { - s.accountType = &accountType - return s -} - -func (s *BUSDConvertService) Do(ctx context.Context) (res *BUSDConvertResponse, err error) { - r := &request{ - method: http.MethodPost, - endpoint: bUSDConvertEndpoint, - secType: secTypeSigned, - } - r.setParam("clientTranId", s.clientTranId) - r.setParam("asset", s.asset) - r.setParam("amount", s.amount) - r.setParam("targetAsset", s.targetAsset) - if s.accountType != nil { - r.setParam("accountType", *s.accountType) - } - data, err := s.c.callAPI(ctx, r) - if err != nil { - return nil, err - } - res = new(BUSDConvertResponse) - err = json.Unmarshal(data, res) - if err != nil { - return nil, err - } - return res, nil -} - -// BUSDConvertResponse define response of BUSDConvertService -type BUSDConvertResponse struct { - TranId int64 `json:"tranId"` - Status string `json:"status"` -} - // BUSD Convert History (USER_DATA) const ( bUSDConvertHistoryEndpoint = "/sapi/v1/asset/convert-transfer/queryByPage" @@ -1683,27 +1751,91 @@ type CloudMiningPaymentHistoryResponse struct { } `json:"rows"` } -// Get API Key Permission (USER_DATA) +// Query User Delegation History(For Master Account) const ( - apiKeyPermissionEndpoint = "/sapi/v1/account/apiRestrictions" + UserDelegationHistoryEndpoint = "/sapi/v1/asset/custody/transfer-history" ) -// APIKeyPermissionService get api key permission -type APIKeyPermissionService struct { - c *Client +// UserDelegationHistoryService cloud mining refund history +type UserDelegationHistoryService struct { + c *Client + email string + startTime uint64 + endTime uint64 + delegationType *string + asset *string + current *int + size *int } -func (s *APIKeyPermissionService) Do(ctx context.Context) (res *APIKeyPermissionResponse, err error) { +// Tranid set tranid +func (s *UserDelegationHistoryService) Email(email string) *UserDelegationHistoryService { + s.email = email + return s +} + +// StartTime set startTime +func (s *UserDelegationHistoryService) StartTime(startTime uint64) *UserDelegationHistoryService { + s.startTime = startTime + return s +} + +// EndTime set endTime +func (s *UserDelegationHistoryService) EndTime(endTime uint64) *UserDelegationHistoryService { + s.endTime = endTime + return s +} + +// ClientTranId set clientTranId +func (s *UserDelegationHistoryService) DelegationType(delegationType string) *UserDelegationHistoryService { + s.delegationType = &delegationType + return s +} + +// Asset set asset +func (s *UserDelegationHistoryService) Asset(asset string) *UserDelegationHistoryService { + s.asset = &asset + return s +} + +// Current set current +func (s *UserDelegationHistoryService) Current(current int) *UserDelegationHistoryService { + s.current = ¤t + return s +} + +// Size set size +func (s *UserDelegationHistoryService) Size(size int) *UserDelegationHistoryService { + s.size = &size + return s +} + +func (s *UserDelegationHistoryService) Do(ctx context.Context) (res *UserDelegationHistoryResponse, err error) { r := &request{ method: http.MethodGet, - endpoint: apiKeyPermissionEndpoint, + endpoint: UserDelegationHistoryEndpoint, secType: secTypeSigned, } + r.setParam("email", s.email) + r.setParam("startTime", s.startTime) + r.setParam("endTime", s.endTime) + if s.delegationType != nil { + r.setParam("clientTranId", *s.delegationType) + } + if s.asset != nil { + r.setParam("asset", *s.asset) + } + if s.current != nil { + r.setParam("current", *s.current) + } + if s.size != nil { + r.setParam("size", *s.size) + } data, err := s.c.callAPI(ctx, r) if err != nil { return nil, err } - res = new(APIKeyPermissionResponse) + res = new(UserDelegationHistoryResponse) err = json.Unmarshal(data, res) if err != nil { return nil, err @@ -1711,42 +1843,39 @@ func (s *APIKeyPermissionService) Do(ctx context.Context) (res *APIKeyPermission return res, nil } -// APIKeyPermissionResponse define response of APIKeyPermissionService -type APIKeyPermissionResponse struct { - IPRestrict bool `json:"ipRestrict"` - CreateTime uint64 `json:"createTime"` - EnableWithdrawals bool `json:"enableWithdrawals"` - EnableInternalTransfer bool `json:"enableInternalTransfer"` - PermitsUniversalTransfer bool `json:"permitsUniversalTransfer"` - EnableVanillaOptions bool `json:"enableVanillaOptions"` - EnableReading bool `json:"enableReading"` - EnableFutures bool `json:"enableFutures"` - EnableMargin bool `json:"enableMargin"` - EnableSpotAndMarginTrading bool `json:"enableSpotAndMarginTrading"` - TradingAuthorityExpirationTime uint64 `json:"tradingAuthorityExpirationTime"` -} - -// Query auto-converting stable coins (USER_DATA) +// UserDelegationHistoryResponse define response of UserDelegationHistoryService +type UserDelegationHistoryResponse struct { + Total int32 `json:"total"` + Rows []struct { + ClientTranId string `json:"clientTranId"` + TransferType string `json:"transferType"` + Asset string `json:"asset"` + Amount string `json:"amount"` + Time uint64 `json:"time"` + } `json:"rows"` +} + +// Account info (USER_DATA) const ( - autoConvertStableCoinEndpoint = "/sapi/v1/capital/contract/convertible-coins" + accountInfoEndpoint = "/sapi/v1/account/info" ) -// AutoConvertStableCoinService auto convert stable coin -type AutoConvertStableCoinService struct { +// AccountInfoService account info +type AccountInfoService struct { c *Client } -func (s *AutoConvertStableCoinService) Do(ctx context.Context) (res *AutoConvertStableCoinResponse, err error) { +func (s *AccountInfoService) Do(ctx context.Context) (res *AccountInfoResponse, err error) { r := &request{ method: http.MethodGet, - endpoint: autoConvertStableCoinEndpoint, + endpoint: accountInfoEndpoint, secType: secTypeSigned, } data, err := s.c.callAPI(ctx, r) if err != nil { return nil, err } - res = new(AutoConvertStableCoinResponse) + res = new(AccountInfoResponse) err = json.Unmarshal(data, res) if err != nil { return nil, err @@ -1754,48 +1883,56 @@ func (s *AutoConvertStableCoinService) Do(ctx context.Context) (res *AutoConvert return res, nil } -// AutoConvertStableCoinResponse define response of AutoConvertStableCoinService -type AutoConvertStableCoinResponse struct { - ConvertEnabled bool `json:"convertEnabled"` - Coins []struct { - Asset string `json:"coin"` - } `json:"coins"` - ExchangeRates []struct { - Asset string `json:"coin"` - } `json:"exchangeRates"` +// AccountInfoResponse define response of AccountInfoService +type AccountInfoResponse struct { + VipLevel int `json:"vipLevel"` + IsMarginEnabled bool `json:"isMarginEnabled"` + IsFutureEnabled bool `json:"isFutureEnabled"` + IsOptionsEnabled bool `json:"isOptionsEnabled"` + IsPortfolioMarginRetailEnabled bool `json:"isPortfolioMarginRetailEnabled"` } -// Wallet Balance (USER_DATA) +// Get API Key Permission (USER_DATA) const ( - walletBalanceEndpoint = "/sapi/v1/asset/wallet/balance" + apiKeyPermissionEndpoint = "/sapi/v1/account/apiRestrictions" ) -// WalletBalanceService gets the user wallet balance in BTC. -type WalletBalanceService struct { +// APIKeyPermissionService get api key permission +type APIKeyPermissionService struct { c *Client } -func (s *WalletBalanceService) Do(ctx context.Context) (res []*WalletBalanceResponse, err error) { +func (s *APIKeyPermissionService) Do(ctx context.Context) (res *APIKeyPermissionResponse, err error) { r := &request{ method: http.MethodGet, - endpoint: walletBalanceEndpoint, + endpoint: apiKeyPermissionEndpoint, secType: secTypeSigned, } data, err := s.c.callAPI(ctx, r) if err != nil { return nil, err } - res = make([]*WalletBalanceResponse, 0) - err = json.Unmarshal(data, &res) + res = new(APIKeyPermissionResponse) + err = json.Unmarshal(data, res) if err != nil { return nil, err } return res, nil } -// WalletBalanceResponse defines the response of WalletBalanceService -type WalletBalanceResponse struct { - Activate bool `json:"activate"` - Balance string `json:"balance"` - WalletName string `json:"walletName"` +// APIKeyPermissionResponse define response of APIKeyPermissionService +type APIKeyPermissionResponse struct { + IPRestrict bool `json:"ipRestrict"` + CreateTime uint64 `json:"createTime"` + EnableReading bool `json:"enableReading"` + EnableWithdrawals bool `json:"enableWithdrawals"` + EnableInternalTransfer bool `json:"enableInternalTransfer"` + EnableMargin bool `json:"enableMargin"` + EnableFutures bool `json:"enableFutures"` + PermitsUniversalTransfer bool `json:"permitsUniversalTransfer"` + EnableVanillaOptions bool `json:"enableVanillaOptions"` + EnableFixApiTrade bool `json:"enableFixApiTrade"` + EnableFixReadOnly bool `json:"enableFixReadOnly"` + EnableSpotAndMarginTrading bool `json:"enableSpotAndMarginTrading"` + EnablePortfolioMarginTrading bool `json:"enablePortfolioMarginTrading"` } diff --git a/wallet_test.go b/wallet_test.go index 848880cd..cbd4e3e4 100644 --- a/wallet_test.go +++ b/wallet_test.go @@ -191,77 +191,73 @@ func (s *walletTestSuite) TestUserUniversalTransfer() { r.Equal(int64(13526853623), res.TranId) } -func (s *walletTestSuite) TestBusdConvert() { +func (s *walletTestSuite) TestGetDepositAddress() { data := []byte(` { - "tranId": 13526853623, - "status": "S" + "address": "1HPn8Rx2y6nNSfagQBKy27GB99Vbzg89wv", + "coin": "BTC", + "tag": "", + "url": "https://btc.com/1HPn8Rx2y6nNSfagQBKy27GB99Vbzg89wv" } `) s.mockDo(data, nil) defer s.assertDo() - clientTranId := "X7612JSNTO8274HXUQJ2" - asset := "USDT" - amount := float64(20) - targetAsset := "BUSD" - + coin := "BTC" + network := "BTC" s.assertReq(func(r *request) { e := newSignedRequest().setParams(params{ - "clientTranId": clientTranId, - "asset": asset, - "amount": amount, - "targetAsset": targetAsset, + "coin": coin, + "network": network, }) s.assertRequestEqual(e, r) }) - res, err := s.client.NewBUSDConvertService(). - ClientTranId(clientTranId). - Asset(asset). - Amount(amount). - TargetAsset(targetAsset). + res, err := s.client.NewDepositAddressService(). + Coin(coin). + Network(network). Do(newContext()) r := s.r() r.NoError(err) - r.Equal(int64(13526853623), res.TranId) - r.Equal("S", res.Status) + r.Equal("1HPn8Rx2y6nNSfagQBKy27GB99Vbzg89wv", res.Address) + r.Equal("", res.Tag) + r.Equal("BTC", res.Coin) + r.Equal("https://btc.com/1HPn8Rx2y6nNSfagQBKy27GB99Vbzg89wv", res.Url) } -func (s *walletTestSuite) TestGetDepositAddress() { - data := []byte(` - { - "address": "1HPn8Rx2y6nNSfagQBKy27GB99Vbzg89wv", - "coin": "BTC", - "tag": "", - "url": "https://btc.com/1HPn8Rx2y6nNSfagQBKy27GB99Vbzg89wv" - } +func (s *walletTestSuite) TestDepositAddressListService() { + data := []byte(`[ + { + "coin": "ETH", + "address": "0xD316E95Fd9E8E237Cb11f8200Babbc5D8D177BA4", + "tag":"", + "isDefault": 0 + } + ] `) s.mockDo(data, nil) defer s.assertDo() coin := "BTC" - network := "BTC" s.assertReq(func(r *request) { e := newSignedRequest().setParams(params{ - "coin": coin, - "network": network, + "coin": coin, }) s.assertRequestEqual(e, r) }) - res, err := s.client.NewDepositAddressService(). + res, err := s.client.NewDepositAddressListService(). Coin(coin). - Network(network). Do(newContext()) r := s.r() r.NoError(err) - r.Equal("1HPn8Rx2y6nNSfagQBKy27GB99Vbzg89wv", res.Address) - r.Equal("", res.Tag) - r.Equal("BTC", res.Coin) - r.Equal("https://btc.com/1HPn8Rx2y6nNSfagQBKy27GB99Vbzg89wv", res.Url) + s.Len(res, 1) + r.Equal("ETH", res[0].Coin) + r.Equal("0xD316E95Fd9E8E237Cb11f8200Babbc5D8D177BA4", res[0].Address) + r.Equal("", res[0].Tag) + r.Equal(int32(0), res[0].IsDefault) } func (s *walletTestSuite) TestAccountApiTradingStatus() { @@ -313,17 +309,19 @@ func (s *walletTestSuite) TestAccountStatusService() { func (s *walletTestSuite) TestAPIKeyPermission() { data := []byte(` { - "ipRestrict": false, - "createTime": 1638289749000, - "enableWithdrawals": true, - "enableInternalTransfer": true, - "permitsUniversalTransfer": true, - "enableVanillaOptions": true, - "enableReading": true, - "enableFutures": true, - "enableMargin": true, - "enableSpotAndMarginTrading": true, - "tradingAuthorityExpirationTime": 1640978149000 + "ipRestrict":false, + "createTime":1698645219000, + "enableReading":true, + "enableWithdrawals":false, + "enableInternalTransfer":false, + "enableMargin":false, + "enableFutures":false, + "permitsUniversalTransfer":false, + "enableVanillaOptions":false, + "enableFixApiTrade": false, + "enableFixReadOnly": true, + "enableSpotAndMarginTrading":false, + "enablePortfolioMarginTrading":true } `) @@ -335,16 +333,18 @@ func (s *walletTestSuite) TestAPIKeyPermission() { s.r().NoError(err) s.NotNil(resp) s.False(resp.IPRestrict) - s.Equal(uint64(1638289749000), resp.CreateTime) - s.True(resp.EnableWithdrawals) - s.True(resp.EnableInternalTransfer) - s.True(resp.PermitsUniversalTransfer) - s.True(resp.EnableVanillaOptions) + s.Equal(uint64(1698645219000), resp.CreateTime) s.True(resp.EnableReading) - s.True(resp.EnableFutures) - s.True(resp.EnableMargin) - s.True(resp.EnableSpotAndMarginTrading) - s.Equal(uint64(1640978149000), resp.TradingAuthorityExpirationTime) + s.False(resp.EnableWithdrawals) + s.False(resp.EnableInternalTransfer) + s.False(resp.EnableMargin) + s.False(resp.EnableFutures) + s.False(resp.PermitsUniversalTransfer) + s.False(resp.EnableVanillaOptions) + s.False(resp.EnableFixApiTrade) + s.True(resp.EnableFixReadOnly) + s.False(resp.EnableSpotAndMarginTrading) + s.True(resp.EnablePortfolioMarginTrading) } func (s *walletTestSuite) TestAssetDetail() { @@ -415,6 +415,84 @@ func (s *walletTestSuite) TestAssetDetailV2() { s.Equal("Please don't deposit any other assets except RUB", resp.AssetDetail.DepositTip) } +func (s *walletTestSuite) TestWalletBalance() { + data := []byte(`[ + { + "activate": true, + "balance": "0", + "walletName": "Spot" + }, + { + "activate": true, + "balance": "0", + "walletName": "Funding" + }, + { + "activate": true, + "balance": "0", + "walletName": "Cross Margin" + }, + { + "activate": true, + "balance": "0", + "walletName": "Isolated Margin" + }, + { + "activate": true, + "balance": "0.71842752", + "walletName": "USDⓈ-M Futures" + }, + { + "activate": true, + "balance": "0", + "walletName": "COIN-M Futures" + }, + { + "activate": true, + "balance": "0", + "walletName": "Earn" + }, + { + "activate": false, + "balance": "0", + "walletName": "Options" + } + ] + `) + + s.mockDo(data, nil) + defer s.assertDo() + + resp, err := s.client.NewWalletBalanceService().Do(context.Background()) + + s.r().NoError(err) + s.Len(resp, 8) + s.Equal(true, resp[0].Activate) + s.Equal("0", resp[0].Balance) + s.Equal("Spot", resp[0].WalletName) + s.Equal(true, resp[1].Activate) + s.Equal("0", resp[1].Balance) + s.Equal("Funding", resp[1].WalletName) + s.Equal(true, resp[2].Activate) + s.Equal("0", resp[2].Balance) + s.Equal("Cross Margin", resp[2].WalletName) + s.Equal(true, resp[3].Activate) + s.Equal("0", resp[3].Balance) + s.Equal("Isolated Margin", resp[3].WalletName) + s.Equal(true, resp[4].Activate) + s.Equal("0.71842752", resp[4].Balance) + s.Equal("USDⓈ-M Futures", resp[4].WalletName) + s.Equal(true, resp[5].Activate) + s.Equal("0", resp[5].Balance) + s.Equal("COIN-M Futures", resp[5].WalletName) + s.Equal(true, resp[6].Activate) + s.Equal("0", resp[6].Balance) + s.Equal("Earn", resp[6].WalletName) + s.Equal(false, resp[7].Activate) + s.Equal("0", resp[7].Balance) + s.Equal("Options", resp[7].WalletName) +} + func (s *walletTestSuite) TestAssetDividendRecord() { data := []byte(` { @@ -453,44 +531,6 @@ func (s *walletTestSuite) TestAssetDividendRecord() { s.Equal(int64(1), resp.Total) } -func (s *walletTestSuite) TestAutoConvertStableCoin() { - data := []byte(` - { - "convertEnabled": true, - "coins": [ - { - "coin": "BUSD" - }, - { - "coin": "USDT" - } - ], - "exchangeRates": [ - { - "coin": "BUSD" - }, - { - "coin": "USDT" - } - ] - } - `) - - s.mockDo(data, nil) - defer s.assertDo() - - resp, err := s.client.NewAutoConvertStableCoinService().Do(context.Background()) - - s.r().NoError(err) - s.True(resp.ConvertEnabled) - s.Len(resp.Coins, 2) - s.Equal("BUSD", resp.Coins[0].Asset) - s.Equal("USDT", resp.Coins[1].Asset) - s.Len(resp.ExchangeRates, 2) - s.Equal("BUSD", resp.ExchangeRates[0].Asset) - s.Equal("USDT", resp.ExchangeRates[1].Asset) -} - func (s *walletTestSuite) TestBUSDConvertHistory() { data := []byte(` { @@ -572,6 +612,64 @@ func (s *walletTestSuite) TestCloudMiningPaymentHistory() { s.Equal(int32(1), resp.Total) } +func (s *walletTestSuite) TestUserDelegationHistory() { + data := []byte(` + { + "total": 3316, + "rows": [ + { + "clientTranId": "293915932290879488", + "transferType": "Undelegate", + "asset": "ETH", + "amount": "1", + "time": 1695205406000 + } + ] + } + `) + + s.mockDo(data, nil) + defer s.assertDo() + + resp, err := s.client.NewUserDelegationHistoryService(). + Email("email@email.com"). + StartTime(1695200406000). + EndTime(1695210406000). + Do(context.Background()) + + s.r().NoError(err) + s.Len(resp.Rows, 1) + s.Equal("293915932290879488", resp.Rows[0].ClientTranId) + s.Equal("Undelegate", resp.Rows[0].TransferType) + s.Equal("ETH", resp.Rows[0].Asset) + s.Equal("1", resp.Rows[0].Amount) + s.Equal(uint64(1695205406000), resp.Rows[0].Time) + s.Equal(int32(3316), resp.Total) +} + +func (s *walletTestSuite) TestAccountInfo() { + data := []byte(` + { + "vipLevel": 0, + "isMarginEnabled": true, + "isFutureEnabled": true, + "isOptionsEnabled":true, + "isPortfolioMarginRetailEnabled":true + } + `) + + s.mockDo(data, nil) + defer s.assertDo() + + resp, err := s.client.NewAccountInfoService().Do(context.Background()) + s.r().NoError(err) + s.Equal(0, resp.VipLevel) + s.True(resp.IsMarginEnabled) + s.True(resp.IsFutureEnabled) + s.True(resp.IsOptionsEnabled) + s.True(resp.IsPortfolioMarginRetailEnabled) +} + func (s *walletTestSuite) TestDepositHistory() { data := []byte(` [ @@ -790,7 +888,6 @@ func (s *walletTestSuite) TestGetAllCoinsInfoService() { "minConfirm": 1, "name": "BEP2", "network": "BNB", - "resetAddressStatus": false, "specialTips": "", "unLockConfirm": 0, "withdrawDesc": "Withdrawal to address", @@ -801,7 +898,9 @@ func (s *walletTestSuite) TestGetAllCoinsInfoService() { "withdrawMin": "0.00200000", "sameAddress": false, "estimatedArrivalTime": 0, - "busy": false + "busy": false, + "contractAddressUrl": "", + "contractAddress": "" } ], "storage": "0.00000000", @@ -838,7 +937,6 @@ func (s *walletTestSuite) TestGetAllCoinsInfoService() { s.Equal(1, resp[0].NetworkList[0].MinConfirm) s.Equal("BEP2", resp[0].NetworkList[0].Name) s.Equal("BNB", resp[0].NetworkList[0].Network) - s.False(resp[0].NetworkList[0].ResetAddressStatus) s.Equal("", resp[0].NetworkList[0].SpecialTips) s.Equal(0, resp[0].NetworkList[0].UnLockConfirm) s.Equal("Withdrawal to address", resp[0].NetworkList[0].WithdrawDesc) @@ -850,18 +948,52 @@ func (s *walletTestSuite) TestGetAllCoinsInfoService() { s.False(resp[0].NetworkList[0].SameAddress) s.Equal(uint64(0), resp[0].NetworkList[0].EstimatedArrivalTime) s.False(resp[0].NetworkList[0].Busy) + s.Equal("", resp[0].NetworkList[0].ContractAddressUrl) + s.Equal("", resp[0].NetworkList[0].ContractAddress) s.Equal("0.00000000", resp[0].Storage) s.True(resp[0].Trading) s.True(resp[0].WithdrawAllEnable) s.Equal("0.00000000", resp[0].Withdrawing) } -func (s *walletTestSuite) TestGetSystemStatus() { - data := []byte(` +func (s *walletTestSuite) TestGetSymbolsDelistSchedule() { + data := []byte(`[ { - "status": 0, - "msg": "normal" + "delistTime": 1686161202000, + "symbols": [ + "ADAUSDT", + "BNBUSDT" + ] + }, + { + "delistTime": 1686222232000, + "symbols": [ + "ETHUSDT" + ] } + ] + `) + + s.mockDo(data, nil) + defer s.assertDo() + + resp, err := s.client.NewGetSymbolsDelistScheduleService().Do(context.Background()) + + s.r().NoError(err) + s.Len(resp, 2) + s.Equal(uint64(1686161202000), resp[0].DelistTime) + s.Equal("ADAUSDT", resp[0].Symbols[0]) + s.Equal("BNBUSDT", resp[0].Symbols[1]) + s.Equal(uint64(1686222232000), resp[1].DelistTime) + s.Equal("ETHUSDT", resp[1].Symbols[0]) +} + +func (s *walletTestSuite) TestGetSystemStatus() { + data := []byte(` + { + "status": 0, + "msg": "normal" + } `) s.mockDo(data, nil) diff --git a/websocket_api.go b/websocket_api.go index 977ac5f1..64809603 100644 --- a/websocket_api.go +++ b/websocket_api.go @@ -270,7 +270,7 @@ type TestConnectivityResponse struct { Status int `json:"status"` Error *WsAPIErrorResponse `json:"error,omitempty"` Result struct{} `json:"result,omitempty"` - RateLimits WsAPIRateLimit `json:"rateLimits,omitempty"` + RateLimits []*WsAPIRateLimit `json:"rateLimits,omitempty"` } type CheckServerTimeService struct { diff --git a/websocket_api_account.go b/websocket_api_account.go index ef8ff065..411a91d8 100644 --- a/websocket_api_account.go +++ b/websocket_api_account.go @@ -283,7 +283,7 @@ type OrderHistoryItem struct { Price string `json:"price"` OrigQty string `json:"origQty"` ExecutedQty string `json:"executedQty"` - CumulativeQuoteQty string `json:"cummulativeQuoteQty"` + CummulativeQuoteQty string `json:"cummulativeQuoteQty"` Status string `json:"status"` TimeInForce string `json:"timeInForce"` Type string `json:"type"`