mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-21 22:43:52 +00:00
maxapi: use requestgen to query and submit orders
This commit is contained in:
parent
93b19faa3a
commit
5cba6a6133
|
@ -1,260 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/cmd/cmdutil"
|
||||
"github.com/c9s/bbgo/pkg/exchange/max"
|
||||
maxapi "github.com/c9s/bbgo/pkg/exchange/max/maxapi"
|
||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
"github.com/c9s/bbgo/pkg/util"
|
||||
)
|
||||
|
||||
func init() {
|
||||
rootCmd.PersistentFlags().String("max-api-key", "", "max api key")
|
||||
rootCmd.PersistentFlags().String("max-api-secret", "", "max api secret")
|
||||
rootCmd.PersistentFlags().String("symbol", "maxusdt", "symbol")
|
||||
|
||||
rootCmd.Flags().String("side", "buy", "side")
|
||||
rootCmd.Flags().Int("num-orders", 5, "number of orders for one side")
|
||||
rootCmd.Flags().Float64("behind-volume", 1000.0, "behind volume depth")
|
||||
rootCmd.Flags().Float64("base-quantity", 100.0, "base quantity")
|
||||
rootCmd.Flags().Float64("price-tick", 0.02, "price tick")
|
||||
rootCmd.Flags().Float64("buy-sell-ratio", 1.0, "price tick")
|
||||
}
|
||||
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "trade",
|
||||
Short: "start trader",
|
||||
|
||||
// SilenceUsage is an option to silence usage when an error occurs.
|
||||
SilenceUsage: true,
|
||||
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
symbol := viper.GetString("symbol")
|
||||
if len(symbol) == 0 {
|
||||
return errors.New("empty symbol")
|
||||
}
|
||||
|
||||
key, secret := viper.GetString("max-api-key"), viper.GetString("max-api-secret")
|
||||
if len(key) == 0 || len(secret) == 0 {
|
||||
return errors.New("empty key or secret")
|
||||
}
|
||||
|
||||
side, err := cmd.Flags().GetString("side")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
iv, err := cmd.Flags().GetInt("num-orders")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var numOrders = iv
|
||||
|
||||
fv, err := cmd.Flags().GetFloat64("base-quantity")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var baseQuantity = fixedpoint.NewFromFloat(fv)
|
||||
|
||||
fv, err = cmd.Flags().GetFloat64("price-tick")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var priceTick = fixedpoint.NewFromFloat(fv)
|
||||
|
||||
fv, err = cmd.Flags().GetFloat64("behind-volume")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var behindVolume = fixedpoint.NewFromFloat(fv)
|
||||
|
||||
buySellRatio, err := cmd.Flags().GetFloat64("buy-sell-ratio")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
maxRest := maxapi.NewRestClient(maxapi.ProductionAPIURL)
|
||||
maxRest.Auth(key, secret)
|
||||
|
||||
stream := max.NewStream(key, secret)
|
||||
stream.Subscribe(types.BookChannel, symbol, types.SubscribeOptions{})
|
||||
|
||||
stream.OnOrderUpdate(func(order types.Order) {
|
||||
log.Infof("order: %+v", order)
|
||||
})
|
||||
|
||||
stream.OnBalanceSnapshot(func(balances types.BalanceMap) {
|
||||
log.Infof("balances: %+v", balances)
|
||||
})
|
||||
|
||||
streambook := types.NewStreamBook(symbol)
|
||||
streambook.BindStream(stream)
|
||||
|
||||
cancelSideOrders := func(symbol string, side string) {
|
||||
if err := maxRest.OrderService.CancelAll(side, symbol); err != nil {
|
||||
log.WithError(err).Error("cancel all error")
|
||||
}
|
||||
|
||||
streambook.C.Drain(2*time.Second, 5*time.Second)
|
||||
}
|
||||
|
||||
updateSideOrders := func(symbol string, side string, baseQuantity fixedpoint.Value) {
|
||||
book := streambook.Copy()
|
||||
|
||||
var pvs types.PriceVolumeSlice
|
||||
|
||||
switch side {
|
||||
case "buy":
|
||||
pvs = book.Bids
|
||||
case "sell":
|
||||
pvs = book.Asks
|
||||
}
|
||||
|
||||
if pvs == nil || len(pvs) == 0 {
|
||||
log.Warn("empty bids or asks")
|
||||
return
|
||||
}
|
||||
|
||||
index := pvs.IndexByVolumeDepth(behindVolume)
|
||||
if index == -1 {
|
||||
// do not place orders
|
||||
log.Warn("depth is not enough")
|
||||
return
|
||||
}
|
||||
|
||||
var price = pvs[index].Price
|
||||
var orders = generateOrders(symbol, side, price, priceTick, baseQuantity, numOrders)
|
||||
if len(orders) == 0 {
|
||||
log.Warn("empty orders")
|
||||
return
|
||||
}
|
||||
log.Infof("submitting %d orders", len(orders))
|
||||
|
||||
retOrders, err := maxRest.OrderService.CreateMulti(symbol, orders)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("create multi error")
|
||||
}
|
||||
_ = retOrders
|
||||
|
||||
streambook.C.Drain(2*time.Second, 5*time.Second)
|
||||
}
|
||||
|
||||
update := func() {
|
||||
switch side {
|
||||
case "both":
|
||||
cancelSideOrders(symbol, "buy")
|
||||
updateSideOrders(symbol, "buy", baseQuantity.MulFloat64(buySellRatio))
|
||||
|
||||
cancelSideOrders(symbol, "sell")
|
||||
updateSideOrders(symbol, "sell", baseQuantity.MulFloat64(1.0/buySellRatio))
|
||||
|
||||
default:
|
||||
cancelSideOrders(symbol, side)
|
||||
updateSideOrders(symbol, side, baseQuantity)
|
||||
}
|
||||
}
|
||||
|
||||
go func() {
|
||||
ticker := time.NewTicker(1 * time.Minute)
|
||||
defer ticker.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
|
||||
case <-streambook.C:
|
||||
streambook.C.Drain(2*time.Second, 5*time.Second)
|
||||
update()
|
||||
|
||||
case <-ticker.C:
|
||||
update()
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
log.Info("connecting websocket...")
|
||||
if err := stream.Connect(ctx); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
cmdutil.WaitForSignal(ctx, syscall.SIGINT, syscall.SIGTERM)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func generateOrders(symbol, side string, price, priceTick, baseVolume fixedpoint.Value, numOrders int) (orders []maxapi.Order) {
|
||||
var expBase = fixedpoint.NewFromFloat(0.0)
|
||||
|
||||
switch side {
|
||||
case "buy":
|
||||
if priceTick > 0 {
|
||||
priceTick = -priceTick
|
||||
}
|
||||
case "sell":
|
||||
if priceTick < 0 {
|
||||
priceTick = -priceTick
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < numOrders; i++ {
|
||||
volume := math.Exp(expBase.Float64()) * baseVolume.Float64()
|
||||
|
||||
// skip order less than 10usd
|
||||
if volume*price.Float64() < 10.0 {
|
||||
log.Warnf("amount too small (< 10usd). price=%f volume=%f amount=%f", price.Float64(), volume, volume*price.Float64())
|
||||
continue
|
||||
}
|
||||
|
||||
orders = append(orders, maxapi.Order{
|
||||
Side: side,
|
||||
OrderType: maxapi.OrderTypeLimit,
|
||||
Market: symbol,
|
||||
Price: util.FormatFloat(price.Float64(), 3),
|
||||
Volume: util.FormatFloat(volume, 2),
|
||||
// GroupID: 0,
|
||||
})
|
||||
|
||||
log.Infof("%s order: %.2f @ %.3f", side, volume, price.Float64())
|
||||
|
||||
if len(orders) >= numOrders {
|
||||
break
|
||||
}
|
||||
|
||||
price = price + priceTick
|
||||
declog := math.Log10(math.Abs(priceTick.Float64()))
|
||||
expBase += fixedpoint.NewFromFloat(math.Pow10(-int(declog)) * math.Abs(priceTick.Float64()))
|
||||
log.Infof("expBase: %f", expBase.Float64())
|
||||
}
|
||||
|
||||
return orders
|
||||
}
|
||||
|
||||
func main() {
|
||||
viper.AutomaticEnv()
|
||||
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
|
||||
|
||||
if err := viper.BindPFlags(rootCmd.PersistentFlags()); err != nil {
|
||||
log.WithError(err).Error("bind pflags error")
|
||||
}
|
||||
|
||||
if err := rootCmd.ExecuteContext(context.Background()); err != nil {
|
||||
log.WithError(err).Error("cmd error")
|
||||
}
|
||||
}
|
|
@ -164,7 +164,7 @@ func (e *Exchange) QueryOrder(ctx context.Context, q types.OrderQuery) (*types.O
|
|||
return nil, err
|
||||
}
|
||||
|
||||
maxOrder, err := e.client.OrderService.Get(uint64(orderID))
|
||||
maxOrder, err := e.client.OrderService.NewGetOrderRequest().Id(uint64(orderID)).Do(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -399,14 +399,14 @@ func (e *Exchange) CancelOrders(ctx context.Context, orders ...types.Order) (err
|
|||
for _, o := range orphanOrders {
|
||||
var req = e.client.OrderService.NewOrderCancelRequest()
|
||||
if o.OrderID > 0 {
|
||||
req.ID(o.OrderID)
|
||||
req.Id(o.OrderID)
|
||||
} else if len(o.ClientOrderID) > 0 && o.ClientOrderID != types.NoClientOrderID {
|
||||
req.ClientOrderID(o.ClientOrderID)
|
||||
} else {
|
||||
return fmt.Errorf("order id or client order id is not defined, order=%+v", o)
|
||||
}
|
||||
|
||||
if err := req.Do(ctx); err != nil {
|
||||
if _, err := req.Do(ctx); err != nil {
|
||||
log.WithError(err).Errorf("order cancel error")
|
||||
err2 = err
|
||||
}
|
||||
|
|
247
pkg/exchange/max/maxapi/create_order_request_requestgen.go
Normal file
247
pkg/exchange/max/maxapi/create_order_request_requestgen.go
Normal file
|
@ -0,0 +1,247 @@
|
|||
// Code generated by "requestgen -method POST -url v2/orders -type CreateOrderRequest -responseType .Order"; DO NOT EDIT.
|
||||
|
||||
package max
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func (c *CreateOrderRequest) Market(market string) *CreateOrderRequest {
|
||||
c.market = market
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *CreateOrderRequest) Side(side string) *CreateOrderRequest {
|
||||
c.side = side
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *CreateOrderRequest) Volume(volume string) *CreateOrderRequest {
|
||||
c.volume = volume
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *CreateOrderRequest) OrderType(orderType string) *CreateOrderRequest {
|
||||
c.orderType = orderType
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *CreateOrderRequest) Price(price string) *CreateOrderRequest {
|
||||
c.price = &price
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *CreateOrderRequest) StopPrice(stopPrice string) *CreateOrderRequest {
|
||||
c.stopPrice = &stopPrice
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *CreateOrderRequest) ClientOrderID(clientOrderID string) *CreateOrderRequest {
|
||||
c.clientOrderID = &clientOrderID
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *CreateOrderRequest) GroupID(groupID string) *CreateOrderRequest {
|
||||
c.groupID = &groupID
|
||||
return c
|
||||
}
|
||||
|
||||
// GetQueryParameters builds and checks the query parameters and returns url.Values
|
||||
func (c *CreateOrderRequest) GetQueryParameters() (url.Values, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
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 (c *CreateOrderRequest) GetParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
// check market field -> json key market
|
||||
market := c.market
|
||||
|
||||
// TEMPLATE check-required
|
||||
if len(market) == 0 {
|
||||
return nil, fmt.Errorf("market is required, empty string given")
|
||||
}
|
||||
// END TEMPLATE check-required
|
||||
|
||||
// assign parameter of market
|
||||
params["market"] = market
|
||||
// check side field -> json key side
|
||||
side := c.side
|
||||
|
||||
// TEMPLATE check-required
|
||||
if len(side) == 0 {
|
||||
return nil, fmt.Errorf("side is required, empty string given")
|
||||
}
|
||||
// END TEMPLATE check-required
|
||||
|
||||
// assign parameter of side
|
||||
params["side"] = side
|
||||
// check volume field -> json key volume
|
||||
volume := c.volume
|
||||
|
||||
// TEMPLATE check-required
|
||||
if len(volume) == 0 {
|
||||
return nil, fmt.Errorf("volume is required, empty string given")
|
||||
}
|
||||
// END TEMPLATE check-required
|
||||
|
||||
// assign parameter of volume
|
||||
params["volume"] = volume
|
||||
// check orderType field -> json key ord_type
|
||||
orderType := c.orderType
|
||||
|
||||
// assign parameter of orderType
|
||||
params["ord_type"] = orderType
|
||||
// check price field -> json key price
|
||||
if c.price != nil {
|
||||
price := *c.price
|
||||
|
||||
// assign parameter of price
|
||||
params["price"] = price
|
||||
} else {
|
||||
}
|
||||
// check stopPrice field -> json key stop_price
|
||||
if c.stopPrice != nil {
|
||||
stopPrice := *c.stopPrice
|
||||
|
||||
// assign parameter of stopPrice
|
||||
params["stop_price"] = stopPrice
|
||||
} else {
|
||||
}
|
||||
// check clientOrderID field -> json key client_oid
|
||||
if c.clientOrderID != nil {
|
||||
clientOrderID := *c.clientOrderID
|
||||
|
||||
// assign parameter of clientOrderID
|
||||
params["client_oid"] = clientOrderID
|
||||
} else {
|
||||
}
|
||||
// check groupID field -> json key group_id
|
||||
if c.groupID != nil {
|
||||
groupID := *c.groupID
|
||||
|
||||
// assign parameter of groupID
|
||||
params["group_id"] = groupID
|
||||
} else {
|
||||
}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
// GetParametersQuery converts the parameters from GetParameters into the url.Values format
|
||||
func (c *CreateOrderRequest) GetParametersQuery() (url.Values, error) {
|
||||
query := url.Values{}
|
||||
|
||||
params, err := c.GetParameters()
|
||||
if err != nil {
|
||||
return query, err
|
||||
}
|
||||
|
||||
for k, v := range params {
|
||||
if c.isVarSlice(v) {
|
||||
c.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 (c *CreateOrderRequest) GetParametersJSON() ([]byte, error) {
|
||||
params, err := c.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 (c *CreateOrderRequest) GetSlugParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func (c *CreateOrderRequest) 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 (c *CreateOrderRequest) 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 (c *CreateOrderRequest) isVarSlice(v interface{}) bool {
|
||||
rt := reflect.TypeOf(v)
|
||||
switch rt.Kind() {
|
||||
case reflect.Slice:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *CreateOrderRequest) GetSlugsMap() (map[string]string, error) {
|
||||
slugs := map[string]string{}
|
||||
params, err := c.GetSlugParameters()
|
||||
if err != nil {
|
||||
return slugs, nil
|
||||
}
|
||||
|
||||
for k, v := range params {
|
||||
slugs[k] = fmt.Sprintf("%v", v)
|
||||
}
|
||||
|
||||
return slugs, nil
|
||||
}
|
||||
|
||||
func (c *CreateOrderRequest) Do(ctx context.Context) (*Order, error) {
|
||||
|
||||
params, err := c.GetParameters()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
query := url.Values{}
|
||||
|
||||
apiURL := "v2/orders"
|
||||
|
||||
req, err := c.client.NewAuthenticatedRequest(ctx, "POST", apiURL, query, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response, err := c.client.SendRequest(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var apiResponse Order
|
||||
if err := response.DecodeJSON(&apiResponse); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &apiResponse, nil
|
||||
}
|
174
pkg/exchange/max/maxapi/get_order_history_request_requestgen.go
Normal file
174
pkg/exchange/max/maxapi/get_order_history_request_requestgen.go
Normal file
|
@ -0,0 +1,174 @@
|
|||
// Code generated by "requestgen -method GET -url v2/orders/history -type GetOrderHistoryRequest -responseType []Order"; DO NOT EDIT.
|
||||
|
||||
package max
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func (g *GetOrderHistoryRequest) Market(market string) *GetOrderHistoryRequest {
|
||||
g.market = market
|
||||
return g
|
||||
}
|
||||
|
||||
func (g *GetOrderHistoryRequest) FromID(fromID int64) *GetOrderHistoryRequest {
|
||||
g.fromID = &fromID
|
||||
return g
|
||||
}
|
||||
|
||||
func (g *GetOrderHistoryRequest) Limit(limit int) *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{}{}
|
||||
|
||||
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{}{}
|
||||
// check market field -> json key market
|
||||
market := g.market
|
||||
|
||||
// assign parameter of market
|
||||
params["market"] = market
|
||||
// check fromID field -> json key from_id
|
||||
if g.fromID != nil {
|
||||
fromID := *g.fromID
|
||||
|
||||
// assign parameter of fromID
|
||||
params["from_id"] = fromID
|
||||
} else {
|
||||
}
|
||||
// check limit field -> json key limit
|
||||
if g.limit != nil {
|
||||
limit := *g.limit
|
||||
|
||||
// assign parameter of limit
|
||||
params["limit"] = limit
|
||||
} else {
|
||||
}
|
||||
|
||||
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) ([]Order, error) {
|
||||
|
||||
// empty params for GET operation
|
||||
var params interface{}
|
||||
query, err := g.GetParametersQuery()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
apiURL := "v2/orders/history"
|
||||
|
||||
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 []Order
|
||||
if err := response.DecodeJSON(&apiResponse); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return apiResponse, nil
|
||||
}
|
164
pkg/exchange/max/maxapi/get_order_request_requestgen.go
Normal file
164
pkg/exchange/max/maxapi/get_order_request_requestgen.go
Normal file
|
@ -0,0 +1,164 @@
|
|||
// Code generated by "requestgen -method GET -url v2/order -type GetOrderRequest -responseType .Order"; DO NOT EDIT.
|
||||
|
||||
package max
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func (g *GetOrderRequest) Id(id uint64) *GetOrderRequest {
|
||||
g.id = &id
|
||||
return g
|
||||
}
|
||||
|
||||
func (g *GetOrderRequest) ClientOrderID(clientOrderID string) *GetOrderRequest {
|
||||
g.clientOrderID = &clientOrderID
|
||||
return g
|
||||
}
|
||||
|
||||
// GetQueryParameters builds and checks the query parameters and returns url.Values
|
||||
func (g *GetOrderRequest) GetQueryParameters() (url.Values, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
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 *GetOrderRequest) GetParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
// check id field -> json key id
|
||||
if g.id != nil {
|
||||
id := *g.id
|
||||
|
||||
// assign parameter of id
|
||||
params["id"] = id
|
||||
} else {
|
||||
}
|
||||
// check clientOrderID field -> json key client_oid
|
||||
if g.clientOrderID != nil {
|
||||
clientOrderID := *g.clientOrderID
|
||||
|
||||
// assign parameter of clientOrderID
|
||||
params["client_oid"] = clientOrderID
|
||||
} else {
|
||||
}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
// GetParametersQuery converts the parameters from GetParameters into the url.Values format
|
||||
func (g *GetOrderRequest) 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 *GetOrderRequest) 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 *GetOrderRequest) GetSlugParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func (g *GetOrderRequest) 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 *GetOrderRequest) 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 *GetOrderRequest) isVarSlice(v interface{}) bool {
|
||||
rt := reflect.TypeOf(v)
|
||||
switch rt.Kind() {
|
||||
case reflect.Slice:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (g *GetOrderRequest) 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 *GetOrderRequest) Do(ctx context.Context) (*Order, error) {
|
||||
|
||||
// empty params for GET operation
|
||||
var params interface{}
|
||||
query, err := g.GetParametersQuery()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
apiURL := "v2/order"
|
||||
|
||||
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 Order
|
||||
if err := response.DecodeJSON(&apiResponse); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &apiResponse, nil
|
||||
}
|
227
pkg/exchange/max/maxapi/get_orders_request_requestgen.go
Normal file
227
pkg/exchange/max/maxapi/get_orders_request_requestgen.go
Normal file
|
@ -0,0 +1,227 @@
|
|||
// Code generated by "requestgen -method GET -url v2/orders -type GetOrdersRequest -responseType []Order"; DO NOT EDIT.
|
||||
|
||||
package max
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func (g *GetOrdersRequest) Market(market string) *GetOrdersRequest {
|
||||
g.market = market
|
||||
return g
|
||||
}
|
||||
|
||||
func (g *GetOrdersRequest) Side(side string) *GetOrdersRequest {
|
||||
g.side = &side
|
||||
return g
|
||||
}
|
||||
|
||||
func (g *GetOrdersRequest) GroupID(groupID uint32) *GetOrdersRequest {
|
||||
g.groupID = &groupID
|
||||
return g
|
||||
}
|
||||
|
||||
func (g *GetOrdersRequest) Limit(limit int) *GetOrdersRequest {
|
||||
g.limit = &limit
|
||||
return g
|
||||
}
|
||||
|
||||
func (g *GetOrdersRequest) Page(page int) *GetOrdersRequest {
|
||||
g.page = &page
|
||||
return g
|
||||
}
|
||||
|
||||
func (g *GetOrdersRequest) OrderBy(orderBy string) *GetOrdersRequest {
|
||||
g.orderBy = &orderBy
|
||||
return g
|
||||
}
|
||||
|
||||
func (g *GetOrdersRequest) State(state []OrderState) *GetOrdersRequest {
|
||||
g.state = state
|
||||
return g
|
||||
}
|
||||
|
||||
// GetQueryParameters builds and checks the query parameters and returns url.Values
|
||||
func (g *GetOrdersRequest) GetQueryParameters() (url.Values, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
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 *GetOrdersRequest) GetParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
// check market field -> json key market
|
||||
market := g.market
|
||||
|
||||
// assign parameter of market
|
||||
params["market"] = market
|
||||
// check side field -> json key side
|
||||
if g.side != nil {
|
||||
side := *g.side
|
||||
|
||||
// assign parameter of side
|
||||
params["side"] = side
|
||||
} else {
|
||||
}
|
||||
// check groupID field -> json key groupID
|
||||
if g.groupID != nil {
|
||||
groupID := *g.groupID
|
||||
|
||||
// assign parameter of groupID
|
||||
params["groupID"] = groupID
|
||||
} else {
|
||||
}
|
||||
// check limit field -> json key limit
|
||||
if g.limit != nil {
|
||||
limit := *g.limit
|
||||
|
||||
// assign parameter of limit
|
||||
params["limit"] = limit
|
||||
} else {
|
||||
}
|
||||
// check page field -> json key page
|
||||
if g.page != nil {
|
||||
page := *g.page
|
||||
|
||||
// assign parameter of page
|
||||
params["page"] = page
|
||||
} else {
|
||||
}
|
||||
// check orderBy field -> json key order_by
|
||||
if g.orderBy != nil {
|
||||
orderBy := *g.orderBy
|
||||
|
||||
// assign parameter of orderBy
|
||||
params["order_by"] = orderBy
|
||||
} else {
|
||||
orderBy := "desc"
|
||||
|
||||
// assign parameter of orderBy
|
||||
params["order_by"] = orderBy
|
||||
}
|
||||
// check state field -> json key state
|
||||
state := g.state
|
||||
|
||||
// assign parameter of state
|
||||
params["state"] = state
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
// GetParametersQuery converts the parameters from GetParameters into the url.Values format
|
||||
func (g *GetOrdersRequest) 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 *GetOrdersRequest) 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 *GetOrdersRequest) GetSlugParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func (g *GetOrdersRequest) 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 *GetOrdersRequest) 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 *GetOrdersRequest) isVarSlice(v interface{}) bool {
|
||||
rt := reflect.TypeOf(v)
|
||||
switch rt.Kind() {
|
||||
case reflect.Slice:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (g *GetOrdersRequest) 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 *GetOrdersRequest) Do(ctx context.Context) ([]Order, error) {
|
||||
|
||||
// empty params for GET operation
|
||||
var params interface{}
|
||||
query, err := g.GetParametersQuery()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
apiURL := "v2/orders"
|
||||
|
||||
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 []Order
|
||||
if err := response.DecodeJSON(&apiResponse); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return apiResponse, nil
|
||||
}
|
|
@ -1,11 +1,14 @@
|
|||
package max
|
||||
|
||||
//go:generate -command GetRequest requestgen -method GET
|
||||
//go:generate -command PostRequest requestgen -method POST
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/c9s/requestgen"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
|
@ -172,6 +175,40 @@ func (s *OrderService) Open(market string, options QueryOrderOptions) ([]Order,
|
|||
return orders, nil
|
||||
}
|
||||
|
||||
//go:generate GetRequest -url "v2/orders/history" -type GetOrderHistoryRequest -responseType []Order
|
||||
type GetOrderHistoryRequest struct {
|
||||
client requestgen.AuthenticatedAPIClient
|
||||
|
||||
market string `param:"market"`
|
||||
fromID *int64 `param:"from_id"`
|
||||
limit *int `param:"limit"`
|
||||
}
|
||||
|
||||
func (s *OrderService) NewGetOrderHistoryRequest() *GetOrderHistoryRequest {
|
||||
return &GetOrderHistoryRequest{
|
||||
client: s.client,
|
||||
}
|
||||
}
|
||||
|
||||
//go:generate GetRequest -url "v2/orders" -type GetOrdersRequest -responseType []Order
|
||||
type GetOrdersRequest struct {
|
||||
client requestgen.AuthenticatedAPIClient
|
||||
|
||||
market string `param:"market"`
|
||||
side *string `param:"side"`
|
||||
groupID *uint32 `param:"groupID"`
|
||||
limit *int `param:"limit"`
|
||||
page *int `param:"page"`
|
||||
orderBy *string `param:"order_by" default:"desc"`
|
||||
state []OrderState `param:"state"`
|
||||
}
|
||||
|
||||
func (s *OrderService) NewGetOrdersRequest() *GetOrdersRequest {
|
||||
return &GetOrdersRequest{
|
||||
client: s.client,
|
||||
}
|
||||
}
|
||||
|
||||
// All returns all orders for the authenticated account.
|
||||
func (s *OrderService) All(market string, limit, page int, states ...OrderState) ([]Order, error) {
|
||||
payload := map[string]interface{}{
|
||||
|
@ -200,52 +237,9 @@ func (s *OrderService) All(market string, limit, page int, states ...OrderState)
|
|||
return orders, nil
|
||||
}
|
||||
|
||||
// CancelAll active orders for the authenticated account.
|
||||
func (s *OrderService) CancelAll(side string, market string) error {
|
||||
payload := map[string]interface{}{}
|
||||
if side == "buy" || side == "sell" {
|
||||
payload["side"] = side
|
||||
}
|
||||
if market != "all" {
|
||||
payload["market"] = market
|
||||
}
|
||||
|
||||
req, err := s.client.newAuthenticatedRequest(nil, "POST", "v2/orders/clear", nil, payload, relUrlV2OrdersClear)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = s.client.SendRequest(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Options carry the option fields for REST API
|
||||
type Options map[string]interface{}
|
||||
|
||||
// Create a new order.
|
||||
func (s *OrderService) Create(market string, side string, volume float64, price float64, orderType string, options Options) (*Order, error) {
|
||||
options["market"] = market
|
||||
options["volume"] = strconv.FormatFloat(volume, 'f', -1, 64)
|
||||
options["price"] = strconv.FormatFloat(price, 'f', -1, 64)
|
||||
options["side"] = side
|
||||
options["ord_type"] = orderType
|
||||
response, err := s.client.sendAuthenticatedRequest("POST", "v2/orders", options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var order = Order{}
|
||||
if err := response.DecodeJSON(&order); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &order, nil
|
||||
}
|
||||
|
||||
// Create multiple order in a single request
|
||||
func (s *OrderService) CreateMulti(market string, orders []Order) (*MultiOrderResponse, error) {
|
||||
req := s.NewCreateMultiOrderRequest()
|
||||
|
@ -254,151 +248,41 @@ func (s *OrderService) CreateMulti(market string, orders []Order) (*MultiOrderRe
|
|||
return req.Do(context.Background())
|
||||
}
|
||||
|
||||
// Cancel the order with id `orderID`.
|
||||
func (s *OrderService) Cancel(orderID uint64, clientOrderID string) error {
|
||||
req := s.NewOrderCancelRequest()
|
||||
|
||||
if orderID > 0 {
|
||||
req.ID(orderID)
|
||||
} else if len(clientOrderID) > 0 {
|
||||
req.ClientOrderID(clientOrderID)
|
||||
}
|
||||
|
||||
return req.Do(context.Background())
|
||||
}
|
||||
|
||||
type OrderCancelAllRequestParams struct {
|
||||
*PrivateRequestParams
|
||||
|
||||
Side string `json:"side,omitempty"`
|
||||
Market string `json:"market,omitempty"`
|
||||
GroupID int64 `json:"groupID,omitempty"`
|
||||
}
|
||||
|
||||
//go:generate PostRequest -url "v2/orders/clear" -type OrderCancelAllRequest -responseType []Order
|
||||
type OrderCancelAllRequest struct {
|
||||
client *RestClient
|
||||
client requestgen.AuthenticatedAPIClient
|
||||
|
||||
params OrderCancelAllRequestParams
|
||||
|
||||
side *string
|
||||
market *string
|
||||
groupID *uint32
|
||||
}
|
||||
|
||||
func (r *OrderCancelAllRequest) Side(side string) *OrderCancelAllRequest {
|
||||
r.side = &side
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *OrderCancelAllRequest) Market(market string) *OrderCancelAllRequest {
|
||||
r.market = &market
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *OrderCancelAllRequest) GroupID(groupID uint32) *OrderCancelAllRequest {
|
||||
r.groupID = &groupID
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *OrderCancelAllRequest) Do(ctx context.Context) (orders []Order, err error) {
|
||||
var payload = map[string]interface{}{}
|
||||
if r.side != nil {
|
||||
payload["side"] = *r.side
|
||||
}
|
||||
if r.market != nil {
|
||||
payload["market"] = *r.market
|
||||
}
|
||||
if r.groupID != nil {
|
||||
payload["groupID"] = *r.groupID
|
||||
}
|
||||
|
||||
req, err := r.client.newAuthenticatedRequest(nil, "POST", "v2/orders/clear", nil, payload, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
response, err := r.client.SendRequest(req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = response.DecodeJSON(&orders)
|
||||
return
|
||||
side *string `param:"side"`
|
||||
market *string `param:"market"`
|
||||
groupID *uint32 `param:"groupID"`
|
||||
}
|
||||
|
||||
func (s *OrderService) NewOrderCancelAllRequest() *OrderCancelAllRequest {
|
||||
return &OrderCancelAllRequest{client: s.client}
|
||||
}
|
||||
|
||||
type OrderCancelRequestParams struct {
|
||||
*PrivateRequestParams
|
||||
|
||||
ID uint64 `json:"id,omitempty"`
|
||||
ClientOrderID string `json:"client_oid,omitempty"`
|
||||
}
|
||||
|
||||
//go:generate PostRequest -url "v2/order/delete" -type OrderCancelRequest -responseType .Order
|
||||
type OrderCancelRequest struct {
|
||||
client *RestClient
|
||||
client requestgen.AuthenticatedAPIClient
|
||||
|
||||
params OrderCancelRequestParams
|
||||
}
|
||||
|
||||
func (r *OrderCancelRequest) ID(id uint64) *OrderCancelRequest {
|
||||
r.params.ID = id
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *OrderCancelRequest) ClientOrderID(id string) *OrderCancelRequest {
|
||||
r.params.ClientOrderID = id
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *OrderCancelRequest) Do(ctx context.Context) error {
|
||||
req, err := r.client.newAuthenticatedRequest(nil, "POST", "v2/order/delete", nil, &r.params, relUrlV2OrderDelete)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
response, err := r.client.SendRequest(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var order = Order{}
|
||||
if err := response.DecodeJSON(&order); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
id *uint64 `param:"id,omitempty"`
|
||||
clientOrderID *string `param:"client_oid,omitempty"`
|
||||
}
|
||||
|
||||
func (s *OrderService) NewOrderCancelRequest() *OrderCancelRequest {
|
||||
return &OrderCancelRequest{client: s.client}
|
||||
}
|
||||
|
||||
// Status retrieves the given order from the API.
|
||||
func (s *OrderService) Get(orderID uint64) (*Order, error) {
|
||||
payload := map[string]interface{}{
|
||||
"id": orderID,
|
||||
//go:generate GetRequest -url "v2/order" -type GetOrderRequest -responseType .Order
|
||||
type GetOrderRequest struct {
|
||||
client requestgen.AuthenticatedAPIClient
|
||||
|
||||
id *uint64 `param:"id,omitempty"`
|
||||
clientOrderID *string `param:"client_oid,omitempty"`
|
||||
}
|
||||
|
||||
req, err := s.client.newAuthenticatedRequest(nil, "GET", "v2/order", nil, payload, relUrlV2Order)
|
||||
if err != nil {
|
||||
return &Order{}, err
|
||||
}
|
||||
|
||||
response, err := s.client.SendRequest(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var order = Order{}
|
||||
|
||||
if err := response.DecodeJSON(&order); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &order, nil
|
||||
func (s *OrderService) NewGetOrderRequest() *GetOrderRequest {
|
||||
return &GetOrderRequest{client: s.client}
|
||||
}
|
||||
|
||||
type MultiOrderRequestParams struct {
|
||||
|
@ -482,97 +366,19 @@ func (s *OrderService) NewCreateMultiOrderRequest() *CreateMultiOrderRequest {
|
|||
return &CreateMultiOrderRequest{client: s.client}
|
||||
}
|
||||
|
||||
//go:generate PostRequest -url "v2/orders" -type CreateOrderRequest -responseType .Order
|
||||
type CreateOrderRequest struct {
|
||||
client *RestClient
|
||||
client requestgen.AuthenticatedAPIClient
|
||||
|
||||
market *string
|
||||
volume *string
|
||||
price *string
|
||||
stopPrice *string
|
||||
side *string
|
||||
orderType *string
|
||||
clientOrderID *string
|
||||
groupID *string
|
||||
}
|
||||
market string `param:"market,required"`
|
||||
side string `param:"side,required"`
|
||||
volume string `param:"volume,required"`
|
||||
orderType string `param:"ord_type"`
|
||||
|
||||
func (r *CreateOrderRequest) Market(market string) *CreateOrderRequest {
|
||||
r.market = &market
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *CreateOrderRequest) Volume(volume string) *CreateOrderRequest {
|
||||
r.volume = &volume
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *CreateOrderRequest) Price(price string) *CreateOrderRequest {
|
||||
r.price = &price
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *CreateOrderRequest) StopPrice(price string) *CreateOrderRequest {
|
||||
r.stopPrice = &price
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *CreateOrderRequest) Side(side string) *CreateOrderRequest {
|
||||
r.side = &side
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *CreateOrderRequest) OrderType(orderType string) *CreateOrderRequest {
|
||||
r.orderType = &orderType
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *CreateOrderRequest) ClientOrderID(clientOrderID string) *CreateOrderRequest {
|
||||
r.clientOrderID = &clientOrderID
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *CreateOrderRequest) Do(ctx context.Context) (order *Order, err error) {
|
||||
var payload = map[string]interface{}{
|
||||
"market": r.market,
|
||||
"volume": r.volume,
|
||||
"side": r.side,
|
||||
}
|
||||
|
||||
if r.price != nil {
|
||||
payload["price"] = r.price
|
||||
}
|
||||
|
||||
if r.stopPrice != nil {
|
||||
payload["stop_price"] = r.stopPrice
|
||||
}
|
||||
|
||||
if r.orderType != nil {
|
||||
payload["ord_type"] = r.orderType
|
||||
}
|
||||
|
||||
if r.clientOrderID != nil {
|
||||
payload["client_oid"] = r.clientOrderID
|
||||
}
|
||||
|
||||
if r.groupID != nil {
|
||||
payload["group_id"] = r.groupID
|
||||
}
|
||||
|
||||
req, err := r.client.newAuthenticatedRequest(nil, "POST", "v2/orders", nil, payload, relUrlV2Orders)
|
||||
if err != nil {
|
||||
return order, errors.Wrapf(err, "order create error")
|
||||
}
|
||||
|
||||
response, err := r.client.SendRequest(req)
|
||||
if err != nil {
|
||||
return order, err
|
||||
}
|
||||
|
||||
order = &Order{}
|
||||
if err := response.DecodeJSON(order); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return order, err
|
||||
price *string `param:"price"`
|
||||
stopPrice *string `param:"stop_price"`
|
||||
clientOrderID *string `param:"client_oid"`
|
||||
groupID *string `param:"group_id"`
|
||||
}
|
||||
|
||||
func (s *OrderService) NewCreateOrderRequest() *CreateOrderRequest {
|
||||
|
|
176
pkg/exchange/max/maxapi/order_cancel_all_request_requestgen.go
Normal file
176
pkg/exchange/max/maxapi/order_cancel_all_request_requestgen.go
Normal file
|
@ -0,0 +1,176 @@
|
|||
// Code generated by "requestgen -method POST -url v2/orders/clear -type OrderCancelAllRequest -responseType []Order"; DO NOT EDIT.
|
||||
|
||||
package max
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func (o *OrderCancelAllRequest) Side(side string) *OrderCancelAllRequest {
|
||||
o.side = &side
|
||||
return o
|
||||
}
|
||||
|
||||
func (o *OrderCancelAllRequest) Market(market string) *OrderCancelAllRequest {
|
||||
o.market = &market
|
||||
return o
|
||||
}
|
||||
|
||||
func (o *OrderCancelAllRequest) GroupID(groupID uint32) *OrderCancelAllRequest {
|
||||
o.groupID = &groupID
|
||||
return o
|
||||
}
|
||||
|
||||
// GetQueryParameters builds and checks the query parameters and returns url.Values
|
||||
func (o *OrderCancelAllRequest) GetQueryParameters() (url.Values, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
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 (o *OrderCancelAllRequest) GetParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
// check side field -> json key side
|
||||
if o.side != nil {
|
||||
side := *o.side
|
||||
|
||||
// assign parameter of side
|
||||
params["side"] = side
|
||||
} else {
|
||||
}
|
||||
// check market field -> json key market
|
||||
if o.market != nil {
|
||||
market := *o.market
|
||||
|
||||
// assign parameter of market
|
||||
params["market"] = market
|
||||
} else {
|
||||
}
|
||||
// check groupID field -> json key groupID
|
||||
if o.groupID != nil {
|
||||
groupID := *o.groupID
|
||||
|
||||
// assign parameter of groupID
|
||||
params["groupID"] = groupID
|
||||
} else {
|
||||
}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
// GetParametersQuery converts the parameters from GetParameters into the url.Values format
|
||||
func (o *OrderCancelAllRequest) GetParametersQuery() (url.Values, error) {
|
||||
query := url.Values{}
|
||||
|
||||
params, err := o.GetParameters()
|
||||
if err != nil {
|
||||
return query, err
|
||||
}
|
||||
|
||||
for k, v := range params {
|
||||
if o.isVarSlice(v) {
|
||||
o.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 (o *OrderCancelAllRequest) GetParametersJSON() ([]byte, error) {
|
||||
params, err := o.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 (o *OrderCancelAllRequest) GetSlugParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func (o *OrderCancelAllRequest) 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 (o *OrderCancelAllRequest) 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 (o *OrderCancelAllRequest) isVarSlice(v interface{}) bool {
|
||||
rt := reflect.TypeOf(v)
|
||||
switch rt.Kind() {
|
||||
case reflect.Slice:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *OrderCancelAllRequest) GetSlugsMap() (map[string]string, error) {
|
||||
slugs := map[string]string{}
|
||||
params, err := o.GetSlugParameters()
|
||||
if err != nil {
|
||||
return slugs, nil
|
||||
}
|
||||
|
||||
for k, v := range params {
|
||||
slugs[k] = fmt.Sprintf("%v", v)
|
||||
}
|
||||
|
||||
return slugs, nil
|
||||
}
|
||||
|
||||
func (o *OrderCancelAllRequest) Do(ctx context.Context) ([]Order, error) {
|
||||
|
||||
params, err := o.GetParameters()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
query := url.Values{}
|
||||
|
||||
apiURL := "v2/orders/clear"
|
||||
|
||||
req, err := o.client.NewAuthenticatedRequest(ctx, "POST", apiURL, query, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response, err := o.client.SendRequest(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var apiResponse []Order
|
||||
if err := response.DecodeJSON(&apiResponse); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return apiResponse, nil
|
||||
}
|
163
pkg/exchange/max/maxapi/order_cancel_request_requestgen.go
Normal file
163
pkg/exchange/max/maxapi/order_cancel_request_requestgen.go
Normal file
|
@ -0,0 +1,163 @@
|
|||
// Code generated by "requestgen -method POST -url v2/order/delete -type OrderCancelRequest -responseType .Order"; DO NOT EDIT.
|
||||
|
||||
package max
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func (o *OrderCancelRequest) Id(id uint64) *OrderCancelRequest {
|
||||
o.id = &id
|
||||
return o
|
||||
}
|
||||
|
||||
func (o *OrderCancelRequest) ClientOrderID(clientOrderID string) *OrderCancelRequest {
|
||||
o.clientOrderID = &clientOrderID
|
||||
return o
|
||||
}
|
||||
|
||||
// GetQueryParameters builds and checks the query parameters and returns url.Values
|
||||
func (o *OrderCancelRequest) GetQueryParameters() (url.Values, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
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 (o *OrderCancelRequest) GetParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
// check id field -> json key id
|
||||
if o.id != nil {
|
||||
id := *o.id
|
||||
|
||||
// assign parameter of id
|
||||
params["id"] = id
|
||||
} else {
|
||||
}
|
||||
// check clientOrderID field -> json key client_oid
|
||||
if o.clientOrderID != nil {
|
||||
clientOrderID := *o.clientOrderID
|
||||
|
||||
// assign parameter of clientOrderID
|
||||
params["client_oid"] = clientOrderID
|
||||
} else {
|
||||
}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
// GetParametersQuery converts the parameters from GetParameters into the url.Values format
|
||||
func (o *OrderCancelRequest) GetParametersQuery() (url.Values, error) {
|
||||
query := url.Values{}
|
||||
|
||||
params, err := o.GetParameters()
|
||||
if err != nil {
|
||||
return query, err
|
||||
}
|
||||
|
||||
for k, v := range params {
|
||||
if o.isVarSlice(v) {
|
||||
o.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 (o *OrderCancelRequest) GetParametersJSON() ([]byte, error) {
|
||||
params, err := o.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 (o *OrderCancelRequest) GetSlugParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func (o *OrderCancelRequest) 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 (o *OrderCancelRequest) 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 (o *OrderCancelRequest) isVarSlice(v interface{}) bool {
|
||||
rt := reflect.TypeOf(v)
|
||||
switch rt.Kind() {
|
||||
case reflect.Slice:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *OrderCancelRequest) GetSlugsMap() (map[string]string, error) {
|
||||
slugs := map[string]string{}
|
||||
params, err := o.GetSlugParameters()
|
||||
if err != nil {
|
||||
return slugs, nil
|
||||
}
|
||||
|
||||
for k, v := range params {
|
||||
slugs[k] = fmt.Sprintf("%v", v)
|
||||
}
|
||||
|
||||
return slugs, nil
|
||||
}
|
||||
|
||||
func (o *OrderCancelRequest) Do(ctx context.Context) (*Order, error) {
|
||||
|
||||
params, err := o.GetParameters()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
query := url.Values{}
|
||||
|
||||
apiURL := "v2/order/delete"
|
||||
|
||||
req, err := o.client.NewAuthenticatedRequest(ctx, "POST", apiURL, query, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response, err := o.client.SendRequest(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var apiResponse Order
|
||||
if err := response.DecodeJSON(&apiResponse); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &apiResponse, nil
|
||||
}
|
114
pkg/exchange/max/maxapi/order_test.go
Normal file
114
pkg/exchange/max/maxapi/order_test.go
Normal file
|
@ -0,0 +1,114 @@
|
|||
package max
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func maskSecret(s string) string {
|
||||
re := regexp.MustCompile(`\b(\w{4})\w+\b`)
|
||||
s = re.ReplaceAllString(s, "$1******")
|
||||
return s
|
||||
}
|
||||
|
||||
func integrationTestConfigured(t *testing.T, prefix string) (key, secret string, ok bool) {
|
||||
var hasKey, hasSecret bool
|
||||
key, hasKey = os.LookupEnv(prefix + "_API_KEY")
|
||||
secret, hasSecret = os.LookupEnv(prefix + "_API_SECRET")
|
||||
ok = hasKey && hasSecret && os.Getenv("TEST_"+prefix) == "1"
|
||||
if ok {
|
||||
t.Logf(prefix+" api integration test enabled, key = %s, secret = %s", maskSecret(key), maskSecret(secret))
|
||||
}
|
||||
return key, secret, ok
|
||||
}
|
||||
|
||||
func TestOrderService_GetOrdersRequest(t *testing.T) {
|
||||
key, secret, ok := integrationTestConfigured(t, "MAX")
|
||||
if !ok {
|
||||
t.SkipNow()
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
client := NewRestClient(ProductionAPIURL)
|
||||
client.Auth(key, secret)
|
||||
|
||||
req3 := client.OrderService.NewGetOrdersRequest()
|
||||
req3.State([]OrderState{OrderStateDone, OrderStateFinalizing})
|
||||
// req3.State([]OrderState{OrderStateDone})
|
||||
req3.Market("btcusdt")
|
||||
orders, err := req3.Do(ctx)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, orders)
|
||||
}
|
||||
|
||||
func TestOrderService_GetOrdersRequest_SingleState(t *testing.T) {
|
||||
key, secret, ok := integrationTestConfigured(t, "MAX")
|
||||
if !ok {
|
||||
t.SkipNow()
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
client := NewRestClient(ProductionAPIURL)
|
||||
client.Auth(key, secret)
|
||||
|
||||
req3 := client.OrderService.NewGetOrdersRequest()
|
||||
req3.State([]OrderState{OrderStateDone})
|
||||
req3.Market("btcusdt")
|
||||
orders, err := req3.Do(ctx)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, orders)
|
||||
}
|
||||
|
||||
func TestOrderService_GetOrderHistoryRequest(t *testing.T) {
|
||||
key, secret, ok := integrationTestConfigured(t, "MAX")
|
||||
if !ok {
|
||||
t.SkipNow()
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
client := NewRestClient(ProductionAPIURL)
|
||||
client.Auth(key, secret)
|
||||
|
||||
req := client.OrderService.NewGetOrderHistoryRequest()
|
||||
req.Market("btcusdt")
|
||||
req.FromID(1)
|
||||
orders, err := req.Do(ctx)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, orders)
|
||||
}
|
||||
|
||||
|
||||
func TestOrderService(t *testing.T) {
|
||||
key, secret, ok := integrationTestConfigured(t, "MAX")
|
||||
if !ok {
|
||||
t.SkipNow()
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
client := NewRestClient(ProductionAPIURL)
|
||||
client.Auth(key, secret)
|
||||
req := client.OrderService.NewCreateOrderRequest()
|
||||
order, err := req.Market("btcusdt").
|
||||
Price("10000").
|
||||
Volume("0.001").
|
||||
OrderType("limit").
|
||||
Side("buy").Do(ctx)
|
||||
|
||||
if assert.NoError(t, err) {
|
||||
assert.NotNil(t, order)
|
||||
req2 := client.OrderService.NewOrderCancelRequest()
|
||||
req2.Id(order.ID)
|
||||
cancelResp, err := req2.Do(ctx)
|
||||
assert.NoError(t, err)
|
||||
t.Logf("cancelResponse: %+v", cancelResp)
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package max
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/url"
|
||||
|
@ -46,7 +47,7 @@ type Ticker struct {
|
|||
|
||||
func (s *PublicService) Timestamp() (serverTimestamp int64, err error) {
|
||||
// sync timestamp with server
|
||||
req, err := s.client.NewRequest(nil, "GET", "v2/timestamp", nil, nil)
|
||||
req, err := s.client.NewRequest(context.Background(), "GET", "v2/timestamp", nil, nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
@ -65,7 +66,7 @@ func (s *PublicService) Timestamp() (serverTimestamp int64, err error) {
|
|||
}
|
||||
|
||||
func (s *PublicService) Markets() ([]Market, error) {
|
||||
req, err := s.client.NewRequest(nil, "GET", "v2/markets", url.Values{}, nil)
|
||||
req, err := s.client.NewRequest(context.Background(), "GET", "v2/markets", url.Values{}, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -85,7 +86,7 @@ func (s *PublicService) Markets() ([]Market, error) {
|
|||
|
||||
func (s *PublicService) Tickers() (map[string]Ticker, error) {
|
||||
var endPoint = "v2/tickers"
|
||||
req, err := s.client.NewRequest(nil, "GET", endPoint, url.Values{}, nil)
|
||||
req, err := s.client.NewRequest(context.Background(), "GET", endPoint, url.Values{}, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -116,7 +117,7 @@ func (s *PublicService) Tickers() (map[string]Ticker, error) {
|
|||
|
||||
func (s *PublicService) Ticker(market string) (*Ticker, error) {
|
||||
var endPoint = "v2/tickers/" + market
|
||||
req, err := s.client.NewRequest(nil, "GET", endPoint, url.Values{}, nil)
|
||||
req, err := s.client.NewRequest(context.Background(), "GET", endPoint, url.Values{}, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -250,7 +251,7 @@ func (s *PublicService) KLines(symbol string, resolution string, start time.Time
|
|||
queries.Set("limit", strconv.Itoa(limit)) // default to 30, max limit = 10,000
|
||||
}
|
||||
|
||||
req, err := s.client.NewRequest(nil, "GET", fmt.Sprintf("%s/k", s.client.BaseURL), queries, nil)
|
||||
req, err := s.client.NewRequest(context.Background(), "GET", fmt.Sprintf("%s/k", s.client.BaseURL), queries, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("request build error: %s", err.Error())
|
||||
}
|
||||
|
|
|
@ -15,9 +15,9 @@ import (
|
|||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
|
@ -224,18 +224,18 @@ func (c *RestClient) newAuthenticatedRequest(ctx context.Context, m string, refU
|
|||
}
|
||||
|
||||
var p []byte
|
||||
var payload map[string]interface{}
|
||||
|
||||
switch d := data.(type) {
|
||||
|
||||
case nil:
|
||||
payload := map[string]interface{}{
|
||||
payload = map[string]interface{}{
|
||||
"nonce": c.getNonce(),
|
||||
"path": c.BaseURL.ResolveReference(rel).Path,
|
||||
}
|
||||
p, err = json.Marshal(payload)
|
||||
|
||||
case map[string]interface{}:
|
||||
payload := map[string]interface{}{
|
||||
payload = map[string]interface{}{
|
||||
"nonce": c.getNonce(),
|
||||
"path": c.BaseURL.ResolveReference(rel).Path,
|
||||
}
|
||||
|
@ -243,19 +243,22 @@ func (c *RestClient) newAuthenticatedRequest(ctx context.Context, m string, refU
|
|||
for k, v := range d {
|
||||
payload[k] = v
|
||||
}
|
||||
|
||||
p, err = json.Marshal(payload)
|
||||
|
||||
default:
|
||||
params, err := getPrivateRequestParamsObject(data)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "unsupported payload type: %T", d)
|
||||
}
|
||||
|
||||
params.Nonce = c.getNonce()
|
||||
params.Path = c.BaseURL.ResolveReference(rel).Path
|
||||
if m == "GET" {
|
||||
for k, vs := range params {
|
||||
k = strings.TrimSuffix(k, "[]")
|
||||
if len(vs) == 1 {
|
||||
payload[k] = vs[0]
|
||||
} else {
|
||||
payload[k] = vs
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p, err = json.Marshal(d)
|
||||
p, err = castPayload(payload)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if debugMaxRequestPayload {
|
||||
|
@ -282,8 +285,6 @@ func (c *RestClient) newAuthenticatedRequest(ctx context.Context, m string, refU
|
|||
encoded := base64.StdEncoding.EncodeToString(p)
|
||||
|
||||
req.Header.Add("Content-Type", "application/json")
|
||||
// accept is not necessary
|
||||
// req.Header.Add("Accept", "application/json")
|
||||
req.Header.Add("X-MAX-ACCESSKEY", c.APIKey)
|
||||
req.Header.Add("X-MAX-PAYLOAD", encoded)
|
||||
req.Header.Add("X-MAX-SIGNATURE", signPayload(encoded, c.APISecret))
|
||||
|
@ -300,38 +301,6 @@ func (c *RestClient) newAuthenticatedRequest(ctx context.Context, m string, refU
|
|||
return req, nil
|
||||
}
|
||||
|
||||
func getPrivateRequestParamsObject(v interface{}) (*PrivateRequestParams, error) {
|
||||
vt := reflect.ValueOf(v)
|
||||
|
||||
if vt.Kind() == reflect.Ptr {
|
||||
vt = vt.Elem()
|
||||
}
|
||||
|
||||
if vt.Kind() != reflect.Struct {
|
||||
return nil, errors.New("reflect error: given object is not a struct" + vt.Kind().String())
|
||||
}
|
||||
|
||||
if !vt.CanSet() {
|
||||
return nil, errors.New("reflect error: can not set object")
|
||||
}
|
||||
|
||||
field := vt.FieldByName("PrivateRequestParams")
|
||||
if !field.IsValid() {
|
||||
return nil, errors.New("reflect error: field PrivateRequestParams not found")
|
||||
}
|
||||
|
||||
if field.IsNil() {
|
||||
field.Set(reflect.ValueOf(&PrivateRequestParams{}))
|
||||
}
|
||||
|
||||
params, ok := field.Interface().(*PrivateRequestParams)
|
||||
if !ok {
|
||||
return nil, errors.New("reflect error: failed to cast value to *PrivateRequestParams")
|
||||
}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func signPayload(payload string, secret string) string {
|
||||
var sig = hmac.New(sha256.New, []byte(secret))
|
||||
_, err := sig.Write([]byte(payload))
|
||||
|
@ -460,25 +429,27 @@ func ToErrorResponse(response *requestgen.Response) (errorResponse *ErrorRespons
|
|||
// convert 5xx error from the HTML page to the ErrorResponse
|
||||
errorResponse.Err.Message = htmlTagPattern.ReplaceAllLiteralString(string(response.Body), "")
|
||||
return errorResponse, nil
|
||||
case "text/plain":
|
||||
errorResponse.Err.Message = string(response.Body)
|
||||
return errorResponse, nil
|
||||
}
|
||||
|
||||
return errorResponse, fmt.Errorf("unexpected response content type %s", contentType)
|
||||
}
|
||||
|
||||
func castPayload(payload interface{}) ([]byte, error) {
|
||||
if payload != nil {
|
||||
if payload == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
switch v := payload.(type) {
|
||||
case string:
|
||||
return []byte(v), nil
|
||||
|
||||
case []byte:
|
||||
return v, nil
|
||||
}
|
||||
|
||||
default:
|
||||
body, err := json.Marshal(v)
|
||||
body, err := json.Marshal(payload)
|
||||
return body, err
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user