github.com/diadata-org/diadata@v1.4.593/pkg/utils/assetQuotationEIP712Signer.go (about) 1 package utils 2 3 import ( 4 "bytes" 5 "crypto/ecdsa" 6 "crypto/elliptic" 7 "encoding/hex" 8 "fmt" 9 "math/big" 10 "time" 11 12 "github.com/ethereum/go-ethereum/common" 13 "github.com/ethereum/go-ethereum/common/hexutil" 14 "github.com/ethereum/go-ethereum/common/math" 15 "github.com/ethereum/go-ethereum/crypto" 16 ) 17 18 type AssetQuotationSigner struct { 19 privateKey string 20 domain TypedDataDomain 21 types Types 22 } 23 24 func NewAssetQuotationSigner(privateKey string) *AssetQuotationSigner { 25 domain := TypedDataDomain{ 26 Name: "DiaData", 27 Version: "1.0.0", 28 ChainId: math.NewHexOrDecimal256(1), 29 VerifyingContract: common.HexToAddress("0x0000000000000000000000000000000000000000").Hex(), 30 } 31 32 types := Types{ 33 "Message": []Type{ 34 {Name: "Symbol", Type: "string"}, 35 {Name: "Address", Type: "address"}, 36 {Name: "Blockchain", Type: "string"}, 37 {Name: "Price", Type: "uint256"}, 38 {Name: "Time", Type: "uint256"}, 39 }, 40 "EIP712Domain": []Type{ 41 {Name: "name", Type: "string"}, 42 {Name: "version", Type: "string"}, 43 {Name: "chainId", Type: "uint256"}, 44 {Name: "verifyingContract", Type: "address"}, 45 }, 46 } 47 return &AssetQuotationSigner{privateKey: privateKey, domain: domain, types: types} 48 } 49 50 func (aqs *AssetQuotationSigner) Sign(symbol, address, blockchain string, price float64, time time.Time) (string, error) { 51 52 message := map[string]interface{}{ 53 "Symbol": symbol, 54 "Address": common.HexToAddress(address).Hex(), 55 "Blockchain": blockchain, 56 "Price": big.NewInt(int64(price * 100000000)).String(), 57 "Time": big.NewInt(time.Unix()).String(), 58 } 59 60 typedData := TypedData{ 61 Types: aqs.types, 62 PrimaryType: "Message", 63 Domain: aqs.domain, 64 Message: message, 65 } 66 67 typedDataHash, _, err := TypedDataAndHash(typedData) 68 if err != nil { 69 return "", err 70 } 71 72 pk, err := hexToPrivateKey(aqs.privateKey) 73 if err != nil { 74 return "", err 75 } 76 signature, err := crypto.Sign(typedDataHash, pk) 77 if err != nil { 78 return "", err 79 80 } 81 82 var buf bytes.Buffer 83 buf.Write(signature) 84 // buf.WriteByte(1) // recovery ID 85 sigData := hexutil.Encode(buf.Bytes()) 86 // fmt.Println("sigdata", sigData) 87 88 return sigData, nil 89 } 90 91 func hexToPrivateKey(hexKey string) (*ecdsa.PrivateKey, error) { 92 // Decode the hex string into a byte slice 93 keyBytes, err := hex.DecodeString(hexKey) 94 if err != nil { 95 return nil, err 96 } 97 98 // Parse the byte slice as a big integer 99 keyBigInt := new(big.Int).SetBytes(keyBytes) 100 101 // Generate a new secp256k1 elliptic curve 102 curve := elliptic.P256() 103 104 // Convert the big integer to a private key using the elliptic curve 105 privateKey := new(ecdsa.PrivateKey) 106 privateKey.PublicKey.Curve = curve 107 privateKey.D = keyBigInt 108 privateKey.PublicKey.X, privateKey.PublicKey.Y = curve.ScalarBaseMult(keyBytes) 109 110 // Verify that the private key is valid 111 if !curve.IsOnCurve(privateKey.PublicKey.X, privateKey.PublicKey.Y) { 112 return nil, fmt.Errorf("invalid private key") 113 } 114 115 return privateKey, nil 116 }