Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package gnosis
- import (
- "context"
- "fmt"
- "strings"
- "crypto/ecdsa"
- "encoding/json"
- "net/http"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/math"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/signer/core"
- "github.com/pkg/errors"
- )
- var eip712OrderTypes = core.Types{
- "EIP712Domain": {
- {
- Name: "name",
- Type: "string",
- },
- {
- Name: "version",
- Type: "string",
- },
- {
- Name: "chainId",
- Type: "uint256",
- },
- {
- Name: "verifyingContract",
- Type: "address",
- },
- },
- "Order": {
- {
- Name: "sellToken",
- Type: "address",
- },
- {
- Name: "buyToken",
- Type: "address",
- },
- {
- Name: "receiver",
- Type: "address",
- },
- {
- Name: "sellAmount",
- Type: "uint256",
- },
- {
- Name: "buyAmount",
- Type: "uint256",
- },
- {
- Name: "validTo",
- Type: "uint32",
- },
- {
- Name: "appData",
- Type: "bytes32",
- },
- {
- Name: "feeAmount",
- Type: "uint256",
- },
- {
- Name: "kind",
- Type: "string",
- },
- {
- Name: "partiallyFillable",
- Type: "bool",
- },
- {
- Name: "sellTokenBalance",
- Type: "string",
- },
- {
- Name: "buyTokenBalance",
- Type: "string",
- },
- },
- }
- var domain = core.TypedDataDomain{
- Name: "Gnosis Protocol",
- Version: "v2",
- ChainId: math.NewHexOrDecimal256(1),
- VerifyingContract: "0x9008D19f58AAbD9eD0D60971565AA8510560ab41",
- }
- // CounterOrder represents a Gnosis CounterOrder.
- type CounterOrder struct {
- SellToken string `json:"sellToken,omitempty"`
- BuyToken string `json:"buyToken,omitempty"`
- Receiver string `json:"receiver,omitempty"`
- SellAmount string `json:"sellAmount"`
- BuyAmount string `json:"buyAmount"`
- ValidTo uint32 `json:"validTo,omitempty"`
- AppData string `json:"appData,omitempty"`
- FeeAmount string `json:"feeAmount"`
- Kind string `json:"kind,omitempty"`
- PartiallyFillable bool `json:"partiallyFillable"`
- Signature string `json:"signature,omitempty"`
- SigningScheme string `json:"signingScheme,omitempty"`
- SellTokenBalance string `json:"sellTokenBalance,omitempty"`
- BuyTokenBalance string `json:"buyTokenBalance,omitempty"`
- From string `json:"from,omitempty"`
- }
- // Hash computes this counter order's hash.
- func (o *CounterOrder) Hash() (common.Hash, error) {
- var message = map[string]interface{}{
- "sellToken": o.SellToken,
- "buyToken": o.BuyToken,
- "receiver": o.Receiver,
- "sellAmount": o.SellAmount,
- "buyAmount": o.BuyAmount,
- "validTo": fmt.Sprintf("%d", o.ValidTo),
- "appData": common.Hex2Bytes(strings.TrimPrefix(o.AppData, "0x")),
- "feeAmount": o.FeeAmount,
- "kind": o.Kind,
- "partiallyFillable": o.PartiallyFillable,
- "sellTokenBalance": o.SellTokenBalance,
- "buyTokenBalance": o.BuyTokenBalance,
- }
- var typedData = core.TypedData{
- Types: eip712OrderTypes,
- PrimaryType: "Order",
- Domain: domain,
- Message: message,
- }
- domainSeparator, err := typedData.HashStruct("EIP712Domain", typedData.Domain.Map())
- if err != nil {
- return common.Hash{}, errors.Wrap(err, "computing domain separator")
- }
- typedDataHash, err := typedData.HashStruct(typedData.PrimaryType, typedData.Message)
- if err != nil {
- return common.Hash{}, errors.Wrap(err, "computing typed data hash")
- }
- rawData := []byte(fmt.Sprintf("\x19\x01%s%s", string(domainSeparator), string(typedDataHash)))
- return crypto.Keccak256Hash(rawData), nil
- }
- func signHash (hash []byte, pk *ecdsa.PrivateKey) ([]byte, error) {
- signatureBytes, err := crypto.Sign(accounts.TextHash(hash), pk)
- if err != nil {
- return nil, err
- }
- vParam := signatureBytes[64]
- if vParam == byte(0) {
- vParam = byte(27)
- } else if vParam == byte(1) {
- vParam = byte(28)
- }
- signatureBytes[64] = vParam
- return signatureBytes, nil
- }
- func main() {
- ctx := context.Background()
- baseURL := "https://protocol-mainnet.gnosis.io/api/v1"
- privateKey := "<insert here>"
- publicKey := "<insert here>"
- pk, err := crypto.HexToECDSA(privateKey)
- if err != nil {
- panic(err)
- }
- counterOrder := &CounterOrder{
- SellToken: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
- BuyToken: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
- Receiver: strings.ToLower(publicKey),
- BuyAmount: "10",
- SellAmount: "10",
- ValidTo: 1631199182,
- AppData: "some app data",
- Kind: "buy",
- FeeAmount: "5",
- PartiallyFillable: false,
- SellTokenBalance: "erc20",
- BuyTokenBalance: "erc20",
- SigningScheme: "ethsign",
- From: strings.ToLower(publicKey),
- }
- hash, err := counterOrder.Hash()
- if err != nil {
- return nil, errors.Wrap(err, "computing order hash")
- }
- signatureBytes, err := signHash(hash.Bytes())
- if err != nil {
- return nil, errors.Wrap(err, "signing order hash")
- }
- counterOrder.Signature = fmt.Sprintf("0x%s", common.Bytes2Hex(signatureBytes))
- payloadBytes, err := json.Marshal(counterOrder)
- if err != nil {
- return nil, errors.Wrap(err, "marshaling counter order")
- }
- request, err := http.NewRequest(http.MethodPost, baseURL+"/orders", bytes.NewBuffer(payloadBytes))
- if err != nil {
- return nil, errors.Wrap(err, "constructing request")
- }
- request = request.WithContext(ctx)
- response, err := http.DefaultClient.Do(request)
- if err != nil {
- return nil, errors.Wrap(err, "sending request")
- }
- defer response.Body.Close()
- bytes, err := ioutil.ReadAll(response.Body)
- if err != nil {
- return nil, errors.Wrapf(err, "could not read response body (status=%d): %s", response.StatusCode, string(bytes))
- }
- if response.StatusCode != http.StatusCreated {
- return nil, errors.Errorf("received status code %d with body: %s", response.StatusCode, string(bytes))
- }
- return counterOrder, nil
- }
Add Comment
Please, Sign In to add comment