code.vegaprotocol.io/vega@v0.79.0/datanode/entities/order.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 entities 17 18 import ( 19 "encoding/hex" 20 "encoding/json" 21 "fmt" 22 "math" 23 "time" 24 25 "code.vegaprotocol.io/vega/core/types" 26 "code.vegaprotocol.io/vega/libs/ptr" 27 v2 "code.vegaprotocol.io/vega/protos/data-node/api/v2" 28 "code.vegaprotocol.io/vega/protos/vega" 29 30 "github.com/shopspring/decimal" 31 ) 32 33 type _Order struct{} 34 35 type OrderID = ID[_Order] 36 37 type Order struct { 38 ID OrderID 39 MarketID MarketID 40 PartyID PartyID 41 Side Side 42 Price decimal.Decimal 43 Size int64 44 Remaining int64 45 TimeInForce OrderTimeInForce 46 Type OrderType 47 Status OrderStatus 48 Reference string 49 Reason OrderError 50 Version int32 51 PeggedOffset decimal.Decimal 52 BatchID int32 53 PeggedReference PeggedReference 54 LpID []byte 55 CreatedAt time.Time 56 UpdatedAt time.Time 57 ExpiresAt time.Time 58 TxHash TxHash 59 VegaTime time.Time 60 SeqNum uint64 61 PostOnly bool 62 ReduceOnly bool 63 64 // Iceberg fields 65 ReservedRemaining *int64 66 PeakSize *int64 67 MinimumVisibleSize *int64 68 } 69 70 func (o Order) ToProto() *vega.Order { 71 var peggedOrder *vega.PeggedOrder 72 if o.PeggedReference != types.PeggedReferenceUnspecified { 73 peggedOrder = &vega.PeggedOrder{ 74 Reference: o.PeggedReference, 75 Offset: o.PeggedOffset.String(), 76 } 77 } 78 79 var reason *OrderError 80 if o.Reason != OrderErrorUnspecified { 81 reason = ptr.From(o.Reason) 82 } 83 84 var icebergOrder *vega.IcebergOrder 85 if o.PeakSize != nil { 86 icebergOrder = &vega.IcebergOrder{ 87 ReservedRemaining: uint64(*o.ReservedRemaining), 88 PeakSize: uint64(*o.PeakSize), 89 MinimumVisibleSize: uint64(*o.MinimumVisibleSize), 90 } 91 } 92 93 vo := vega.Order{ 94 Id: o.ID.String(), 95 MarketId: o.MarketID.String(), 96 PartyId: o.PartyID.String(), 97 Side: o.Side, 98 Price: o.Price.String(), 99 Size: uint64(o.Size), 100 Remaining: uint64(o.Remaining), 101 TimeInForce: o.TimeInForce, 102 Type: o.Type, 103 CreatedAt: o.CreatedAt.UnixNano(), 104 Status: o.Status, 105 ExpiresAt: o.ExpiresAt.UnixNano(), 106 Reference: o.Reference, 107 Reason: reason, 108 UpdatedAt: o.UpdatedAt.UnixNano(), 109 Version: uint64(o.Version), 110 BatchId: uint64(o.BatchID), 111 PeggedOrder: peggedOrder, 112 LiquidityProvisionId: hex.EncodeToString(o.LpID), 113 PostOnly: o.PostOnly, 114 ReduceOnly: o.ReduceOnly, 115 IcebergOrder: icebergOrder, 116 } 117 return &vo 118 } 119 120 func (o Order) ToProtoEdge(_ ...any) (*v2.OrderEdge, error) { 121 return &v2.OrderEdge{ 122 Node: o.ToProto(), 123 Cursor: o.Cursor().Encode(), 124 }, nil 125 } 126 127 func OrderFromProto(po *vega.Order, seqNum uint64, txHash TxHash) (Order, error) { 128 price, err := decimal.NewFromString(po.Price) 129 if err != nil { 130 return Order{}, fmt.Errorf("price is not a valid integer: %v", po.Price) 131 } 132 133 if po.Size > math.MaxInt64 { 134 return Order{}, fmt.Errorf("size is larger than a 64-bit integer: %v", po.Size) 135 } 136 size := int64(po.Size) 137 138 if po.Remaining > math.MaxInt64 { 139 return Order{}, fmt.Errorf("remaining is larger than a 64-bit integer: %v", po.Remaining) 140 } 141 remaining := int64(po.Remaining) 142 143 if po.Version >= math.MaxInt32 { 144 return Order{}, fmt.Errorf("version is larger than a 32-bit integer: %v", po.Version) 145 } 146 version := int32(po.Version) 147 148 if po.BatchId >= math.MaxInt32 { 149 return Order{}, fmt.Errorf("batch ID is larger than a 32-bit integer: %v", po.Version) 150 } 151 batchID := int32(po.BatchId) 152 153 lpID, err := hex.DecodeString(po.LiquidityProvisionId) 154 if err != nil { 155 return Order{}, fmt.Errorf("liquidity Provision ID is not a valid hex string: %v", po.LiquidityProvisionId) 156 } 157 158 peggedOffset := decimal.Zero 159 var peggedReference types.PeggedReference 160 if po.PeggedOrder != nil { 161 peggedOffset, err = decimal.NewFromString(po.PeggedOrder.Offset) 162 if err != nil { 163 return Order{}, fmt.Errorf("pegged Offset not a valid decimal: %v", po.Price) 164 } 165 peggedReference = po.PeggedOrder.Reference 166 } 167 168 reason := OrderErrorUnspecified 169 if po.Reason != nil { 170 reason = *po.Reason 171 } 172 173 var PeakSize, MinimumVisibleSize, reservedRemaining *int64 174 if po.IcebergOrder != nil { 175 if po.IcebergOrder.ReservedRemaining > math.MaxInt64 { 176 return Order{}, fmt.Errorf("iceberg reserved remaining is larger than a 64-bit integer: %v", po.Remaining) 177 } 178 reservedRemaining = ptr.From(int64(po.IcebergOrder.ReservedRemaining)) 179 180 if po.IcebergOrder.PeakSize > math.MaxInt64 { 181 return Order{}, fmt.Errorf("iceberg peak size is larger than a 64-bit integer: %v", po.Remaining) 182 } 183 PeakSize = ptr.From(int64(po.IcebergOrder.PeakSize)) 184 185 if po.IcebergOrder.MinimumVisibleSize > math.MaxInt64 { 186 return Order{}, fmt.Errorf("iceberg minimum visible size is larger than a 64-bit integer: %v", po.Remaining) 187 } 188 MinimumVisibleSize = ptr.From(int64(po.IcebergOrder.MinimumVisibleSize)) 189 } 190 191 o := Order{ 192 ID: OrderID(po.Id), 193 MarketID: MarketID(po.MarketId), 194 PartyID: PartyID(po.PartyId), 195 Side: po.Side, 196 Price: price, 197 Size: size, 198 Remaining: remaining, 199 TimeInForce: po.TimeInForce, 200 Type: po.Type, 201 Status: po.Status, 202 Reference: po.Reference, 203 Reason: reason, 204 Version: version, 205 PeggedOffset: peggedOffset, 206 BatchID: batchID, 207 PeggedReference: peggedReference, 208 LpID: lpID, 209 CreatedAt: NanosToPostgresTimestamp(po.CreatedAt), 210 UpdatedAt: NanosToPostgresTimestamp(po.UpdatedAt), 211 ExpiresAt: NanosToPostgresTimestamp(po.ExpiresAt), 212 SeqNum: seqNum, 213 TxHash: txHash, 214 PostOnly: po.PostOnly, 215 ReduceOnly: po.ReduceOnly, 216 ReservedRemaining: reservedRemaining, 217 PeakSize: PeakSize, 218 MinimumVisibleSize: MinimumVisibleSize, 219 } 220 221 return o, nil 222 } 223 224 type OrderKey struct { 225 ID OrderID 226 Version int32 227 VegaTime time.Time 228 } 229 230 func (o Order) Key() OrderKey { 231 return OrderKey{o.ID, o.Version, o.VegaTime} 232 } 233 234 func (o Order) ToRow() []interface{} { 235 return []interface{}{ 236 o.ID, o.MarketID, o.PartyID, o.Side, o.Price, 237 o.Size, o.Remaining, o.TimeInForce, o.Type, o.Status, 238 o.Reference, o.Reason, o.Version, o.PeggedOffset, o.BatchID, 239 o.PeggedReference, o.LpID, o.CreatedAt, o.UpdatedAt, o.ExpiresAt, 240 o.TxHash, o.VegaTime, o.SeqNum, o.PostOnly, o.ReduceOnly, o.ReservedRemaining, 241 o.PeakSize, o.MinimumVisibleSize, 242 } 243 } 244 245 var OrderColumns = []string{ 246 "id", "market_id", "party_id", "side", "price", 247 "size", "remaining", "time_in_force", "type", "status", 248 "reference", "reason", "version", "pegged_offset", "batch_id", 249 "pegged_reference", "lp_id", "created_at", "updated_at", "expires_at", 250 "tx_hash", "vega_time", "seq_num", "post_only", "reduce_only", "reserved_remaining", 251 "peak_size", "minimum_visible_size", 252 } 253 254 type OrderCursor struct { 255 CreatedAt time.Time `json:"createdAt"` 256 ID OrderID `json:"id"` 257 VegaTime time.Time `json:"vegaTime"` 258 } 259 260 func (oc *OrderCursor) Parse(cursorString string) error { 261 if cursorString == "" { 262 return nil 263 } 264 return json.Unmarshal([]byte(cursorString), oc) 265 } 266 267 func (oc OrderCursor) String() string { 268 bs, err := json.Marshal(oc) 269 if err != nil { 270 // This should never happen. 271 panic(fmt.Errorf("could not marshal order cursor: %w", err)) 272 } 273 return string(bs) 274 } 275 276 func (o Order) Cursor() *Cursor { 277 cursor := OrderCursor{ 278 CreatedAt: o.CreatedAt, 279 ID: o.ID, 280 VegaTime: o.VegaTime, 281 } 282 283 return NewCursor(cursor.String()) 284 }