github.com/InjectiveLabs/sdk-go@v1.53.0/chain/exchange/types/orderbook.go (about) 1 package types 2 3 import ( 4 "os" 5 "sort" 6 "strings" 7 8 "cosmossdk.io/math" 9 "github.com/ethereum/go-ethereum/common" 10 "github.com/olekukonko/tablewriter" 11 ) 12 13 func NewOrderbook(marketID common.Hash) *Orderbook { 14 return &Orderbook{ 15 MarketId: marketID.Bytes(), 16 BuyLevels: make([]*Level, 0), 17 SellLevels: make([]*Level, 0), 18 } 19 } 20 21 func NewOrderbookWithLevels(marketID common.Hash, buyLevels, sellLevels []*Level) *Orderbook { 22 return &Orderbook{ 23 MarketId: marketID.Bytes(), 24 BuyLevels: buyLevels, 25 SellLevels: sellLevels, 26 } 27 } 28 29 func (o *Orderbook) AppendLevel(isBuy bool, level *Level) { 30 if isBuy { 31 o.BuyLevels = append(o.BuyLevels, level) 32 return 33 } 34 o.SellLevels = append(o.SellLevels, level) 35 } 36 37 func (o *Orderbook) IsCrossed() bool { 38 if len(o.BuyLevels) == 0 || len(o.SellLevels) == 0 { 39 return false 40 } 41 42 highestBuyLevel := o.BuyLevels[len(o.BuyLevels)-1] 43 44 if highestBuyLevel.Q.IsZero() { 45 return false 46 } 47 48 lowestSellPrice := math.LegacyZeroDec() 49 50 isQuantityAllZero := true 51 52 for _, level := range o.SellLevels { 53 if level.Q.IsZero() { 54 continue 55 } 56 lowestSellPrice = level.P 57 isQuantityAllZero = false 58 break 59 } 60 61 if isQuantityAllZero { 62 return false 63 } 64 65 return highestBuyLevel.P.GTE(lowestSellPrice) 66 } 67 68 // PrintDisplay is a helper function to print the orderbook in a human readable format for debugging purposes 69 func (o *Orderbook) PrintDisplay() { 70 PrintDisplayLevels(o.BuyLevels, o.SellLevels) 71 } 72 73 // PrintDisplayLevels is a helper function to print the orderbook in a human readable format for debugging purposes 74 func PrintDisplayLevels(buyLevels, sellLevels []*Level) { 75 buyLevelsSorted := make([]*Level, len(buyLevels)) 76 copy(buyLevelsSorted, buyLevels) 77 sellLevelsSorted := make([]*Level, len(sellLevels)) 78 copy(sellLevelsSorted, sellLevels) 79 if len(buyLevels) > 1 { 80 sort.SliceStable(buyLevelsSorted, func(i, j int) bool { 81 return buyLevelsSorted[i].GetPrice().GT(buyLevelsSorted[j].GetPrice()) 82 }) 83 } 84 if len(sellLevelsSorted) > 1 { 85 sort.SliceStable(sellLevelsSorted, func(i, j int) bool { 86 return sellLevelsSorted[i].GetPrice().LT(sellLevelsSorted[j].GetPrice()) 87 }) 88 } 89 90 table := tablewriter.NewWriter(os.Stdout) 91 table.SetHeader([]string{"Buy Price", "Buy Quantity", "Sell Price", "Sell Quantity"}) 92 93 maxLength := len(buyLevelsSorted) 94 if len(sellLevelsSorted) > maxLength { 95 maxLength = len(sellLevelsSorted) 96 } 97 98 for idx := 0; idx < maxLength; idx++ { 99 row := make([]string, 0) 100 if idx < len(buyLevelsSorted) { 101 row = append(row, getReadableDec(buyLevelsSorted[idx].P), getReadableDec(buyLevelsSorted[idx].Q)) 102 } else { 103 row = append(row, "-", "-") 104 } 105 if idx < len(sellLevelsSorted) { 106 row = append(row, getReadableDec(sellLevelsSorted[idx].P), getReadableDec(sellLevelsSorted[idx].Q)) 107 } else { 108 row = append(row, "-", "-") 109 } 110 table.Append(row) 111 } 112 table.Render() 113 } 114 115 func (o *Orderbook) Equals(other *Orderbook) bool { 116 if len(o.BuyLevels) != len(other.BuyLevels) || len(o.SellLevels) != len(other.SellLevels) { 117 return false 118 } 119 for i, level := range o.BuyLevels { 120 metaLevel := other.BuyLevels[i] 121 if !level.Q.Equal(metaLevel.Q) || !level.P.Equal(metaLevel.P) { 122 return false 123 } 124 } 125 return true 126 } 127 128 // getReadableDec is a test utility function to return a readable representation of decimal strings 129 func getReadableDec(d math.LegacyDec) string { 130 if d.IsNil() { 131 return d.String() 132 } 133 dec := strings.TrimRight(d.String(), "0") 134 if len(dec) < 2 { 135 return dec 136 } 137 138 if dec[len(dec)-1:] == "." { 139 return dec + "0" 140 } 141 return dec 142 } 143 144 func NewLevel(price, quantity math.LegacyDec) *Level { 145 return &Level{ 146 P: price, 147 Q: quantity, 148 } 149 } 150 151 func (l *Level) GetPrice() math.LegacyDec { 152 return l.P 153 } 154 155 func (l *Level) GetQuantity() math.LegacyDec { 156 return l.Q 157 }