Hi! I have been trying to figure out how to create EIP-712 signatures with ethers. I am pretty close. I discovered that using the wallet object's signMessage method is not doing the same thing as ethereumjs-util's ecsign method.
I also see that you can do this:
new ethers.utils.SigningKey('0x123...').signDigest(digestAsBuffer);
which is the same. But sadly private keys don't usually hang out in browser js.
Is there a way to do something like this?
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
signer.signDigest(digestAsBuffer);
Sort of like I did it here with web3.js. https://github.com/compound-developers/compound-governance-examples/blob/master/signature-examples/vote_by_signature.html#L62
Thank you.
You will have to use the eth_signTypedData when using a JsonRpcProvider and until I add a standard method for it, it won鈥檛 be possible to override for other subclasses of Signer. I need to research whether it is even possible in the hardware wallets.
It is generally wildly unsafe to allow signing a raw digest, which is why it isn鈥檛 generally available. There is certainly no way to add that functionality to Signer. Wallet only has the option because (like you said) the private key is just chilling there. :)
I鈥檓 finishing up some fixes for the react-native users of ethers, but EIP-712 is something I鈥檇 like to get to in the near future. :)
I found a way to make it work with Web3Provider and JsonRpcProvider (as long as you have a signer).
Here are examples for browser and Node.js based on this module I made as a dependency. Call it EIP712 in the following code examples.
Web Browser:
const provider = new ethers.providers.Web3Provider(window.ethereum);
// define your domain, primaryType, message, types
const signer = provider.getSigner();
EIP712.sign(domain, primaryType, message, types, signer).then((signature) => {
console.log('signature', signature);
}).catch(console.error);
Node.js
const provider = new ethers.providers.JsonRpcProvider('mainnet');
const wallet = new ethers.Wallet(privateKey, provider);
// define your domain, primaryType, message, types
const signer = wallet;
EIP712.sign(domain, primaryType, message, types, signer).then((signature) => {
console.log('signature', signature);
}).catch(console.error);
Most helpful comment
You will have to use the
eth_signTypedDatawhen using a JsonRpcProvider and until I add a standard method for it, it won鈥檛 be possible to override for other subclasses of Signer. I need to research whether it is even possible in the hardware wallets.It is generally wildly unsafe to allow signing a raw digest, which is why it isn鈥檛 generally available. There is certainly no way to add that functionality to Signer. Wallet only has the option because (like you said) the private key is just chilling there. :)
I鈥檓 finishing up some fixes for the react-native users of ethers, but EIP-712 is something I鈥檇 like to get to in the near future. :)