gctrpc/order manager: Add ModifyOrder endpoint (#724)

* gctcli: modifyorder stubs

* gctcli: add ModifyOrderRequest and ModifyOrderResponse in rpc.proto

* gctcli: regenerate rpc.pb.go after the addition of ModifyOrder structs

* gctrpc: add ModifyOrder() and regenerate dependent files

* gctcli: modifyorder command now uses newly generated ModifyOrder() RPC

* exchanges/order/orders.go: use time.Time.Equal() instead of ==

* gctrpc: update ModifyOrderRequest and ModifyResponse and regenerate gRPC

* gctcli/commands: rework modifyorder

* engine: implement RPCServer.ModifyOrder

* engine: commit an initial version OrderManager.Modify(), still does not update state of managed orders

* engine: OrderManager.Modify now updates the inner state of managed orders, but introduces race conditions, needs fixes

* engine/order_manager.go: comply with golangci-lint

* gctcli: fix getOrderCommand.ArgsUsage

* gctcli: fix getModifyOrderCommand args and ArgsUsage

* engine: OrderManager.Modify() now correctly updates price of modified order

* engine: RPCServer.ModifyOrder now uses checkParams() as advised

* exchanges: (1) IBotExchange.ModifyOrder now returns a Modify struct, (2) all exchanges are updated to comply with that change

* exchanges/order: Detail.UpdateOrderFromModify also updates the ID

* engine/order_manager: add store.modifyExisting() and use it in OrderManager.Modify to update (on success) the state of the modified order

* exchanges: Bitfinex.ModifyOrder() now returns the ID in case of an error

* engine: OrdetManager.Modify() now emits an order event

* exchanges/bithumb: proper order.payment_currency key

* engine/order_manager: populate more Modify fields as they are needed by (some) exchanges, add comments

* engine: test OrderManager.Modify()

* engine: test store.modifyExisting()

* engine: write a docstring for store.modifyExisting

* engine: OrderManager.Modify() now also sets Modify.Price and Modify.Amount in case of zero values

* engine: TestOrderManager_Modify() now verify the effects of price and/or amount set to 0

* engine: OrderManger.Modify() now uses the commsManager to let observers know of errors

* engine: TestOrderManager_Modify() uses t.Fatal()

* engine: TestOrderManager_Modify() and TestStore_modifyOrder() supply t.Error() with proper messages

* exchanges/order_manager_test: fix a golangci-lint complaint

* engine/order_manager: fix an error comparison bug and simplify

* gctcli/commands: check if either price or amount is set, otherwise we would waste an API call
This commit is contained in:
Yordan Miladinov
2021-08-06 03:09:14 +03:00
committed by GitHub
parent 547d123984
commit 2da239735f
41 changed files with 1805 additions and 950 deletions

View File

@@ -572,8 +572,7 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config)
Price: config.OrderSubmission.Price,
Amount: config.OrderSubmission.Amount,
}
var modifyOrderResponse string
modifyOrderResponse, err = e.ModifyOrder(&modifyRequest)
modifyOrderResponse, err := e.ModifyOrder(&modifyRequest)
msg = ""
if err != nil {
msg = err.Error()

View File

@@ -1450,7 +1450,7 @@ func getManagedOrders(c *cli.Context) error {
var getOrderCommand = &cli.Command{
Name: "getorder",
Usage: "gets the specified order info",
ArgsUsage: "<exchange> <order_id> <pair>",
ArgsUsage: "<exchange> <asset> <pair> <order_id>",
Action: getOrder,
Flags: []cli.Flag{
&cli.StringFlag{
@@ -2236,6 +2236,39 @@ var cancelAllOrdersCommand = &cli.Command{
},
}
var modifyOrderCommand = &cli.Command{
Name: "modifyorder",
Usage: "modify price and/or amount of a previously submitted order",
ArgsUsage: "<exchange> <asset> <pair> <order_id>",
Action: modifyOrder,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "exchange",
Usage: "exchange this order is submitted to",
},
&cli.StringFlag{
Name: "asset",
Usage: "required asset type",
},
&cli.StringFlag{
Name: "pair",
Usage: "required trading pair",
},
&cli.StringFlag{
Name: "order_id",
Usage: "id of the order to be modified",
},
&cli.Float64Flag{
Name: "price",
Usage: "new order price",
},
&cli.Float64Flag{
Name: "amount",
Usage: "new order amount",
},
},
}
func cancelAllOrders(c *cli.Context) error {
var exchangeName string
if c.IsSet("exchange") {
@@ -2269,6 +2302,98 @@ func cancelAllOrders(c *cli.Context) error {
return nil
}
func modifyOrder(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
return cli.ShowCommandHelp(c, "modifyorder")
}
// Parse positional arguments.
var exchangeName string
var orderID string
var currencyPair string
var assetType string
if c.IsSet("exchange") {
exchangeName = c.String("exchange")
} else {
exchangeName = c.Args().First()
}
if !validExchange(exchangeName) {
return errInvalidExchange
}
if c.IsSet("asset") {
assetType = c.String("asset")
} else {
assetType = c.Args().Get(1)
}
assetType = strings.ToLower(assetType)
if !validAsset(assetType) {
return errInvalidAsset
}
if c.IsSet("pair") {
currencyPair = c.String("pair")
} else {
currencyPair = c.Args().Get(2)
}
if !validPair(currencyPair) {
return errInvalidPair
}
p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter)
if err != nil {
return err
}
if c.IsSet("order_id") {
orderID = c.String("order_id")
} else {
orderID = c.Args().Get(3)
}
// Parse optional flags.
var price float64
var amount float64
if c.IsSet("price") {
price = c.Float64("price")
}
if c.IsSet("amount") {
amount = c.Float64("amount")
}
if price == 0 && amount == 0 {
return errors.New("either --price or --amount should be present")
}
// Setup gRPC, make a request and display response.
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.ModifyOrder(context.Background(), &gctrpc.ModifyOrderRequest{
Exchange: exchangeName,
OrderId: orderID,
Pair: &gctrpc.CurrencyPair{
Delimiter: p.Delimiter,
Base: p.Base.String(),
Quote: p.Quote.String(),
},
Asset: assetType,
Price: price,
Amount: amount,
})
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var getEventsCommand = &cli.Command{
Name: "getevents",
Usage: "gets all events",

View File

@@ -126,6 +126,7 @@ func main() {
cancelOrderCommand,
cancelBatchOrdersCommand,
cancelAllOrdersCommand,
modifyOrderCommand,
getEventsCommand,
addEventCommand,
removeEventCommand,