mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-06-06 23:16:53 +00:00
context: Add authenticated HTTP credentials (#892)
* gRPC: context overide * exchanges: continue update * exchange: Update context handling *Add setter methods for API credentials *Shift credentials functionality to its own file in exchanges package *Add tests *Refactor function DeployCredentialsToContext for library usage *Add function to process credential metadata from API boundary to internal use context value. *Add OTP rpc handling * exchanges: reverts to old style in GetFeeByType, reverts some code I accidently deleted. Plus things and other. XD * template: update * exchanges: fix linter issues * REMOVE THAT AWESOME NEW LINE! * gct: fix some tests * I cant spell :( * exchanges/gctscript: fix more tests * coinnut: fix tests * Update exchanges/credentials.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * Update exchanges/credentials.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * Update exchanges/credentials.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * Update exchanges/credentials.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * Update exchanges/credentials.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * glorious: nits * exchanges/gctcli: stop applying empty credentials * fix linters * exchanges: add test * rpceserver: actually check error for errors * rpcserver: fix up tests * Update exchanges/credentials.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * exchanges/creds: move tests to corresponding files, add protection and segration for Credentials struct & ptr values * exchanges/creds: allow subaccount to override default credentials via gRPC * exchanges/credentials: don't return nil in GetCredentials * creds: spelling * exchanges: fix glorious NITS! * credentials: Add in test and refactor IsEmpty method. * credentials: change type positioning (glorious) * exchange_template: Fix template changes * DOCS: Refresh * docs: fix spelling * DOCS: fix alignment and add package * DOCS: ALIGN! Co-authored-by: Ryan O'Hara-Reid <ryan.oharareid@thrasher.io> Co-authored-by: Scott <gloriousCode@users.noreply.github.com>
This commit is contained in:
@@ -388,7 +388,7 @@ func (f *FTX) GetMarginBorrowRates(ctx context.Context) ([]MarginFundingData, er
|
||||
r := struct {
|
||||
Data []MarginFundingData `json:"result"`
|
||||
}{}
|
||||
return r.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, marginBorrowRates, "", nil, &r)
|
||||
return r.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, marginBorrowRates, nil, &r)
|
||||
}
|
||||
|
||||
// GetMarginLendingRates gets lending rates for margin trading
|
||||
@@ -396,7 +396,7 @@ func (f *FTX) GetMarginLendingRates(ctx context.Context) ([]MarginFundingData, e
|
||||
r := struct {
|
||||
Data []MarginFundingData `json:"result"`
|
||||
}{}
|
||||
return r.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, marginLendingRates, "", nil, &r)
|
||||
return r.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, marginLendingRates, nil, &r)
|
||||
}
|
||||
|
||||
// MarginDailyBorrowedAmounts gets daily borrowed amounts for margin
|
||||
@@ -412,7 +412,7 @@ func (f *FTX) GetMarginMarketInfo(ctx context.Context, market string) ([]MarginM
|
||||
r := struct {
|
||||
Data []MarginMarketInfo `json:"result"`
|
||||
}{}
|
||||
return r.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, fmt.Sprintf(marginMarketInfo, market), "", nil, &r)
|
||||
return r.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, fmt.Sprintf(marginMarketInfo, market), nil, &r)
|
||||
}
|
||||
|
||||
// GetMarginBorrowHistory gets the margin borrow history data
|
||||
@@ -430,7 +430,7 @@ func (f *FTX) GetMarginBorrowHistory(ctx context.Context, startTime, endTime tim
|
||||
params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10))
|
||||
}
|
||||
endpoint := common.EncodeURLValues(marginBorrowHistory, params)
|
||||
return r.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, "", nil, &r)
|
||||
return r.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, nil, &r)
|
||||
}
|
||||
|
||||
// GetMarginMarketLendingHistory gets the markets margin lending rate history
|
||||
@@ -450,7 +450,7 @@ func (f *FTX) GetMarginMarketLendingHistory(ctx context.Context, coin currency.C
|
||||
params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10))
|
||||
}
|
||||
endpoint := common.EncodeURLValues(marginLendingHistory, params)
|
||||
return r.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, "", params, &r)
|
||||
return r.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, params, &r)
|
||||
}
|
||||
|
||||
// GetMarginLendingHistory gets margin lending history
|
||||
@@ -470,7 +470,7 @@ func (f *FTX) GetMarginLendingHistory(ctx context.Context, coin currency.Code, s
|
||||
params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10))
|
||||
}
|
||||
endpoint := common.EncodeURLValues(marginLendHistory, params)
|
||||
return r.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, marginLendHistory, "", endpoint, &r)
|
||||
return r.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, marginLendHistory, endpoint, &r)
|
||||
}
|
||||
|
||||
// GetMarginLendingOffers gets margin lending offers
|
||||
@@ -478,7 +478,7 @@ func (f *FTX) GetMarginLendingOffers(ctx context.Context) ([]LendingOffersData,
|
||||
r := struct {
|
||||
Data []LendingOffersData `json:"result"`
|
||||
}{}
|
||||
return r.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, marginLendingOffers, "", nil, &r)
|
||||
return r.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, marginLendingOffers, nil, &r)
|
||||
}
|
||||
|
||||
// GetLendingInfo gets margin lending info
|
||||
@@ -486,7 +486,7 @@ func (f *FTX) GetLendingInfo(ctx context.Context) ([]LendingInfoData, error) {
|
||||
r := struct {
|
||||
Data []LendingInfoData `json:"result"`
|
||||
}{}
|
||||
return r.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, marginLendingInfo, "", nil, &r)
|
||||
return r.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, marginLendingInfo, nil, &r)
|
||||
}
|
||||
|
||||
// SubmitLendingOffer submits an offer for margin lending
|
||||
@@ -500,7 +500,7 @@ func (f *FTX) SubmitLendingOffer(ctx context.Context, coin currency.Code, size,
|
||||
req["size"] = size
|
||||
req["rate"] = rate
|
||||
|
||||
if err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, marginLendingOffers, "", req, &resp); err != nil {
|
||||
if err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, marginLendingOffers, req, &resp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -511,11 +511,11 @@ func (f *FTX) SubmitLendingOffer(ctx context.Context, coin currency.Code, size,
|
||||
}
|
||||
|
||||
// GetAccountInfo gets account info
|
||||
func (f *FTX) GetAccountInfo(ctx context.Context, subAccount string) (AccountInfoData, error) {
|
||||
func (f *FTX) GetAccountInfo(ctx context.Context) (AccountInfoData, error) {
|
||||
resp := struct {
|
||||
Data AccountInfoData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getAccountInfo, subAccount, nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getAccountInfo, nil, &resp)
|
||||
}
|
||||
|
||||
// GetPositions gets the users positions
|
||||
@@ -523,26 +523,26 @@ func (f *FTX) GetPositions(ctx context.Context) ([]PositionData, error) {
|
||||
resp := struct {
|
||||
Data []PositionData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getPositions, "", nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getPositions, nil, &resp)
|
||||
}
|
||||
|
||||
// ChangeAccountLeverage changes default leverage used by account
|
||||
func (f *FTX) ChangeAccountLeverage(ctx context.Context, leverage float64) error {
|
||||
req := make(map[string]interface{})
|
||||
req["leverage"] = leverage
|
||||
return f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, setLeverage, "", req, nil)
|
||||
return f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, setLeverage, req, nil)
|
||||
}
|
||||
|
||||
// GetCoins gets coins' data in the account wallet
|
||||
func (f *FTX) GetCoins(ctx context.Context, subAccount string) ([]WalletCoinsData, error) {
|
||||
func (f *FTX) GetCoins(ctx context.Context) ([]WalletCoinsData, error) {
|
||||
resp := struct {
|
||||
Data []WalletCoinsData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getCoins, subAccount, nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getCoins, nil, &resp)
|
||||
}
|
||||
|
||||
// GetBalances gets balances of the account
|
||||
func (f *FTX) GetBalances(ctx context.Context, subAccount string, includeLockedBreakdown, includeFreeIgnoringCollateral bool) ([]WalletBalance, error) {
|
||||
func (f *FTX) GetBalances(ctx context.Context, includeLockedBreakdown, includeFreeIgnoringCollateral bool) ([]WalletBalance, error) {
|
||||
resp := struct {
|
||||
Data []WalletBalance `json:"result"`
|
||||
}{}
|
||||
@@ -554,7 +554,7 @@ func (f *FTX) GetBalances(ctx context.Context, subAccount string, includeLockedB
|
||||
vals.Set("includeFreeIgnoringCollateral", strconv.FormatBool(includeFreeIgnoringCollateral))
|
||||
}
|
||||
balanceURL := common.EncodeURLValues(getBalances, vals)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, balanceURL, subAccount, nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, balanceURL, nil, &resp)
|
||||
}
|
||||
|
||||
// GetAllWalletBalances gets all wallets' balances
|
||||
@@ -562,7 +562,7 @@ func (f *FTX) GetAllWalletBalances(ctx context.Context) (AllWalletBalances, erro
|
||||
resp := struct {
|
||||
Data AllWalletBalances `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getAllWalletBalances, "", nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getAllWalletBalances, nil, &resp)
|
||||
}
|
||||
|
||||
// FetchDepositAddress gets deposit address for a given coin
|
||||
@@ -575,7 +575,7 @@ func (f *FTX) FetchDepositAddress(ctx context.Context, coin currency.Code, chain
|
||||
vals.Set("method", strings.ToLower(chain))
|
||||
}
|
||||
path := common.EncodeURLValues(getDepositAddress+coin.Upper().String(), vals)
|
||||
return &resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, path, "", nil, &resp)
|
||||
return &resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, path, nil, &resp)
|
||||
}
|
||||
|
||||
// FetchDepositHistory gets deposit history
|
||||
@@ -583,7 +583,7 @@ func (f *FTX) FetchDepositHistory(ctx context.Context) ([]DepositItem, error) {
|
||||
resp := struct {
|
||||
Data []DepositItem `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getDepositHistory, "", nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getDepositHistory, nil, &resp)
|
||||
}
|
||||
|
||||
// FetchWithdrawalHistory gets withdrawal history
|
||||
@@ -591,7 +591,7 @@ func (f *FTX) FetchWithdrawalHistory(ctx context.Context) ([]WithdrawItem, error
|
||||
resp := struct {
|
||||
Data []WithdrawItem `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getWithdrawalHistory, "", nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getWithdrawalHistory, nil, &resp)
|
||||
}
|
||||
|
||||
// Withdraw sends a withdrawal request
|
||||
@@ -619,7 +619,7 @@ func (f *FTX) Withdraw(ctx context.Context, coin currency.Code, address, tag, pa
|
||||
resp := struct {
|
||||
Data WithdrawItem `json:"result"`
|
||||
}{}
|
||||
return &resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, withdrawRequest, "", req, &resp)
|
||||
return &resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, withdrawRequest, req, &resp)
|
||||
}
|
||||
|
||||
// GetOpenOrders gets open orders
|
||||
@@ -632,7 +632,7 @@ func (f *FTX) GetOpenOrders(ctx context.Context, marketName string) ([]OrderData
|
||||
Data []OrderData `json:"result"`
|
||||
}{}
|
||||
endpoint := common.EncodeURLValues(getOpenOrders, params)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, "", nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, nil, &resp)
|
||||
}
|
||||
|
||||
// FetchOrderHistory gets order history
|
||||
@@ -655,7 +655,7 @@ func (f *FTX) FetchOrderHistory(ctx context.Context, marketName string, startTim
|
||||
params.Set("limit", limit)
|
||||
}
|
||||
endpoint := common.EncodeURLValues(getOrderHistory, params)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, "", nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, nil, &resp)
|
||||
}
|
||||
|
||||
// GetOpenTriggerOrders gets trigger orders that are currently open
|
||||
@@ -671,7 +671,7 @@ func (f *FTX) GetOpenTriggerOrders(ctx context.Context, marketName, orderType st
|
||||
Data []TriggerOrderData `json:"result"`
|
||||
}{}
|
||||
endpoint := common.EncodeURLValues(getOpenTriggerOrders, params)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, "", nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, nil, &resp)
|
||||
}
|
||||
|
||||
// GetTriggerOrderTriggers gets trigger orders that are currently open
|
||||
@@ -679,7 +679,7 @@ func (f *FTX) GetTriggerOrderTriggers(ctx context.Context, orderID string) ([]Tr
|
||||
resp := struct {
|
||||
Data []TriggerData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, fmt.Sprintf(getTriggerOrderTriggers, orderID), "", nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, fmt.Sprintf(getTriggerOrderTriggers, orderID), nil, &resp)
|
||||
}
|
||||
|
||||
// GetTriggerOrderHistory gets trigger orders that are currently open
|
||||
@@ -708,7 +708,7 @@ func (f *FTX) GetTriggerOrderHistory(ctx context.Context, marketName string, sta
|
||||
Data []TriggerOrderData `json:"result"`
|
||||
}{}
|
||||
endpoint := common.EncodeURLValues(getTriggerOrderHistory, params)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, "", nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, nil, &resp)
|
||||
}
|
||||
|
||||
// Order places an order
|
||||
@@ -740,7 +740,7 @@ func (f *FTX) Order(
|
||||
resp := struct {
|
||||
Data OrderData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, placeOrder, "", req, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, placeOrder, req, &resp)
|
||||
}
|
||||
|
||||
// TriggerOrder places an order
|
||||
@@ -770,7 +770,7 @@ func (f *FTX) TriggerOrder(ctx context.Context, marketName, side, orderType, red
|
||||
resp := struct {
|
||||
Data TriggerOrderData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, placeTriggerOrder, "", req, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, placeTriggerOrder, req, &resp)
|
||||
}
|
||||
|
||||
// ModifyPlacedOrder modifies a placed order
|
||||
@@ -784,7 +784,7 @@ func (f *FTX) ModifyPlacedOrder(ctx context.Context, orderID, clientID string, p
|
||||
resp := struct {
|
||||
Data OrderData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(modifyOrder, orderID), "", req, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(modifyOrder, orderID), req, &resp)
|
||||
}
|
||||
|
||||
// ModifyOrderByClientID modifies a placed order via clientOrderID
|
||||
@@ -798,7 +798,7 @@ func (f *FTX) ModifyOrderByClientID(ctx context.Context, clientOrderID, clientID
|
||||
resp := struct {
|
||||
Data OrderData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(modifyOrderByClientID, clientOrderID), "", req, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(modifyOrderByClientID, clientOrderID), req, &resp)
|
||||
}
|
||||
|
||||
// ModifyTriggerOrder modifies an existing trigger order
|
||||
@@ -820,7 +820,7 @@ func (f *FTX) ModifyTriggerOrder(ctx context.Context, orderID, orderType string,
|
||||
resp := struct {
|
||||
Data TriggerOrderData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(modifyTriggerOrder, orderID), "", req, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(modifyTriggerOrder, orderID), req, &resp)
|
||||
}
|
||||
|
||||
// GetOrderStatus gets the order status of a given orderID
|
||||
@@ -828,7 +828,7 @@ func (f *FTX) GetOrderStatus(ctx context.Context, orderID string) (OrderData, er
|
||||
resp := struct {
|
||||
Data OrderData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getOrderStatus+orderID, "", nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getOrderStatus+orderID, nil, &resp)
|
||||
}
|
||||
|
||||
// GetOrderStatusByClientID gets the order status of a given clientOrderID
|
||||
@@ -836,7 +836,7 @@ func (f *FTX) GetOrderStatusByClientID(ctx context.Context, clientOrderID string
|
||||
resp := struct {
|
||||
Data OrderData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getOrderStatusByClientID+clientOrderID, "", nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getOrderStatusByClientID+clientOrderID, nil, &resp)
|
||||
}
|
||||
|
||||
func (f *FTX) deleteOrderByPath(ctx context.Context, path string) (string, error) {
|
||||
@@ -845,7 +845,7 @@ func (f *FTX) deleteOrderByPath(ctx context.Context, path string) (string, error
|
||||
Success bool `json:"success"`
|
||||
Error string `json:"error"`
|
||||
}{}
|
||||
err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodDelete, path, "", nil, &resp)
|
||||
err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodDelete, path, nil, &resp)
|
||||
// If there is an error reported, but the resp struct reports one of a very few
|
||||
// specific error causes, we still consider this a successful cancellation.
|
||||
if err != nil && !resp.Success && (resp.Error == "Order already closed" || resp.Error == "Order already queued for cancellation") {
|
||||
@@ -905,7 +905,7 @@ func (f *FTX) GetFills(ctx context.Context, market currency.Pair, item asset.Ite
|
||||
params.Set("end_time", strconv.FormatInt(nextEnd.Unix(), 10))
|
||||
}
|
||||
endpoint := common.EncodeURLValues(getFills, params)
|
||||
err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, "", nil, &data)
|
||||
err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, nil, &data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -950,7 +950,7 @@ func (f *FTX) GetFundingPayments(ctx context.Context, startTime, endTime time.Ti
|
||||
params.Set("future", future)
|
||||
}
|
||||
endpoint := common.EncodeURLValues(getFundingPayments, params)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, "", nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, nil, &resp)
|
||||
}
|
||||
|
||||
// ListLeveragedTokens lists leveraged tokens
|
||||
@@ -958,7 +958,7 @@ func (f *FTX) ListLeveragedTokens(ctx context.Context) ([]LeveragedTokensData, e
|
||||
resp := struct {
|
||||
Data []LeveragedTokensData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getLeveragedTokens, "", nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getLeveragedTokens, nil, &resp)
|
||||
}
|
||||
|
||||
// GetTokenInfo gets token info
|
||||
@@ -966,7 +966,7 @@ func (f *FTX) GetTokenInfo(ctx context.Context, tokenName string) ([]LeveragedTo
|
||||
resp := struct {
|
||||
Data []LeveragedTokensData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getTokenInfo+tokenName, "", nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getTokenInfo+tokenName, nil, &resp)
|
||||
}
|
||||
|
||||
// ListLTBalances gets leveraged tokens' balances
|
||||
@@ -974,7 +974,7 @@ func (f *FTX) ListLTBalances(ctx context.Context) ([]LTBalanceData, error) {
|
||||
resp := struct {
|
||||
Data []LTBalanceData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getLTBalances, "", nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getLTBalances, nil, &resp)
|
||||
}
|
||||
|
||||
// ListLTCreations lists the leveraged tokens' creation requests
|
||||
@@ -982,7 +982,7 @@ func (f *FTX) ListLTCreations(ctx context.Context) ([]LTCreationData, error) {
|
||||
resp := struct {
|
||||
Data []LTCreationData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getLTCreations, "", nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getLTCreations, nil, &resp)
|
||||
}
|
||||
|
||||
// RequestLTCreation sends a request to create a leveraged token
|
||||
@@ -992,7 +992,7 @@ func (f *FTX) RequestLTCreation(ctx context.Context, tokenName string, size floa
|
||||
resp := struct {
|
||||
Data RequestTokenCreationData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(requestLTCreation, tokenName), "", req, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(requestLTCreation, tokenName), req, &resp)
|
||||
}
|
||||
|
||||
// ListLTRedemptions lists the leveraged tokens' redemption requests
|
||||
@@ -1000,7 +1000,7 @@ func (f *FTX) ListLTRedemptions(ctx context.Context) ([]LTRedemptionData, error)
|
||||
resp := struct {
|
||||
Data []LTRedemptionData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getLTRedemptions, "", nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getLTRedemptions, nil, &resp)
|
||||
}
|
||||
|
||||
// RequestLTRedemption sends a request to redeem a leveraged token
|
||||
@@ -1010,7 +1010,7 @@ func (f *FTX) RequestLTRedemption(ctx context.Context, tokenName string, size fl
|
||||
resp := struct {
|
||||
Data LTRedemptionRequestData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(requestLTRedemption, tokenName), "", req, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(requestLTRedemption, tokenName), req, &resp)
|
||||
}
|
||||
|
||||
// GetQuoteRequests gets a list of quote requests
|
||||
@@ -1018,7 +1018,7 @@ func (f *FTX) GetQuoteRequests(ctx context.Context) ([]QuoteRequestData, error)
|
||||
resp := struct {
|
||||
Data []QuoteRequestData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getListQuotes, "", nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getListQuotes, nil, &resp)
|
||||
}
|
||||
|
||||
// GetYourQuoteRequests gets a list of your quote requests
|
||||
@@ -1026,7 +1026,7 @@ func (f *FTX) GetYourQuoteRequests(ctx context.Context) ([]PersonalQuotesData, e
|
||||
resp := struct {
|
||||
Data []PersonalQuotesData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getMyQuotesRequests, "", nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getMyQuotesRequests, nil, &resp)
|
||||
}
|
||||
|
||||
// CreateQuoteRequest sends a request to create a quote
|
||||
@@ -1051,7 +1051,7 @@ func (f *FTX) CreateQuoteRequest(ctx context.Context, underlying currency.Code,
|
||||
resp := struct {
|
||||
Data CreateQuoteRequestData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, createQuoteRequest, "", req, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, createQuoteRequest, req, &resp)
|
||||
}
|
||||
|
||||
// DeleteQuote sends request to cancel a quote
|
||||
@@ -1059,13 +1059,13 @@ func (f *FTX) DeleteQuote(ctx context.Context, requestID string) (CancelQuoteReq
|
||||
resp := struct {
|
||||
Data CancelQuoteRequestData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodDelete, deleteQuote+requestID, "", nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodDelete, deleteQuote+requestID, nil, &resp)
|
||||
}
|
||||
|
||||
// GetQuotesForYourQuote gets a list of quotes for your quote
|
||||
func (f *FTX) GetQuotesForYourQuote(ctx context.Context, requestID string) (QuoteForQuoteData, error) {
|
||||
var resp QuoteForQuoteData
|
||||
return resp, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, fmt.Sprintf(endpointQuote, requestID), "", nil, &resp)
|
||||
return resp, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, fmt.Sprintf(endpointQuote, requestID), nil, &resp)
|
||||
}
|
||||
|
||||
// MakeQuote makes a quote for a quote
|
||||
@@ -1075,7 +1075,7 @@ func (f *FTX) MakeQuote(ctx context.Context, requestID, price string) ([]QuoteFo
|
||||
resp := struct {
|
||||
Data []QuoteForQuoteData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(endpointQuote, requestID), "", nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(endpointQuote, requestID), nil, &resp)
|
||||
}
|
||||
|
||||
// MyQuotes gets a list of my quotes for quotes
|
||||
@@ -1083,7 +1083,7 @@ func (f *FTX) MyQuotes(ctx context.Context) ([]QuoteForQuoteData, error) {
|
||||
resp := struct {
|
||||
Data []QuoteForQuoteData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getMyQuotes, "", nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getMyQuotes, nil, &resp)
|
||||
}
|
||||
|
||||
// DeleteMyQuote deletes my quote for quotes
|
||||
@@ -1091,7 +1091,7 @@ func (f *FTX) DeleteMyQuote(ctx context.Context, quoteID string) ([]QuoteForQuot
|
||||
resp := struct {
|
||||
Data []QuoteForQuoteData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodDelete, deleteMyQuote+quoteID, "", nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodDelete, deleteMyQuote+quoteID, nil, &resp)
|
||||
}
|
||||
|
||||
// AcceptQuote accepts the quote for quote
|
||||
@@ -1099,7 +1099,7 @@ func (f *FTX) AcceptQuote(ctx context.Context, quoteID string) ([]QuoteForQuoteD
|
||||
resp := struct {
|
||||
Data []QuoteForQuoteData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(acceptQuote, quoteID), "", nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(acceptQuote, quoteID), nil, &resp)
|
||||
}
|
||||
|
||||
// GetAccountOptionsInfo gets account's options' info
|
||||
@@ -1107,7 +1107,7 @@ func (f *FTX) GetAccountOptionsInfo(ctx context.Context) (AccountOptionsInfoData
|
||||
resp := struct {
|
||||
Data AccountOptionsInfoData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getOptionsInfo, "", nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getOptionsInfo, nil, &resp)
|
||||
}
|
||||
|
||||
// GetOptionsPositions gets options' positions
|
||||
@@ -1115,7 +1115,7 @@ func (f *FTX) GetOptionsPositions(ctx context.Context) ([]OptionsPositionsData,
|
||||
resp := struct {
|
||||
Data []OptionsPositionsData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getOptionsPositions, "", nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getOptionsPositions, nil, &resp)
|
||||
}
|
||||
|
||||
// GetPublicOptionsTrades gets options' trades from public
|
||||
@@ -1154,7 +1154,7 @@ func (f *FTX) GetOptionsFills(ctx context.Context, startTime, endTime time.Time,
|
||||
if limit != "" {
|
||||
req["limit"] = limit
|
||||
}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getOptionsFills, "", req, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getOptionsFills, req, &resp)
|
||||
}
|
||||
|
||||
// GetStakes returns a list of staked assets
|
||||
@@ -1162,7 +1162,7 @@ func (f *FTX) GetStakes(ctx context.Context) ([]Stake, error) {
|
||||
resp := struct {
|
||||
Data []Stake `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, stakes, "", nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, stakes, nil, &resp)
|
||||
}
|
||||
|
||||
// GetUnstakeRequests returns a collection of unstake requests
|
||||
@@ -1170,7 +1170,7 @@ func (f *FTX) GetUnstakeRequests(ctx context.Context) ([]UnstakeRequest, error)
|
||||
resp := struct {
|
||||
Data []UnstakeRequest `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, unstakeRequests, "", nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, unstakeRequests, nil, &resp)
|
||||
}
|
||||
|
||||
// GetStakeBalances returns a collection of staked coin balances
|
||||
@@ -1178,7 +1178,7 @@ func (f *FTX) GetStakeBalances(ctx context.Context) ([]StakeBalance, error) {
|
||||
resp := struct {
|
||||
Data []StakeBalance `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, stakeBalances, "", nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, stakeBalances, nil, &resp)
|
||||
}
|
||||
|
||||
// UnstakeRequest unstakes an existing staked coin
|
||||
@@ -1189,7 +1189,7 @@ func (f *FTX) UnstakeRequest(ctx context.Context, coin currency.Code, size float
|
||||
req := make(map[string]interface{})
|
||||
req["coin"] = coin.Upper().String()
|
||||
req["size"] = strconv.FormatFloat(size, 'f', -1, 64)
|
||||
return &resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, unstakeRequests, "", req, &resp)
|
||||
return &resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, unstakeRequests, req, &resp)
|
||||
}
|
||||
|
||||
// CancelUnstakeRequest cancels a pending unstake request
|
||||
@@ -1198,7 +1198,7 @@ func (f *FTX) CancelUnstakeRequest(ctx context.Context, requestID int64) (bool,
|
||||
Result string
|
||||
}{}
|
||||
path := unstakeRequests + "/" + strconv.FormatInt(requestID, 10)
|
||||
if err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodDelete, path, "", nil, &resp); err != nil {
|
||||
if err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodDelete, path, nil, &resp); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
@@ -1213,7 +1213,7 @@ func (f *FTX) GetStakingRewards(ctx context.Context) ([]StakeReward, error) {
|
||||
resp := struct {
|
||||
Data []StakeReward `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, stakingRewards, "", nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, stakingRewards, nil, &resp)
|
||||
}
|
||||
|
||||
// StakeRequest submits a stake request based on the specified currency and size
|
||||
@@ -1224,13 +1224,14 @@ func (f *FTX) StakeRequest(ctx context.Context, coin currency.Code, size float64
|
||||
req := make(map[string]interface{})
|
||||
req["coin"] = coin.Upper().String()
|
||||
req["size"] = strconv.FormatFloat(size, 'f', -1, 64)
|
||||
return &resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, serumStakes, "", req, &resp)
|
||||
return &resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, serumStakes, req, &resp)
|
||||
}
|
||||
|
||||
// SendAuthHTTPRequest sends an authenticated request
|
||||
func (f *FTX) SendAuthHTTPRequest(ctx context.Context, ep exchange.URL, method, path, subAccount string, data, result interface{}) error {
|
||||
if !f.AllowAuthenticatedRequest() {
|
||||
return fmt.Errorf("%s %w", f.Name, exchange.ErrAuthenticatedRequestWithoutCredentialsSet)
|
||||
func (f *FTX) SendAuthHTTPRequest(ctx context.Context, ep exchange.URL, method, path string, data, result interface{}) error {
|
||||
creds, err := f.GetCredentials(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
endpoint, err := f.API.Endpoints.GetURL(ep)
|
||||
@@ -1255,20 +1256,17 @@ func (f *FTX) SendAuthHTTPRequest(ctx context.Context, ep exchange.URL, method,
|
||||
|
||||
hmac, err = crypto.GetHMAC(crypto.HashSHA256,
|
||||
[]byte(sigPayload),
|
||||
[]byte(f.API.Credentials.Secret))
|
||||
[]byte(creds.Secret))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
headers := make(map[string]string)
|
||||
headers["FTX-KEY"] = f.API.Credentials.Key
|
||||
headers["FTX-KEY"] = creds.Key
|
||||
headers["FTX-SIGN"] = crypto.HexEncodeToString(hmac)
|
||||
headers["FTX-TS"] = ts
|
||||
if subAccount == "" && f.API.Credentials.Subaccount != "" {
|
||||
subAccount = f.API.Credentials.Subaccount
|
||||
}
|
||||
if subAccount != "" {
|
||||
headers["FTX-SUBACCOUNT"] = url.QueryEscape(subAccount)
|
||||
if creds.SubAccount != "" {
|
||||
headers["FTX-SUBACCOUNT"] = url.QueryEscape(creds.SubAccount)
|
||||
}
|
||||
headers["Content-Type"] = "application/json"
|
||||
|
||||
@@ -1297,7 +1295,7 @@ func (f *FTX) GetFee(ctx context.Context, feeBuilder *exchange.FeeBuilder) (floa
|
||||
case exchange.OfflineTradeFee:
|
||||
fee = getOfflineTradeFee(feeBuilder)
|
||||
default:
|
||||
feeData, err := f.GetAccountInfo(ctx, "")
|
||||
feeData, err := f.GetAccountInfo(ctx)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -1382,7 +1380,7 @@ func (f *FTX) RequestForQuotes(ctx context.Context, base, quote currency.Code, a
|
||||
req["fromCoin"] = base.Upper().String()
|
||||
req["toCoin"] = quote.Upper().String()
|
||||
req["size"] = amount
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, requestOTCQuote, "", req, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, requestOTCQuote, req, &resp)
|
||||
}
|
||||
|
||||
// GetOTCQuoteStatus gets quote status of a quote
|
||||
@@ -1392,12 +1390,12 @@ func (f *FTX) GetOTCQuoteStatus(ctx context.Context, marketName, quoteID string)
|
||||
}{}
|
||||
params := url.Values{}
|
||||
params.Set("market", marketName)
|
||||
return &resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getOTCQuoteStatus+quoteID, "", params, &resp)
|
||||
return &resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getOTCQuoteStatus+quoteID, params, &resp)
|
||||
}
|
||||
|
||||
// AcceptOTCQuote requests for otc quotes
|
||||
func (f *FTX) AcceptOTCQuote(ctx context.Context, quoteID string) error {
|
||||
return f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(acceptOTCQuote, quoteID), "", nil, nil)
|
||||
return f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(acceptOTCQuote, quoteID), nil, nil)
|
||||
}
|
||||
|
||||
// GetSubaccounts returns the users subaccounts
|
||||
@@ -1405,7 +1403,7 @@ func (f *FTX) GetSubaccounts(ctx context.Context) ([]Subaccount, error) {
|
||||
resp := struct {
|
||||
Data []Subaccount `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, subaccounts, "", nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, subaccounts, nil, &resp)
|
||||
}
|
||||
|
||||
// CreateSubaccount creates a new subaccount
|
||||
@@ -1419,7 +1417,7 @@ func (f *FTX) CreateSubaccount(ctx context.Context, name string) (*Subaccount, e
|
||||
resp := struct {
|
||||
Data Subaccount `json:"result"`
|
||||
}{}
|
||||
if err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, subaccounts, "", d, &resp); err != nil {
|
||||
if err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, subaccounts, d, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &resp.Data, nil
|
||||
@@ -1437,7 +1435,7 @@ func (f *FTX) UpdateSubaccountName(ctx context.Context, oldName, newName string)
|
||||
resp := struct {
|
||||
Data Subaccount `json:"result"`
|
||||
}{}
|
||||
if err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, subaccountsUpdateName, "", d, &resp); err != nil {
|
||||
if err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, subaccountsUpdateName, d, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &resp.Data, nil
|
||||
@@ -1453,7 +1451,7 @@ func (f *FTX) DeleteSubaccount(ctx context.Context, name string) error {
|
||||
resp := struct {
|
||||
Data Subaccount `json:"result"`
|
||||
}{}
|
||||
return f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodDelete, subaccounts, "", d, &resp)
|
||||
return f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodDelete, subaccounts, d, &resp)
|
||||
}
|
||||
|
||||
// SubaccountBalances returns the user's subaccount balances
|
||||
@@ -1464,7 +1462,7 @@ func (f *FTX) SubaccountBalances(ctx context.Context, name string) ([]Subaccount
|
||||
resp := struct {
|
||||
Data []SubaccountBalance `json:"result"`
|
||||
}{}
|
||||
if err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, fmt.Sprintf(subaccountsBalance, name), "", nil, &resp); err != nil {
|
||||
if err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, fmt.Sprintf(subaccountsBalance, name), nil, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.Data, nil
|
||||
@@ -1495,7 +1493,7 @@ func (f *FTX) SubaccountTransfer(ctx context.Context, coin currency.Code, source
|
||||
resp := struct {
|
||||
Data SubaccountTransferStatus `json:"result"`
|
||||
}{}
|
||||
if err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, subaccountsTransfer, "", d, &resp); err != nil {
|
||||
if err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, subaccountsTransfer, d, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &resp.Data, nil
|
||||
@@ -1557,7 +1555,7 @@ func (f *FTX) GetCollateral(ctx context.Context, maintenance bool) (*CollateralR
|
||||
u.Add("marginType", "initial")
|
||||
}
|
||||
url := common.EncodeURLValues(collateral, u)
|
||||
if err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, url, "", nil, &resp); err != nil {
|
||||
if err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, url, nil, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &resp.Data, nil
|
||||
@@ -1700,7 +1698,7 @@ func (f *FTX) LoadCollateralWeightings(ctx context.Context) error {
|
||||
if !f.GetAuthenticatedAPISupport(exchange.RestAuthentication) {
|
||||
return nil
|
||||
}
|
||||
coins, err := f.GetCoins(ctx, "")
|
||||
coins, err := f.GetCoins(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ func TestMain(m *testing.M) {
|
||||
}
|
||||
|
||||
func areTestAPIKeysSet() bool {
|
||||
return f.ValidateAPICredentials()
|
||||
return f.ValidateAPICredentials(f.GetDefaultCredentials()) == nil
|
||||
}
|
||||
|
||||
// Implement tests for API endpoints below
|
||||
@@ -264,7 +264,7 @@ func TestGetAccountInfo(t *testing.T) {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip()
|
||||
}
|
||||
_, err := f.GetAccountInfo(context.Background(), subaccount)
|
||||
_, err := f.GetAccountInfo(context.Background())
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -286,19 +286,19 @@ func TestGetBalances(t *testing.T) {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip()
|
||||
}
|
||||
_, err := f.GetBalances(context.Background(), subaccount, false, false)
|
||||
_, err := f.GetBalances(context.Background(), false, false)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
_, err = f.GetBalances(context.Background(), subaccount, true, false)
|
||||
_, err = f.GetBalances(context.Background(), true, false)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
_, err = f.GetBalances(context.Background(), subaccount, false, true)
|
||||
_, err = f.GetBalances(context.Background(), false, true)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
_, err = f.GetBalances(context.Background(), subaccount, true, true)
|
||||
_, err = f.GetBalances(context.Background(), true, true)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -331,7 +331,7 @@ func TestGetCoins(t *testing.T) {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip()
|
||||
}
|
||||
_, err := f.GetCoins(context.Background(), subaccount)
|
||||
_, err := f.GetCoins(context.Background())
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -1767,7 +1767,6 @@ func TestScaleCollateral(t *testing.T) {
|
||||
|
||||
result, err := f.ScaleCollateral(
|
||||
context.Background(),
|
||||
"",
|
||||
&order.CollateralCalculator{
|
||||
CollateralCurrency: currency.USDT,
|
||||
Asset: asset.Spot,
|
||||
@@ -1787,7 +1786,7 @@ func TestScaleCollateral(t *testing.T) {
|
||||
if !areTestAPIKeysSet() {
|
||||
return
|
||||
}
|
||||
accountInfo, err := f.GetAccountInfo(context.Background(), subaccount)
|
||||
accountInfo, err := f.GetAccountInfo(context.Background())
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -1813,7 +1812,6 @@ func TestScaleCollateral(t *testing.T) {
|
||||
}
|
||||
_, err = f.ScaleCollateral(
|
||||
context.Background(),
|
||||
"",
|
||||
&order.CollateralCalculator{
|
||||
CollateralCurrency: coin,
|
||||
Asset: asset.Spot,
|
||||
@@ -1831,7 +1829,6 @@ func TestScaleCollateral(t *testing.T) {
|
||||
}
|
||||
providedUSDValue += v[v2].USDValue
|
||||
_, err = f.ScaleCollateral(context.Background(),
|
||||
subaccount,
|
||||
&order.CollateralCalculator{
|
||||
CollateralCurrency: coin,
|
||||
Asset: asset.Spot,
|
||||
@@ -1845,7 +1842,6 @@ func TestScaleCollateral(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
_, err = f.ScaleCollateral(context.Background(),
|
||||
subaccount,
|
||||
&order.CollateralCalculator{
|
||||
CollateralCurrency: coin,
|
||||
Asset: asset.Spot,
|
||||
@@ -1861,7 +1857,6 @@ func TestScaleCollateral(t *testing.T) {
|
||||
|
||||
_, err = f.ScaleCollateral(
|
||||
context.Background(),
|
||||
"",
|
||||
&order.CollateralCalculator{
|
||||
CollateralCurrency: coin,
|
||||
Asset: asset.Spot,
|
||||
@@ -1926,7 +1921,6 @@ func TestCalculateTotalCollateral(t *testing.T) {
|
||||
}
|
||||
}
|
||||
calc := &order.TotalCollateralCalculator{
|
||||
SubAccount: subaccount,
|
||||
CollateralAssets: scales,
|
||||
FetchPositions: false,
|
||||
CalculateOffline: true,
|
||||
@@ -1936,7 +1930,7 @@ func TestCalculateTotalCollateral(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
localScaling := total.AvailableCollateral.InexactFloat64()
|
||||
accountInfo, err := f.GetAccountInfo(context.Background(), subaccount)
|
||||
accountInfo, err := f.GetAccountInfo(context.Background())
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ func (f *FTX) WsConnect() error {
|
||||
go f.wsReadData()
|
||||
|
||||
if f.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
|
||||
err = f.WsAuth()
|
||||
err = f.WsAuth(context.TODO())
|
||||
if err != nil {
|
||||
f.Websocket.DataHandler <- err
|
||||
f.Websocket.SetCanUseAuthenticatedEndpoints(false)
|
||||
@@ -77,13 +77,17 @@ func (f *FTX) WsConnect() error {
|
||||
}
|
||||
|
||||
// WsAuth sends an authentication message to receive auth data
|
||||
func (f *FTX) WsAuth() error {
|
||||
func (f *FTX) WsAuth(ctx context.Context) error {
|
||||
creds, err := f.GetCredentials(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
intNonce := time.Now().UnixMilli()
|
||||
strNonce := strconv.FormatInt(intNonce, 10)
|
||||
hmac, err := crypto.GetHMAC(
|
||||
crypto.HashSHA256,
|
||||
[]byte(strNonce+"websocket_login"),
|
||||
[]byte(f.API.Credentials.Secret),
|
||||
[]byte(creds.Secret),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -91,10 +95,10 @@ func (f *FTX) WsAuth() error {
|
||||
sign := crypto.HexEncodeToString(hmac)
|
||||
req := Authenticate{Operation: "login",
|
||||
Args: AuthenticationData{
|
||||
Key: f.API.Credentials.Key,
|
||||
Key: creds.Key,
|
||||
Sign: sign,
|
||||
Time: intNonce,
|
||||
SubAccount: f.API.Credentials.Subaccount,
|
||||
SubAccount: creds.SubAccount,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -458,16 +458,20 @@ func (f *FTX) UpdateOrderbook(ctx context.Context, p currency.Pair, assetType as
|
||||
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies
|
||||
func (f *FTX) UpdateAccountInfo(ctx context.Context, a asset.Item) (account.Holdings, error) {
|
||||
creds, err := f.GetCredentials(ctx)
|
||||
if err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
var resp account.Holdings
|
||||
|
||||
var data AllWalletBalances
|
||||
if f.API.Credentials.Subaccount != "" {
|
||||
balances, err := f.GetBalances(ctx, "", false, false)
|
||||
if creds.SubAccount != "" {
|
||||
balances, err := f.GetBalances(ctx, false, false)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
data = make(AllWalletBalances)
|
||||
data[f.API.Credentials.Subaccount] = balances
|
||||
data[creds.SubAccount] = balances
|
||||
} else {
|
||||
// Get all wallet balances used so we can transfer between accounts if
|
||||
// needed.
|
||||
@@ -1147,8 +1151,8 @@ func (f *FTX) UnsubscribeToWebsocketChannels(channels []stream.ChannelSubscripti
|
||||
}
|
||||
|
||||
// AuthenticateWebsocket sends an authentication message to the websocket
|
||||
func (f *FTX) AuthenticateWebsocket(_ context.Context) error {
|
||||
return f.WsAuth()
|
||||
func (f *FTX) AuthenticateWebsocket(ctx context.Context) error {
|
||||
return f.WsAuth(ctx)
|
||||
}
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
@@ -1268,7 +1272,7 @@ func (f *FTX) UpdateOrderExecutionLimits(ctx context.Context, _ asset.Item) erro
|
||||
// GetAvailableTransferChains returns the available transfer blockchains for the specific
|
||||
// cryptocurrency
|
||||
func (f *FTX) GetAvailableTransferChains(ctx context.Context, cryptocurrency currency.Code) ([]string, error) {
|
||||
coins, err := f.GetCoins(ctx, "")
|
||||
coins, err := f.GetCoins(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1292,24 +1296,27 @@ func (f *FTX) CalculatePNL(ctx context.Context, pnl *order.PNLCalculatorRequest)
|
||||
result := &order.PNLResult{
|
||||
Time: pnl.Time,
|
||||
}
|
||||
var err error
|
||||
creds, err := f.GetCredentials(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if pnl.CalculateOffline {
|
||||
// PNLCalculator matches FTX's pnl calculation method
|
||||
calc := order.PNLCalculator{}
|
||||
result, err = calc.CalculatePNL(ctx, pnl)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s %s %w", f.Name, f.API.Credentials.Subaccount, err)
|
||||
return nil, fmt.Errorf("%s %s %w", f.Name, creds.SubAccount, err)
|
||||
}
|
||||
}
|
||||
|
||||
ep := pnl.EntryPrice.InexactFloat64()
|
||||
info, err := f.GetAccountInfo(ctx, "")
|
||||
info, err := f.GetAccountInfo(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if info.Liquidating || info.Collateral == 0 {
|
||||
result.IsLiquidated = true
|
||||
return result, fmt.Errorf("%s %s %w", f.Name, f.API.Credentials.Subaccount, order.ErrPositionLiquidated)
|
||||
return result, fmt.Errorf("%s %s %w", f.Name, creds.SubAccount, order.ErrPositionLiquidated)
|
||||
}
|
||||
for i := range info.Positions {
|
||||
if !pnl.Pair.Equal(info.Positions[i].Future) {
|
||||
@@ -1327,13 +1334,13 @@ func (f *FTX) CalculatePNL(ctx context.Context, pnl *order.PNLCalculatorRequest)
|
||||
calc := order.PNLCalculator{}
|
||||
result, err = calc.CalculatePNL(ctx, pnl)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s %s %w", f.Name, f.API.Credentials.Subaccount, err)
|
||||
return nil, fmt.Errorf("%s %s %w", f.Name, creds.SubAccount, err)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// ScaleCollateral takes your totals and scales them according to FTX's rules
|
||||
func (f *FTX) ScaleCollateral(ctx context.Context, subAccount string, calc *order.CollateralCalculator) (*order.CollateralByCurrency, error) {
|
||||
func (f *FTX) ScaleCollateral(ctx context.Context, calc *order.CollateralCalculator) (*order.CollateralByCurrency, error) {
|
||||
if calc.CalculateOffline {
|
||||
result := &order.CollateralByCurrency{
|
||||
Currency: calc.CollateralCurrency,
|
||||
@@ -1398,7 +1405,6 @@ func (f *FTX) ScaleCollateral(ctx context.Context, subAccount string, calc *orde
|
||||
}
|
||||
resp, err := f.calculateTotalCollateralOnline(ctx,
|
||||
&order.TotalCollateralCalculator{
|
||||
SubAccount: subAccount,
|
||||
CollateralAssets: []order.CollateralCalculator{*calc},
|
||||
},
|
||||
nil,
|
||||
@@ -1444,7 +1450,7 @@ func (f *FTX) CalculateTotalCollateral(ctx context.Context, calc *order.TotalCol
|
||||
}
|
||||
}
|
||||
var collateralByCurrency *order.CollateralByCurrency
|
||||
collateralByCurrency, err = f.ScaleCollateral(ctx, calc.SubAccount, &calc.CollateralAssets[i])
|
||||
collateralByCurrency, err = f.ScaleCollateral(ctx, &calc.CollateralAssets[i])
|
||||
if err != nil {
|
||||
if errors.Is(err, errCollateralCurrencyNotFound) {
|
||||
log.Error(log.ExchangeSys, err)
|
||||
@@ -1501,7 +1507,7 @@ func (f *FTX) calculateTotalCollateralOnline(ctx context.Context, calc *order.To
|
||||
TotalValueOfPositiveSpotBalances: c.PositiveSpotBalanceTotal,
|
||||
CollateralContributedByPositiveSpotBalances: c.CollateralFromPositiveSpotBalances,
|
||||
}
|
||||
balances, err := f.GetBalances(ctx, calc.SubAccount, true, true)
|
||||
balances, err := f.GetBalances(ctx, true, true)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s %w", f.Name, err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user