github.com/gagliardetto/solana-go@v1.11.0/programs/serum/math.go (about) 1 // Copyright 2021 github.com/gagliardetto 2 // This file has been modified by github.com/gagliardetto 3 // 4 // Copyright 2020 dfuse Platform Inc. 5 // 6 // Licensed under the Apache License, Version 2.0 (the "License"); 7 // you may not use this file except in compliance with the License. 8 // You may obtain a copy of the License at 9 // 10 // http://www.apache.org/licenses/LICENSE-2.0 11 // 12 // Unless required by applicable law or agreed to in writing, software 13 // distributed under the License is distributed on an "AS IS" BASIS, 14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 // See the License for the specific language governing permissions and 16 // limitations under the License. 17 18 package serum 19 20 import ( 21 "encoding/binary" 22 "encoding/hex" 23 "fmt" 24 "math/big" 25 ) 26 27 var _10b = big.NewInt(10) 28 29 var decimalsBigInt = []*big.Int{ 30 new(big.Int).Exp(_10b, big.NewInt(1), nil), 31 new(big.Int).Exp(_10b, big.NewInt(2), nil), 32 new(big.Int).Exp(_10b, big.NewInt(3), nil), 33 new(big.Int).Exp(_10b, big.NewInt(4), nil), 34 new(big.Int).Exp(_10b, big.NewInt(5), nil), 35 new(big.Int).Exp(_10b, big.NewInt(6), nil), 36 new(big.Int).Exp(_10b, big.NewInt(7), nil), 37 new(big.Int).Exp(_10b, big.NewInt(8), nil), 38 new(big.Int).Exp(_10b, big.NewInt(9), nil), 39 new(big.Int).Exp(_10b, big.NewInt(10), nil), 40 new(big.Int).Exp(_10b, big.NewInt(11), nil), 41 new(big.Int).Exp(_10b, big.NewInt(12), nil), 42 new(big.Int).Exp(_10b, big.NewInt(13), nil), 43 new(big.Int).Exp(_10b, big.NewInt(14), nil), 44 new(big.Int).Exp(_10b, big.NewInt(15), nil), 45 new(big.Int).Exp(_10b, big.NewInt(16), nil), 46 new(big.Int).Exp(_10b, big.NewInt(17), nil), 47 new(big.Int).Exp(_10b, big.NewInt(18), nil), 48 } 49 50 func decimalMultiplier(decimal uint) *big.Int { 51 if decimal == 0 { 52 return new(big.Int).Exp(_10b, big.NewInt(0), nil) 53 } 54 if decimal <= uint(len(decimalsBigInt)) { 55 return decimalsBigInt[decimal-1] 56 } 57 return new(big.Int).Exp(_10b, big.NewInt(int64(decimal)), nil) 58 } 59 60 func I() *big.Int { 61 return new(big.Int) 62 } 63 64 func F() *big.Float { 65 return new(big.Float) 66 } 67 68 func divideBnToNumber(numerator, denomiator *big.Float) *big.Float { 69 return F().Quo(numerator, denomiator) 70 } 71 72 func GetSeqNum(orderId string, side Side) (uint64, error) { 73 d, err := hex.DecodeString(orderId) 74 if err != nil { 75 return 0, fmt.Errorf("unable to decode order ID: %w", err) 76 } 77 78 if len(d) < 16 { 79 return 0, fmt.Errorf("order ID too short expecting atleast 8 bytes got %d", len(d)) 80 } 81 82 v := binary.BigEndian.Uint64(d[8:]) 83 84 if side == SideBid { 85 return ^v, nil 86 } 87 88 return v, nil 89 } 90 91 func PriceLotsToNumber(price, baseLotSize, quoteLotSize, baseDecimals, quoteDecimals uint64) *big.Float { 92 baseMultiplier := F().SetInt(decimalMultiplier(uint(baseDecimals))) 93 quoteMultiplier := F().SetInt(decimalMultiplier(uint(quoteDecimals))) 94 numerator := F().Mul(F().Mul(F().SetUint64(price), F().SetUint64(quoteLotSize)), baseMultiplier) 95 denominator := F().Mul(F().SetUint64(baseLotSize), quoteMultiplier) 96 return F().Quo(numerator, denominator) 97 }