github.com/0xsequence/ethkit@v1.25.0/ethcoder/typed_data_test.go (about)

     1  package ethcoder_test
     2  
     3  import (
     4  	"math/big"
     5  	"testing"
     6  
     7  	"github.com/0xsequence/ethkit/ethcoder"
     8  	"github.com/0xsequence/ethkit/ethwallet"
     9  	"github.com/0xsequence/ethkit/go-ethereum/common"
    10  	"github.com/stretchr/testify/assert"
    11  )
    12  
    13  func TestTypedDataTypes(t *testing.T) {
    14  	types := ethcoder.TypedDataTypes{
    15  		"Person": {
    16  			{Name: "name", Type: "string"},
    17  			{Name: "wallet", Type: "address"},
    18  		},
    19  		"Mail": {
    20  			{Name: "from", Type: "Person"},
    21  			{Name: "to", Type: "Person"},
    22  			{Name: "contents", Type: "string"},
    23  			{Name: "asset", Type: "Asset"},
    24  		},
    25  		"Asset": {
    26  			{Name: "name", Type: "string"},
    27  		},
    28  	}
    29  
    30  	encodeType, err := types.EncodeType("Person")
    31  	assert.NoError(t, err)
    32  	assert.Equal(t, "Person(string name,address wallet)", encodeType)
    33  
    34  	typeHash, _ := types.TypeHash("Person")
    35  	typeHashHex := ethcoder.HexEncode(typeHash)
    36  	assert.Equal(t, "0xb9d8c78acf9b987311de6c7b45bb6a9c8e1bf361fa7fd3467a2163f994c79500", typeHashHex)
    37  
    38  	encodeType, err = types.EncodeType("Mail")
    39  	assert.NoError(t, err)
    40  	assert.Equal(t, "Mail(Person from,Person to,string contents,Asset asset)Asset(string name)Person(string name,address wallet)", encodeType)
    41  }
    42  
    43  func TestTypedDataCase1(t *testing.T) {
    44  	verifyingContract := common.HexToAddress("0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC")
    45  
    46  	typedData := &ethcoder.TypedData{
    47  		Types: ethcoder.TypedDataTypes{
    48  			"EIP712Domain": {
    49  				{Name: "name", Type: "string"},
    50  				{Name: "version", Type: "string"},
    51  				{Name: "chainId", Type: "uint256"},
    52  				{Name: "verifyingContract", Type: "address"},
    53  			},
    54  			"Person": {
    55  				{Name: "name", Type: "string"},
    56  				{Name: "wallet", Type: "address"},
    57  			},
    58  		},
    59  		PrimaryType: "Person",
    60  		Domain: ethcoder.TypedDataDomain{
    61  			Name:              "Ether Mail",
    62  			Version:           "1",
    63  			ChainID:           big.NewInt(1),
    64  			VerifyingContract: &verifyingContract,
    65  		},
    66  		Message: map[string]interface{}{
    67  			"name": "Bob",
    68  			// "wallet": common.HexToAddress("0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB"), // NOTE: passing common.Address object works too
    69  			"wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB",
    70  		},
    71  	}
    72  
    73  	domainHash, err := typedData.HashStruct("EIP712Domain", typedData.Domain.Map())
    74  	assert.NoError(t, err)
    75  	assert.Equal(t, "0xf2cee375fa42b42143804025fc449deafd50cc031ca257e0b194a650a912090f", ethcoder.HexEncode(domainHash))
    76  
    77  	digest, err := typedData.EncodeDigest()
    78  	assert.NoError(t, err)
    79  	assert.Equal(t, "0x0a94cf6625e5860fc4f330d75bcd0c3a4737957d2321d1a024540ab5320fe903", ethcoder.HexEncode(digest))
    80  
    81  	// fmt.Println("===> digest", HexEncode(digest))
    82  
    83  	// lets sign it..
    84  	wallet, err := ethwallet.NewWalletFromMnemonic("dose weasel clever culture letter volume endorse used harvest ripple circle install")
    85  	assert.NoError(t, err)
    86  
    87  	ethSigedTypedData, err := wallet.SignMessage([]byte(digest))
    88  	ethSigedTypedDataHex := ethcoder.HexEncode(ethSigedTypedData)
    89  	assert.NoError(t, err)
    90  
    91  	assert.Equal(t,
    92  		"0x842ed2d5c3bf97c4977ee84e600fec7d0f9c5e21d4090b5035a3ea650ec6127d18053e4aafb631de26eb3fd5d61e4a6f2d6a106ee8e3d8d5cb0c4571d06798741b",
    93  		ethSigedTypedDataHex,
    94  	)
    95  
    96  	// recover / validate signature
    97  	valid, err := ethwallet.ValidateEthereumSignature(wallet.Address().Hex(), digest, ethSigedTypedDataHex)
    98  	assert.NoError(t, err)
    99  	assert.True(t, valid)
   100  }
   101  
   102  func TestTypedDataCase2(t *testing.T) {
   103  	verifyingContract := common.HexToAddress("0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC")
   104  
   105  	typedData := &ethcoder.TypedData{
   106  		Types: ethcoder.TypedDataTypes{
   107  			"EIP712Domain": {
   108  				{Name: "name", Type: "string"},
   109  				{Name: "version", Type: "string"},
   110  				{Name: "chainId", Type: "uint256"},
   111  				{Name: "verifyingContract", Type: "address"},
   112  			},
   113  			"Person": {
   114  				{Name: "name", Type: "string"},
   115  				{Name: "wallet", Type: "address"},
   116  				{Name: "count", Type: "uint8"},
   117  			},
   118  		},
   119  		PrimaryType: "Person",
   120  		Domain: ethcoder.TypedDataDomain{
   121  			Name:              "Ether Mail",
   122  			Version:           "1",
   123  			ChainID:           big.NewInt(1),
   124  			VerifyingContract: &verifyingContract,
   125  		},
   126  		Message: map[string]interface{}{
   127  			"name": "Bob",
   128  			// "wallet": common.HexToAddress("0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB"), // NOTE: passing common.Address object works too
   129  			"wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB",
   130  			"count":  uint8(4),
   131  		},
   132  	}
   133  
   134  	domainHash, err := typedData.HashStruct("EIP712Domain", typedData.Domain.Map())
   135  	assert.NoError(t, err)
   136  	assert.Equal(t, "0xf2cee375fa42b42143804025fc449deafd50cc031ca257e0b194a650a912090f", ethcoder.HexEncode(domainHash))
   137  
   138  	digest, err := typedData.EncodeDigest()
   139  	assert.NoError(t, err)
   140  	assert.Equal(t, "0x2218fda59750be7bb9e5dfb2b49e4ec000dc2542862c5826f1fe980d6d727e95", ethcoder.HexEncode(digest))
   141  
   142  	// fmt.Println("===> digest", HexEncode(digest))
   143  
   144  }