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:
Ryan O'Hara-Reid
2022-03-21 13:58:08 +11:00
committed by GitHub
parent 58b9f8b9ec
commit 09fa2f236a
122 changed files with 3006 additions and 2126 deletions

View File

@@ -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
}

View File

@@ -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)
}

View File

@@ -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,
},
}

View File

@@ -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)
}