diff --git a/proto/tradebin/tx.proto b/proto/tradebin/tx.proto index c8a8bcb1..b264f750 100644 --- a/proto/tradebin/tx.proto +++ b/proto/tradebin/tx.proto @@ -10,6 +10,7 @@ service Msg { rpc CreateMarket(MsgCreateMarket) returns (MsgCreateMarketResponse); rpc CreateOrder(MsgCreateOrder) returns (MsgCreateOrderResponse); rpc CancelOrder(MsgCancelOrder) returns (MsgCancelOrderResponse); + rpc FillOrders(MsgFillOrders) returns (MsgFillOrdersResponse); // this line is used by starport scaffolding # proto/tx/rpc } @@ -43,4 +44,18 @@ message MsgCancelOrder { message MsgCancelOrderResponse { } +message FillOrderItem { + string price = 1; + string amount = 2; +} + +message MsgFillOrders { + string creator = 1; + string marketId = 2; + string order_type = 3; + repeated FillOrderItem orders = 4; +} + +message MsgFillOrdersResponse {} + // this line is used by starport scaffolding # proto/tx/message diff --git a/x/tradebin/client/cli/tx.go b/x/tradebin/client/cli/tx.go index 15df9f9e..27605d43 100644 --- a/x/tradebin/client/cli/tx.go +++ b/x/tradebin/client/cli/tx.go @@ -1,7 +1,11 @@ package cli import ( + "encoding/json" "fmt" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + "strconv" "time" "github.com/spf13/cobra" @@ -13,6 +17,7 @@ import ( var ( DefaultRelativePacketTimeoutTimestamp = uint64((time.Duration(10) * time.Minute).Nanoseconds()) + _ = strconv.Itoa(0) ) const ( @@ -37,3 +42,142 @@ func GetTxCmd() *cobra.Command { return cmd } + +func CmdCancelOrder() *cobra.Command { + cmd := &cobra.Command{ + Use: "cancel-order [market-id] [order-id] [order-type]", + Short: "Broadcast message CancelOrder", + Args: cobra.ExactArgs(3), + RunE: func(cmd *cobra.Command, args []string) (err error) { + argMarketId := args[0] + argOrderId := args[1] + argOrderType := args[2] + + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + msg := types.NewMsgCancelOrder( + clientCtx.GetFromAddress().String(), + argMarketId, + argOrderId, + argOrderType, + ) + if err := msg.ValidateBasic(); err != nil { + return err + } + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +func CmdCreateMarket() *cobra.Command { + cmd := &cobra.Command{ + Use: "create-market [base] [quote]", + Short: "Broadcast message CreateMarket", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) (err error) { + argAsset1 := args[0] + argAsset2 := args[1] + + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + msg := types.NewMsgCreateMarket( + clientCtx.GetFromAddress().String(), + argAsset1, + argAsset2, + ) + if err := msg.ValidateBasic(); err != nil { + return err + } + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +func CmdCreateOrder() *cobra.Command { + cmd := &cobra.Command{ + Use: "create-order [order-type] [amount] [price] [market-id]", + Short: "Broadcast message CreateOrder", + Args: cobra.ExactArgs(4), + RunE: func(cmd *cobra.Command, args []string) (err error) { + argOrderType := args[0] + argAmount := args[1] + argPrice := args[2] + argMarketId := args[3] + + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + msg := types.NewMsgCreateOrder( + clientCtx.GetFromAddress().String(), + argOrderType, + argAmount, + argPrice, + argMarketId, + ) + if err := msg.ValidateBasic(); err != nil { + return err + } + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +func CmdFillOrders() *cobra.Command { + cmd := &cobra.Command{ + Use: "fill-orders [order-type] [market-id] [orders]", + Short: "Broadcast message FillOrders", + Long: "This command expects [orders] to be an array of objects of form: {amount: 231, price:0.32}", + Args: cobra.ExactArgs(3), + RunE: func(cmd *cobra.Command, args []string) (err error) { + argOrderType := args[0] + argMarketId := args[1] + argOrders := args[2] + var decodedOrders []*types.FillOrderItem + err = json.Unmarshal([]byte(argOrders), &decodedOrders) + if err != nil { + return err + } + + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + msg := types.NewMsgFillOrders( + clientCtx.GetFromAddress().String(), + argOrderType, + argMarketId, + decodedOrders, + ) + if err := msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} diff --git a/x/tradebin/client/cli/tx_cancel_order.go b/x/tradebin/client/cli/tx_cancel_order.go deleted file mode 100644 index 54eb0307..00000000 --- a/x/tradebin/client/cli/tx_cancel_order.go +++ /dev/null @@ -1,46 +0,0 @@ -package cli - -import ( - "strconv" - - "github.com/bze-alphateam/bze/x/tradebin/types" - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/client/tx" - "github.com/spf13/cobra" -) - -var _ = strconv.Itoa(0) - -func CmdCancelOrder() *cobra.Command { - cmd := &cobra.Command{ - Use: "cancel-order [market-id] [order-id] [order-type]", - Short: "Broadcast message CancelOrder", - Args: cobra.ExactArgs(3), - RunE: func(cmd *cobra.Command, args []string) (err error) { - argMarketId := args[0] - argOrderId := args[1] - argOrderType := args[2] - - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - - msg := types.NewMsgCancelOrder( - clientCtx.GetFromAddress().String(), - argMarketId, - argOrderId, - argOrderType, - ) - if err := msg.ValidateBasic(); err != nil { - return err - } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) - }, - } - - flags.AddTxFlagsToCmd(cmd) - - return cmd -} diff --git a/x/tradebin/client/cli/tx_create_market.go b/x/tradebin/client/cli/tx_create_market.go deleted file mode 100644 index 34593488..00000000 --- a/x/tradebin/client/cli/tx_create_market.go +++ /dev/null @@ -1,44 +0,0 @@ -package cli - -import ( - "strconv" - - "github.com/bze-alphateam/bze/x/tradebin/types" - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/client/tx" - "github.com/spf13/cobra" -) - -var _ = strconv.Itoa(0) - -func CmdCreateMarket() *cobra.Command { - cmd := &cobra.Command{ - Use: "create-market [base] [quote]", - Short: "Broadcast message CreateMarket", - Args: cobra.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) (err error) { - argAsset1 := args[0] - argAsset2 := args[1] - - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - - msg := types.NewMsgCreateMarket( - clientCtx.GetFromAddress().String(), - argAsset1, - argAsset2, - ) - if err := msg.ValidateBasic(); err != nil { - return err - } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) - }, - } - - flags.AddTxFlagsToCmd(cmd) - - return cmd -} diff --git a/x/tradebin/client/cli/tx_create_order.go b/x/tradebin/client/cli/tx_create_order.go deleted file mode 100644 index 0c4faedb..00000000 --- a/x/tradebin/client/cli/tx_create_order.go +++ /dev/null @@ -1,48 +0,0 @@ -package cli - -import ( - "strconv" - - "github.com/bze-alphateam/bze/x/tradebin/types" - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/client/tx" - "github.com/spf13/cobra" -) - -var _ = strconv.Itoa(0) - -func CmdCreateOrder() *cobra.Command { - cmd := &cobra.Command{ - Use: "create-order [order-type] [amount] [price] [market-id]", - Short: "Broadcast message CreateOrder", - Args: cobra.ExactArgs(4), - RunE: func(cmd *cobra.Command, args []string) (err error) { - argOrderType := args[0] - argAmount := args[1] - argPrice := args[2] - argMarketId := args[3] - - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - - msg := types.NewMsgCreateOrder( - clientCtx.GetFromAddress().String(), - argOrderType, - argAmount, - argPrice, - argMarketId, - ) - if err := msg.ValidateBasic(); err != nil { - return err - } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) - }, - } - - flags.AddTxFlagsToCmd(cmd) - - return cmd -} diff --git a/x/tradebin/keeper/msg_server_cancel_order.go b/x/tradebin/keeper/msg_server_cancel_order.go index b6d7b697..93910f88 100644 --- a/x/tradebin/keeper/msg_server_cancel_order.go +++ b/x/tradebin/keeper/msg_server_cancel_order.go @@ -25,7 +25,7 @@ func (k msgServer) CancelOrder(goCtx context.Context, msg *types.MsgCancelOrder) qm := types.QueueMessage{ MarketId: msg.MarketId, - MessageType: types.OrderTypeCancel, + MessageType: types.MessageTypeCancel, OrderId: msg.OrderId, OrderType: msg.OrderType, Owner: msg.Creator, diff --git a/x/tradebin/keeper/msg_server_cancel_order_test.go b/x/tradebin/keeper/msg_server_cancel_order_test.go index 4e96f8dd..01f47e2a 100644 --- a/x/tradebin/keeper/msg_server_cancel_order_test.go +++ b/x/tradebin/keeper/msg_server_cancel_order_test.go @@ -71,7 +71,7 @@ func (suite *IntegrationTestSuite) TestCancelOrder_CancelBuy_Success() { suite.Require().Len(qms, 1) suite.Require().Equal(qms[0].MarketId, order.MarketId) - suite.Require().Equal(qms[0].MessageType, types.OrderTypeCancel) + suite.Require().Equal(qms[0].MessageType, types.MessageTypeCancel) suite.Require().Equal(qms[0].OrderId, order.Id) suite.Require().Equal(qms[0].OrderType, order.OrderType) suite.Require().Equal(qms[0].Owner, order.Owner) @@ -100,7 +100,7 @@ func (suite *IntegrationTestSuite) TestCancelOrder_CancelSell_Success() { suite.Require().Len(qms, 1) suite.Require().Equal(qms[0].MarketId, order.MarketId) - suite.Require().Equal(qms[0].MessageType, types.OrderTypeCancel) + suite.Require().Equal(qms[0].MessageType, types.MessageTypeCancel) suite.Require().Equal(qms[0].OrderId, order.Id) suite.Require().Equal(qms[0].OrderType, order.OrderType) suite.Require().Equal(qms[0].Owner, order.Owner) diff --git a/x/tradebin/keeper/msg_server_create_order.go b/x/tradebin/keeper/msg_server_create_order.go index e6fb3ad2..cb67e8dc 100644 --- a/x/tradebin/keeper/msg_server_create_order.go +++ b/x/tradebin/keeper/msg_server_create_order.go @@ -50,7 +50,7 @@ func (k msgServer) CreateOrder(goCtx context.Context, msg *types.MsgCreateOrder) return nil, err } - _, err = k.captureOrderFees(ctx, msg, accAddr) + _, err = k.captureMsgFees(ctx, msg, accAddr) if err != nil { return nil, err } @@ -81,13 +81,18 @@ func (k msgServer) CreateOrder(goCtx context.Context, msg *types.MsgCreateOrder) return &types.MsgCreateOrderResponse{}, nil } -func (k msgServer) captureOrderFees(ctx sdk.Context, msg *types.MsgCreateOrder, sender sdk.AccAddress) (coin sdk.Coin, err error) { +func (k msgServer) captureMsgFees(ctx sdk.Context, msg *types.MsgCreateOrder, sender sdk.AccAddress) (sdk.Coin, error) { //used to decide if it's market taker or market maker _, found := k.GetAggregatedOrder(ctx, msg.MarketId, types.TheOtherOrderType(msg.OrderType), msg.Price) + + return k.captureTradingFees(ctx, sender, found) +} + +func (k msgServer) captureTradingFees(ctx sdk.Context, sender sdk.AccAddress, isTaker bool) (coin sdk.Coin, err error) { params := k.GetParams(ctx) var fee string var destination string - if found { + if isTaker { //is market taker fee = params.GetMarketTakerFee() destination = params.GetTakerFeeDestination() @@ -274,3 +279,84 @@ func (k msgServer) emitOrderCreateMessageEvent(ctx sdk.Context, qm *types.QueueM }, ) } + +func (k msgServer) FillOrders(goCtx context.Context, msg *types.MsgFillOrders) (*types.MsgFillOrdersResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + accAddr, err := sdk.AccAddressFromBech32(msg.Creator) + if err != nil { + return nil, err + } + + market, found := k.GetMarketById(ctx, msg.MarketId) + if !found { + return nil, types.ErrMarketNotFound.Wrapf("market id: %s", msg.MarketId) + } + + ctx.GasMeter().ConsumeGas(types.FillOrdersExtraGas, "fill_orders") + totalCoins := sdk.NewCoins() + for _, fo := range msg.Orders { + minAmt := CalculateMinAmount(fo.Price) + amtInt, ok := sdk.NewIntFromString(fo.Amount) + if !ok { + return nil, types.ErrInvalidOrderAmount.Wrapf("amount could not be converted to Int") + } + if minAmt.GT(amtInt) { + ctx.Logger().Debug("order amount is smaller than minimum", "order_to_fill", fo) + + continue + } + + //calculate needed funds for this order + //inverse the order type because the message specifies what kind of orders it wants to fill + //so if user says he wants to fill buy orders, we need to act like he's selling, and vice versa + ocReq := types.OrderCoinsArguments{ + OrderType: types.TheOtherOrderType(msg.OrderType), + OrderPrice: fo.Price, + OrderAmount: amtInt, + Market: &market, + UserAddress: msg.Creator, + UserReceives: false, + } + + orderCoins, err := k.GetOrderCoinsWithDust(ctx, ocReq) + if err != nil { + return nil, err + } + //messages of type "buy" are added on queue as messageType = "fill_buy" + //messages of type "sell" are added on queue as messageType = "fill_sell" + //orderType is the opposite of the orders we want to fill: if we fill "buy" it means we "sell", and vice versa. + qm := types.QueueMessage{ + MarketId: msg.MarketId, + OrderType: ocReq.OrderType, // already inversed when ocReq was built a few lines above + MessageType: types.OrderTypeToMessageTypeFill(msg.OrderType), + Amount: fo.Amount, + Price: fo.Price, + Owner: msg.Creator, + } + + k.SetQueueMessage(ctx, qm) + k.StoreProcessedUserDust(ctx, orderCoins.UserDust, &orderCoins.Dust) + + totalCoins = totalCoins.Add(orderCoins.Coin) + //take extra gas for each order to fill + ctx.GasMeter().ConsumeGas(types.FillOrdersExtraGas, "fill_orders") + } + + if totalCoins.IsZero() { + return nil, types.ErrInvalidOrdersToFill + } + + _, err = k.captureTradingFees(ctx, accAddr, true) + if err != nil { + return nil, err + } + + //capture user funds for this order + err = k.bankKeeper.SendCoinsFromAccountToModule(ctx, accAddr, types.ModuleName, totalCoins) + if err != nil { + return nil, err + } + + return &types.MsgFillOrdersResponse{}, nil +} diff --git a/x/tradebin/keeper/msg_server_create_order_test.go b/x/tradebin/keeper/msg_server_create_order_test.go index 9515406b..4178382c 100644 --- a/x/tradebin/keeper/msg_server_create_order_test.go +++ b/x/tradebin/keeper/msg_server_create_order_test.go @@ -422,11 +422,11 @@ func (suite *IntegrationTestSuite) TestCreateOrder_MarketTaker_StressBalance() { } for i := 0; i < 5; i++ { - suite.randomOrderCreateMessages(suite.randomNumber(3000), creators, market) - suite.randomOrderCreateMessages(suite.randomNumber(3000), creators, market1) - suite.randomOrderCreateMessages(suite.randomNumber(3000), creators, market2) - suite.randomOrderCreateMessages(suite.randomNumber(3000), creators, market3) - suite.randomOrderCreateMessages(suite.randomNumber(3000), creators, market4) + suite.randomOrderCreateMessages(suite.randomNumber(1000), creators, market) + suite.randomOrderCreateMessages(suite.randomNumber(1000), creators, market1) + suite.randomOrderCreateMessages(suite.randomNumber(1000), creators, market2) + suite.randomOrderCreateMessages(suite.randomNumber(1000), creators, market3) + suite.randomOrderCreateMessages(suite.randomNumber(1000), creators, market4) engine.ProcessQueueMessages(suite.ctx) } diff --git a/x/tradebin/keeper/queue_message_processor.go b/x/tradebin/keeper/queue_message_processor.go index 63594abc..c52fde41 100644 --- a/x/tradebin/keeper/queue_message_processor.go +++ b/x/tradebin/keeper/queue_message_processor.go @@ -90,7 +90,12 @@ func (pe *ProcessingEngine) getMessageHandler() func(ctx sdk.Context, message ty var wrappingFn func(ctx sdk.Context) error switch message.MessageType { - case types.OrderTypeCancel: + case types.MessageTypeFillBuy: + case types.MessageTypeFillSell: + wrappingFn = func(ctx sdk.Context) error { + return pe.fillOrder(ctx, message) + } + case types.MessageTypeCancel: wrappingFn = func(ctx sdk.Context) error { return pe.cancelOrder(ctx, message) } @@ -195,81 +200,28 @@ func (pe *ProcessingEngine) addOrder(ctx sdk.Context, message types.QueueMessage return nil } - aggAmountInt, ok := sdk.NewIntFromString(agg.Amount) - if !ok { - - return fmt.Errorf("could not convert agg amount") - } - - oppositeOrderRefs := pe.k.GetPriceOrderByPrice(ctx, message.MarketId, types.TheOtherOrderType(message.OrderType), message.Price) - logger.Info("found orders to fill", "number_of_orders", len(oppositeOrderRefs)) //should always exist market, _ := pe.k.GetMarketById(ctx, message.MarketId) minAmount := CalculateMinAmount(message.Price) msgOwnerAddr, _ := sdk.AccAddressFromBech32(message.Owner) - for _, orderRef := range oppositeOrderRefs { - //stop when all message amount was spent - if !msgAmountInt.IsPositive() { - logger.Debug("msg amount is not positive anymore. exiting oppositeOrderRefs iteration") - break - } - - orderToFill, _ := pe.k.GetOrder(ctx, orderRef.MarketId, orderRef.OrderType, orderRef.Id) - logger.Debug("preparing to fill message with order", "orderToFill", orderToFill) - orderAmountInt, ok := sdk.NewIntFromString(orderToFill.Amount) - if !ok { - - return fmt.Errorf("could not convert order to fill amount") - } - - //find how much to send to the found order's owner - amountToExecute := pe.getExecutedAmount(msgAmountInt, orderAmountInt, minAmount) - if amountToExecute.IsZero() { - break - } - - msgAmountInt = msgAmountInt.Sub(amountToExecute) - message.Amount = msgAmountInt.String() - - orderAmountInt = orderAmountInt.Sub(amountToExecute) - orderToFill.Amount = orderAmountInt.String() - - aggAmountInt = aggAmountInt.Sub(amountToExecute) - agg.Amount = aggAmountInt.String() - - err := pe.fundUsersAccounts(ctx, &orderToFill, &market, amountToExecute, msgOwnerAddr) - if err != nil { - - return err - } - - if orderAmountInt.GT(zeroInt) { - logger.Debug("order partially filled") - pe.k.SaveOrder(ctx, orderToFill) - } else { - logger.Debug("order fully filled") - pe.k.RemoveOrder(ctx, orderToFill) - } - - pe.addHistoryOrder(ctx, &orderToFill, amountToExecute, &message) - pe.emitOrderExecutedEvent(ctx, &orderToFill, amountToExecute.String(), message.Owner) - } - if aggAmountInt.GT(zeroInt) { - pe.k.SetAggregatedOrder(ctx, agg) - logger.Info("aggregated order updated") - } else { - pe.k.RemoveAggregatedOrder(ctx, agg) - logger.Info("aggregated order removed") + remaining, err := pe.fillAggregatedOrder(ctx, &agg, &message, msgAmountInt, &market) + if err != nil { + return fmt.Errorf("could not fill aggregated order: %v", err) } - if msgAmountInt.Equal(zeroInt) { + if remaining.Equal(zeroInt) { logger.Info("message was completely filled") return nil } + aggAmountInt, ok := sdk.NewIntFromString(agg.Amount) + if !ok { + return fmt.Errorf("could not convert agg amount") + } + //if min amount condition is met and all orders were filled we can proceed to place the order - if msgAmountInt.GTE(minAmount) && aggAmountInt.IsZero() { + if remaining.GTE(minAmount) && aggAmountInt.IsZero() { order := pe.saveOrder(ctx, message, message.Amount) pe.addOrderToAggregate(ctx, order) @@ -278,33 +230,8 @@ func (pe *ProcessingEngine) addOrder(ctx sdk.Context, message types.QueueMessage } logger.Info("message remaining amount is too low, returning dust") - //we have a remaining amount smaller than min amount. We should send it back to the msg owner - coinReq := types.OrderCoinsArguments{ - OrderType: message.OrderType, - OrderPrice: message.Price, - OrderAmount: msgAmountInt, - Market: &market, - UserAddress: message.Owner, - UserReceives: true, - } - - orderCoins, err := pe.k.GetOrderCoinsWithDust(ctx, coinReq) - if err != nil { - return fmt.Errorf("could not get order coins: %v", err) - } - if orderCoins.Coin.IsPositive() { - err = pe.bank.SendCoinsFromModuleToAccount(ctx, types.ModuleName, msgOwnerAddr, sdk.NewCoins(orderCoins.Coin)) - if err != nil { - - return fmt.Errorf("error when returning funds to message owner: %v", err) - } - } else { - logger.Info("will not send dust to order message owner because the amount is 0 (zero) but will save dust", "orderCoins", orderCoins) - } - pe.k.StoreProcessedUserDust(ctx, orderCoins.UserDust, &orderCoins.Dust) - - return nil + return pe.refundMessageFunds(ctx, &message, *remaining, &market, msgOwnerAddr) } func (pe *ProcessingEngine) fundUsersAccounts(ctx sdk.Context, order *types.Order, market *types.Market, amount sdk.Int, taker sdk.AccAddress) error { @@ -553,3 +480,141 @@ func (pe *ProcessingEngine) emitOrderSavedEvent(ctx sdk.Context, order *types.Or pe.logger.Error(err.Error()) } } + +func (pe *ProcessingEngine) fillOrder(ctx sdk.Context, message types.QueueMessage) error { + logger := pe.logger.With( + "message", message, + "func", "fillOrder", + ) + logger.Info("filling order on market") + + msgAmountInt, ok := sdk.NewIntFromString(message.Amount) + if !ok { + + return fmt.Errorf("could not convert queue message amount") + } + + //should always exist + market, _ := pe.k.GetMarketById(ctx, message.MarketId) + msgOwnerAddr, _ := sdk.AccAddressFromBech32(message.Owner) + + //find opposite orders if they exist + agg, found := pe.k.GetAggregatedOrder(ctx, message.MarketId, types.TheOtherOrderType(message.OrderType), message.Price) + if !found { + //no pending orders to fill. refund the amount for this order + return pe.refundMessageFunds(ctx, &message, msgAmountInt, &market, msgOwnerAddr) + } + + remainingAmount, err := pe.fillAggregatedOrder(ctx, &agg, &message, msgAmountInt, &market) + if err != nil { + return err + } + + if !remainingAmount.IsPositive() { + logger.Info("message was completely filled") + return nil + } + + //we haven't filled the entire message amount so we have to refund the msg owner's coins + + return pe.refundMessageFunds(ctx, &message, msgAmountInt, &market, msgOwnerAddr) +} + +func (pe *ProcessingEngine) refundMessageFunds(ctx sdk.Context, message *types.QueueMessage, refundAmount sdk.Int, market *types.Market, msgOwnerAddr sdk.AccAddress) error { + coinReq := types.OrderCoinsArguments{ + OrderType: message.OrderType, + OrderPrice: message.Price, + OrderAmount: refundAmount, + Market: market, + UserAddress: message.Owner, + UserReceives: true, + } + + orderCoins, err := pe.k.GetOrderCoinsWithDust(ctx, coinReq) + if err != nil { + return fmt.Errorf("could not get order coins: %v", err) + } + + if orderCoins.Coin.IsPositive() { + err = pe.bank.SendCoinsFromModuleToAccount(ctx, types.ModuleName, msgOwnerAddr, sdk.NewCoins(orderCoins.Coin)) + if err != nil { + + return fmt.Errorf("error when returning funds to message owner: %v", err) + } + } else { + ctx.Logger().Info("will not send dust to order message owner because the amount is 0 (zero) but will save dust", "orderCoins", orderCoins) + } + pe.k.StoreProcessedUserDust(ctx, orderCoins.UserDust, &orderCoins.Dust) + + return nil +} + +func (pe *ProcessingEngine) fillAggregatedOrder(ctx sdk.Context, agg *types.AggregatedOrder, message *types.QueueMessage, msgAmountInt sdk.Int, market *types.Market) (*sdk.Int, error) { + msgOwnerAddr, _ := sdk.AccAddressFromBech32(message.Owner) + zeroInt := sdk.ZeroInt() + aggAmountInt, ok := sdk.NewIntFromString(agg.Amount) + if !ok { + return nil, fmt.Errorf("could not convert agg amount") + } + + oppositeOrderRefs := pe.k.GetPriceOrderByPrice(ctx, message.MarketId, types.TheOtherOrderType(message.OrderType), message.Price) + ctx.Logger().Info("found orders to fill", "number_of_orders", len(oppositeOrderRefs)) + minAmount := CalculateMinAmount(message.Price) + for _, orderRef := range oppositeOrderRefs { + //stop when all message amount was spent + if !msgAmountInt.IsPositive() { + ctx.Logger().Debug("msg amount is not positive anymore. exiting oppositeOrderRefs iteration") + break + } + + orderToFill, _ := pe.k.GetOrder(ctx, orderRef.MarketId, orderRef.OrderType, orderRef.Id) + ctx.Logger().Debug("preparing to fill message with order", "orderToFill", orderToFill) + orderAmountInt, ok := sdk.NewIntFromString(orderToFill.Amount) + if !ok { + + return nil, fmt.Errorf("could not convert order to fill amount") + } + + //find how much to send to the found order's owner + amountToExecute := pe.getExecutedAmount(msgAmountInt, orderAmountInt, minAmount) + if amountToExecute.IsZero() { + break + } + + msgAmountInt = msgAmountInt.Sub(amountToExecute) + message.Amount = msgAmountInt.String() + + orderAmountInt = orderAmountInt.Sub(amountToExecute) + orderToFill.Amount = orderAmountInt.String() + + aggAmountInt = aggAmountInt.Sub(amountToExecute) + agg.Amount = aggAmountInt.String() + + err := pe.fundUsersAccounts(ctx, &orderToFill, market, amountToExecute, msgOwnerAddr) + if err != nil { + + return nil, err + } + + if orderAmountInt.GT(zeroInt) { + ctx.Logger().Debug("order partially filled") + pe.k.SaveOrder(ctx, orderToFill) + } else { + ctx.Logger().Debug("order fully filled") + pe.k.RemoveOrder(ctx, orderToFill) + } + + pe.addHistoryOrder(ctx, &orderToFill, amountToExecute, message) + pe.emitOrderExecutedEvent(ctx, &orderToFill, amountToExecute.String(), message.Owner) + } + + if aggAmountInt.GT(zeroInt) { + pe.k.SetAggregatedOrder(ctx, *agg) + ctx.Logger().Info("aggregated order updated") + } else { + pe.k.RemoveAggregatedOrder(ctx, *agg) + ctx.Logger().Info("aggregated order removed") + } + + return &msgAmountInt, nil +} diff --git a/x/tradebin/keeper/queue_message_processor_test.go b/x/tradebin/keeper/queue_message_processor_test.go index af630cb5..a395ccf3 100644 --- a/x/tradebin/keeper/queue_message_processor_test.go +++ b/x/tradebin/keeper/queue_message_processor_test.go @@ -185,7 +185,7 @@ func (suite *IntegrationTestSuite) TestQueueMessageProcessor_CancelOrder() { suite.Require().Nil(err) qm := types.QueueMessage{ MarketId: or.MarketId, - MessageType: types.OrderTypeCancel, + MessageType: types.MessageTypeCancel, OrderId: or.Id, OrderType: or.OrderType, Owner: addr1.String(), diff --git a/x/tradebin/types/errors.go b/x/tradebin/types/errors.go index a1c13cb3..7dd6d390 100644 --- a/x/tradebin/types/errors.go +++ b/x/tradebin/types/errors.go @@ -19,4 +19,5 @@ var ( ErrOrderNotFound = sdkerrors.Register(ModuleName, 4008, "order not found") ErrUnauthorizedOrder = sdkerrors.Register(ModuleName, 4009, "not authorized") ErrInvalidDenom = sdkerrors.Register(ModuleName, 4010, "invalid denom provided") + ErrInvalidOrdersToFill = sdkerrors.Register(ModuleName, 4011, "invalid orders to fill") ) diff --git a/x/tradebin/types/message_cancel_order.go b/x/tradebin/types/message_cancel_order.go index d80c8350..2e312958 100644 --- a/x/tradebin/types/message_cancel_order.go +++ b/x/tradebin/types/message_cancel_order.go @@ -8,7 +8,9 @@ import ( const ( TypeMsgCancelOrder = "cancel_order" - OrderTypeCancel = "cancel" + MessageTypeCancel = "cancel" + MessageTypeFillBuy = "fill_buy" + MessageTypeFillSell = "fill_sell" ) var _ sdk.Msg = &MsgCancelOrder{} @@ -63,3 +65,22 @@ func (msg *MsgCancelOrder) ValidateBasic() error { return nil } + +func MessageTypeToOrderType(messageType string) string { + switch messageType { + case MessageTypeFillSell: + return OrderTypeBuy + case MessageTypeFillBuy: + return OrderTypeSell + default: + return messageType + } +} + +func OrderTypeToMessageTypeFill(orderType string) string { + if orderType == OrderTypeBuy { + return MessageTypeFillBuy + } + + return MessageTypeFillSell +} diff --git a/x/tradebin/types/message_fill_orders.go b/x/tradebin/types/message_fill_orders.go new file mode 100644 index 00000000..4b0cafed --- /dev/null +++ b/x/tradebin/types/message_fill_orders.go @@ -0,0 +1,61 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +var _ sdk.Msg = &MsgFillOrders{} + +func NewMsgFillOrders(creator string, marketId string, orderType string, orders []*FillOrderItem) *MsgFillOrders { + return &MsgFillOrders{ + Creator: creator, + MarketId: marketId, + OrderType: orderType, + Orders: orders, + } +} + +func (msg *MsgFillOrders) Route() string { + return RouterKey +} + +func (msg *MsgFillOrders) Type() string { + return TypeMsgCancelOrder +} + +func (msg *MsgFillOrders) GetSigners() []sdk.AccAddress { + creator, err := sdk.AccAddressFromBech32(msg.Creator) + if err != nil { + panic(err) + } + + return []sdk.AccAddress{creator} +} + +func (msg *MsgFillOrders) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(msg) + + return sdk.MustSortJSON(bz) +} + +func (msg *MsgFillOrders) ValidateBasic() error { + _, err := sdk.AccAddressFromBech32(msg.Creator) + if err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid creator address (%s)", err) + } + + if msg.MarketId == "" { + return sdkerrors.Wrapf(ErrInvalidOrderMarketId, "empty market_id") + } + + if msg.OrderType != OrderTypeSell && msg.OrderType != OrderTypeBuy { + return sdkerrors.Wrapf(ErrInvalidOrderType, "invalid order type") + } + + if len(msg.Orders) == 0 { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "no orders to fill provided") + } + + return nil +} diff --git a/x/tradebin/types/tx.pb.go b/x/tradebin/types/tx.pb.go index fa5792dd..36ded52a 100644 --- a/x/tradebin/types/tx.pb.go +++ b/x/tradebin/types/tx.pb.go @@ -339,6 +339,162 @@ func (m *MsgCancelOrderResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgCancelOrderResponse proto.InternalMessageInfo +type FillOrderItem struct { + Price string `protobuf:"bytes,1,opt,name=price,proto3" json:"price,omitempty"` + Amount string `protobuf:"bytes,2,opt,name=amount,proto3" json:"amount,omitempty"` +} + +func (m *FillOrderItem) Reset() { *m = FillOrderItem{} } +func (m *FillOrderItem) String() string { return proto.CompactTextString(m) } +func (*FillOrderItem) ProtoMessage() {} +func (*FillOrderItem) Descriptor() ([]byte, []int) { + return fileDescriptor_adab200f727dc48e, []int{6} +} +func (m *FillOrderItem) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *FillOrderItem) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_FillOrderItem.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *FillOrderItem) XXX_Merge(src proto.Message) { + xxx_messageInfo_FillOrderItem.Merge(m, src) +} +func (m *FillOrderItem) XXX_Size() int { + return m.Size() +} +func (m *FillOrderItem) XXX_DiscardUnknown() { + xxx_messageInfo_FillOrderItem.DiscardUnknown(m) +} + +var xxx_messageInfo_FillOrderItem proto.InternalMessageInfo + +func (m *FillOrderItem) GetPrice() string { + if m != nil { + return m.Price + } + return "" +} + +func (m *FillOrderItem) GetAmount() string { + if m != nil { + return m.Amount + } + return "" +} + +type MsgFillOrders struct { + Creator string `protobuf:"bytes,1,opt,name=creator,proto3" json:"creator,omitempty"` + MarketId string `protobuf:"bytes,2,opt,name=marketId,proto3" json:"marketId,omitempty"` + OrderType string `protobuf:"bytes,3,opt,name=order_type,json=orderType,proto3" json:"order_type,omitempty"` + Orders []*FillOrderItem `protobuf:"bytes,4,rep,name=orders,proto3" json:"orders,omitempty"` +} + +func (m *MsgFillOrders) Reset() { *m = MsgFillOrders{} } +func (m *MsgFillOrders) String() string { return proto.CompactTextString(m) } +func (*MsgFillOrders) ProtoMessage() {} +func (*MsgFillOrders) Descriptor() ([]byte, []int) { + return fileDescriptor_adab200f727dc48e, []int{7} +} +func (m *MsgFillOrders) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgFillOrders) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgFillOrders.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgFillOrders) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgFillOrders.Merge(m, src) +} +func (m *MsgFillOrders) XXX_Size() int { + return m.Size() +} +func (m *MsgFillOrders) XXX_DiscardUnknown() { + xxx_messageInfo_MsgFillOrders.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgFillOrders proto.InternalMessageInfo + +func (m *MsgFillOrders) GetCreator() string { + if m != nil { + return m.Creator + } + return "" +} + +func (m *MsgFillOrders) GetMarketId() string { + if m != nil { + return m.MarketId + } + return "" +} + +func (m *MsgFillOrders) GetOrderType() string { + if m != nil { + return m.OrderType + } + return "" +} + +func (m *MsgFillOrders) GetOrders() []*FillOrderItem { + if m != nil { + return m.Orders + } + return nil +} + +type MsgFillOrdersResponse struct { +} + +func (m *MsgFillOrdersResponse) Reset() { *m = MsgFillOrdersResponse{} } +func (m *MsgFillOrdersResponse) String() string { return proto.CompactTextString(m) } +func (*MsgFillOrdersResponse) ProtoMessage() {} +func (*MsgFillOrdersResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_adab200f727dc48e, []int{8} +} +func (m *MsgFillOrdersResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgFillOrdersResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgFillOrdersResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgFillOrdersResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgFillOrdersResponse.Merge(m, src) +} +func (m *MsgFillOrdersResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgFillOrdersResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgFillOrdersResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgFillOrdersResponse proto.InternalMessageInfo + func init() { proto.RegisterType((*MsgCreateMarket)(nil), "bze.tradebin.v1.MsgCreateMarket") proto.RegisterType((*MsgCreateMarketResponse)(nil), "bze.tradebin.v1.MsgCreateMarketResponse") @@ -346,36 +502,45 @@ func init() { proto.RegisterType((*MsgCreateOrderResponse)(nil), "bze.tradebin.v1.MsgCreateOrderResponse") proto.RegisterType((*MsgCancelOrder)(nil), "bze.tradebin.v1.MsgCancelOrder") proto.RegisterType((*MsgCancelOrderResponse)(nil), "bze.tradebin.v1.MsgCancelOrderResponse") + proto.RegisterType((*FillOrderItem)(nil), "bze.tradebin.v1.FillOrderItem") + proto.RegisterType((*MsgFillOrders)(nil), "bze.tradebin.v1.MsgFillOrders") + proto.RegisterType((*MsgFillOrdersResponse)(nil), "bze.tradebin.v1.MsgFillOrdersResponse") } func init() { proto.RegisterFile("tradebin/tx.proto", fileDescriptor_adab200f727dc48e) } var fileDescriptor_adab200f727dc48e = []byte{ - // 378 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x93, 0xcf, 0x4e, 0xf2, 0x40, - 0x14, 0xc5, 0x29, 0xff, 0xbe, 0x8f, 0xab, 0x91, 0x38, 0x31, 0x58, 0x49, 0xac, 0xa4, 0x1b, 0xd9, - 0xd0, 0x46, 0x7d, 0x03, 0x5d, 0x18, 0x16, 0xc4, 0x84, 0x68, 0x4c, 0xd8, 0x98, 0x69, 0x7b, 0x03, - 0x44, 0xe8, 0xd4, 0xe9, 0x60, 0x80, 0x8d, 0xaf, 0x60, 0xc2, 0x4b, 0xb9, 0x64, 0xe9, 0xd2, 0xc0, - 0x8b, 0x98, 0x0e, 0x0c, 0xd0, 0x2a, 0xb2, 0x9b, 0x73, 0xe7, 0xcc, 0x3d, 0xbf, 0x99, 0x9b, 0x81, - 0x43, 0xc1, 0xa9, 0x87, 0x4e, 0xd7, 0xb7, 0xc5, 0xd0, 0x0a, 0x38, 0x13, 0x8c, 0x14, 0x9d, 0x31, - 0x5a, 0xaa, 0x6c, 0xbd, 0x5e, 0x98, 0x0f, 0x50, 0x6c, 0x84, 0xed, 0x1b, 0x8e, 0x54, 0x60, 0x83, - 0xf2, 0x67, 0x14, 0x44, 0x87, 0x7f, 0x6e, 0xa4, 0x19, 0xd7, 0xb5, 0x8a, 0x56, 0x2d, 0x34, 0x95, - 0x24, 0x04, 0xb2, 0x0e, 0x0d, 0x51, 0x4f, 0xcb, 0xb2, 0x5c, 0x93, 0x23, 0xc8, 0xbd, 0x0c, 0x98, - 0x40, 0x3d, 0x23, 0x8b, 0x0b, 0x61, 0x9e, 0xc0, 0x71, 0xa2, 0x6d, 0x13, 0xc3, 0x80, 0xf9, 0x21, - 0x9a, 0x13, 0x0d, 0x0e, 0x56, 0x7b, 0x77, 0xdc, 0x43, 0xfe, 0x47, 0xe2, 0x29, 0x00, 0x8b, 0x2c, - 0x4f, 0x62, 0x14, 0xa8, 0xdc, 0x82, 0xac, 0xdc, 0x8f, 0x02, 0x24, 0x25, 0xc8, 0xd3, 0x3e, 0x1b, - 0xf8, 0x62, 0x99, 0xbe, 0x54, 0x11, 0x54, 0xc0, 0xbb, 0x2e, 0xea, 0xd9, 0x05, 0x94, 0x14, 0xa4, - 0x0c, 0xff, 0xfb, 0x92, 0xa5, 0xee, 0xe9, 0x39, 0xb9, 0xb1, 0xd2, 0xa6, 0x0e, 0xa5, 0x38, 0xd4, - 0x8a, 0xf7, 0x6d, 0x81, 0x4b, 0x7d, 0x17, 0x7b, 0xbb, 0x70, 0x37, 0x13, 0xd2, 0xf1, 0x84, 0xe8, - 0x94, 0x04, 0xaf, 0x7b, 0x4b, 0x58, 0x25, 0x13, 0x97, 0xcc, 0x26, 0x2e, 0xa9, 0xd0, 0xd6, 0x00, - 0x0a, 0xed, 0x72, 0x92, 0x86, 0x4c, 0x23, 0x6c, 0x93, 0x16, 0xec, 0xc7, 0x26, 0x58, 0xb1, 0x12, - 0x63, 0xb6, 0x12, 0xc3, 0x28, 0x57, 0x77, 0x39, 0x54, 0x06, 0x79, 0x84, 0xbd, 0xcd, 0x51, 0x9d, - 0x6d, 0x3f, 0x28, 0x0d, 0xe5, 0xf3, 0x1d, 0x86, 0x58, 0xe3, 0x8d, 0x47, 0xfd, 0xbd, 0xf1, 0xda, - 0xb0, 0xa5, 0xf1, 0xcf, 0x57, 0xb9, 0xbe, 0xfd, 0x98, 0x19, 0xda, 0x74, 0x66, 0x68, 0x5f, 0x33, - 0x43, 0x7b, 0x9f, 0x1b, 0xa9, 0xe9, 0xdc, 0x48, 0x7d, 0xce, 0x8d, 0x54, 0xab, 0xd6, 0xee, 0x8a, - 0xce, 0xc0, 0xb1, 0x5c, 0xd6, 0xb7, 0x9d, 0x31, 0xd6, 0x68, 0x2f, 0xe8, 0x50, 0x81, 0x54, 0x2a, - 0x7b, 0x68, 0xaf, 0xff, 0xcb, 0x28, 0xc0, 0xd0, 0xc9, 0xcb, 0x3f, 0x73, 0xf5, 0x1d, 0x00, 0x00, - 0xff, 0xff, 0x34, 0x20, 0x2d, 0x2d, 0x48, 0x03, 0x00, 0x00, + // 469 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x94, 0xcd, 0x6e, 0x13, 0x31, + 0x10, 0xc7, 0xe3, 0x24, 0x0d, 0x74, 0x4a, 0xa9, 0xb0, 0xa0, 0x35, 0x91, 0x30, 0xd1, 0x1e, 0x20, + 0x97, 0x6e, 0x44, 0x91, 0xb8, 0x71, 0x01, 0x09, 0x94, 0x43, 0x84, 0x14, 0x15, 0x21, 0xf5, 0x82, + 0xbc, 0xc9, 0x28, 0x8d, 0x48, 0xd6, 0x8b, 0xed, 0xa0, 0xa6, 0x17, 0x5e, 0x01, 0x89, 0x2b, 0x0f, + 0xc4, 0xb1, 0x47, 0x8e, 0x28, 0x39, 0xf1, 0x16, 0x68, 0xbd, 0xeb, 0xfd, 0xea, 0x47, 0xa4, 0xde, + 0xf6, 0x3f, 0x33, 0x9e, 0xf9, 0xfd, 0xd7, 0x23, 0xc3, 0x03, 0xa3, 0xc4, 0x18, 0x83, 0x69, 0xd8, + 0x33, 0x67, 0x7e, 0xa4, 0xa4, 0x91, 0x74, 0x2f, 0x38, 0x47, 0xdf, 0x85, 0xfd, 0x6f, 0x2f, 0xbc, + 0x8f, 0xb0, 0x37, 0xd0, 0x93, 0xb7, 0x0a, 0x85, 0xc1, 0x81, 0x50, 0x5f, 0xd0, 0x50, 0x06, 0x77, + 0x46, 0xb1, 0x96, 0x8a, 0x91, 0x0e, 0xe9, 0x6e, 0x0f, 0x9d, 0xa4, 0x14, 0x9a, 0x81, 0xd0, 0xc8, + 0xea, 0x36, 0x6c, 0xbf, 0xe9, 0x43, 0xd8, 0xfa, 0xba, 0x90, 0x06, 0x59, 0xc3, 0x06, 0x13, 0xe1, + 0x3d, 0x86, 0x83, 0x4a, 0xdb, 0x21, 0xea, 0x48, 0x86, 0x1a, 0xbd, 0x9f, 0x04, 0xee, 0x67, 0xb9, + 0x0f, 0x6a, 0x8c, 0xea, 0x86, 0x89, 0x4f, 0x00, 0x64, 0x5c, 0xf2, 0xd9, 0x2c, 0x23, 0x37, 0x77, + 0xdb, 0x46, 0x8e, 0x97, 0x11, 0xd2, 0x7d, 0x68, 0x89, 0xb9, 0x5c, 0x84, 0x26, 0x9d, 0x9e, 0xaa, + 0x18, 0x2a, 0x52, 0xd3, 0x11, 0xb2, 0x66, 0x02, 0x65, 0x05, 0x6d, 0xc3, 0xdd, 0xb9, 0x65, 0xe9, + 0x8f, 0xd9, 0x96, 0x4d, 0x64, 0xda, 0x63, 0xb0, 0x5f, 0x86, 0xca, 0x78, 0xbf, 0x27, 0xb8, 0x22, + 0x1c, 0xe1, 0x6c, 0x13, 0x6e, 0x71, 0x42, 0xbd, 0x3c, 0x21, 0x3e, 0x65, 0xc1, 0xfb, 0xe3, 0x14, + 0xd6, 0xc9, 0x8a, 0xc9, 0x66, 0xc5, 0xa4, 0x43, 0xcb, 0x01, 0x32, 0xb4, 0xd7, 0xb0, 0xfb, 0x6e, + 0x3a, 0x4b, 0x82, 0x7d, 0x83, 0xf3, 0xdc, 0x37, 0x29, 0xfa, 0xce, 0xff, 0x52, 0xbd, 0xf8, 0x97, + 0xbc, 0x5f, 0x04, 0x76, 0x07, 0x7a, 0x92, 0xb5, 0xd0, 0xb7, 0x74, 0x56, 0xe6, 0x6f, 0x54, 0x2f, + 0xe9, 0x15, 0xb4, 0xac, 0xd0, 0xac, 0xd9, 0x69, 0x74, 0x77, 0x8e, 0xb8, 0x5f, 0x59, 0x42, 0xbf, + 0x64, 0x62, 0x98, 0x56, 0x7b, 0x07, 0xf0, 0xa8, 0x44, 0xe7, 0x6c, 0x1f, 0xfd, 0xab, 0x43, 0x63, + 0xa0, 0x27, 0xf4, 0x04, 0xee, 0x95, 0x16, 0xb7, 0x73, 0xa9, 0x71, 0x65, 0x07, 0xdb, 0xdd, 0x4d, + 0x15, 0x6e, 0x06, 0xfd, 0x04, 0x3b, 0xc5, 0x0d, 0x7d, 0x7a, 0xfd, 0x41, 0x5b, 0xd0, 0x7e, 0xbe, + 0xa1, 0xa0, 0xd4, 0xb8, 0xb0, 0x4b, 0x57, 0x37, 0xce, 0x0b, 0xae, 0x69, 0x7c, 0x79, 0x19, 0xe8, + 0x31, 0x40, 0xe1, 0x26, 0xf9, 0x55, 0xc7, 0xf2, 0x7c, 0xfb, 0xd9, 0xcd, 0x79, 0xd7, 0xf5, 0xcd, + 0xfb, 0xdf, 0x2b, 0x4e, 0x2e, 0x56, 0x9c, 0xfc, 0x5d, 0x71, 0xf2, 0x63, 0xcd, 0x6b, 0x17, 0x6b, + 0x5e, 0xfb, 0xb3, 0xe6, 0xb5, 0x93, 0xc3, 0xc9, 0xd4, 0x9c, 0x2e, 0x02, 0x7f, 0x24, 0xe7, 0xbd, + 0xe0, 0x1c, 0x0f, 0xc5, 0x2c, 0x3a, 0x15, 0x06, 0x85, 0x55, 0xbd, 0xb3, 0x5e, 0xfe, 0xf8, 0x2c, + 0x23, 0xd4, 0x41, 0xcb, 0x3e, 0x40, 0x2f, 0xff, 0x07, 0x00, 0x00, 0xff, 0xff, 0x6d, 0x1a, 0xbd, + 0xc6, 0x95, 0x04, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -393,6 +558,7 @@ type MsgClient interface { CreateMarket(ctx context.Context, in *MsgCreateMarket, opts ...grpc.CallOption) (*MsgCreateMarketResponse, error) CreateOrder(ctx context.Context, in *MsgCreateOrder, opts ...grpc.CallOption) (*MsgCreateOrderResponse, error) CancelOrder(ctx context.Context, in *MsgCancelOrder, opts ...grpc.CallOption) (*MsgCancelOrderResponse, error) + FillOrders(ctx context.Context, in *MsgFillOrders, opts ...grpc.CallOption) (*MsgFillOrdersResponse, error) } type msgClient struct { @@ -430,11 +596,21 @@ func (c *msgClient) CancelOrder(ctx context.Context, in *MsgCancelOrder, opts .. return out, nil } +func (c *msgClient) FillOrders(ctx context.Context, in *MsgFillOrders, opts ...grpc.CallOption) (*MsgFillOrdersResponse, error) { + out := new(MsgFillOrdersResponse) + err := c.cc.Invoke(ctx, "/bze.tradebin.v1.Msg/FillOrders", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // MsgServer is the server API for Msg service. type MsgServer interface { CreateMarket(context.Context, *MsgCreateMarket) (*MsgCreateMarketResponse, error) CreateOrder(context.Context, *MsgCreateOrder) (*MsgCreateOrderResponse, error) CancelOrder(context.Context, *MsgCancelOrder) (*MsgCancelOrderResponse, error) + FillOrders(context.Context, *MsgFillOrders) (*MsgFillOrdersResponse, error) } // UnimplementedMsgServer can be embedded to have forward compatible implementations. @@ -450,6 +626,9 @@ func (*UnimplementedMsgServer) CreateOrder(ctx context.Context, req *MsgCreateOr func (*UnimplementedMsgServer) CancelOrder(ctx context.Context, req *MsgCancelOrder) (*MsgCancelOrderResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method CancelOrder not implemented") } +func (*UnimplementedMsgServer) FillOrders(ctx context.Context, req *MsgFillOrders) (*MsgFillOrdersResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method FillOrders not implemented") +} func RegisterMsgServer(s grpc1.Server, srv MsgServer) { s.RegisterService(&_Msg_serviceDesc, srv) @@ -509,6 +688,24 @@ func _Msg_CancelOrder_Handler(srv interface{}, ctx context.Context, dec func(int return interceptor(ctx, in, info, handler) } +func _Msg_FillOrders_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgFillOrders) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).FillOrders(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/bze.tradebin.v1.Msg/FillOrders", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).FillOrders(ctx, req.(*MsgFillOrders)) + } + return interceptor(ctx, in, info, handler) +} + var _Msg_serviceDesc = grpc.ServiceDesc{ ServiceName: "bze.tradebin.v1.Msg", HandlerType: (*MsgServer)(nil), @@ -525,6 +722,10 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "CancelOrder", Handler: _Msg_CancelOrder_Handler, }, + { + MethodName: "FillOrders", + Handler: _Msg_FillOrders_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "tradebin/tx.proto", @@ -752,6 +953,124 @@ func (m *MsgCancelOrderResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) return len(dAtA) - i, nil } +func (m *FillOrderItem) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *FillOrderItem) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *FillOrderItem) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Amount) > 0 { + i -= len(m.Amount) + copy(dAtA[i:], m.Amount) + i = encodeVarintTx(dAtA, i, uint64(len(m.Amount))) + i-- + dAtA[i] = 0x12 + } + if len(m.Price) > 0 { + i -= len(m.Price) + copy(dAtA[i:], m.Price) + i = encodeVarintTx(dAtA, i, uint64(len(m.Price))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgFillOrders) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgFillOrders) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgFillOrders) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Orders) > 0 { + for iNdEx := len(m.Orders) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Orders[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + } + if len(m.OrderType) > 0 { + i -= len(m.OrderType) + copy(dAtA[i:], m.OrderType) + i = encodeVarintTx(dAtA, i, uint64(len(m.OrderType))) + i-- + dAtA[i] = 0x1a + } + if len(m.MarketId) > 0 { + i -= len(m.MarketId) + copy(dAtA[i:], m.MarketId) + i = encodeVarintTx(dAtA, i, uint64(len(m.MarketId))) + i-- + dAtA[i] = 0x12 + } + if len(m.Creator) > 0 { + i -= len(m.Creator) + copy(dAtA[i:], m.Creator) + i = encodeVarintTx(dAtA, i, uint64(len(m.Creator))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgFillOrdersResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgFillOrdersResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgFillOrdersResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + func encodeVarintTx(dAtA []byte, offset int, v uint64) int { offset -= sovTx(v) base := offset @@ -865,6 +1184,59 @@ func (m *MsgCancelOrderResponse) Size() (n int) { return n } +func (m *FillOrderItem) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Price) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Amount) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgFillOrders) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Creator) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.MarketId) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.OrderType) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if len(m.Orders) > 0 { + for _, e := range m.Orders { + l = e.Size() + n += 1 + l + sovTx(uint64(l)) + } + } + return n +} + +func (m *MsgFillOrdersResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + func sovTx(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -894,10 +1266,206 @@ func (m *MsgCreateMarket) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgCreateMarket: wiretype end group for non-group") + return fmt.Errorf("proto: MsgCreateMarket: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgCreateMarket: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Creator", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Creator = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Base", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Base = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Quote", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Quote = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgCreateMarketResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgCreateMarketResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgCreateMarketResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgCreateOrder) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgCreateOrder: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgCreateMarket: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgCreateOrder: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -934,7 +1502,7 @@ func (m *MsgCreateMarket) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Base", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field OrderType", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -962,11 +1530,11 @@ func (m *MsgCreateMarket) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Base = string(dAtA[iNdEx:postIndex]) + m.OrderType = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Quote", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -994,7 +1562,71 @@ func (m *MsgCreateMarket) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Quote = string(dAtA[iNdEx:postIndex]) + m.Amount = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Price", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Price = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MarketId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.MarketId = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex @@ -1017,7 +1649,7 @@ func (m *MsgCreateMarket) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgCreateMarketResponse) Unmarshal(dAtA []byte) error { +func (m *MsgCreateOrderResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1040,10 +1672,10 @@ func (m *MsgCreateMarketResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgCreateMarketResponse: wiretype end group for non-group") + return fmt.Errorf("proto: MsgCreateOrderResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgCreateMarketResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgCreateOrderResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: @@ -1067,7 +1699,7 @@ func (m *MsgCreateMarketResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgCreateOrder) Unmarshal(dAtA []byte) error { +func (m *MsgCancelOrder) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1090,10 +1722,10 @@ func (m *MsgCreateOrder) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgCreateOrder: wiretype end group for non-group") + return fmt.Errorf("proto: MsgCancelOrder: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgCreateOrder: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgCancelOrder: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -1130,7 +1762,7 @@ func (m *MsgCreateOrder) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field OrderType", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field MarketId", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -1158,11 +1790,11 @@ func (m *MsgCreateOrder) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.OrderType = string(dAtA[iNdEx:postIndex]) + m.MarketId = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field OrderId", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -1190,11 +1822,11 @@ func (m *MsgCreateOrder) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Amount = string(dAtA[iNdEx:postIndex]) + m.OrderId = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 4: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Price", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field OrderType", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -1222,40 +1854,58 @@ func (m *MsgCreateOrder) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Price = string(dAtA[iNdEx:postIndex]) + m.OrderType = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field MarketId", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err } - intStringLen := int(stringLen) - if intStringLen < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthTx } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTx + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF } - if postIndex > l { + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgCancelOrderResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { return io.ErrUnexpectedEOF } - m.MarketId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgCancelOrderResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgCancelOrderResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) @@ -1277,7 +1927,7 @@ func (m *MsgCreateOrder) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgCreateOrderResponse) Unmarshal(dAtA []byte) error { +func (m *FillOrderItem) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1300,12 +1950,76 @@ func (m *MsgCreateOrderResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgCreateOrderResponse: wiretype end group for non-group") + return fmt.Errorf("proto: FillOrderItem: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgCreateOrderResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: FillOrderItem: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Price", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Price = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Amount = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) @@ -1327,7 +2041,7 @@ func (m *MsgCreateOrderResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgCancelOrder) Unmarshal(dAtA []byte) error { +func (m *MsgFillOrders) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1350,10 +2064,10 @@ func (m *MsgCancelOrder) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgCancelOrder: wiretype end group for non-group") + return fmt.Errorf("proto: MsgFillOrders: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgCancelOrder: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgFillOrders: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -1422,7 +2136,7 @@ func (m *MsgCancelOrder) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field OrderId", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field OrderType", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -1450,13 +2164,13 @@ func (m *MsgCancelOrder) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.OrderId = string(dAtA[iNdEx:postIndex]) + m.OrderType = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 4: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field OrderType", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Orders", wireType) } - var stringLen uint64 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTx @@ -1466,23 +2180,25 @@ func (m *MsgCancelOrder) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { + if msglen < 0 { return ErrInvalidLengthTx } - postIndex := iNdEx + intStringLen + postIndex := iNdEx + msglen if postIndex < 0 { return ErrInvalidLengthTx } if postIndex > l { return io.ErrUnexpectedEOF } - m.OrderType = string(dAtA[iNdEx:postIndex]) + m.Orders = append(m.Orders, &FillOrderItem{}) + if err := m.Orders[len(m.Orders)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } iNdEx = postIndex default: iNdEx = preIndex @@ -1505,7 +2221,7 @@ func (m *MsgCancelOrder) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgCancelOrderResponse) Unmarshal(dAtA []byte) error { +func (m *MsgFillOrdersResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1528,10 +2244,10 @@ func (m *MsgCancelOrderResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgCancelOrderResponse: wiretype end group for non-group") + return fmt.Errorf("proto: MsgFillOrdersResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgCancelOrderResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgFillOrdersResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: diff --git a/x/tradebin/types/types.go b/x/tradebin/types/types.go index 62840262..0e214a35 100644 --- a/x/tradebin/types/types.go +++ b/x/tradebin/types/types.go @@ -2,6 +2,10 @@ package types import sdk "github.com/cosmos/cosmos-sdk/types" +const ( + FillOrdersExtraGas = 5000 +) + type OrderCoins struct { Coin sdk.Coin Dust sdk.Dec