diff --git a/client/mm/event_log.go b/client/mm/event_log.go
index 9871af4ee3..13d523ec1f 100644
--- a/client/mm/event_log.go
+++ b/client/mm/event_log.go
@@ -117,7 +117,7 @@ type eventLogDB interface {
// all of the events will be returned. If refID is not nil, the events
// including and after the event with the ID will be returned. If
// pendingOnly is true, only pending events will be returned.
- runEvents(startTime int64, mkt *MarketWithHost, n uint64, refID *uint64, pendingOnly bool) ([]*MarketMakingEvent, error)
+ runEvents(startTime int64, mkt *MarketWithHost, n uint64, refID *uint64, pendingOnly bool, filters *RunLogFilters) ([]*MarketMakingEvent, error)
}
// eventUpdate is used to asynchronously add events to the event log.
@@ -623,7 +623,7 @@ func decodeMarketMakingEvent(eventB []byte) (*MarketMakingEvent, error) {
// events will be returned. If refID is not nil, the events including and after the
// event with the ID will be returned. If pendingOnly is true, only pending events
// will be returned.
-func (db *boltEventLogDB) runEvents(startTime int64, mkt *MarketWithHost, n uint64, refID *uint64, pendingOnly bool) ([]*MarketMakingEvent, error) {
+func (db *boltEventLogDB) runEvents(startTime int64, mkt *MarketWithHost, n uint64, refID *uint64, pendingOnly bool, filter *RunLogFilters) ([]*MarketMakingEvent, error) {
events := make([]*MarketMakingEvent, 0, 32)
return events, db.View(func(tx *bbolt.Tx) error {
@@ -667,6 +667,10 @@ func (db *boltEventLogDB) runEvents(startTime int64, mkt *MarketWithHost, n uint
continue
}
+ if !filter.filter(e) {
+ continue
+ }
+
events = append(events, e)
if n > 0 && uint64(len(events)) >= n {
break
diff --git a/client/mm/exchange_adaptor.go b/client/mm/exchange_adaptor.go
index bc42233e59..ff19bac19d 100644
--- a/client/mm/exchange_adaptor.go
+++ b/client/mm/exchange_adaptor.go
@@ -3236,6 +3236,7 @@ type ProfitLoss struct {
ModsUSD float64 `json:"modsUSD"`
Final map[uint32]*Amount `json:"final"`
FinalUSD float64 `json:"finalUSD"`
+ Diffs map[uint32]*Amount `json:"diffs"`
Profit float64 `json:"profit"`
ProfitRatio float64 `json:"profitRatio"`
}
@@ -3250,6 +3251,7 @@ func newProfitLoss(
pl := &ProfitLoss{
Initial: make(map[uint32]*Amount, len(initialBalances)),
Mods: make(map[uint32]*Amount, len(mods)),
+ Diffs: make(map[uint32]*Amount, len(initialBalances)),
Final: make(map[uint32]*Amount, len(finalBalances)),
}
for assetID, v := range initialBalances {
@@ -3262,6 +3264,8 @@ func newProfitLoss(
mod := NewAmount(assetID, mods[assetID], fiatRate)
pl.InitialUSD += init.USD
pl.ModsUSD += mod.USD
+ diff := int64(finalBalances[assetID]) - int64(initialBalances[assetID]) - mods[assetID]
+ pl.Diffs[assetID] = NewAmount(assetID, diff, fiatRate)
}
for assetID, v := range finalBalances {
if v == 0 {
diff --git a/client/mm/mm.go b/client/mm/mm.go
index 08f49d8770..99da4c67a6 100644
--- a/client/mm/mm.go
+++ b/client/mm/mm.go
@@ -1237,25 +1237,72 @@ func (m *MarketMaker) updatePendingEvent(mkt *MarketWithHost, event *MarketMakin
}
}
+type RunLogFilters struct {
+ DexBuys bool `json:"dexBuys"`
+ DexSells bool `json:"dexSells"`
+ CexBuys bool `json:"cexBuys"`
+ CexSells bool `json:"cexSells"`
+ Deposits bool `json:"deposits"`
+ Withdrawals bool `json:"withdrawals"`
+}
+
+func (f *RunLogFilters) filter(event *MarketMakingEvent) bool {
+ switch {
+ case event.DEXOrderEvent != nil:
+ if event.DEXOrderEvent.Sell {
+ return f.DexSells
+ }
+ return f.DexBuys
+ case event.CEXOrderEvent != nil:
+ if event.CEXOrderEvent.Sell {
+ return f.CexSells
+ }
+ return f.CexBuys
+ case event.DepositEvent != nil:
+ return f.Deposits
+ case event.WithdrawalEvent != nil:
+ return f.Withdrawals
+ default:
+ return false
+ }
+}
+
+var noFilters = &RunLogFilters{
+ DexBuys: true,
+ DexSells: true,
+ CexBuys: true,
+ CexSells: true,
+ Deposits: true,
+ Withdrawals: true,
+}
+
// RunLogs returns the event logs of a market making run. At most n events are
// returned, if n == 0 then all events are returned. If refID is not nil, then
// the events including and after refID are returned.
-func (m *MarketMaker) RunLogs(startTime int64, mkt *MarketWithHost, n uint64, refID *uint64) ([]*MarketMakingEvent, *MarketMakingRunOverview, error) {
+// Updated events are events that were updated from pending to confirmed during
+// this call. For completed runs, on each call to RunLogs, all pending events are
+// checked for updates, and anything that was updated is returned.
+func (m *MarketMaker) RunLogs(startTime int64, mkt *MarketWithHost, n uint64, refID *uint64, filters *RunLogFilters) (events, updatedEvents []*MarketMakingEvent, overview *MarketMakingRunOverview, err error) {
var running bool
runningBotsLookup := m.runningBotsLookup()
if bot, found := runningBotsLookup[*mkt]; found {
running = bot.timeStart() == startTime
}
+ if filters == nil {
+ filters = noFilters
+ }
+
if !running {
- pendingEvents, err := m.eventLogDB.runEvents(startTime, mkt, 0, nil, true)
+ pendingEvents, err := m.eventLogDB.runEvents(startTime, mkt, 0, nil, true, noFilters)
if err != nil {
- return nil, nil, err
+ return nil, nil, nil, err
}
if len(pendingEvents) > 0 {
+ updatedEvents = make([]*MarketMakingEvent, 0, len(pendingEvents))
overview, err := m.eventLogDB.runOverview(startTime, mkt)
if err != nil {
- return nil, nil, err
+ return nil, nil, nil, err
}
for _, event := range pendingEvents {
if event.Pending {
@@ -1264,23 +1311,24 @@ func (m *MarketMaker) RunLogs(startTime int64, mkt *MarketWithHost, n uint64, re
m.log.Errorf("Error updating pending event: %v", err)
continue
}
+ updatedEvents = append(updatedEvents, updatedEvent)
m.eventLogDB.storeEvent(startTime, mkt, updatedEvent, nil)
}
}
}
}
- events, err := m.eventLogDB.runEvents(startTime, mkt, n, refID, false)
+ events, err = m.eventLogDB.runEvents(startTime, mkt, n, refID, false, filters)
if err != nil {
- return nil, nil, err
+ return nil, nil, nil, err
}
- overview, err := m.eventLogDB.runOverview(startTime, mkt)
+ overview, err = m.eventLogDB.runOverview(startTime, mkt)
if err != nil {
- return nil, nil, err
+ return nil, nil, nil, err
}
- return events, overview, nil
+ return events, updatedEvents, overview, nil
}
// CEXBook generates a snapshot of the specified CEX order book.
diff --git a/client/webserver/api.go b/client/webserver/api.go
index 3ebd696cc3..9979eff4bb 100644
--- a/client/webserver/api.go
+++ b/client/webserver/api.go
@@ -1745,25 +1745,28 @@ func (s *WebServer) apiRunLogs(w http.ResponseWriter, r *http.Request) {
Market *mm.MarketWithHost `json:"market"`
N uint64 `json:"n"`
RefID *uint64 `json:"refID,omitempty"`
+ Filters *mm.RunLogFilters `json:"filters,omitempty"`
}
if !readPost(w, r, &req) {
return
}
- logs, overview, err := s.mm.RunLogs(req.StartTime, req.Market, req.N, req.RefID)
+ logs, updatedLogs, overview, err := s.mm.RunLogs(req.StartTime, req.Market, req.N, req.RefID, req.Filters)
if err != nil {
s.writeAPIError(w, fmt.Errorf("error getting run logs: %w", err))
return
}
writeJSON(w, &struct {
- OK bool `json:"ok"`
- Overview *mm.MarketMakingRunOverview `json:"overview"`
- Logs []*mm.MarketMakingEvent `json:"logs"`
+ OK bool `json:"ok"`
+ Overview *mm.MarketMakingRunOverview `json:"overview"`
+ Logs []*mm.MarketMakingEvent `json:"logs"`
+ UpdatedLogs []*mm.MarketMakingEvent `json:"updatedLogs"`
}{
- OK: true,
- Overview: overview,
- Logs: logs,
+ OK: true,
+ Overview: overview,
+ Logs: logs,
+ UpdatedLogs: updatedLogs,
})
}
diff --git a/client/webserver/locales/en-us.go b/client/webserver/locales/en-us.go
index 831796a7ae..73b627f802 100644
--- a/client/webserver/locales/en-us.go
+++ b/client/webserver/locales/en-us.go
@@ -622,4 +622,15 @@ var EnUS = map[string]*intl.Translation{
"remotegap_tooltip": {T: "The buy-sell spread on the linked cex market"},
"max_zero_no_fees": {T: ` balance < min fees ~`},
"max_zero_no_bal": {T: `low balance`},
+ "balance_diff": {T: "Balance Diff"},
+ "usd_diff": {T: "USD Diff"},
+ "usd_rate": {T: "USD Rate"},
+ "dex_sell": {T: "DEX Sell"},
+ "dex_buy": {T: "DEX Buy"},
+ "cex_sell": {T: "CEX Sell"},
+ "cex_buy": {T: "CEX Buy"},
+ "deposit": {T: "Deposit"},
+ "withdrawal": {T: "Withdrawal"},
+ "filters": {T: "Filters"},
+ "Apply": {T: "Apply"},
}
diff --git a/client/webserver/site/src/css/components.scss b/client/webserver/site/src/css/components.scss
index 44b2e7998d..af2a3b3d3e 100644
--- a/client/webserver/site/src/css/components.scss
+++ b/client/webserver/site/src/css/components.scss
@@ -291,6 +291,7 @@ div[data-handler=order],
div[data-handler=orders],
div[data-handler=register],
div[data-handler=settings],
+div[data-handler=mmlogs],
div[data-handler=wallets] {
#forms>form:not(.plain) {
border-radius: 5px;
diff --git a/client/webserver/site/src/css/mm.scss b/client/webserver/site/src/css/mm.scss
index 81c621b7d1..7aefedaaaf 100644
--- a/client/webserver/site/src/css/mm.scss
+++ b/client/webserver/site/src/css/mm.scss
@@ -6,6 +6,15 @@ div[data-handler=mm] {
width: 300px;
}
+ #eventsTablePanel {
+ & > div {
+ @include stylish-overflow;
+
+ height: 100%;
+ overflow-x: hidden;
+ }
+ }
+
.gap-factor-input,
.lots-input {
max-width: 75px;
diff --git a/client/webserver/site/src/html/mmarchives.tmpl b/client/webserver/site/src/html/mmarchives.tmpl
index 33997ef552..902a15ccb3 100644
--- a/client/webserver/site/src/html/mmarchives.tmpl
+++ b/client/webserver/site/src/html/mmarchives.tmpl
@@ -8,29 +8,31 @@
[[[previous_mm_runs]]]
{{template "bottom"}}
diff --git a/client/webserver/site/src/html/mmlogs.tmpl b/client/webserver/site/src/html/mmlogs.tmpl
index 28a8354eb9..9795beb50a 100644
--- a/client/webserver/site/src/html/mmlogs.tmpl
+++ b/client/webserver/site/src/html/mmlogs.tmpl
@@ -1,6 +1,7 @@
{{define "mmlogs"}}
{{template "top" .}}
-
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+ [[[start_time]]] |
+ |
+
+
+ [[[end_time]]] |
+ |
+
+
+
+
+
+
+
+
+
+ [[[Asset]]] |
+ [[[balance_diff]]] |
+ [[[usd_rate]]] |
+ [[[usd_diff]]] |
+
+
+
+
+ |
+ |
+ |
+ |
+
+
+
+
+ [[[profit_loss]]] |
+ |
+
+
+
+
+
+
-
+
-
+