github.com/InjectiveLabs/sdk-go@v1.53.0/client/chain/orderhash.go (about) 1 package chain 2 3 import ( 4 "context" 5 "strconv" 6 7 exchangetypes "github.com/InjectiveLabs/sdk-go/chain/exchange/types" 8 "github.com/ethereum/go-ethereum/common" 9 ethmath "github.com/ethereum/go-ethereum/common/math" 10 gethsigner "github.com/ethereum/go-ethereum/signer/core/apitypes" 11 "golang.org/x/crypto/sha3" 12 ) 13 14 var AuctionSubaccountID = common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111") 15 16 var eip712OrderTypes = gethsigner.Types{ 17 "EIP712Domain": { 18 {Name: "name", Type: "string"}, 19 {Name: "version", Type: "string"}, 20 {Name: "chainId", Type: "uint256"}, 21 {Name: "verifyingContract", Type: "address"}, 22 {Name: "salt", Type: "bytes32"}, 23 }, 24 "OrderInfo": { 25 {Name: "SubaccountId", Type: "string"}, 26 {Name: "FeeRecipient", Type: "string"}, 27 {Name: "Price", Type: "string"}, 28 {Name: "Quantity", Type: "string"}, 29 }, 30 "SpotOrder": { 31 {Name: "MarketId", Type: "string"}, 32 {Name: "OrderInfo", Type: "OrderInfo"}, 33 {Name: "Salt", Type: "string"}, 34 {Name: "OrderType", Type: "string"}, 35 {Name: "TriggerPrice", Type: "string"}, 36 }, 37 "DerivativeOrder": { 38 {Name: "MarketId", Type: "string"}, 39 {Name: "OrderInfo", Type: "OrderInfo"}, 40 {Name: "OrderType", Type: "string"}, 41 {Name: "Margin", Type: "string"}, 42 {Name: "TriggerPrice", Type: "string"}, 43 {Name: "Salt", Type: "string"}, 44 }, 45 } 46 47 type OrderHashes struct { 48 Spot []common.Hash 49 Derivative []common.Hash 50 } 51 52 var domain = gethsigner.TypedDataDomain{ 53 Name: "Injective Protocol", 54 Version: "2.0.0", 55 ChainId: ethmath.NewHexOrDecimal256(888), 56 VerifyingContract: "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC", 57 Salt: "0x0000000000000000000000000000000000000000000000000000000000000000", 58 } 59 60 func (c *chainClient) UpdateSubaccountNonceFromChain() error { 61 for subaccountId := range c.subaccountToNonce { 62 err := c.SynchronizeSubaccountNonce(subaccountId) 63 if err != nil { 64 return err 65 } 66 } 67 return nil 68 } 69 70 func (c *chainClient) SynchronizeSubaccountNonce(subaccountId common.Hash) error { 71 res, err := c.GetSubAccountNonce(context.Background(), subaccountId) 72 if err != nil { 73 return err 74 } 75 c.subaccountToNonce[subaccountId] = res.Nonce 76 return nil 77 } 78 79 func (c *chainClient) ComputeOrderHashes(spotOrders []exchangetypes.SpotOrder, derivativeOrders []exchangetypes.DerivativeOrder, subaccountId common.Hash) (OrderHashes, error) { 80 if len(spotOrders)+len(derivativeOrders) == 0 { 81 return OrderHashes{}, nil 82 } 83 84 orderHashes := OrderHashes{} 85 // get nonce 86 if _, exist := c.subaccountToNonce[subaccountId]; !exist { 87 if err := c.SynchronizeSubaccountNonce(subaccountId); err != nil { 88 return OrderHashes{}, err 89 } 90 } 91 92 nonce := c.subaccountToNonce[subaccountId] 93 for _, o := range spotOrders { 94 nonce += 1 95 triggerPrice := "" 96 if o.TriggerPrice != nil { 97 triggerPrice = o.TriggerPrice.String() 98 } 99 message := map[string]interface{}{ 100 "MarketId": o.MarketId, 101 "OrderInfo": map[string]interface{}{ 102 "SubaccountId": o.OrderInfo.SubaccountId, 103 "FeeRecipient": o.OrderInfo.FeeRecipient, 104 "Price": o.OrderInfo.Price.String(), 105 "Quantity": o.OrderInfo.Quantity.String(), 106 }, 107 "Salt": strconv.Itoa(int(nonce)), 108 "OrderType": string(o.OrderType), 109 "TriggerPrice": triggerPrice, 110 } 111 typedData := gethsigner.TypedData{ 112 Types: eip712OrderTypes, 113 PrimaryType: "SpotOrder", 114 Domain: domain, 115 Message: message, 116 } 117 domainSeparator, err := typedData.HashStruct("EIP712Domain", typedData.Domain.Map()) 118 if err != nil { 119 return OrderHashes{}, err 120 } 121 typedDataHash, err := typedData.HashStruct(typedData.PrimaryType, typedData.Message) 122 if err != nil { 123 return OrderHashes{}, err 124 } 125 126 w := sha3.NewLegacyKeccak256() 127 w.Write([]byte("\x19\x01")) 128 w.Write([]byte(domainSeparator)) 129 w.Write([]byte(typedDataHash)) 130 131 hash := common.BytesToHash(w.Sum(nil)) 132 orderHashes.Spot = append(orderHashes.Spot, hash) 133 } 134 135 for _, o := range derivativeOrders { 136 nonce += 1 137 triggerPrice := "" 138 if o.TriggerPrice != nil { 139 triggerPrice = o.TriggerPrice.String() 140 } 141 message := map[string]interface{}{ 142 "MarketId": o.MarketId, 143 "OrderInfo": map[string]interface{}{ 144 "SubaccountId": o.OrderInfo.SubaccountId, 145 "FeeRecipient": o.OrderInfo.FeeRecipient, 146 "Price": o.OrderInfo.Price.String(), 147 "Quantity": o.OrderInfo.Quantity.String(), 148 }, 149 "Margin": o.Margin.String(), 150 "OrderType": string(o.OrderType), 151 "TriggerPrice": triggerPrice, 152 "Salt": strconv.Itoa(int(nonce)), 153 } 154 typedData := gethsigner.TypedData{ 155 Types: eip712OrderTypes, 156 PrimaryType: "DerivativeOrder", 157 Domain: domain, 158 Message: message, 159 } 160 domainSeparator, err := typedData.HashStruct("EIP712Domain", typedData.Domain.Map()) 161 if err != nil { 162 return OrderHashes{}, err 163 } 164 typedDataHash, err := typedData.HashStruct(typedData.PrimaryType, typedData.Message) 165 if err != nil { 166 return OrderHashes{}, err 167 } 168 169 w := sha3.NewLegacyKeccak256() 170 w.Write([]byte("\x19\x01")) 171 w.Write([]byte(domainSeparator)) 172 w.Write([]byte(typedDataHash)) 173 174 hash := common.BytesToHash(w.Sum(nil)) 175 orderHashes.Derivative = append(orderHashes.Derivative, hash) 176 } 177 178 c.subaccountToNonce[subaccountId] = nonce 179 180 return orderHashes, nil 181 }