let walletProvider, walletSigner;
{ name: "name", type: "string" },
{ name: "version", type: "string" },
{ name: "verifyingContract", type: "address" },
{ name: "salt", type: "bytes32" },
const metaTransactionType = [
{ name: "nonce", type: "uint256" },
{ name: "from", type: "address" },
{ name: "functionSignature", type: "bytes" }
// replace the chainId 42 if network is not kovan
verifyingContract: config.contract.address,
salt: ethers.utils.hexZeroPad((ethers.BigNumber.from(42)).toHexString(), 32)
let contract = new ethers.Contract(<CONTRACT_ADDRESS>,
<CONTRACT_ABI>, biconomy.getSignerByAddress(userAddress));
let contractInterface = new ethers.utils.Interface(<CONTRACT_ABI>);
This provider is linked to your wallet.
If needed, substitute your wallet solution in place of window.ethereum
walletProvider = new ethers.providers.Web3Provider(window.ethereum);
walletSigner = walletProvider.getSigner();
let nonce = await contract.getNonce(userAddress);
let functionSignature = contractInterface.encodeFunctionData("setQuote", [newQuote]);
message.nonce = parseInt(nonce);
message.from = userAddress;
message.functionSignature = functionSignature;
const dataToSign = JSON.stringify({
EIP712Domain: domainType,
MetaTransaction: metaTransactionType
primaryType: "MetaTransaction",
/*Its important to use eth_signTypedData_v3 and not v4 to get EIP712 signature
because we have used salt in domain data instead of chainId*/
// Get the EIP-712 Signature and send the transaction
let signature = await walletProvider.send("eth_signTypedData_v3", [userAddress, dataToSign])
let { r, s, v } = getSignatureParameters(signature);
let tx = contract.executeMetaTransaction(userAddress,
functionSignature, r, s, v);
console.log("Transaction hash : ", tx.hash);
const getSignatureParameters = signature => {
if (!ethers.utils.isHexString(signature)) {
'Given value "'.concat(signature, '" is not a valid hex string.')
var r = signature.slice(0, 66);
var s = "0x".concat(signature.slice(66, 130));
var v = "0x".concat(signature.slice(130, 132));
v = ethers.BigNumber.from(v).toNumber();
if (![27, 28].includes(v)) v += 27;