-
Notifications
You must be signed in to change notification settings - Fork 0
/
memclob_cancels.go
125 lines (110 loc) · 3.79 KB
/
memclob_cancels.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package memclob
import (
"fmt"
"github.com/jinxprotocol/v4-chain/protocol/x/clob/types"
)
// memclobCancels is a utility struct used for storing order cancelations that each expire at a given block height.
type memclobCancels struct {
// A map of all known canceled order IDs mapped to their expiry block.
orderIdToExpiry map[types.OrderId]uint32
// A map from a block height to a set of all canceled order IDs that expire at the block.
expiryToOrderIds map[uint32]map[types.OrderId]bool
}
// newMemclobCancels returns a new `memclobCancels`.
func newMemclobCancels() *memclobCancels {
return &memclobCancels{
orderIdToExpiry: make(map[types.OrderId]uint32),
expiryToOrderIds: make(map[uint32]map[types.OrderId]bool),
}
}
// get returns the `tilBlock` expiry of an order cancelation and a bool indicating whether the expiry exists.
func (c *memclobCancels) get(
orderId types.OrderId,
) (
tilBlock uint32,
exists bool,
) {
tilBlock, exists = c.orderIdToExpiry[orderId]
return tilBlock, exists
}
// addShortTermCancel adds an `orderId` to all data structures, expiring at block `tilBlock`.
// Panics if the `orderId` already exists in the data structures.
func (c *memclobCancels) addShortTermCancel(
orderId types.OrderId,
tilBlock uint32,
) {
orderId.MustBeShortTermOrder()
// Add the `orderId` to the `orderIdToExpiry` map, panicing if it already exists.
if _, exists := c.orderIdToExpiry[orderId]; exists {
panic(fmt.Sprintf(
"mustAddCancel: orderId %+v already exists in orderIdToExpiry",
orderId,
))
}
c.orderIdToExpiry[orderId] = tilBlock
// Fetch a reference to the `expiryToOrderIds` for this `tilBlock`, creating it if it does not already exist.
orderIdsInBlock, exists := c.expiryToOrderIds[tilBlock]
if !exists {
orderIdsInBlock = make(map[types.OrderId]bool)
c.expiryToOrderIds[tilBlock] = orderIdsInBlock
} else if _, exists = orderIdsInBlock[orderId]; exists {
panic(fmt.Sprintf(
"memclobCancels#add: orderId %+v already exists in expiryToOrderIds[%d]",
orderId,
tilBlock,
))
}
// Set the `OrderId` in the `expiryToOrderIds` data structure for the new cancel's `tilBlock`.
orderIdsInBlock[orderId] = true
}
// remove removes an `orderId` from all data structs. Panics if the `orderId` is not found.
func (c *memclobCancels) remove(
orderId types.OrderId,
) {
// Panic if the `orderId` does not exist in the `orderIdToExpiry` map.
goodTilBlock, exists := c.orderIdToExpiry[orderId]
if !exists {
panic(fmt.Sprintf(
"memclobCancels#remove: orderId %+v does not exist in orderIdToExpiry",
orderId,
))
}
// Panic if the `orderId` does not exist in the appropriate submap of `expiryToOrderIds`.
expiryToOrderIdsForBlock, exists := c.expiryToOrderIds[goodTilBlock]
if !exists {
panic(fmt.Sprintf(
"memclobCancels#remove: %d does not exist in expiryToOrderIds",
goodTilBlock,
))
}
if _, exists = expiryToOrderIdsForBlock[orderId]; !exists {
panic(fmt.Sprintf(
"memclobCancels#remove: orderId %+v does not exist in expiryToOrderIds[%d]",
orderId,
goodTilBlock,
))
}
// Delete the `orderId` from the `orderIdToExpiry` map.
delete(c.orderIdToExpiry, orderId)
// Delete the `orderId` from the `expiryToOrderIds` submap.
// If this is the last order in the submap, delete the submap.
if len(expiryToOrderIdsForBlock) == 1 {
delete(c.expiryToOrderIds, goodTilBlock)
} else {
delete(expiryToOrderIdsForBlock, orderId)
}
}
// removeAllAtBlock iterates through (and removes from all data structures) the IDs that expire at a certain `block`.
func (c *memclobCancels) removeAllAtBlock(
block uint32,
) {
orderIds, exists := c.expiryToOrderIds[block]
// If map entry does not exist, return early.
if !exists {
return
}
// Remove all ids. This also removes `block` from the `expiryToOrderIds` map.
for id := range orderIds {
c.remove(id)
}
}