From 73ffbe6ceffb7f8699fb1be6f3b50cf1b81623e3 Mon Sep 17 00:00:00 2001 From: Marton Date: Thu, 28 Nov 2024 00:06:44 +0100 Subject: [PATCH] mm/core: Fix multi trade funding error (#3099) When the wallet is not able to fund all the orders requested, it resulted in a panic in the mm code, because a nil MultiTradeResult was returned. This also fixes the UI to properly display unknown errors in the epoch report. --- client/asset/interface.go | 2 +- client/core/core.go | 22 ++++++++++++++-------- client/mm/exchange_adaptor.go | 13 ++++++++++--- client/mm/mm.go | 2 +- client/mm/utils.go | 2 +- client/webserver/site/src/js/mmutil.ts | 4 ++++ 6 files changed, 31 insertions(+), 14 deletions(-) diff --git a/client/asset/interface.go b/client/asset/interface.go index d1761f0353..d24489ca34 100644 --- a/client/asset/interface.go +++ b/client/asset/interface.go @@ -565,7 +565,7 @@ type Wallet interface { // FundMultiOrder funds multiple orders at once. The return values will // be in the same order as the passed orders. If less values are returned // than the number of orders, then the orders at the end of the list were - // not about to be funded. + // not able to be funded. FundMultiOrder(ord *MultiOrder, maxLock uint64) (coins []Coins, redeemScripts [][]dex.Bytes, fundingFees uint64, err error) // MaxFundingFees returns the max fees that could be paid for funding a swap. MaxFundingFees(numTrades uint32, feeRate uint64, options map[string]string) uint64 diff --git a/client/core/core.go b/client/core/core.go index b3884390ea..52134fa7c7 100644 --- a/client/core/core.go +++ b/client/core/core.go @@ -5759,23 +5759,29 @@ type MultiTradeResult struct { // MultiTrade is used to place multiple standing limit orders on the same // side of the same market simultaneously. func (c *Core) MultiTrade(pw []byte, form *MultiTradeForm) []*MultiTradeResult { - results := make([]*MultiTradeResult, len(form.Placements)) + results := make([]*MultiTradeResult, 0, len(form.Placements)) + reqs, err := c.prepareMultiTradeRequests(pw, form) if err != nil { - for i := range results { - results[i] = &MultiTradeResult{Error: err} + for range form.Placements { + results = append(results, &MultiTradeResult{Error: err}) } return results } - for i, req := range reqs { - var corder *Order - corder, err = c.sendTradeRequest(req) + for i := range form.Placements { + if i >= len(reqs) { + results = append(results, &MultiTradeResult{Error: errors.New("wallet unable to fund order")}) + continue + } + + req := reqs[i] + corder, err := c.sendTradeRequest(req) if err != nil { - results[i] = &MultiTradeResult{Error: err} + results = append(results, &MultiTradeResult{Error: err}) continue } - results[i] = &MultiTradeResult{Order: corder} + results = append(results, &MultiTradeResult{Order: corder}) } return results diff --git a/client/mm/exchange_adaptor.go b/client/mm/exchange_adaptor.go index 813775759c..0c69412283 100644 --- a/client/mm/exchange_adaptor.go +++ b/client/mm/exchange_adaptor.go @@ -3630,11 +3630,14 @@ func (u *unifiedExchangeAdaptor) tradingLimitNotReached(epochNum uint64) bool { if err == nil && !tradingLimitReached { return } - + var unknownErr string + if err != nil { + unknownErr = err.Error() + } u.updateEpochReport(&EpochReport{ PreOrderProblems: &BotProblems{ UserLimitTooLow: tradingLimitReached, - UnknownError: err, + UnknownError: unknownErr, }, EpochNum: epochNum, }) @@ -3707,6 +3710,10 @@ func (u *unifiedExchangeAdaptor) checkBotHealth(epochNum uint64) (healthy bool) if healthy { return } + var unknownErr string + if err != nil { + unknownErr = err.Error() + } problems := &BotProblems{ NoWalletPeers: map[uint32]bool{ u.baseID: baseAssetNoPeers, @@ -3717,7 +3724,7 @@ func (u *unifiedExchangeAdaptor) checkBotHealth(epochNum uint64) (healthy bool) u.quoteID: quoteAssetNotSynced, }, AccountSuspended: accountSuspended, - UnknownError: err, + UnknownError: unknownErr, } u.updateEpochReport(&EpochReport{ PreOrderProblems: problems, diff --git a/client/mm/mm.go b/client/mm/mm.go index b9c3cba0dd..c4f69b9076 100644 --- a/client/mm/mm.go +++ b/client/mm/mm.go @@ -264,7 +264,7 @@ type BotProblems struct { // CausesSelfMatch is true if the order would cause a self match. CausesSelfMatch bool `json:"causesSelfMatch"` // UnknownError is set if an error occurred that was not one of the above. - UnknownError error `json:"unknownError"` + UnknownError string `json:"unknownError"` } // EpochReport contains a report of a bot's activity during an epoch. diff --git a/client/mm/utils.go b/client/mm/utils.go index 948f7aa5a3..41a3189fdc 100644 --- a/client/mm/utils.go +++ b/client/mm/utils.go @@ -68,5 +68,5 @@ func updateBotProblemsBasedOnError(problems *BotProblems, err error) { return } - problems.UnknownError = err + problems.UnknownError = err.Error() } diff --git a/client/webserver/site/src/js/mmutil.ts b/client/webserver/site/src/js/mmutil.ts index f3d951bf26..a94081dd6d 100644 --- a/client/webserver/site/src/js/mmutil.ts +++ b/client/webserver/site/src/js/mmutil.ts @@ -1352,6 +1352,10 @@ function botProblemMessages (problems: BotProblems | undefined, cexName: string, msgs.push(intl.prep(intl.ID_CAUSES_SELF_MATCH)) } + if (problems.unknownError) { + msgs.push(problems.unknownError) + } + return msgs }