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  }