mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-21 22:43:52 +00:00
add QueryClosedOrders() and QueryTrades() for okex, also fix conflict for QueryOrderTrades() and update typo error in QueryOrderTrades()
This commit is contained in:
parent
cf31796224
commit
99a69f4f2f
|
@ -23,7 +23,7 @@ import (
|
||||||
// Market data limiter means public api, this includes QueryMarkets, QueryTicker, QueryTickers, QueryKLines
|
// Market data limiter means public api, this includes QueryMarkets, QueryTicker, QueryTickers, QueryKLines
|
||||||
var (
|
var (
|
||||||
marketDataLimiter = rate.NewLimiter(rate.Every(100*time.Millisecond), 5)
|
marketDataLimiter = rate.NewLimiter(rate.Every(100*time.Millisecond), 5)
|
||||||
tradeRateLimiter = rate.NewLimiter(rate.Every(100*time.Millisecond), 5)
|
tradeRateLimiter = rate.NewLimiter(rate.Every(300*time.Millisecond), 5)
|
||||||
orderRateLimiter = rate.NewLimiter(rate.Every(300*time.Millisecond), 5)
|
orderRateLimiter = rate.NewLimiter(rate.Every(300*time.Millisecond), 5)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -32,6 +32,11 @@ const ID = "okex"
|
||||||
// PlatformToken is the platform currency of OKEx, pre-allocate static string here
|
// PlatformToken is the platform currency of OKEx, pre-allocate static string here
|
||||||
const PlatformToken = "OKB"
|
const PlatformToken = "OKB"
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Constant For query limit
|
||||||
|
defaultQueryLimit = 100
|
||||||
|
)
|
||||||
|
|
||||||
var log = logrus.WithFields(logrus.Fields{
|
var log = logrus.WithFields(logrus.Fields{
|
||||||
"exchange": ID,
|
"exchange": ID,
|
||||||
})
|
})
|
||||||
|
@ -360,7 +365,7 @@ func (e *Exchange) QueryOrder(ctx context.Context, q types.OrderQuery) (*types.O
|
||||||
return nil, errors.New("okex.QueryOrder: OrderId or ClientOrderId is required parameter")
|
return nil, errors.New("okex.QueryOrder: OrderId or ClientOrderId is required parameter")
|
||||||
}
|
}
|
||||||
req := e.client.NewGetOrderDetailsRequest()
|
req := e.client.NewGetOrderDetailsRequest()
|
||||||
req.InstrumentID(q.Symbol).
|
req.InstrumentID(toLocalSymbol(q.Symbol)).
|
||||||
OrderID(q.OrderID).
|
OrderID(q.OrderID).
|
||||||
ClientOrderID(q.ClientOrderID)
|
ClientOrderID(q.ClientOrderID)
|
||||||
|
|
||||||
|
@ -380,9 +385,9 @@ func (e *Exchange) QueryOrderTrades(ctx context.Context, q types.OrderQuery) ([]
|
||||||
log.Warn("!!!OKEX EXCHANGE API NOTICE!!! Okex does not support searching for trades using OrderClientId.")
|
log.Warn("!!!OKEX EXCHANGE API NOTICE!!! Okex does not support searching for trades using OrderClientId.")
|
||||||
}
|
}
|
||||||
|
|
||||||
req := e.client.NewGetTransactionHistoriesRequest()
|
req := e.client.NewGetTransactionHistoryRequest()
|
||||||
if len(q.Symbol) != 0 {
|
if len(q.Symbol) != 0 {
|
||||||
req.InstrumentID(q.Symbol)
|
req.InstrumentID(toLocalSymbol(q.Symbol))
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(q.OrderID) != 0 {
|
if len(q.OrderID) != 0 {
|
||||||
|
@ -411,6 +416,131 @@ func (e *Exchange) QueryOrderTrades(ctx context.Context, q types.OrderQuery) ([]
|
||||||
if errs != nil {
|
if errs != nil {
|
||||||
return nil, errs
|
return nil, errs
|
||||||
}
|
}
|
||||||
|
return trades, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
QueryClosedOrders can query closed orders in last 3 months, there are no time interval limitations, as long as until >= since.
|
||||||
|
Please Use lastOrderID as cursor, only return orders later than that order, that order is not included.
|
||||||
|
If you want to query orders by time range, please just pass since and until.
|
||||||
|
If you want to query by cursor, please pass lastOrderID.
|
||||||
|
Because it gets the correct response even when you pass all parameters with the right time interval and invalid lastOrderID, like 0.
|
||||||
|
Time interval boundary unit is second.
|
||||||
|
since is inclusive, ex. order created in 1694155903, get response if query since 1694155903, get empty if query since 1694155904
|
||||||
|
until is not inclusive, ex. order created in 1694155903, get response if query until 1694155904, get empty if query until 1694155903
|
||||||
|
*/
|
||||||
|
func (e *Exchange) QueryClosedOrders(ctx context.Context, symbol string, since, until time.Time, lastOrderID uint64) ([]types.Order, error) {
|
||||||
|
if symbol == "" {
|
||||||
|
return nil, ErrSymbolRequired
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tradeRateLimiter.Wait(ctx); err != nil {
|
||||||
|
return nil, fmt.Errorf("query closed order rate limiter wait error: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var lastOrder string
|
||||||
|
if lastOrderID <= 0 {
|
||||||
|
lastOrder = ""
|
||||||
|
} else {
|
||||||
|
lastOrder = strconv.FormatUint(lastOrderID, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := e.client.NewGetOrderHistoryRequest().
|
||||||
|
InstrumentID(toLocalSymbol(symbol)).
|
||||||
|
StartTime(since).
|
||||||
|
EndTime(until).
|
||||||
|
Limit(defaultQueryLimit).
|
||||||
|
Before(lastOrder).
|
||||||
|
Do(ctx)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to call get order histories error: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var orders []types.Order
|
||||||
|
|
||||||
|
for _, order := range res {
|
||||||
|
o, err2 := toGlobalOrder(&order)
|
||||||
|
if err2 != nil {
|
||||||
|
err = multierr.Append(err, err2)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
orders = append(orders, *o)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return types.SortOrdersAscending(orders), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
QueryTrades can query trades in last 3 months, there are no time interval limitations, as long as end_time >= start_time.
|
||||||
|
OKEX do not provide api to query by tradeID, So use /api/v5/trade/orders-history-archive as its official site do.
|
||||||
|
Please Use LastTradeID as cursor, only return trades later than that trade, that trade is not included.
|
||||||
|
If you want to query trades by time range, please just pass start_time and end_time.
|
||||||
|
If you want to query by cursor, please pass LastTradeID.
|
||||||
|
Because it gets the correct response even when you pass all parameters with the right time interval and invalid LastTradeID, like 0.
|
||||||
|
*/
|
||||||
|
func (e *Exchange) QueryTrades(ctx context.Context, symbol string, options *types.TradeQueryOptions) ([]types.Trade, error) {
|
||||||
|
if symbol == "" {
|
||||||
|
return nil, ErrSymbolRequired
|
||||||
|
}
|
||||||
|
|
||||||
|
req := e.client.NewGetOrderHistoryRequest().InstrumentID(toLocalSymbol(symbol))
|
||||||
|
|
||||||
|
limit := uint64(options.Limit)
|
||||||
|
if limit > defaultQueryLimit || limit <= 0 {
|
||||||
|
log.Debugf("limit is exceeded default limit %d or zero, got: %d, Do not pass limit", defaultQueryLimit, options.Limit)
|
||||||
|
} else {
|
||||||
|
req.Limit(limit)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tradeRateLimiter.Wait(ctx); err != nil {
|
||||||
|
return nil, fmt.Errorf("query trades rate limiter wait error: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
var response []okexapi.OrderDetails
|
||||||
|
// query by time interval
|
||||||
|
if options.StartTime != nil || options.EndTime != nil {
|
||||||
|
if options.StartTime != nil {
|
||||||
|
req.StartTime(*options.StartTime)
|
||||||
|
}
|
||||||
|
if options.EndTime != nil {
|
||||||
|
req.EndTime(*options.EndTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
response, err = req.Do(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to call get order histories error: %w", err)
|
||||||
|
}
|
||||||
|
} else if options.StartTime == nil && options.EndTime == nil && options.LastTradeID == 0 { // query by no any parameters
|
||||||
|
response, err = req.Do(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to call get order histories error: %w", err)
|
||||||
|
}
|
||||||
|
} else { // query by trade id
|
||||||
|
lastTradeID := strconv.FormatUint(options.LastTradeID, 10)
|
||||||
|
res, err := req.Do(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to call get order histories error: %w", err)
|
||||||
|
}
|
||||||
|
for _, trade := range res {
|
||||||
|
if trade.LastTradeID == lastTradeID {
|
||||||
|
response, err = req.Before(trade.OrderID).Do(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to call get order histories error: %w", err)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trades, err := toGlobalTrades(response)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to trans order detail to trades error: %w", err)
|
||||||
|
}
|
||||||
return trades, nil
|
return trades, nil
|
||||||
}
|
}
|
||||||
|
|
40
pkg/exchange/okex/okexapi/get_order_history_request.go
Normal file
40
pkg/exchange/okex/okexapi/get_order_history_request.go
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
package okexapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/c9s/requestgen"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:generate GetRequest -url "/api/v5/trade/orders-history-archive" -type GetOrderHistoryRequest -responseDataType .APIResponse
|
||||||
|
type GetOrderHistoryRequest struct {
|
||||||
|
client requestgen.AuthenticatedAPIClient
|
||||||
|
|
||||||
|
instrumentType InstrumentType `param:"instType,query"`
|
||||||
|
instrumentID *string `param:"instId,query"`
|
||||||
|
orderType *OrderType `param:"ordType,query"`
|
||||||
|
// underlying and instrumentFamil Applicable to FUTURES/SWAP/OPTION
|
||||||
|
underlying *string `param:"uly,query"`
|
||||||
|
instrumentFamily *string `param:"instFamily,query"`
|
||||||
|
|
||||||
|
state *OrderState `param:"state,query"`
|
||||||
|
after *string `param:"after,query"`
|
||||||
|
before *string `param:"before,query"`
|
||||||
|
startTime *time.Time `param:"begin,query,milliseconds"`
|
||||||
|
|
||||||
|
// endTime for each request, startTime and endTime can be any interval, but should be in last 3 months
|
||||||
|
endTime *time.Time `param:"end,query,milliseconds"`
|
||||||
|
|
||||||
|
// limit for data size per page. Default: 100
|
||||||
|
limit *uint64 `param:"limit,query"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type OrderList []OrderDetails
|
||||||
|
|
||||||
|
// NewGetOrderHistoriesRequest is descending order by createdTime
|
||||||
|
func (c *RestClient) NewGetOrderHistoryRequest() *GetOrderHistoryRequest {
|
||||||
|
return &GetOrderHistoryRequest{
|
||||||
|
client: c,
|
||||||
|
instrumentType: InstrumentTypeSpot,
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,319 @@
|
||||||
|
// Code generated by "requestgen -method GET -responseType .APIResponse -responseDataField Data -url /api/v5/trade/orders-history-archive -type GetOrderHistoryRequest -responseDataType .OrderList"; DO NOT EDIT.
|
||||||
|
|
||||||
|
package okexapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"reflect"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (g *GetOrderHistoryRequest) InstrumentType(instrumentType InstrumentType) *GetOrderHistoryRequest {
|
||||||
|
g.instrumentType = instrumentType
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GetOrderHistoryRequest) InstrumentID(instrumentID string) *GetOrderHistoryRequest {
|
||||||
|
g.instrumentID = &instrumentID
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GetOrderHistoryRequest) OrderType(orderType OrderType) *GetOrderHistoryRequest {
|
||||||
|
g.orderType = &orderType
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GetOrderHistoryRequest) Underlying(underlying string) *GetOrderHistoryRequest {
|
||||||
|
g.underlying = &underlying
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GetOrderHistoryRequest) InstrumentFamily(instrumentFamily string) *GetOrderHistoryRequest {
|
||||||
|
g.instrumentFamily = &instrumentFamily
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GetOrderHistoryRequest) State(state OrderState) *GetOrderHistoryRequest {
|
||||||
|
g.state = &state
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GetOrderHistoryRequest) After(after string) *GetOrderHistoryRequest {
|
||||||
|
g.after = &after
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GetOrderHistoryRequest) Before(before string) *GetOrderHistoryRequest {
|
||||||
|
g.before = &before
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GetOrderHistoryRequest) StartTime(startTime time.Time) *GetOrderHistoryRequest {
|
||||||
|
g.startTime = &startTime
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GetOrderHistoryRequest) EndTime(endTime time.Time) *GetOrderHistoryRequest {
|
||||||
|
g.endTime = &endTime
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GetOrderHistoryRequest) Limit(limit uint64) *GetOrderHistoryRequest {
|
||||||
|
g.limit = &limit
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetQueryParameters builds and checks the query parameters and returns url.Values
|
||||||
|
func (g *GetOrderHistoryRequest) GetQueryParameters() (url.Values, error) {
|
||||||
|
var params = map[string]interface{}{}
|
||||||
|
// check instrumentType field -> json key instType
|
||||||
|
instrumentType := g.instrumentType
|
||||||
|
|
||||||
|
// TEMPLATE check-valid-values
|
||||||
|
switch instrumentType {
|
||||||
|
case InstrumentTypeSpot, InstrumentTypeSwap, InstrumentTypeFutures, InstrumentTypeOption, InstrumentTypeMARGIN:
|
||||||
|
params["instType"] = instrumentType
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("instType value %v is invalid", instrumentType)
|
||||||
|
|
||||||
|
}
|
||||||
|
// END TEMPLATE check-valid-values
|
||||||
|
|
||||||
|
// assign parameter of instrumentType
|
||||||
|
params["instType"] = instrumentType
|
||||||
|
// check instrumentID field -> json key instId
|
||||||
|
if g.instrumentID != nil {
|
||||||
|
instrumentID := *g.instrumentID
|
||||||
|
|
||||||
|
// assign parameter of instrumentID
|
||||||
|
params["instId"] = instrumentID
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
// check orderType field -> json key ordType
|
||||||
|
if g.orderType != nil {
|
||||||
|
orderType := *g.orderType
|
||||||
|
|
||||||
|
// TEMPLATE check-valid-values
|
||||||
|
switch orderType {
|
||||||
|
case OrderTypeMarket, OrderTypeLimit, OrderTypePostOnly, OrderTypeFOK, OrderTypeIOC:
|
||||||
|
params["ordType"] = orderType
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("ordType value %v is invalid", orderType)
|
||||||
|
|
||||||
|
}
|
||||||
|
// END TEMPLATE check-valid-values
|
||||||
|
|
||||||
|
// assign parameter of orderType
|
||||||
|
params["ordType"] = orderType
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
// check underlying field -> json key uly
|
||||||
|
if g.underlying != nil {
|
||||||
|
underlying := *g.underlying
|
||||||
|
|
||||||
|
// assign parameter of underlying
|
||||||
|
params["uly"] = underlying
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
// check instrumentFamily field -> json key instFamily
|
||||||
|
if g.instrumentFamily != nil {
|
||||||
|
instrumentFamily := *g.instrumentFamily
|
||||||
|
|
||||||
|
// assign parameter of instrumentFamily
|
||||||
|
params["instFamily"] = instrumentFamily
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
// check state field -> json key state
|
||||||
|
if g.state != nil {
|
||||||
|
state := *g.state
|
||||||
|
|
||||||
|
// TEMPLATE check-valid-values
|
||||||
|
switch state {
|
||||||
|
case OrderStateCanceled, OrderStateLive, OrderStatePartiallyFilled, OrderStateFilled:
|
||||||
|
params["state"] = state
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("state value %v is invalid", state)
|
||||||
|
|
||||||
|
}
|
||||||
|
// END TEMPLATE check-valid-values
|
||||||
|
|
||||||
|
// assign parameter of state
|
||||||
|
params["state"] = state
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
// check after field -> json key after
|
||||||
|
if g.after != nil {
|
||||||
|
after := *g.after
|
||||||
|
|
||||||
|
// assign parameter of after
|
||||||
|
params["after"] = after
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
// check before field -> json key before
|
||||||
|
if g.before != nil {
|
||||||
|
before := *g.before
|
||||||
|
|
||||||
|
// assign parameter of before
|
||||||
|
params["before"] = before
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
// check startTime field -> json key begin
|
||||||
|
if g.startTime != nil {
|
||||||
|
startTime := *g.startTime
|
||||||
|
|
||||||
|
// assign parameter of startTime
|
||||||
|
// convert time.Time to milliseconds time stamp
|
||||||
|
params["begin"] = strconv.FormatInt(startTime.UnixNano()/int64(time.Millisecond), 10)
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
// check endTime field -> json key end
|
||||||
|
if g.endTime != nil {
|
||||||
|
endTime := *g.endTime
|
||||||
|
|
||||||
|
// assign parameter of endTime
|
||||||
|
// convert time.Time to milliseconds time stamp
|
||||||
|
params["end"] = strconv.FormatInt(endTime.UnixNano()/int64(time.Millisecond), 10)
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
// check limit field -> json key limit
|
||||||
|
if g.limit != nil {
|
||||||
|
limit := *g.limit
|
||||||
|
|
||||||
|
// assign parameter of limit
|
||||||
|
params["limit"] = limit
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
|
||||||
|
query := url.Values{}
|
||||||
|
for _k, _v := range params {
|
||||||
|
query.Add(_k, fmt.Sprintf("%v", _v))
|
||||||
|
}
|
||||||
|
|
||||||
|
return query, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetParameters builds and checks the parameters and return the result in a map object
|
||||||
|
func (g *GetOrderHistoryRequest) GetParameters() (map[string]interface{}, error) {
|
||||||
|
var params = map[string]interface{}{}
|
||||||
|
|
||||||
|
return params, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetParametersQuery converts the parameters from GetParameters into the url.Values format
|
||||||
|
func (g *GetOrderHistoryRequest) GetParametersQuery() (url.Values, error) {
|
||||||
|
query := url.Values{}
|
||||||
|
|
||||||
|
params, err := g.GetParameters()
|
||||||
|
if err != nil {
|
||||||
|
return query, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _k, _v := range params {
|
||||||
|
if g.isVarSlice(_v) {
|
||||||
|
g.iterateSlice(_v, func(it interface{}) {
|
||||||
|
query.Add(_k+"[]", fmt.Sprintf("%v", it))
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
query.Add(_k, fmt.Sprintf("%v", _v))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return query, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetParametersJSON converts the parameters from GetParameters into the JSON format
|
||||||
|
func (g *GetOrderHistoryRequest) GetParametersJSON() ([]byte, error) {
|
||||||
|
params, err := g.GetParameters()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.Marshal(params)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSlugParameters builds and checks the slug parameters and return the result in a map object
|
||||||
|
func (g *GetOrderHistoryRequest) GetSlugParameters() (map[string]interface{}, error) {
|
||||||
|
var params = map[string]interface{}{}
|
||||||
|
|
||||||
|
return params, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GetOrderHistoryRequest) applySlugsToUrl(url string, slugs map[string]string) string {
|
||||||
|
for _k, _v := range slugs {
|
||||||
|
needleRE := regexp.MustCompile(":" + _k + "\\b")
|
||||||
|
url = needleRE.ReplaceAllString(url, _v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return url
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GetOrderHistoryRequest) iterateSlice(slice interface{}, _f func(it interface{})) {
|
||||||
|
sliceValue := reflect.ValueOf(slice)
|
||||||
|
for _i := 0; _i < sliceValue.Len(); _i++ {
|
||||||
|
it := sliceValue.Index(_i).Interface()
|
||||||
|
_f(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GetOrderHistoryRequest) isVarSlice(_v interface{}) bool {
|
||||||
|
rt := reflect.TypeOf(_v)
|
||||||
|
switch rt.Kind() {
|
||||||
|
case reflect.Slice:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GetOrderHistoryRequest) GetSlugsMap() (map[string]string, error) {
|
||||||
|
slugs := map[string]string{}
|
||||||
|
params, err := g.GetSlugParameters()
|
||||||
|
if err != nil {
|
||||||
|
return slugs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _k, _v := range params {
|
||||||
|
slugs[_k] = fmt.Sprintf("%v", _v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return slugs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GetOrderHistoryRequest) Do(ctx context.Context) (OrderList, error) {
|
||||||
|
|
||||||
|
// no body params
|
||||||
|
var params interface{}
|
||||||
|
query, err := g.GetQueryParameters()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
apiURL := "/api/v5/trade/orders-history-archive"
|
||||||
|
|
||||||
|
req, err := g.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
response, err := g.client.SendRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var apiResponse APIResponse
|
||||||
|
if err := response.DecodeJSON(&apiResponse); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var data OrderList
|
||||||
|
if err := json.Unmarshal(apiResponse.Data, &data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return data, nil
|
||||||
|
}
|
|
@ -6,8 +6,8 @@ import (
|
||||||
"github.com/c9s/requestgen"
|
"github.com/c9s/requestgen"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate GetRequest -url "/api/v5/trade/fills-history" -type GetTransactionHistoriesRequest -responseDataType .APIResponse
|
//go:generate GetRequest -url "/api/v5/trade/fills-history" -type GetTransactionHistoryRequest -responseDataType .APIResponse
|
||||||
type GetTransactionHistoriesRequest struct {
|
type GetTransactionHistoryRequest struct {
|
||||||
client requestgen.AuthenticatedAPIClient
|
client requestgen.AuthenticatedAPIClient
|
||||||
|
|
||||||
instrumentType InstrumentType `param:"instType,query"`
|
instrumentType InstrumentType `param:"instType,query"`
|
||||||
|
@ -29,11 +29,9 @@ type GetTransactionHistoriesRequest struct {
|
||||||
limit *uint64 `param:"limit,query"`
|
limit *uint64 `param:"limit,query"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type OrderList []OrderDetails
|
|
||||||
|
|
||||||
// NewGetOrderHistoriesRequest is descending order by createdTime
|
// NewGetOrderHistoriesRequest is descending order by createdTime
|
||||||
func (c *RestClient) NewGetTransactionHistoriesRequest() *GetTransactionHistoriesRequest {
|
func (c *RestClient) NewGetTransactionHistoryRequest() *GetTransactionHistoryRequest {
|
||||||
return &GetTransactionHistoriesRequest{
|
return &GetTransactionHistoryRequest{
|
||||||
client: c,
|
client: c,
|
||||||
instrumentType: InstrumentTypeSpot,
|
instrumentType: InstrumentTypeSpot,
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
// Code generated by "requestgen -method GET -responseType .APIResponse -responseDataField Data -url /api/v5/trade/fills-history -type GetTransactionHistoriesRequest -responseDataType .OrderList"; DO NOT EDIT.
|
// Code generated by "requestgen -method GET -responseType .APIResponse -responseDataField Data -url /api/v5/trade/fills-history -type GetTransactionHistoryRequest -responseDataType .OrderList"; DO NOT EDIT.
|
||||||
|
|
||||||
package okexapi
|
package okexapi
|
||||||
|
|
||||||
|
@ -13,63 +13,63 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (g *GetTransactionHistoriesRequest) InstrumentType(instrumentType InstrumentType) *GetTransactionHistoriesRequest {
|
func (g *GetTransactionHistoryRequest) InstrumentType(instrumentType InstrumentType) *GetTransactionHistoryRequest {
|
||||||
g.instrumentType = instrumentType
|
g.instrumentType = instrumentType
|
||||||
return g
|
return g
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GetTransactionHistoriesRequest) InstrumentID(instrumentID string) *GetTransactionHistoriesRequest {
|
func (g *GetTransactionHistoryRequest) InstrumentID(instrumentID string) *GetTransactionHistoryRequest {
|
||||||
g.instrumentID = &instrumentID
|
g.instrumentID = &instrumentID
|
||||||
return g
|
return g
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GetTransactionHistoriesRequest) OrderType(orderType OrderType) *GetTransactionHistoriesRequest {
|
func (g *GetTransactionHistoryRequest) OrderType(orderType OrderType) *GetTransactionHistoryRequest {
|
||||||
g.orderType = &orderType
|
g.orderType = &orderType
|
||||||
return g
|
return g
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GetTransactionHistoriesRequest) OrderID(orderID string) *GetTransactionHistoriesRequest {
|
func (g *GetTransactionHistoryRequest) OrderID(orderID string) *GetTransactionHistoryRequest {
|
||||||
g.orderID = orderID
|
g.orderID = orderID
|
||||||
return g
|
return g
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GetTransactionHistoriesRequest) Underlying(underlying string) *GetTransactionHistoriesRequest {
|
func (g *GetTransactionHistoryRequest) Underlying(underlying string) *GetTransactionHistoryRequest {
|
||||||
g.underlying = &underlying
|
g.underlying = &underlying
|
||||||
return g
|
return g
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GetTransactionHistoriesRequest) InstrumentFamily(instrumentFamily string) *GetTransactionHistoriesRequest {
|
func (g *GetTransactionHistoryRequest) InstrumentFamily(instrumentFamily string) *GetTransactionHistoryRequest {
|
||||||
g.instrumentFamily = &instrumentFamily
|
g.instrumentFamily = &instrumentFamily
|
||||||
return g
|
return g
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GetTransactionHistoriesRequest) After(after string) *GetTransactionHistoriesRequest {
|
func (g *GetTransactionHistoryRequest) After(after string) *GetTransactionHistoryRequest {
|
||||||
g.after = &after
|
g.after = &after
|
||||||
return g
|
return g
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GetTransactionHistoriesRequest) Before(before string) *GetTransactionHistoriesRequest {
|
func (g *GetTransactionHistoryRequest) Before(before string) *GetTransactionHistoryRequest {
|
||||||
g.before = &before
|
g.before = &before
|
||||||
return g
|
return g
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GetTransactionHistoriesRequest) StartTime(startTime time.Time) *GetTransactionHistoriesRequest {
|
func (g *GetTransactionHistoryRequest) StartTime(startTime time.Time) *GetTransactionHistoryRequest {
|
||||||
g.startTime = &startTime
|
g.startTime = &startTime
|
||||||
return g
|
return g
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GetTransactionHistoriesRequest) EndTime(endTime time.Time) *GetTransactionHistoriesRequest {
|
func (g *GetTransactionHistoryRequest) EndTime(endTime time.Time) *GetTransactionHistoryRequest {
|
||||||
g.endTime = &endTime
|
g.endTime = &endTime
|
||||||
return g
|
return g
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GetTransactionHistoriesRequest) Limit(limit uint64) *GetTransactionHistoriesRequest {
|
func (g *GetTransactionHistoryRequest) Limit(limit uint64) *GetTransactionHistoryRequest {
|
||||||
g.limit = &limit
|
g.limit = &limit
|
||||||
return g
|
return g
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetQueryParameters builds and checks the query parameters and returns url.Values
|
// GetQueryParameters builds and checks the query parameters and returns url.Values
|
||||||
func (g *GetTransactionHistoriesRequest) GetQueryParameters() (url.Values, error) {
|
func (g *GetTransactionHistoryRequest) GetQueryParameters() (url.Values, error) {
|
||||||
var params = map[string]interface{}{}
|
var params = map[string]interface{}{}
|
||||||
// check instrumentType field -> json key instType
|
// check instrumentType field -> json key instType
|
||||||
instrumentType := g.instrumentType
|
instrumentType := g.instrumentType
|
||||||
|
@ -187,14 +187,14 @@ func (g *GetTransactionHistoriesRequest) GetQueryParameters() (url.Values, error
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetParameters builds and checks the parameters and return the result in a map object
|
// GetParameters builds and checks the parameters and return the result in a map object
|
||||||
func (g *GetTransactionHistoriesRequest) GetParameters() (map[string]interface{}, error) {
|
func (g *GetTransactionHistoryRequest) GetParameters() (map[string]interface{}, error) {
|
||||||
var params = map[string]interface{}{}
|
var params = map[string]interface{}{}
|
||||||
|
|
||||||
return params, nil
|
return params, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetParametersQuery converts the parameters from GetParameters into the url.Values format
|
// GetParametersQuery converts the parameters from GetParameters into the url.Values format
|
||||||
func (g *GetTransactionHistoriesRequest) GetParametersQuery() (url.Values, error) {
|
func (g *GetTransactionHistoryRequest) GetParametersQuery() (url.Values, error) {
|
||||||
query := url.Values{}
|
query := url.Values{}
|
||||||
|
|
||||||
params, err := g.GetParameters()
|
params, err := g.GetParameters()
|
||||||
|
@ -216,7 +216,7 @@ func (g *GetTransactionHistoriesRequest) GetParametersQuery() (url.Values, error
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetParametersJSON converts the parameters from GetParameters into the JSON format
|
// GetParametersJSON converts the parameters from GetParameters into the JSON format
|
||||||
func (g *GetTransactionHistoriesRequest) GetParametersJSON() ([]byte, error) {
|
func (g *GetTransactionHistoryRequest) GetParametersJSON() ([]byte, error) {
|
||||||
params, err := g.GetParameters()
|
params, err := g.GetParameters()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -226,13 +226,13 @@ func (g *GetTransactionHistoriesRequest) GetParametersJSON() ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSlugParameters builds and checks the slug parameters and return the result in a map object
|
// GetSlugParameters builds and checks the slug parameters and return the result in a map object
|
||||||
func (g *GetTransactionHistoriesRequest) GetSlugParameters() (map[string]interface{}, error) {
|
func (g *GetTransactionHistoryRequest) GetSlugParameters() (map[string]interface{}, error) {
|
||||||
var params = map[string]interface{}{}
|
var params = map[string]interface{}{}
|
||||||
|
|
||||||
return params, nil
|
return params, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GetTransactionHistoriesRequest) applySlugsToUrl(url string, slugs map[string]string) string {
|
func (g *GetTransactionHistoryRequest) applySlugsToUrl(url string, slugs map[string]string) string {
|
||||||
for _k, _v := range slugs {
|
for _k, _v := range slugs {
|
||||||
needleRE := regexp.MustCompile(":" + _k + "\\b")
|
needleRE := regexp.MustCompile(":" + _k + "\\b")
|
||||||
url = needleRE.ReplaceAllString(url, _v)
|
url = needleRE.ReplaceAllString(url, _v)
|
||||||
|
@ -241,7 +241,7 @@ func (g *GetTransactionHistoriesRequest) applySlugsToUrl(url string, slugs map[s
|
||||||
return url
|
return url
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GetTransactionHistoriesRequest) iterateSlice(slice interface{}, _f func(it interface{})) {
|
func (g *GetTransactionHistoryRequest) iterateSlice(slice interface{}, _f func(it interface{})) {
|
||||||
sliceValue := reflect.ValueOf(slice)
|
sliceValue := reflect.ValueOf(slice)
|
||||||
for _i := 0; _i < sliceValue.Len(); _i++ {
|
for _i := 0; _i < sliceValue.Len(); _i++ {
|
||||||
it := sliceValue.Index(_i).Interface()
|
it := sliceValue.Index(_i).Interface()
|
||||||
|
@ -249,7 +249,7 @@ func (g *GetTransactionHistoriesRequest) iterateSlice(slice interface{}, _f func
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GetTransactionHistoriesRequest) isVarSlice(_v interface{}) bool {
|
func (g *GetTransactionHistoryRequest) isVarSlice(_v interface{}) bool {
|
||||||
rt := reflect.TypeOf(_v)
|
rt := reflect.TypeOf(_v)
|
||||||
switch rt.Kind() {
|
switch rt.Kind() {
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
|
@ -258,7 +258,7 @@ func (g *GetTransactionHistoriesRequest) isVarSlice(_v interface{}) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GetTransactionHistoriesRequest) GetSlugsMap() (map[string]string, error) {
|
func (g *GetTransactionHistoryRequest) GetSlugsMap() (map[string]string, error) {
|
||||||
slugs := map[string]string{}
|
slugs := map[string]string{}
|
||||||
params, err := g.GetSlugParameters()
|
params, err := g.GetSlugParameters()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -272,7 +272,7 @@ func (g *GetTransactionHistoriesRequest) GetSlugsMap() (map[string]string, error
|
||||||
return slugs, nil
|
return slugs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GetTransactionHistoriesRequest) Do(ctx context.Context) (OrderList, error) {
|
func (g *GetTransactionHistoryRequest) Do(ctx context.Context) (OrderList, error) {
|
||||||
|
|
||||||
// no body params
|
// no body params
|
||||||
var params interface{}
|
var params interface{}
|
62
pkg/exchange/okex/query_closed_orders_test.go
Normal file
62
pkg/exchange/okex/query_closed_orders_test.go
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
package okex
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/c9s/bbgo/pkg/testutil"
|
||||||
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_QueryClosedOrders(t *testing.T) {
|
||||||
|
|
||||||
|
key, secret, passphrase, ok := testutil.IntegrationTestWithPassphraseConfigured(t, types.ExchangeOKEx.String())
|
||||||
|
if !ok {
|
||||||
|
t.Skip("Please configure all credentials about OKEX")
|
||||||
|
}
|
||||||
|
|
||||||
|
e := New(key, secret, passphrase)
|
||||||
|
|
||||||
|
queryOrder := types.OrderQuery{
|
||||||
|
Symbol: "BTCUSDT",
|
||||||
|
}
|
||||||
|
|
||||||
|
// test by order id as a cursor
|
||||||
|
closedOrder, err := e.QueryClosedOrders(context.Background(), string(queryOrder.Symbol), time.Time{}, time.Time{}, 609869603774656544)
|
||||||
|
if assert.NoError(t, err) {
|
||||||
|
assert.NotEmpty(t, closedOrder)
|
||||||
|
}
|
||||||
|
t.Logf("closed order detail: %+v", closedOrder)
|
||||||
|
// test by time interval
|
||||||
|
closedOrder, err = e.QueryClosedOrders(context.Background(), string(queryOrder.Symbol), time.Now().Add(-90*24*time.Hour), time.Now(), 0)
|
||||||
|
if assert.NoError(t, err) {
|
||||||
|
assert.NotEmpty(t, closedOrder)
|
||||||
|
}
|
||||||
|
t.Logf("closed order detail: %+v", closedOrder)
|
||||||
|
// test by no parameter
|
||||||
|
closedOrder, err = e.QueryClosedOrders(context.Background(), string(queryOrder.Symbol), time.Time{}, time.Time{}, 0)
|
||||||
|
if assert.NoError(t, err) {
|
||||||
|
assert.NotEmpty(t, closedOrder)
|
||||||
|
}
|
||||||
|
t.Logf("closed order detail: %+v", closedOrder)
|
||||||
|
// test by time interval (boundary test)
|
||||||
|
closedOrder, err = e.QueryClosedOrders(context.Background(), string(queryOrder.Symbol), time.Unix(1694155903, 999), time.Now(), 0)
|
||||||
|
if assert.NoError(t, err) {
|
||||||
|
assert.NotEmpty(t, closedOrder)
|
||||||
|
}
|
||||||
|
t.Logf("closed order detail: %+v", closedOrder)
|
||||||
|
// test by time interval (boundary test)
|
||||||
|
closedOrder, err = e.QueryClosedOrders(context.Background(), string(queryOrder.Symbol), time.Unix(1694154903, 999), time.Unix(1694155904, 0), 0)
|
||||||
|
if assert.NoError(t, err) {
|
||||||
|
assert.NotEmpty(t, closedOrder)
|
||||||
|
}
|
||||||
|
t.Logf("closed order detail: %+v", closedOrder)
|
||||||
|
// test by time interval and order id together
|
||||||
|
closedOrder, err = e.QueryClosedOrders(context.Background(), string(queryOrder.Symbol), time.Unix(1694154903, 999), time.Now(), 609869603774656544)
|
||||||
|
if assert.NoError(t, err) {
|
||||||
|
assert.NotEmpty(t, closedOrder)
|
||||||
|
}
|
||||||
|
t.Logf("closed order detail: %+v", closedOrder)
|
||||||
|
}
|
|
@ -25,7 +25,7 @@ func Test_QueryOrder(t *testing.T) {
|
||||||
e := New(key, secret, passphrase)
|
e := New(key, secret, passphrase)
|
||||||
|
|
||||||
queryOrder := types.OrderQuery{
|
queryOrder := types.OrderQuery{
|
||||||
Symbol: "BTC-USDT",
|
Symbol: "BTCUSDT",
|
||||||
OrderID: "609869603774656544",
|
OrderID: "609869603774656544",
|
||||||
}
|
}
|
||||||
orderDetail, err := e.QueryOrder(context.Background(), queryOrder)
|
orderDetail, err := e.QueryOrder(context.Background(), queryOrder)
|
||||||
|
|
57
pkg/exchange/okex/query_trades_test.go
Normal file
57
pkg/exchange/okex/query_trades_test.go
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
package okex
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/c9s/bbgo/pkg/testutil"
|
||||||
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_QueryTrades(t *testing.T) {
|
||||||
|
key, secret, passphrase, ok := testutil.IntegrationTestWithPassphraseConfigured(t, "OKEX")
|
||||||
|
if !ok {
|
||||||
|
t.Skip("Please configure all credentials about OKEX")
|
||||||
|
}
|
||||||
|
|
||||||
|
e := New(key, secret, passphrase)
|
||||||
|
|
||||||
|
queryOrder := types.OrderQuery{
|
||||||
|
Symbol: "BTCUSDT",
|
||||||
|
}
|
||||||
|
|
||||||
|
since := time.Now().AddDate(0, -3, 0)
|
||||||
|
until := time.Now()
|
||||||
|
|
||||||
|
queryOption := types.TradeQueryOptions{
|
||||||
|
StartTime: &since,
|
||||||
|
EndTime: &until,
|
||||||
|
Limit: 100,
|
||||||
|
}
|
||||||
|
// query by time interval
|
||||||
|
transactionDetail, err := e.QueryTrades(context.Background(), queryOrder.Symbol, &queryOption)
|
||||||
|
if assert.NoError(t, err) {
|
||||||
|
assert.NotEmpty(t, transactionDetail)
|
||||||
|
}
|
||||||
|
t.Logf("transaction detail: %+v", transactionDetail)
|
||||||
|
// query by trade id
|
||||||
|
transactionDetail, err = e.QueryTrades(context.Background(), queryOrder.Symbol, &types.TradeQueryOptions{LastTradeID: 432044402})
|
||||||
|
if assert.NoError(t, err) {
|
||||||
|
assert.NotEmpty(t, transactionDetail)
|
||||||
|
}
|
||||||
|
t.Logf("transaction detail: %+v", transactionDetail)
|
||||||
|
// query by no time interval and no trade id
|
||||||
|
transactionDetail, err = e.QueryTrades(context.Background(), queryOrder.Symbol, &types.TradeQueryOptions{})
|
||||||
|
if assert.NoError(t, err) {
|
||||||
|
assert.NotEmpty(t, transactionDetail)
|
||||||
|
}
|
||||||
|
t.Logf("transaction detail: %+v", transactionDetail)
|
||||||
|
// query by limit exceed default value
|
||||||
|
transactionDetail, err = e.QueryTrades(context.Background(), queryOrder.Symbol, &types.TradeQueryOptions{Limit: 150})
|
||||||
|
if assert.NoError(t, err) {
|
||||||
|
assert.NotEmpty(t, transactionDetail)
|
||||||
|
}
|
||||||
|
t.Logf("transaction detail: %+v", transactionDetail)
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ package testutil
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -26,6 +27,7 @@ func IntegrationTestConfigured(t *testing.T, prefix string) (key, secret string,
|
||||||
|
|
||||||
func IntegrationTestWithPassphraseConfigured(t *testing.T, prefix string) (key, secret, passphrase string, ok bool) {
|
func IntegrationTestWithPassphraseConfigured(t *testing.T, prefix string) (key, secret, passphrase string, ok bool) {
|
||||||
var hasKey, hasSecret, hasPassphrase bool
|
var hasKey, hasSecret, hasPassphrase bool
|
||||||
|
prefix = strings.ToUpper(prefix)
|
||||||
key, hasKey = os.LookupEnv(prefix + "_API_KEY")
|
key, hasKey = os.LookupEnv(prefix + "_API_KEY")
|
||||||
secret, hasSecret = os.LookupEnv(prefix + "_API_SECRET")
|
secret, hasSecret = os.LookupEnv(prefix + "_API_SECRET")
|
||||||
passphrase, hasPassphrase = os.LookupEnv(prefix + "_API_PASSPHRASE")
|
passphrase, hasPassphrase = os.LookupEnv(prefix + "_API_PASSPHRASE")
|
||||||
|
|
Loading…
Reference in New Issue
Block a user