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 := ðcoder.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 := ðcoder.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 }