code.vegaprotocol.io/vega@v0.79.0/core/integration/steps/amm_events.go (about) 1 // Copyright (C) 2023 Gobalsky Labs Limited 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Affero General Public License as 5 // published by the Free Software Foundation, either version 3 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Affero General Public License for more details. 12 // 13 // You should have received a copy of the GNU Affero General Public License 14 // along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 package steps 17 18 import ( 19 "fmt" 20 21 "code.vegaprotocol.io/vega/core/events" 22 "code.vegaprotocol.io/vega/core/integration/stubs" 23 "code.vegaprotocol.io/vega/core/types" 24 "code.vegaprotocol.io/vega/libs/ptr" 25 "code.vegaprotocol.io/vega/logging" 26 27 "github.com/cucumber/godog" 28 ) 29 30 func AMMPoolStatusShouldBe(broker *stubs.BrokerStub, table *godog.Table) error { 31 recent := broker.GetLastAMMPoolEvents() 32 for _, r := range parseAMMEventTable(table) { 33 row := ammEvtRow{ 34 r: r, 35 } 36 mID, pID := row.market(), row.party() 37 mmap, ok := recent[mID] 38 if !ok { 39 return fmt.Errorf("no AMM events found for market %s", mID) 40 } 41 pEvt, ok := mmap[pID] 42 if !ok { 43 return fmt.Errorf("no AMM events found for party %s in market %s", pID, mID) 44 } 45 if err := row.matchesEvt(pEvt); err != nil { 46 return err 47 } 48 } 49 return nil 50 } 51 52 func ExpectToSeeAMMEvents(broker *stubs.BrokerStub, table *godog.Table) error { 53 evtMap := broker.GetAMMPoolEventMap() 54 for _, r := range parseAMMEventTable(table) { 55 row := ammEvtRow{ 56 r: r, 57 } 58 mID, pID := row.market(), row.party() 59 mmap, ok := evtMap[mID] 60 if !ok { 61 return fmt.Errorf("no AMM events found for market %s", mID) 62 } 63 pEvts, ok := mmap[pID] 64 if !ok { 65 return fmt.Errorf("no AMM events found for party %s in market %s", pID, mID) 66 } 67 var err error 68 for _, e := range pEvts { 69 if err = row.matchesEvt(e); err == nil { 70 break 71 } 72 } 73 if err != nil { 74 return fmt.Errorf("expected AMM event for party %s on market %s not found, last AMM pool event mismatch: %v", pID, mID, err) 75 } 76 } 77 return nil 78 } 79 80 func SetAMMPartyAlias(broker *stubs.BrokerStub, exec Execution, table *godog.Table) error { 81 // get the most recent event by market and party 82 recent := broker.GetLastAMMPoolEvents() 83 for _, r := range parseAMMAccountAlias(table) { 84 row := ammEvtRow{ 85 r: r, 86 } 87 mID, pID := row.market(), row.party() 88 mmap, ok := recent[mID] 89 if !ok { 90 return fmt.Errorf("no AMM events found for market %s", mID) 91 } 92 pEvt, ok := mmap[pID] 93 if !ok { 94 return fmt.Errorf("no AMM event found for party %s in market %s", pID, mID) 95 } 96 pid := pEvt.AMMPool().AmmPartyId 97 exec.SetAMMSubAccountIDAlias(row.alias(), pid) 98 } 99 return nil 100 } 101 102 type ammEvtRow struct { 103 r RowWrapper 104 } 105 106 func parseAMMAccountAlias(table *godog.Table) []RowWrapper { 107 return StrictParseTable(table, []string{ 108 "party", 109 "market id", 110 "alias", 111 }, nil) 112 } 113 114 func parseAMMEventTable(table *godog.Table) []RowWrapper { 115 return StrictParseTable(table, []string{ 116 "party", 117 "market id", 118 "amount", 119 "status", 120 }, []string{ 121 "reason", 122 "base", 123 "lower bound", 124 "upper bound", 125 "lower leverage", 126 "upper leverage", 127 }) 128 } 129 130 func DebugAMMPoolEvents(broker *stubs.BrokerStub, log *logging.Logger) error { 131 evts := broker.GetAMMPoolEvents() 132 logEvents(log, evts) 133 return nil 134 } 135 136 func DebugAMMPoolEventsForPartyMarket(broker *stubs.BrokerStub, log *logging.Logger, party, market *string) error { 137 if party == nil && market == nil { 138 return DebugAMMPoolEvents(broker, log) 139 } 140 if market == nil { 141 logEvents(log, broker.GetAMMPoolEventsByParty(*party)) 142 return nil 143 } 144 if party == nil { 145 logEvents(log, broker.GetAMMPoolEventsByMarket(*market)) 146 return nil 147 } 148 logEvents(log, broker.GetAMMPoolEventsByPartyAndMarket(*party, *market)) 149 return nil 150 } 151 152 func logEvents(log *logging.Logger, evts []*events.AMMPool) { 153 for _, e := range evts { 154 pool := e.AMMPool() 155 if pool.Parameters == nil { 156 log.Info(fmt.Sprintf("AMM Party: %s on Market: %s - Amount: %s - no parameters", pool.PartyId, pool.MarketId, pool.Commitment)) 157 continue 158 } 159 160 var lowerLeverage, upperLeverage, lowerBound, upperBound string 161 if pool.Parameters.LeverageAtLowerBound != nil { 162 lowerLeverage = *pool.Parameters.LeverageAtLowerBound 163 } 164 if pool.Parameters.LeverageAtUpperBound != nil { 165 upperLeverage = *pool.Parameters.LeverageAtUpperBound 166 } 167 168 if pool.Parameters.UpperBound != nil { 169 upperBound = *pool.Parameters.UpperBound 170 } 171 if pool.Parameters.LowerBound != nil { 172 lowerBound = *pool.Parameters.LowerBound 173 } 174 175 log.Info(fmt.Sprintf( 176 "AMM Party: %s on Market: %s - Amount: %s\nStatus: %s, Reason: %s\n Base: %s, Bounds: %s-%s, Leverages: %s-%s", 177 pool.PartyId, pool.MarketId, pool.Commitment, 178 pool.Status.String(), pool.StatusReason.String(), 179 pool.Parameters.Base, lowerBound, upperBound, 180 lowerLeverage, upperLeverage, 181 )) 182 } 183 } 184 185 func (a ammEvtRow) matchesEvt(e *events.AMMPool) error { 186 pool := e.AMMPool() 187 188 if pool.PartyId != a.party() || pool.MarketId != a.market() || pool.Commitment != a.r.MustStr("amount") || pool.Status != a.status() { 189 return fmt.Errorf( 190 "expected party %s, market %s, amount %s, status %s - instead got %s, %s, %s, %s", 191 a.party(), a.market(), a.r.MustStr("amount"), a.status().String(), 192 pool.PartyId, pool.MarketId, pool.Commitment, pool.Status.String(), 193 ) 194 } 195 got := make([]any, 0, 10) 196 got = append(got, pool.PartyId, pool.MarketId, pool.Commitment, pool.Status.String()) 197 eFmt := "mismatch for %s, %s, %s, %s" 198 if psr, check := a.reason(); check { 199 if pool.StatusReason != psr { 200 got = append(got, psr.String, pool.StatusReason.String()) 201 return fmt.Errorf(eFmt+" expected reason %s - instead got %s", got...) 202 } 203 got = append(got, psr.String()) 204 eFmt = eFmt + ", %s" 205 } 206 207 checks := map[string]string{ 208 "base": pool.Parameters.Base, 209 "lower bound": ptr.UnBox(pool.Parameters.LowerBound), 210 "upper bound": ptr.UnBox(pool.Parameters.UpperBound), 211 "lower leverage": ptr.UnBox(pool.Parameters.LeverageAtLowerBound), 212 "upper leverage": ptr.UnBox(pool.Parameters.LeverageAtUpperBound), 213 } 214 215 for name, val := range checks { 216 if !a.r.HasColumn(name) { 217 if val != "" { 218 got = append(got, name, "", val) 219 return fmt.Errorf(eFmt+" expected %s %s - instead got %s", got...) 220 } 221 continue 222 } 223 if exp := a.r.MustStr(name); val != exp { 224 got = append(got, name, exp, val) 225 return fmt.Errorf(eFmt+" expected %s %s - instead got %s", got...) 226 } 227 got = append(got, val) 228 eFmt = eFmt + ", %s" 229 } 230 return nil 231 } 232 233 func (a ammEvtRow) party() string { 234 return a.r.MustStr("party") 235 } 236 237 func (a ammEvtRow) market() string { 238 return a.r.MustStr("market id") 239 } 240 241 func (a ammEvtRow) status() types.AMMPoolStatus { 242 return a.r.MustAMMPoolStatus("status") 243 } 244 245 func (a ammEvtRow) reason() (types.AMMStatusReason, bool) { 246 if !a.r.HasColumn("reason") { 247 return types.AMMStatusReasonUnspecified, false 248 } 249 sr := a.r.MustPoolStatusReason("reason") 250 return sr, true 251 } 252 253 func (a ammEvtRow) alias() string { 254 return a.r.MustStr("alias") 255 }