Guest User

Untitled

a guest
Oct 5th, 2021
261
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Go 5.98 KB | None | 0 0
  1. package gnosis
  2.  
  3. import (
  4.     "context"
  5.     "fmt"
  6.     "strings"
  7.     "crypto/ecdsa"
  8.     "encoding/json"
  9.     "net/http"
  10.  
  11.     "github.com/ethereum/go-ethereum/common"
  12.     "github.com/ethereum/go-ethereum/common/math"
  13.     "github.com/ethereum/go-ethereum/crypto"
  14.     "github.com/ethereum/go-ethereum/signer/core"
  15.     "github.com/pkg/errors"
  16. )
  17.  
  18. var eip712OrderTypes = core.Types{
  19.     "EIP712Domain": {
  20.         {
  21.             Name: "name",
  22.             Type: "string",
  23.         },
  24.         {
  25.             Name: "version",
  26.             Type: "string",
  27.         },
  28.         {
  29.             Name: "chainId",
  30.             Type: "uint256",
  31.         },
  32.         {
  33.             Name: "verifyingContract",
  34.             Type: "address",
  35.         },
  36.     },
  37.     "Order": {
  38.         {
  39.             Name: "sellToken",
  40.             Type: "address",
  41.         },
  42.         {
  43.             Name: "buyToken",
  44.             Type: "address",
  45.         },
  46.         {
  47.             Name: "receiver",
  48.             Type: "address",
  49.         },
  50.         {
  51.             Name: "sellAmount",
  52.             Type: "uint256",
  53.         },
  54.         {
  55.             Name: "buyAmount",
  56.             Type: "uint256",
  57.         },
  58.         {
  59.             Name: "validTo",
  60.             Type: "uint32",
  61.         },
  62.         {
  63.             Name: "appData",
  64.             Type: "bytes32",
  65.         },
  66.         {
  67.             Name: "feeAmount",
  68.             Type: "uint256",
  69.         },
  70.         {
  71.             Name: "kind",
  72.             Type: "string",
  73.         },
  74.         {
  75.             Name: "partiallyFillable",
  76.             Type: "bool",
  77.         },
  78.         {
  79.             Name: "sellTokenBalance",
  80.             Type: "string",
  81.         },
  82.         {
  83.             Name: "buyTokenBalance",
  84.             Type: "string",
  85.         },
  86.     },
  87. }
  88.  
  89. var domain = core.TypedDataDomain{
  90.     Name:              "Gnosis Protocol",
  91.     Version:           "v2",
  92.     ChainId:           math.NewHexOrDecimal256(1),
  93.     VerifyingContract: "0x9008D19f58AAbD9eD0D60971565AA8510560ab41",
  94. }
  95.  
  96. // CounterOrder represents a Gnosis CounterOrder.
  97. type CounterOrder struct {
  98.     SellToken         string `json:"sellToken,omitempty"`
  99.     BuyToken          string `json:"buyToken,omitempty"`
  100.     Receiver          string `json:"receiver,omitempty"`
  101.     SellAmount        string `json:"sellAmount"`
  102.     BuyAmount         string `json:"buyAmount"`
  103.     ValidTo           uint32 `json:"validTo,omitempty"`
  104.     AppData           string `json:"appData,omitempty"`
  105.     FeeAmount         string `json:"feeAmount"`
  106.     Kind              string `json:"kind,omitempty"`
  107.     PartiallyFillable bool   `json:"partiallyFillable"`
  108.     Signature         string `json:"signature,omitempty"`
  109.     SigningScheme     string `json:"signingScheme,omitempty"`
  110.     SellTokenBalance  string `json:"sellTokenBalance,omitempty"`
  111.     BuyTokenBalance   string `json:"buyTokenBalance,omitempty"`
  112.     From              string `json:"from,omitempty"`
  113. }
  114.  
  115. // Hash computes this counter order's hash.
  116. func (o *CounterOrder) Hash() (common.Hash, error) {
  117.     var message = map[string]interface{}{
  118.         "sellToken":         o.SellToken,
  119.         "buyToken":          o.BuyToken,
  120.         "receiver":          o.Receiver,
  121.         "sellAmount":        o.SellAmount,
  122.         "buyAmount":         o.BuyAmount,
  123.         "validTo":           fmt.Sprintf("%d", o.ValidTo),
  124.         "appData":           common.Hex2Bytes(strings.TrimPrefix(o.AppData, "0x")),
  125.         "feeAmount":         o.FeeAmount,
  126.         "kind":              o.Kind,
  127.         "partiallyFillable": o.PartiallyFillable,
  128.         "sellTokenBalance":  o.SellTokenBalance,
  129.         "buyTokenBalance":   o.BuyTokenBalance,
  130.     }
  131.  
  132.     var typedData = core.TypedData{
  133.         Types:       eip712OrderTypes,
  134.         PrimaryType: "Order",
  135.         Domain:      domain,
  136.         Message:     message,
  137.     }
  138.  
  139.     domainSeparator, err := typedData.HashStruct("EIP712Domain", typedData.Domain.Map())
  140.     if err != nil {
  141.         return common.Hash{}, errors.Wrap(err, "computing domain separator")
  142.     }
  143.     typedDataHash, err := typedData.HashStruct(typedData.PrimaryType, typedData.Message)
  144.     if err != nil {
  145.         return common.Hash{}, errors.Wrap(err, "computing typed data hash")
  146.     }
  147.     rawData := []byte(fmt.Sprintf("\x19\x01%s%s", string(domainSeparator), string(typedDataHash)))
  148.     return crypto.Keccak256Hash(rawData), nil
  149. }
  150.  
  151. func signHash (hash []byte, pk *ecdsa.PrivateKey) ([]byte, error) {
  152.         signatureBytes, err := crypto.Sign(accounts.TextHash(hash), pk)
  153.         if err != nil {
  154.             return nil, err
  155.         }
  156.  
  157.         vParam := signatureBytes[64]
  158.         if vParam == byte(0) {
  159.             vParam = byte(27)
  160.         } else if vParam == byte(1) {
  161.             vParam = byte(28)
  162.         }
  163.         signatureBytes[64] = vParam
  164.         return signatureBytes, nil
  165. }
  166.  
  167. func main() {
  168.     ctx := context.Background()
  169.     baseURL := "https://protocol-mainnet.gnosis.io/api/v1"
  170.     privateKey := "<insert here>"
  171.     publicKey := "<insert here>"
  172.     pk, err := crypto.HexToECDSA(privateKey)
  173.     if err != nil {
  174.         panic(err)
  175.     }
  176.     counterOrder := &CounterOrder{
  177.         SellToken:  "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
  178.         BuyToken:   "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
  179.         Receiver:          strings.ToLower(publicKey),
  180.         BuyAmount:         "10",
  181.         SellAmount:        "10",
  182.         ValidTo:           1631199182,
  183.         AppData:           "some app data",
  184.         Kind:              "buy",
  185.         FeeAmount:         "5",
  186.         PartiallyFillable: false,
  187.         SellTokenBalance:  "erc20",
  188.         BuyTokenBalance:   "erc20",
  189.         SigningScheme:     "ethsign",
  190.         From:              strings.ToLower(publicKey),
  191.     }
  192.     hash, err := counterOrder.Hash()
  193.     if err != nil {
  194.         return nil, errors.Wrap(err, "computing order hash")
  195.     }
  196.     signatureBytes, err := signHash(hash.Bytes())
  197.     if err != nil {
  198.         return nil, errors.Wrap(err, "signing order hash")
  199.     }
  200.     counterOrder.Signature = fmt.Sprintf("0x%s", common.Bytes2Hex(signatureBytes))
  201.  
  202.     payloadBytes, err := json.Marshal(counterOrder)
  203.     if err != nil {
  204.         return nil, errors.Wrap(err, "marshaling counter order")
  205.     }
  206.     request, err := http.NewRequest(http.MethodPost, baseURL+"/orders", bytes.NewBuffer(payloadBytes))
  207.     if err != nil {
  208.         return nil, errors.Wrap(err, "constructing request")
  209.     }
  210.     request = request.WithContext(ctx)
  211.     response, err := http.DefaultClient.Do(request)
  212.     if err != nil {
  213.         return nil, errors.Wrap(err, "sending request")
  214.     }
  215.     defer response.Body.Close()
  216.     bytes, err := ioutil.ReadAll(response.Body)
  217.     if err != nil {
  218.         return nil, errors.Wrapf(err, "could not read response body (status=%d): %s", response.StatusCode, string(bytes))
  219.     }
  220.     if response.StatusCode != http.StatusCreated {
  221.         return nil, errors.Errorf("received status code %d with body: %s", response.StatusCode, string(bytes))
  222.     }
  223.     return counterOrder, nil
  224. }
  225.  
Add Comment
Please, Sign In to add comment