code.vegaprotocol.io/vega@v0.79.0/core/events/auction.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 events 17 18 import ( 19 "context" 20 "fmt" 21 "time" 22 23 types "code.vegaprotocol.io/vega/protos/vega" 24 eventspb "code.vegaprotocol.io/vega/protos/vega/events/v1" 25 ) 26 27 type Auction struct { 28 *Base 29 // marketID for the market creating the auction event 30 marketID string 31 // start time in nanoseconds since 1/1/1970 of the current/last auction 32 auctionStart int64 33 // stop time in nanoseconds since 1/1/1970 of the current/last auction 34 auctionStop int64 35 // is/was this an opening auction 36 openingAuction bool 37 // are we leaving the auction (=true) or entering an auction (=false) 38 leave bool 39 // what precisely triggered the auction 40 trigger types.AuctionTrigger 41 // what component extended the ongoing auction (if any) 42 extension types.AuctionTrigger 43 } 44 45 // NewAuctionEvent creates a new auction event object. 46 func NewAuctionEvent(ctx context.Context, marketID string, leave bool, start, stop int64, triggers ...types.AuctionTrigger) *Auction { 47 if len(triggers) == 0 { 48 return nil 49 } 50 trigger := triggers[0] 51 opening := trigger == types.AuctionTrigger_AUCTION_TRIGGER_OPENING 52 e := &Auction{ 53 Base: newBase(ctx, AuctionEvent), 54 marketID: marketID, 55 auctionStart: start, 56 auctionStop: stop, 57 openingAuction: opening, 58 leave: leave, 59 trigger: trigger, 60 } 61 if len(triggers) == 2 { 62 e.extension = triggers[1] 63 } 64 65 return e 66 } 67 68 func (a Auction) MarketID() string { 69 return a.marketID 70 } 71 72 // Auction returns the action performed (either true=leave auction, or false=entering auction). 73 func (a Auction) Auction() bool { 74 return a.leave 75 } 76 77 // MarketEvent - implement market event interface so we can log this event. 78 func (a Auction) MarketEvent() string { 79 // is in auction 80 start := time.Unix(0, a.auctionStart).Format(time.RFC3339Nano) 81 if a.extension != types.AuctionTrigger_AUCTION_TRIGGER_UNSPECIFIED { 82 return fmt.Sprintf("Market %s in auction mode (%s) started at %s (extension reason: %s)", a.marketID, a.trigger, start, a.extension) 83 } 84 stopT := time.Unix(0, a.auctionStop) 85 if a.leave { 86 if a.auctionStop == 0 { 87 stopT = time.Now() 88 } 89 stop := stopT.Format(time.RFC3339Nano) 90 if a.openingAuction { 91 return fmt.Sprintf("Market %s left opening auction started at %s at %s (trigger: %s)", a.marketID, start, stop, a.trigger) 92 } 93 94 return fmt.Sprintf("Market %s left auction started at %s at %s (trigger: %s)", a.marketID, start, stop, a.trigger) 95 } 96 if a.openingAuction { 97 // an opening auction will always have a STOP time 98 stop := stopT.Format(time.RFC3339Nano) 99 100 return fmt.Sprintf("Market %s entered opening auction at %s, will close at %s (trigger: %s)", a.marketID, start, stop, a.trigger) 101 } 102 if a.auctionStop == 0 { 103 return fmt.Sprintf("Market %s entered auction mode at %s (trigger: %s)", a.marketID, start, a.trigger) 104 } 105 106 return fmt.Sprintf("Market %s entered auction mode at %s, auction closes at %s (trigger: %s)", a.marketID, start, stopT.Format(time.RFC3339Nano), a.trigger) 107 } 108 109 // Proto wrap event data in a proto message. 110 func (a Auction) Proto() eventspb.AuctionEvent { 111 return eventspb.AuctionEvent{ 112 MarketId: a.marketID, 113 OpeningAuction: a.openingAuction, 114 Leave: a.leave, 115 Start: a.auctionStart, 116 End: a.auctionStop, 117 Trigger: a.trigger, 118 ExtensionTrigger: a.extension, 119 } 120 } 121 122 // StreamMessage returns the BusEvent message for the event stream API. 123 func (a Auction) StreamMessage() *eventspb.BusEvent { 124 p := a.Proto() 125 126 busEvent := newBusEventFromBase(a.Base) 127 busEvent.Event = &eventspb.BusEvent_Auction{ 128 Auction: &p, 129 } 130 131 return busEvent 132 } 133 134 // StreamMarketMessage - allows for this event to be streamed as just a market event 135 // containing just market ID and a string akin to a log message. 136 func (a Auction) StreamMarketMessage() *eventspb.BusEvent { 137 busEvent := newBusEventFromBase(a.Base) 138 busEvent.Type = eventspb.BusEventType_BUS_EVENT_TYPE_MARKET 139 busEvent.Event = &eventspb.BusEvent_Market{ 140 Market: &eventspb.MarketEvent{ 141 MarketId: a.marketID, 142 Payload: a.MarketEvent(), 143 }, 144 } 145 146 return busEvent 147 } 148 149 func AuctionEventFromStream(ctx context.Context, be *eventspb.BusEvent) *Auction { 150 e := &Auction{ 151 Base: newBaseFromBusEvent(ctx, AuctionEvent, be), 152 marketID: be.GetAuction().MarketId, 153 auctionStart: be.GetAuction().Start, 154 auctionStop: be.GetAuction().End, 155 openingAuction: be.GetAuction().OpeningAuction, 156 leave: be.GetAuction().Leave, 157 trigger: be.GetAuction().Trigger, 158 extension: be.GetAuction().ExtensionTrigger, 159 } 160 161 return e 162 }