let sigUtil = require("eth-sig-util"); // additional dependency
let contract = new ethers.Contract(<CONTRACT_ADDRESS>,
<CONTRACT_ABI>, biconomy.getSignerByAddress(userAddress));
let contractInterface = new ethers.utils.Interface(<CONTRACT_ABI>);
let privateKey = <PRIVATE_KEY>;
let wallet = new ethers.Wallet(privateKey);
let nonce = await contract.getNonce(userAddress);
let functionSignature = contractInterface.encodeFunctionData("setQuote", [newQuote]);
message.nonce = parseInt(nonce);
message.from = userAddress;
message.functionSignature = functionSignature;
//please refer to SDK front end example for domainType and domainData
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*/
const signature = sigUtil.signTypedMessage(new Buffer.from(privateKey, 'hex'), { data: dataToSign }, 'V3');
let { r, s, v } = getSignatureParameters(signature); // same helper used in SDK frontend code
to: <YOUR_CONTRACT_ADDRESS>,
data: contractInterface.encodeFunctionData("executeMetaTransaction", [userAddress, functionData, r, s, v]),
tx = await wallet.signTransaction(rawTx);
let receipt = await ethersProvider.sendTransaction(tx);
/*Ethers check the hash from user's signed tx and hash returned from Biconomy
Both hash are expected to be different as biconomy send the transaction from its relayers*/
// You could also refer to https://github.com/bcnmy/metatx-standard/blob/kovan-demo-ethers-backend/example/react-ui/src/App.js
if (error.returnedHash && error.expectedHash) {
console.log("Transaction hash : ", error.returnedHash);
transactionHash = error.returnedHash;
showErrorMessage("Error while sending transaction");
// display transactionHash
let receipt = await ethersProvider.waitForTransaction(transactionHash);
showErrorMessage("Could not get transaction hash");