code.vegaprotocol.io/vega@v0.79.0/core/integration/stubs/broker_stub.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 stubs 17 18 import ( 19 "context" 20 "errors" 21 "fmt" 22 "sync" 23 24 "code.vegaprotocol.io/vega/core/events" 25 "code.vegaprotocol.io/vega/core/types" 26 "code.vegaprotocol.io/vega/libs/broker" 27 "code.vegaprotocol.io/vega/libs/ptr" 28 proto "code.vegaprotocol.io/vega/protos/vega" 29 vegapb "code.vegaprotocol.io/vega/protos/vega" 30 eventspb "code.vegaprotocol.io/vega/protos/vega/events/v1" 31 ) 32 33 var AccountDoesNotExistErr = errors.New("account does not exist") 34 35 type AssetParty struct { 36 Asset, Party string 37 } 38 39 type BrokerStub struct { 40 mu sync.Mutex 41 data map[events.Type][]events.Event 42 subT map[events.Type][]broker.Subscriber 43 44 immdata map[events.Type][]events.Event 45 immdataSlice []events.Event 46 } 47 48 func NewBrokerStub() *BrokerStub { 49 return &BrokerStub{ 50 data: map[events.Type][]events.Event{}, 51 immdata: map[events.Type][]events.Event{}, 52 subT: map[events.Type][]broker.Subscriber{}, 53 } 54 } 55 56 func (b *BrokerStub) Subscribe(sub broker.Subscriber) int { 57 b.mu.Lock() 58 ty := sub.Types() 59 for _, t := range ty { 60 if _, ok := b.subT[t]; !ok { 61 b.subT[t] = []broker.Subscriber{} 62 } 63 b.subT[t] = append(b.subT[t], sub) 64 } 65 b.mu.Unlock() 66 return 0 67 } 68 69 func (b *BrokerStub) SetStreaming(v bool) bool { return false } 70 71 func (b *BrokerStub) SendBatch(evts []events.Event) { 72 if len(evts) == 0 { 73 return 74 } 75 t := evts[0].Type() 76 b.mu.Lock() 77 if subs, ok := b.subT[t]; ok { 78 for _, sub := range subs { 79 if sub.Ack() { 80 sub.Push(evts...) 81 continue 82 } 83 select { 84 case <-sub.Closed(): 85 continue 86 case <-sub.Skip(): 87 continue 88 case sub.C() <- evts: 89 continue 90 default: 91 continue 92 } 93 } 94 } 95 if _, ok := b.data[t]; !ok { 96 b.data[t] = []events.Event{} 97 } 98 if _, ok := b.immdata[t]; !ok { 99 b.immdata[t] = []events.Event{} 100 } 101 b.data[t] = append(b.data[t], evts...) 102 b.immdata[t] = append(b.immdata[t], evts...) 103 b.mu.Unlock() 104 } 105 106 func (b *BrokerStub) Send(e events.Event) { 107 b.mu.Lock() 108 t := e.Type() 109 if subs, ok := b.subT[t]; ok { 110 for _, sub := range subs { 111 if sub.Ack() { 112 sub.Push(e) 113 } else { 114 select { 115 case <-sub.Closed(): 116 continue 117 case <-sub.Skip(): 118 continue 119 case sub.C() <- []events.Event{e}: 120 continue 121 default: 122 continue 123 } 124 } 125 } 126 } 127 if _, ok := b.data[t]; !ok { 128 b.data[t] = []events.Event{} 129 } 130 if _, ok := b.immdata[t]; !ok { 131 b.immdata[t] = []events.Event{} 132 } 133 b.data[t] = append(b.data[t], e) 134 b.immdata[t] = append(b.immdata[t], e) 135 b.immdataSlice = append(b.immdataSlice, e) 136 b.mu.Unlock() 137 } 138 139 func (b *BrokerStub) Stage(e events.Event) {} 140 141 func (b *BrokerStub) GetAllEventsSinceCleared() []events.Event { 142 b.mu.Lock() 143 evs := []events.Event{} 144 for _, d := range b.data { 145 evs = append(evs, d...) 146 } 147 b.mu.Unlock() 148 return evs 149 } 150 151 func (b *BrokerStub) GetAllEvents() []events.Event { 152 b.mu.Lock() 153 ret := make([]events.Event, len(b.immdataSlice)) 154 copy(ret, b.immdataSlice) 155 b.mu.Unlock() 156 return ret 157 } 158 159 func (b *BrokerStub) GetBatch(t events.Type) []events.Event { 160 b.mu.Lock() 161 r := b.data[t] 162 b.mu.Unlock() 163 return r 164 } 165 166 func (b *BrokerStub) GetRejectedOrderAmendments() []events.TxErr { 167 return b.filterTxErr(func(errProto eventspb.TxErrorEvent) bool { 168 return errProto.GetOrderAmendment() != nil 169 }) 170 } 171 172 func (b *BrokerStub) GetImmBatch(t events.Type) []events.Event { 173 b.mu.Lock() 174 r := b.immdata[t] 175 b.mu.Unlock() 176 return r 177 } 178 179 func (b *BrokerStub) GetPAPVolumeSnapshotByID(marketID string) *events.AutomatedPurchaseAnnounced { 180 paps := b.GetPAPVolumeSnapshot() 181 for i := 0; i < len(paps); i++ { 182 p := paps[len(paps)-i-1] 183 if p.MarketID == marketID { 184 return &p 185 } 186 } 187 return nil 188 } 189 190 func (b *BrokerStub) GetPAPVolumeSnapshot() []events.AutomatedPurchaseAnnounced { 191 batch := b.GetBatch(events.AutomatedPurchaseAnnouncedEvent) 192 193 if len(batch) == 0 { 194 return nil 195 } 196 b.mu.Lock() 197 ret := make([]events.AutomatedPurchaseAnnounced, 0, len(batch)) 198 for _, e := range batch { 199 switch et := e.(type) { 200 case *events.AutomatedPurchaseAnnounced: 201 ret = append(ret, *et) 202 } 203 } 204 b.mu.Unlock() 205 return ret 206 } 207 208 // GetLedgerMovements returns ledger movements, `mutable` argument specifies if these should be all the scenario events or events that can be cleared by the user. 209 func (b *BrokerStub) GetLedgerMovements(mutable bool) []events.LedgerMovements { 210 batch := b.GetBatch(events.LedgerMovementsEvent) 211 if !mutable { 212 batch = b.GetImmBatch((events.LedgerMovementsEvent)) 213 } 214 if len(batch) == 0 { 215 return nil 216 } 217 b.mu.Lock() 218 ret := make([]events.LedgerMovements, 0, len(batch)) 219 for _, e := range batch { 220 switch et := e.(type) { 221 case *events.LedgerMovements: 222 ret = append(ret, *et) 223 } 224 } 225 b.mu.Unlock() 226 return ret 227 } 228 229 func (b *BrokerStub) GetDistressedOrders() []events.DistressedOrders { 230 batch := b.GetImmBatch(events.DistressedOrdersClosedEvent) 231 ret := make([]events.DistressedOrders, 0, len(batch)) 232 for _, e := range batch { 233 switch et := e.(type) { 234 case *events.DistressedOrders: 235 ret = append(ret, *et) 236 case events.DistressedOrders: 237 ret = append(ret, et) 238 } 239 } 240 return ret 241 } 242 243 func (b *BrokerStub) GetSettleDistressed() []events.SettleDistressed { 244 batch := b.GetImmBatch(events.SettleDistressedEvent) 245 ret := make([]events.SettleDistressed, 0, len(batch)) 246 for _, e := range batch { 247 switch et := e.(type) { 248 case *events.SettleDistressed: 249 ret = append(ret, *et) 250 case events.SettleDistressed: 251 ret = append(ret, et) 252 } 253 } 254 return ret 255 } 256 257 func (b *BrokerStub) GetLossSocializationEvents() []events.LossSocialization { 258 evts := b.GetImmBatch(events.LossSocializationEvent) 259 typed := make([]events.LossSocialization, 0, len(evts)) 260 for _, e := range evts { 261 if le, ok := e.(events.LossSocialization); ok { 262 typed = append(typed, le) 263 } 264 } 265 return typed 266 } 267 268 func (b *BrokerStub) GetLossSoc() []*events.LossSoc { 269 evts := b.GetImmBatch(events.LossSocializationEvent) 270 typed := make([]*events.LossSoc, 0, len(evts)) 271 for _, e := range evts { 272 switch le := e.(type) { 273 case events.LossSoc: 274 cpy := le 275 typed = append(typed, &cpy) 276 case *events.LossSoc: 277 typed = append(typed, le) 278 } 279 } 280 return typed 281 } 282 283 func (b *BrokerStub) ClearAllEvents() { 284 b.mu.Lock() 285 b.data = map[events.Type][]events.Event{} 286 b.mu.Unlock() 287 } 288 289 func (b *BrokerStub) ClearTransferResponseEvents() { 290 b.mu.Lock() 291 cs := make([]events.Event, 0, len(b.data[events.LedgerMovementsEvent])) 292 b.data[events.LedgerMovementsEvent] = cs 293 b.mu.Unlock() 294 } 295 296 func (b *BrokerStub) ClearTradeEvents() { 297 b.mu.Lock() 298 te := make([]events.Event, 0, len(b.data[events.TradeEvent])) 299 b.data[events.TradeEvent] = te 300 b.mu.Unlock() 301 } 302 303 // GetTransfers returns ledger entries, mutable argument specifies if these should be all the scenario events or events that can be cleared by the user. 304 func (b *BrokerStub) GetTransfers(mutable bool) []*vegapb.LedgerEntry { 305 transferEvents := b.GetLedgerMovements(mutable) 306 transfers := []*vegapb.LedgerEntry{} 307 for _, e := range transferEvents { 308 for _, response := range e.LedgerMovements() { 309 transfers = append(transfers, response.GetEntries()...) 310 } 311 } 312 return transfers 313 } 314 315 func (b *BrokerStub) GetBookDepth(market string) (sell map[string]uint64, buy map[string]uint64) { 316 batch := b.GetImmBatch(events.OrderEvent) 317 exp := b.GetImmBatch(events.ExpiredOrdersEvent) 318 if len(batch) == 0 { 319 return nil, nil 320 } 321 cancelled := b.GetImmBatch(events.CancelledOrdersEvent) 322 expForMarket := map[string]struct{}{} 323 for _, e := range exp { 324 switch et := e.(type) { 325 case *events.ExpiredOrders: 326 if !et.IsMarket(market) { 327 continue 328 } 329 for _, oid := range et.OrderIDs() { 330 expForMarket[oid] = struct{}{} 331 } 332 case events.ExpiredOrders: 333 if !et.IsMarket(market) { 334 continue 335 } 336 for _, oid := range et.OrderIDs() { 337 expForMarket[oid] = struct{}{} 338 } 339 } 340 } 341 // add cancelled orders to expired for market, we skip them for market depth, 342 // so no need to differentiate between cancelled/expired. 343 for _, c := range cancelled { 344 switch et := c.(type) { 345 case *events.CancelledOrders: 346 if !et.IsMarket(market) { 347 continue 348 } 349 for _, oid := range et.OrderIDs() { 350 expForMarket[oid] = struct{}{} 351 } 352 case events.CancelledOrders: 353 if !et.IsMarket(market) { 354 continue 355 } 356 for _, oid := range et.OrderIDs() { 357 expForMarket[oid] = struct{}{} 358 } 359 } 360 } 361 362 // first get all active orders 363 activeOrders := map[string]*vegapb.Order{} 364 for _, e := range batch { 365 var ord *vegapb.Order 366 switch et := e.(type) { 367 case *events.Order: 368 ord = et.Order() 369 case events.Order: 370 ord = et.Order() 371 default: 372 continue 373 } 374 375 if ord.MarketId != market { 376 continue 377 } 378 379 if ord.Status == vegapb.Order_STATUS_ACTIVE { 380 activeOrders[ord.Id] = ord 381 } else { 382 delete(activeOrders, ord.Id) 383 } 384 } 385 386 // now we have all active orders, let's build both sides 387 sell, buy = map[string]uint64{}, map[string]uint64{} 388 for id, v := range activeOrders { 389 if _, ok := expForMarket[id]; ok { 390 continue 391 } 392 if v.Side == vegapb.Side_SIDE_BUY { 393 buy[v.Price] = buy[v.Price] + v.Remaining 394 continue 395 } 396 sell[v.Price] = sell[v.Price] + v.Remaining 397 } 398 399 return sell, buy 400 } 401 402 func (b *BrokerStub) GetActiveOrderDepth(marketID string) (sell []*vegapb.Order, buy []*vegapb.Order) { 403 batch := b.GetImmBatch(events.OrderEvent) 404 if len(batch) == 0 { 405 return nil, nil 406 } 407 active := make(map[string]*vegapb.Order, len(batch)) 408 for _, e := range batch { 409 var ord *vegapb.Order 410 switch et := e.(type) { 411 case *events.Order: 412 ord = et.Order() 413 case events.Order: 414 ord = et.Order() 415 default: 416 continue 417 } 418 if ord.MarketId != marketID { 419 continue 420 } 421 if ord.Status == vegapb.Order_STATUS_ACTIVE { 422 active[ord.Id] = ord 423 } else { 424 delete(active, ord.Id) 425 } 426 } 427 c := len(active) / 2 428 if len(active)%2 == 1 { 429 c++ 430 } 431 sell, buy = make([]*vegapb.Order, 0, c), make([]*vegapb.Order, 0, c) 432 for _, ord := range active { 433 if ord.Side == vegapb.Side_SIDE_BUY { 434 buy = append(buy, ord) 435 continue 436 } 437 sell = append(sell, ord) 438 } 439 440 return sell, buy 441 } 442 443 func (b *BrokerStub) GetMarket(marketID string) *vegapb.Market { 444 batch := b.GetBatch(events.MarketUpdatedEvent) 445 if len(batch) == 0 { 446 return nil 447 } 448 449 for i := len(batch) - 1; i >= 0; i-- { 450 switch mkt := batch[i].(type) { 451 case *events.MarketUpdated: 452 if mkt.MarketID() != marketID { 453 continue 454 } 455 m := mkt.Proto() 456 return &m 457 case events.MarketUpdated: 458 if mkt.MarketID() != marketID { 459 continue 460 } 461 m := mkt.Proto() 462 return &m 463 } 464 } 465 466 return nil 467 } 468 469 func (b *BrokerStub) GetLastMarketUpdateState(marketID string) *vegapb.Market { 470 batch := b.GetBatch(events.MarketUpdatedEvent) 471 if len(batch) == 0 { 472 return nil 473 } 474 var r *vegapb.Market 475 for _, evt := range batch { 476 switch me := evt.(type) { 477 case *events.MarketUpdated: 478 if me.MarketID() == marketID { 479 t := me.Proto() 480 r = &t 481 } 482 case events.MarketUpdated: 483 if me.MarketID() == marketID { 484 t := me.Proto() 485 r = &t 486 } 487 } 488 } 489 return r 490 } 491 492 func (b *BrokerStub) GetMarkPriceSettings(marketID string) *vegapb.CompositePriceConfiguration { 493 batch := b.GetBatch(events.MarketUpdatedEvent) 494 if len(batch) == 0 { 495 return nil 496 } 497 var r *vegapb.Market 498 for _, evt := range batch { 499 switch me := evt.(type) { 500 case *events.MarketUpdated: 501 if me.MarketID() == marketID { 502 t := me.Proto() 503 r = &t 504 } 505 case events.MarketUpdated: 506 if me.MarketID() == marketID { 507 t := me.Proto() 508 r = &t 509 } 510 } 511 } 512 return r.MarkPriceConfiguration 513 } 514 515 func (b *BrokerStub) GetOrdersByPartyAndMarket(party, market string) []vegapb.Order { 516 orders := b.GetOrderEvents() 517 ret := []vegapb.Order{} 518 for _, oe := range orders { 519 if o := oe.Order(); o.MarketId == market && o.PartyId == party { 520 ret = append(ret, *o) 521 } 522 } 523 return ret 524 } 525 526 func (b *BrokerStub) GetStopOrderEvents() []events.StopOrder { 527 batch := b.GetBatch(events.StopOrderEvent) 528 if len(batch) == 0 { 529 return nil 530 } 531 ret := make([]events.StopOrder, 0, len(batch)) 532 for _, e := range batch { 533 switch et := e.(type) { 534 case *events.StopOrder: 535 // o := vtypes.NewStopOrderFromProto(et.StopOrder()) 536 ret = append(ret, *et) 537 case events.StopOrder: 538 // o := vtypes.NewStopOrderFromProto(et.StopOrder()) 539 ret = append(ret, et) 540 } 541 } 542 543 return ret 544 } 545 546 func (b *BrokerStub) GetOrderEvents() []events.Order { 547 batch := b.GetBatch(events.OrderEvent) 548 if len(batch) == 0 { 549 return nil 550 } 551 last := map[string]*types.Order{} 552 ret := make([]events.Order, 0, len(batch)) 553 for _, e := range batch { 554 var o *types.Order 555 switch et := e.(type) { 556 case *events.Order: 557 o, _ = types.OrderFromProto(et.Order()) 558 ret = append(ret, *et) 559 case events.Order: 560 o, _ = types.OrderFromProto(et.Order()) 561 ret = append(ret, et) 562 } 563 last[o.ID] = o 564 } 565 expired := b.GetBatch(events.ExpiredOrdersEvent) 566 for _, e := range expired { 567 var ids []string 568 switch et := e.(type) { 569 case *events.ExpiredOrders: 570 ids = et.OrderIDs() 571 case events.ExpiredOrders: 572 ids = et.OrderIDs() 573 } 574 for _, id := range ids { 575 if o, ok := last[id]; ok { 576 o.Status = vegapb.Order_STATUS_EXPIRED 577 fe := events.NewOrderEvent(context.Background(), o) 578 ret = append(ret, *fe) 579 } 580 } 581 } 582 return ret 583 } 584 585 func (b *BrokerStub) GetCancelledOrderEvents() []events.CancelledOrders { 586 batch := b.GetBatch(events.CancelledOrdersEvent) 587 if len(batch) == 0 { 588 return nil 589 } 590 ret := make([]events.CancelledOrders, 0, len(batch)) 591 for _, e := range batch { 592 switch et := e.(type) { 593 case events.CancelledOrders: 594 ret = append(ret, et) 595 case *events.CancelledOrders: 596 ret = append(ret, *et) 597 } 598 } 599 return ret 600 } 601 602 func (b *BrokerStub) GetCancelledOrdersPerMarket() map[string]map[string]struct{} { 603 evts := b.GetCancelledOrderEvents() 604 ret := map[string]map[string]struct{}{} 605 for _, e := range evts { 606 mID := e.MarketID() 607 oIDs := map[string]struct{}{} 608 if data, ok := ret[mID]; ok { 609 oIDs = data 610 } 611 for _, oid := range e.OrderIDs() { 612 oIDs[oid] = struct{}{} 613 } 614 ret[mID] = oIDs 615 } 616 return ret 617 } 618 619 func (b *BrokerStub) GetLPEvents() []events.LiquidityProvision { 620 batch := b.GetBatch(events.LiquidityProvisionEvent) 621 if len(batch) == 0 { 622 return nil 623 } 624 ret := make([]events.LiquidityProvision, 0, len(batch)) 625 for _, e := range batch { 626 switch et := e.(type) { 627 case *events.LiquidityProvision: 628 ret = append(ret, *et) 629 case events.LiquidityProvision: 630 ret = append(ret, et) 631 } 632 } 633 return ret 634 } 635 636 func (b *BrokerStub) GetFundingPeriodEvents() []events.FundingPeriod { 637 batch := b.GetBatch(events.FundingPeriodEvent) 638 if len(batch) == 0 { 639 return nil 640 } 641 ret := make([]events.FundingPeriod, 0, len(batch)) 642 for _, e := range batch { 643 switch et := e.(type) { 644 case *events.FundingPeriod: 645 ret = append(ret, *et) 646 case events.FundingPeriod: 647 ret = append(ret, et) 648 } 649 } 650 return ret 651 } 652 653 func (b *BrokerStub) GetFundginPaymentEvents() []events.FundingPayments { 654 batch := b.GetBatch(events.FundingPaymentsEvent) 655 if len(batch) == 0 { 656 return nil 657 } 658 ret := make([]events.FundingPayments, 0, len(batch)) 659 for _, e := range batch { 660 switch et := e.(type) { 661 case *events.FundingPayments: 662 ret = append(ret, *et) 663 case events.FundingPayments: 664 ret = append(ret, et) 665 } 666 } 667 return ret 668 } 669 670 func (b *BrokerStub) GetTradeEvents() []events.Trade { 671 batch := b.GetBatch(events.TradeEvent) 672 if len(batch) == 0 { 673 return nil 674 } 675 ret := make([]events.Trade, 0, len(batch)) 676 for _, e := range batch { 677 switch et := e.(type) { 678 case *events.Trade: 679 ret = append(ret, *et) 680 case events.Trade: 681 ret = append(ret, et) 682 } 683 } 684 return ret 685 } 686 687 func (b *BrokerStub) GetAccountEvents() []events.Acc { 688 // Use GetImmBatch so that clearing events doesn't affact this method 689 batch := b.GetImmBatch(events.AccountEvent) 690 if len(batch) == 0 { 691 return nil 692 } 693 ret := make(map[string]events.Acc, len(batch)) 694 for _, e := range batch { 695 switch et := e.(type) { 696 case *events.Acc: 697 ret[et.Account().Id] = *et 698 case events.Acc: 699 ret[et.Account().Id] = et 700 } 701 } 702 s := make([]events.Acc, 0, len(ret)) 703 for _, e := range ret { 704 s = append(s, e) 705 } 706 return s 707 } 708 709 func (b *BrokerStub) GetDeposits() []vegapb.Deposit { 710 // Use GetImmBatch so that clearing events doesn't affact this method 711 batch := b.GetImmBatch(events.DepositEvent) 712 if len(batch) == 0 { 713 return nil 714 } 715 ret := make([]vegapb.Deposit, 0, len(batch)) 716 for _, e := range batch { 717 switch et := e.(type) { 718 case *events.Deposit: 719 ret = append(ret, et.Deposit()) 720 } 721 } 722 return ret 723 } 724 725 func (b *BrokerStub) GetWithdrawals() []vegapb.Withdrawal { 726 // Use GetImmBatch so that clearing events doesn't affact this method 727 batch := b.GetImmBatch(events.WithdrawalEvent) 728 if len(batch) == 0 { 729 return nil 730 } 731 ret := make([]vegapb.Withdrawal, 0, len(batch)) 732 for _, e := range batch { 733 switch et := e.(type) { 734 case *events.Withdrawal: 735 ret = append(ret, et.Withdrawal()) 736 } 737 } 738 return ret 739 } 740 741 func (b *BrokerStub) GetDelegationBalanceEvents(epochSeq string) []events.DelegationBalance { 742 batch := b.GetBatch(events.DelegationBalanceEvent) 743 if len(batch) == 0 { 744 return nil 745 } 746 747 s := []events.DelegationBalance{} 748 749 for _, e := range batch { 750 switch et := e.(type) { 751 case events.DelegationBalance: 752 if et.EpochSeq == epochSeq { 753 s = append(s, et) 754 } 755 case *events.DelegationBalance: 756 if (*et).EpochSeq == epochSeq { 757 s = append(s, *et) 758 } 759 } 760 } 761 return s 762 } 763 764 func (b *BrokerStub) GetCurrentEpoch() *events.EpochEvent { 765 batch := b.GetBatch(events.EpochUpdate) 766 if len(batch) == 0 { 767 return nil 768 } 769 last := batch[len(batch)-1] 770 switch et := last.(type) { 771 case events.EpochEvent: 772 return &et 773 case *events.EpochEvent: 774 return et 775 } 776 return nil 777 } 778 779 func (b *BrokerStub) GetDelegationBalance(epochSeq string) []vegapb.Delegation { 780 evts := b.GetDelegationBalanceEvents(epochSeq) 781 balances := make([]vegapb.Delegation, 0, len(evts)) 782 783 for _, e := range evts { 784 balances = append(balances, vegapb.Delegation{ 785 Party: e.Party, 786 NodeId: e.NodeID, 787 EpochSeq: e.EpochSeq, 788 Amount: e.Amount.String(), 789 }) 790 } 791 return balances 792 } 793 794 func (b *BrokerStub) GetRewards(epochSeq string) map[AssetParty]events.RewardPayout { 795 batch := b.GetBatch(events.RewardPayoutEvent) 796 if len(batch) == 0 { 797 return nil 798 } 799 800 rewards := map[AssetParty]events.RewardPayout{} 801 802 for _, e := range batch { 803 switch et := e.(type) { 804 case events.RewardPayout: 805 if et.EpochSeq == epochSeq { 806 rewards[AssetParty{et.Asset, et.Party}] = et 807 } 808 case *events.RewardPayout: 809 if (*et).EpochSeq == epochSeq { 810 rewards[AssetParty{et.Asset, et.Party}] = *et 811 } 812 } 813 } 814 return rewards 815 } 816 817 func (b *BrokerStub) GetValidatorScores(epochSeq string) map[string]events.ValidatorScore { 818 batch := b.GetBatch(events.ValidatorScoreEvent) 819 if len(batch) == 0 { 820 return nil 821 } 822 823 scores := map[string]events.ValidatorScore{} 824 825 for _, e := range batch { 826 switch et := e.(type) { 827 case events.ValidatorScore: 828 if et.EpochSeq == epochSeq && et.ValidatorStatus == "tendermint" { 829 scores[et.NodeID] = et 830 } 831 case *events.ValidatorScore: 832 if (*et).EpochSeq == epochSeq && et.ValidatorStatus == "tendermint" { 833 scores[et.NodeID] = *et 834 } 835 } 836 } 837 return scores 838 } 839 840 func (b *BrokerStub) GetAccounts() []vegapb.Account { 841 evts := b.GetAccountEvents() 842 accounts := make([]vegapb.Account, 0, len(evts)) 843 for _, a := range evts { 844 accounts = append(accounts, a.Account()) 845 } 846 return accounts 847 } 848 849 func (b *BrokerStub) GetAuctionEvents() []events.Auction { 850 batch := b.GetBatch(events.AuctionEvent) 851 852 if len(batch) == 0 { 853 return nil 854 } 855 ret := make([]events.Auction, 0, len(batch)) 856 for _, e := range batch { 857 switch et := e.(type) { 858 case *events.Auction: 859 ret = append(ret, *et) 860 case events.Auction: 861 ret = append(ret, et) 862 } 863 } 864 return ret 865 } 866 867 func (b *BrokerStub) GetMarginByPartyAndMarket(partyID, marketID string) (vegapb.MarginLevels, error) { 868 batch := b.GetBatch(events.MarginLevelsEvent) 869 mapped := map[string]map[string]vegapb.MarginLevels{} 870 for _, e := range batch { 871 switch et := e.(type) { 872 case *events.MarginLevels: 873 ml := et.MarginLevels() 874 if _, ok := mapped[ml.PartyId]; !ok { 875 mapped[ml.PartyId] = map[string]vegapb.MarginLevels{} 876 } 877 mapped[ml.PartyId][ml.MarketId] = ml 878 case events.MarginLevels: 879 ml := et.MarginLevels() 880 if _, ok := mapped[ml.PartyId]; !ok { 881 mapped[ml.PartyId] = map[string]vegapb.MarginLevels{} 882 } 883 mapped[ml.PartyId][ml.MarketId] = ml 884 } 885 } 886 mkts, ok := mapped[partyID] 887 if !ok { 888 return vegapb.MarginLevels{}, fmt.Errorf("no margin levels for party (%v)", partyID) 889 } 890 ml, ok := mkts[marketID] 891 if !ok { 892 return vegapb.MarginLevels{}, fmt.Errorf("party (%v) have no margin levels for market (%v)", partyID, marketID) 893 } 894 return ml, nil 895 } 896 897 func (b *BrokerStub) GetMarketInsurancePoolAccount(market string) (vegapb.Account, error) { 898 batch := b.GetAccountEvents() 899 for _, e := range batch { 900 v := e.Account() 901 if v.Owner == "*" && v.MarketId == market && v.Type == vegapb.AccountType_ACCOUNT_TYPE_INSURANCE { 902 return v, nil 903 } 904 } 905 return vegapb.Account{}, errors.New("account does not exist") 906 } 907 908 func (b *BrokerStub) GetStakingRewardAccount(asset string) (vegapb.Account, error) { 909 batch := b.GetAccountEvents() 910 for _, e := range batch { 911 v := e.Account() 912 if v.Owner == "*" && v.Asset == asset && v.Type == vegapb.AccountType_ACCOUNT_TYPE_GLOBAL_REWARD { 913 return v, nil 914 } 915 } 916 return vegapb.Account{}, errors.New("account does not exist") 917 } 918 919 func (b *BrokerStub) GetAssetNetworkTreasuryAccount(asset string) (vegapb.Account, error) { 920 batch := b.GetAccountEvents() 921 for _, e := range batch { 922 v := e.Account() 923 if v.Owner == "*" && v.Asset == asset && v.Type == vegapb.AccountType_ACCOUNT_TYPE_NETWORK_TREASURY { 924 return v, nil 925 } 926 } 927 return vegapb.Account{}, errors.New("account does not exist") 928 } 929 930 func (b *BrokerStub) GetAssetBuyBackFeesAccount(asset string) (vegapb.Account, error) { 931 batch := b.GetAccountEvents() 932 for _, e := range batch { 933 v := e.Account() 934 if v.Owner == "*" && v.Asset == asset && v.Type == vegapb.AccountType_ACCOUNT_TYPE_BUY_BACK_FEES { 935 return v, nil 936 } 937 } 938 return vegapb.Account{}, errors.New("account does not exist") 939 } 940 941 func (b *BrokerStub) GetMarketLPLiquidityFeePoolAccount(party, market string) (vegapb.Account, error) { 942 batch := b.GetAccountEvents() 943 for _, e := range batch { 944 v := e.Account() 945 if v.Owner == party && v.MarketId == market && v.Type == vegapb.AccountType_ACCOUNT_TYPE_LP_LIQUIDITY_FEES { 946 return v, nil 947 } 948 } 949 return vegapb.Account{}, errors.New("account does not exist") 950 } 951 952 func (b *BrokerStub) GetAssetGlobalInsuranceAccount(asset string) (vegapb.Account, error) { 953 batch := b.GetAccountEvents() 954 for _, e := range batch { 955 v := e.Account() 956 if v.Owner == "*" && v.Asset == asset && v.Type == vegapb.AccountType_ACCOUNT_TYPE_GLOBAL_INSURANCE { 957 return v, nil 958 } 959 } 960 return vegapb.Account{}, errors.New("account does not exist") 961 } 962 963 func (b *BrokerStub) GetMarketLPLiquidityBondAccount(party, market string) (vegapb.Account, error) { 964 batch := b.GetAccountEvents() 965 for _, e := range batch { 966 v := e.Account() 967 if v.Owner == party && v.MarketId == market && v.Type == vegapb.AccountType_ACCOUNT_TYPE_BOND { 968 return v, nil 969 } 970 } 971 return vegapb.Account{}, errors.New("account does not exist") 972 } 973 974 func (b *BrokerStub) GetMarketLiquidityFeePoolAccount(market string) (vegapb.Account, error) { 975 batch := b.GetAccountEvents() 976 for _, e := range batch { 977 v := e.Account() 978 if v.Owner == "*" && v.MarketId == market && v.Type == vegapb.AccountType_ACCOUNT_TYPE_FEES_LIQUIDITY { 979 return v, nil 980 } 981 } 982 return vegapb.Account{}, errors.New("account does not exist") 983 } 984 985 func (b *BrokerStub) GetMarketInfrastructureFeePoolAccount(asset string) (vegapb.Account, error) { 986 batch := b.GetAccountEvents() 987 for _, e := range batch { 988 v := e.Account() 989 if v.Owner == "*" && v.Asset == asset && v.Type == vegapb.AccountType_ACCOUNT_TYPE_FEES_INFRASTRUCTURE { 990 return v, nil 991 } 992 } 993 return vegapb.Account{}, errors.New("account does not exist") 994 } 995 996 func (b *BrokerStub) GetPartyOrderMarginAccount(party, market string) (vegapb.Account, error) { 997 batch := b.GetAccountEvents() 998 for _, e := range batch { 999 v := e.Account() 1000 if v.Owner == party && v.Type == vegapb.AccountType_ACCOUNT_TYPE_ORDER_MARGIN && v.MarketId == market { 1001 return v, nil 1002 } 1003 } 1004 return vegapb.Account{}, errors.New("account does not exist") 1005 } 1006 1007 func (b *BrokerStub) GetPartyMarginAccount(party, market string) (vegapb.Account, error) { 1008 batch := b.GetAccountEvents() 1009 for _, e := range batch { 1010 v := e.Account() 1011 if v.Owner == party && v.Type == vegapb.AccountType_ACCOUNT_TYPE_MARGIN && v.MarketId == market { 1012 return v, nil 1013 } 1014 } 1015 return vegapb.Account{}, errors.New("account does not exist") 1016 } 1017 1018 func (b *BrokerStub) GetMarketSettlementAccount(market string) (vegapb.Account, error) { 1019 batch := b.GetAccountEvents() 1020 for _, e := range batch { 1021 v := e.Account() 1022 if v.Owner == "*" && v.MarketId == market && v.Type == vegapb.AccountType_ACCOUNT_TYPE_SETTLEMENT { 1023 return v, nil 1024 } 1025 } 1026 return vegapb.Account{}, errors.New("account does not exist") 1027 } 1028 1029 // GetPartyGeneralAccount returns the latest event WRT the party's general account. 1030 func (b *BrokerStub) GetPartyGeneralAccount(party, asset string) (ga vegapb.Account, err error) { 1031 batch := b.GetAccountEvents() 1032 foundOne := false 1033 for _, e := range batch { 1034 v := e.Account() 1035 if v.Owner == party && v.Type == vegapb.AccountType_ACCOUNT_TYPE_GENERAL && v.Asset == asset { 1036 ga = v 1037 foundOne = true 1038 } 1039 } 1040 if !foundOne { 1041 ga = vegapb.Account{} 1042 err = errors.New("account does not exist") 1043 } 1044 return 1045 } 1046 1047 // GetPartyVestingAccount returns the latest event WRT the party's general account. 1048 func (b *BrokerStub) GetPartyVestingAccount(party, asset string) (ga vegapb.Account, err error) { 1049 batch := b.GetAccountEvents() 1050 err = AccountDoesNotExistErr 1051 for _, e := range batch { 1052 v := e.Account() 1053 if v.Owner == party && v.Type == vegapb.AccountType_ACCOUNT_TYPE_VESTING_REWARDS && v.Asset == asset { 1054 ga = v 1055 err = nil 1056 } 1057 } 1058 return 1059 } 1060 1061 // GetPartyVestingAccount returns the latest event WRT the party's general account. 1062 func (b *BrokerStub) GetPartyVestedAccount(party, asset string) (ga vegapb.Account, err error) { 1063 batch := b.GetAccountEvents() 1064 err = AccountDoesNotExistErr 1065 for _, e := range batch { 1066 v := e.Account() 1067 if v.Owner == party && v.Type == vegapb.AccountType_ACCOUNT_TYPE_VESTED_REWARDS && v.Asset == asset { 1068 ga = v 1069 err = nil 1070 } 1071 } 1072 return 1073 } 1074 1075 // GetPartyGeneralAccount returns the latest event WRT the party's general account. 1076 func (b *BrokerStub) GetPartyHoldingAccount(party, asset string) (ga vegapb.Account, err error) { 1077 batch := b.GetAccountEvents() 1078 err = errors.New("account does not exist") 1079 for _, e := range batch { 1080 v := e.Account() 1081 if v.Owner == party && v.Type == vegapb.AccountType_ACCOUNT_TYPE_HOLDING && v.Asset == asset { 1082 ga = v 1083 err = nil 1084 } 1085 } 1086 1087 return 1088 } 1089 1090 // GetRewardAccountBalance returns the latest event WRT the reward accounts with the given type for the asset. 1091 func (b *BrokerStub) GetRewardAccountBalance(accountType, asset string) (ga vegapb.Account, err error) { 1092 batch := b.GetAccountEvents() 1093 at := vegapb.AccountType(proto.AccountType_value[accountType]) 1094 err = errors.New("account does not exist") 1095 for _, e := range batch { 1096 v := e.Account() 1097 if v.Owner == "*" && v.Type == at && v.Asset == asset { 1098 ga = v 1099 err = nil 1100 } 1101 } 1102 1103 return 1104 } 1105 1106 func (b *BrokerStub) ReferralSetStats() []*types.ReferralSetStats { 1107 batch := b.GetBatch(events.ReferralSetStatsUpdatedEvent) 1108 1109 stats := make([]*types.ReferralSetStats, 0, len(batch)) 1110 for _, event := range batch { 1111 switch et := event.(type) { 1112 case *events.ReferralSetStatsUpdated: 1113 stats = append(stats, et.Unwrap()) 1114 case events.ReferralSetStatsUpdated: 1115 stats = append(stats, et.Unwrap()) 1116 } 1117 } 1118 return stats 1119 } 1120 1121 func (b *BrokerStub) VestingStats() []eventspb.VestingStatsUpdated { 1122 batch := b.GetBatch(events.VestingStatsUpdatedEvent) 1123 1124 stats := make([]eventspb.VestingStatsUpdated, 0, len(batch)) 1125 for _, event := range batch { 1126 switch et := event.(type) { 1127 case *events.VestingStatsUpdated: 1128 stats = append(stats, et.Proto()) 1129 case events.VestingStatsUpdated: 1130 stats = append(stats, et.Proto()) 1131 } 1132 } 1133 return stats 1134 } 1135 1136 func (b *BrokerStub) VolumeDiscountStats() []eventspb.VolumeDiscountStatsUpdated { 1137 batch := b.GetBatch(events.VolumeDiscountStatsUpdatedEvent) 1138 1139 stats := make([]eventspb.VolumeDiscountStatsUpdated, 0, len(batch)) 1140 for _, event := range batch { 1141 switch et := event.(type) { 1142 case *events.VolumeDiscountStatsUpdated: 1143 stats = append(stats, et.Proto()) 1144 case events.VolumeDiscountStatsUpdated: 1145 stats = append(stats, et.Proto()) 1146 } 1147 } 1148 return stats 1149 } 1150 1151 func (b *BrokerStub) PartyActivityStreaks() []eventspb.PartyActivityStreak { 1152 batch := b.GetBatch(events.PartyActivityStreakEvent) 1153 1154 stats := make([]eventspb.PartyActivityStreak, 0, len(batch)) 1155 for _, event := range batch { 1156 switch et := event.(type) { 1157 case *events.PartyActivityStreak: 1158 stats = append(stats, et.Proto()) 1159 case events.PartyActivityStreak: 1160 stats = append(stats, et.Proto()) 1161 } 1162 } 1163 return stats 1164 } 1165 1166 func (b *BrokerStub) GetPartyBondAccount(party, asset string) (ba vegapb.Account, err error) { 1167 batch := b.GetAccountEvents() 1168 err = errors.New("account does not exist") 1169 for _, e := range batch { 1170 v := e.Account() 1171 if v.Owner == party && v.Type == vegapb.AccountType_ACCOUNT_TYPE_BOND && v.Asset == asset { 1172 // may not be the latest ballence, so keep iterating 1173 ba = v 1174 err = nil 1175 } 1176 } 1177 return 1178 } 1179 1180 func (b *BrokerStub) GetPartyBondAccountForMarket(party, asset, marketID string) (ba vegapb.Account, err error) { 1181 batch := b.GetAccountEvents() 1182 err = errors.New("account does not exist") 1183 for _, e := range batch { 1184 v := e.Account() 1185 if v.Owner == party && v.Type == vegapb.AccountType_ACCOUNT_TYPE_BOND && v.Asset == asset && v.MarketId == marketID { 1186 // may not be the latest ballence, so keep iterating 1187 ba = v 1188 err = nil 1189 } 1190 } 1191 return 1192 } 1193 1194 func (b *BrokerStub) GetPartyVestingAccountForMarket(party, asset, marketID string) (vegapb.Account, error) { 1195 batch := b.GetAccountEvents() 1196 for _, e := range batch { 1197 v := e.Account() 1198 if v.Owner == party && v.Type == vegapb.AccountType_ACCOUNT_TYPE_VESTING_REWARDS && v.Asset == asset && v.MarketId == marketID { 1199 return v, nil 1200 } 1201 } 1202 return vegapb.Account{}, errors.New("account does not exist") 1203 } 1204 1205 func (b *BrokerStub) GetPartyVestedAccountForMarket(party, asset, marketID string) (vegapb.Account, error) { 1206 batch := b.GetAccountEvents() 1207 for _, e := range batch { 1208 v := e.Account() 1209 if v.Owner == party && v.Type == vegapb.AccountType_ACCOUNT_TYPE_VESTED_REWARDS && v.Asset == asset && v.MarketId == marketID { 1210 return v, nil 1211 } 1212 } 1213 return vegapb.Account{}, errors.New("account does not exist") 1214 } 1215 1216 func (b *BrokerStub) ClearOrderByReference(party, ref string) error { 1217 b.mu.Lock() 1218 data := b.data[events.OrderEvent] 1219 cleared := make([]events.Event, 0, cap(data)) 1220 for _, evt := range data { 1221 var o *vegapb.Order 1222 switch e := evt.(type) { 1223 case *events.Order: 1224 o = e.Order() 1225 case events.Order: 1226 o = e.Order() 1227 default: 1228 return errors.New("non-order event ended up in order event group") 1229 } 1230 if o.Reference != ref || o.PartyId != party { 1231 cleared = append(cleared, evt) 1232 } 1233 } 1234 b.data[events.OrderEvent] = cleared 1235 b.mu.Unlock() 1236 return nil 1237 } 1238 1239 func (b *BrokerStub) GetFirstByReference(party, ref string) (vegapb.Order, error) { 1240 data := b.GetOrderEvents() 1241 for _, o := range data { 1242 v := o.Order() 1243 if v.Reference == ref && v.PartyId == party { 1244 return *v, nil 1245 } 1246 } 1247 return vegapb.Order{}, fmt.Errorf("no order for party %v and reference %v", party, ref) 1248 } 1249 1250 func (b *BrokerStub) GetByReference(party, ref string) (vegapb.Order, error) { 1251 data := b.GetOrderEvents() 1252 1253 var last vegapb.Order // we need the most recent event, the order object is not updated (copy v pointer, issue 2353) 1254 matched := false 1255 for _, o := range data { 1256 v := o.Order() 1257 if v.Reference == ref && v.PartyId == party { 1258 last = *v 1259 matched = true 1260 } 1261 } 1262 if matched { 1263 if b.IsCancelledOrder(last.MarketId, party, last.Id) { 1264 last.Status = vegapb.Order_STATUS_CANCELLED 1265 } 1266 return last, nil 1267 } 1268 return vegapb.Order{}, fmt.Errorf("no order for party %v and reference %v", party, ref) 1269 } 1270 1271 func (b *BrokerStub) IsCancelledOrder(mkt, party, id string) bool { 1272 batch := b.GetImmBatch(events.CancelledOrdersEvent) 1273 if len(batch) == 0 { 1274 return false 1275 } 1276 for _, e := range batch { 1277 switch et := e.(type) { 1278 case *events.CancelledOrders: 1279 if !et.IsMarket(mkt) || !et.IsParty(party) { 1280 continue 1281 } 1282 for _, oid := range et.OrderIDs() { 1283 if oid == id { 1284 return true 1285 } 1286 } 1287 case events.CancelledOrders: 1288 if !et.IsMarket(mkt) || !et.IsParty(party) { 1289 continue 1290 } 1291 for _, oid := range et.OrderIDs() { 1292 if oid == id { 1293 return true 1294 } 1295 } 1296 } 1297 } 1298 return false 1299 } 1300 1301 func (b *BrokerStub) GetStopByReference(party, ref string) (eventspb.StopOrderEvent, error) { 1302 data := b.GetStopOrderEvents() 1303 1304 var last eventspb.StopOrderEvent // we need the most recent event, the order object is not updated (copy v pointer, issue 2353) 1305 matched := false 1306 for _, o := range data { 1307 v := o.StopOrder() 1308 if v.Submission.Reference == ref && v.StopOrder.PartyId == party { 1309 last = *v 1310 matched = true 1311 } 1312 } 1313 if matched { 1314 return last, nil 1315 } 1316 return eventspb.StopOrderEvent{}, fmt.Errorf("no order for party %v and reference %v", party, ref) 1317 } 1318 1319 func (b *BrokerStub) GetTxErrors() []events.TxErr { 1320 batch := b.GetBatch(events.TxErrEvent) 1321 if len(batch) == 0 { 1322 return nil 1323 } 1324 ret := make([]events.TxErr, 0, len(batch)) 1325 for _, e := range batch { 1326 switch te := e.(type) { 1327 case *events.TxErr: 1328 ret = append(ret, *te) 1329 case events.TxErr: 1330 ret = append(ret, te) 1331 } 1332 } 1333 return ret 1334 } 1335 1336 func (b *BrokerStub) GetLPSErrors() []events.TxErr { 1337 errs := b.GetTxErrors() 1338 if len(errs) == 0 { 1339 return nil 1340 } 1341 ret := make([]events.TxErr, 0, len(errs)/2) 1342 for _, e := range errs { 1343 if p := e.Proto(); p.GetLiquidityProvisionSubmission() != nil { 1344 ret = append(ret, e) 1345 } 1346 } 1347 return ret 1348 } 1349 1350 func (b *BrokerStub) GetTrades() []vegapb.Trade { 1351 data := b.GetTradeEvents() 1352 trades := make([]vegapb.Trade, 0, len(data)) 1353 for _, t := range data { 1354 trades = append(trades, t.Trade()) 1355 } 1356 return trades 1357 } 1358 1359 // AMM events concentrated here 1360 1361 func (b *BrokerStub) GetAMMPoolEvents() []*events.AMMPool { 1362 data := b.GetImmBatch(events.AMMPoolEvent) 1363 ret := make([]*events.AMMPool, 0, len(data)) 1364 for _, e := range data { 1365 switch et := e.(type) { 1366 case events.AMMPool: 1367 ret = append(ret, ptr.From(et)) 1368 case *events.AMMPool: 1369 ret = append(ret, et) 1370 } 1371 } 1372 return ret 1373 } 1374 1375 func (b *BrokerStub) GetAMMPoolEventsByParty(party string) []*events.AMMPool { 1376 evts := b.GetAMMPoolEvents() 1377 ret := make([]*events.AMMPool, 0, 5) // we expect to get more than 1 1378 for _, e := range evts { 1379 if e.IsParty(party) { 1380 ret = append(ret, e) 1381 } 1382 } 1383 return ret 1384 } 1385 1386 func (b *BrokerStub) GetAMMPoolEventsByMarket(id string) []*events.AMMPool { 1387 evts := b.GetAMMPoolEvents() 1388 ret := make([]*events.AMMPool, 0, 10) 1389 for _, e := range evts { 1390 if e.MarketID() == id { 1391 ret = append(ret, e) 1392 } 1393 } 1394 return ret 1395 } 1396 1397 func (b *BrokerStub) GetAMMPoolEventsByPartyAndMarket(party, mID string) []*events.AMMPool { 1398 evts := b.GetAMMPoolEvents() 1399 ret := make([]*events.AMMPool, 0, 5) 1400 for _, e := range evts { 1401 if e.IsParty(party) && e.MarketID() == mID { 1402 ret = append(ret, e) 1403 } 1404 } 1405 return ret 1406 } 1407 1408 func (b *BrokerStub) GetLastAMMPoolEvents() map[string]map[string]*events.AMMPool { 1409 ret := map[string]map[string]*events.AMMPool{} 1410 evts := b.GetAMMPoolEvents() 1411 for _, e := range evts { 1412 mID := e.MarketID() 1413 mmap, ok := ret[mID] 1414 if !ok { 1415 mmap = map[string]*events.AMMPool{} 1416 } 1417 mmap[e.PartyID()] = e 1418 ret[mID] = mmap 1419 } 1420 return ret 1421 } 1422 1423 func (b *BrokerStub) GetAMMPoolEventMap() map[string]map[string][]*events.AMMPool { 1424 ret := map[string]map[string][]*events.AMMPool{} 1425 evts := b.GetAMMPoolEvents() 1426 for _, e := range evts { 1427 mID := e.MarketID() 1428 mmap, ok := ret[mID] 1429 if !ok { 1430 mmap = map[string][]*events.AMMPool{} 1431 } 1432 pID := e.PartyID() 1433 ps, ok := mmap[pID] 1434 if !ok { 1435 ps = []*events.AMMPool{} 1436 } 1437 mmap[pID] = append(ps, e) 1438 ret[mID] = mmap 1439 } 1440 return ret 1441 } 1442 1443 func (b *BrokerStub) ResetType(t events.Type) { 1444 b.mu.Lock() 1445 b.data[t] = []events.Event{} 1446 b.mu.Unlock() 1447 } 1448 1449 func (b *BrokerStub) filterTxErr(predicate func(errProto eventspb.TxErrorEvent) bool) []events.TxErr { 1450 batch := b.GetBatch(events.TxErrEvent) 1451 if len(batch) == 0 { 1452 return nil 1453 } 1454 1455 errs := []events.TxErr{} 1456 b.mu.Lock() 1457 for _, e := range batch { 1458 err := derefTxErr(e) 1459 errProto := err.Proto() 1460 if predicate(errProto) { 1461 errs = append(errs, err) 1462 } 1463 } 1464 b.mu.Unlock() 1465 return errs 1466 } 1467 1468 func (b *BrokerStub) Reset() { 1469 b.mu.Lock() 1470 b.data = map[events.Type][]events.Event{} 1471 b.mu.Unlock() 1472 } 1473 1474 func derefTxErr(e events.Event) events.TxErr { 1475 var dub events.TxErr 1476 switch et := e.(type) { 1477 case *events.TxErr: 1478 dub = *et 1479 case events.TxErr: 1480 dub = et 1481 } 1482 return dub 1483 } 1484 1485 func (b *BrokerStub) SubscribeBatch(subs ...broker.Subscriber) {} 1486 1487 func (b *BrokerStub) Unsubscribe(k int) {}