Skip to content

Instantly share code, notes, and snippets.

@arcticfloyd1984
Created April 12, 2022 23:17
Show Gist options
  • Save arcticfloyd1984/518c449afdcbf4500d429934cab280fe to your computer and use it in GitHub Desktop.
Save arcticfloyd1984/518c449afdcbf4500d429934cab280fe to your computer and use it in GitHub Desktop.
Batched Transactions
const { Biconomy } = require("@biconomy/mexa");
const { ethers } = require("ethers");
const axios = require('axios').default;
const privateKey = "0xd952fa86f1e2fed30fb3a6da6e5c24d7deb65b6bb46da3ece5f56fd39e64bbd0";
let userAddress1 = ethers.utils.getAddress("0x040a9cbc4453b0eeae12f3210117b422b890c1ed");
let userAddress2 = ethers.utils.getAddress("0x4c07e2fa10f9871142883139b32cb03f2a180494");
let userAddress3 = ethers.utils.getAddress("0x6561ad57cde7863bce871977c951af21bec2e74c");
let userAddress4 = ethers.utils.getAddress("0xaa7f52b2bf183ce85c1d291d838030df41018a44");
let userAddress5 = ethers.utils.getAddress("0x02649f6d43556e76cf7a515a9f589bb23287378d");
let userAddresses = [userAddress1, userAddress2, userAddress3, userAddress4, userAddress5];
let contracts = [];
let biconomy;
let jsonRpcProvider;
let signer;
let helperAttributes = {
domainType: [
{ name: "name", type: "string" },
{ name: "version", type: "string" },
{ name: "verifyingContract", type: "address" },
{ name: "salt", type: "bytes32" },
],
forwardRequestType: [
{name:'from',type:'address'},
{name:'to',type:'address'},
{name:'token',type:'address'},
{name:'txGas',type:'uint256'},
{name:'tokenGasPrice',type:'uint256'},
{name:'batchId',type:'uint256'},
{name:'batchNonce',type:'uint256'},
{name:'deadline',type:'uint256'},
{name:'data',type:'bytes'}
],
biconomyForwarderDomainData: {
name : "Biconomy Forwarder",
version : "1",
}
};
let ethersProvider;
const abi = [ { "inputs": [ { "internalType": "string", "name": "newQuote", "type": "string" } ], "name": "setQuote", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "_trustedForwarder", "type": "address" } ], "name": "setTrustedForwarder", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "stateMutability": "nonpayable", "type": "constructor" }, { "inputs": [], "name": "admin", "outputs": [ { "internalType": "address", "name": "", "type": "address" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "getQuote", "outputs": [ { "internalType": "string", "name": "currentQuote", "type": "string" }, { "internalType": "address", "name": "currentOwner", "type": "address" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "forwarder", "type": "address" } ], "name": "isTrustedForwarder", "outputs": [ { "internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "owner", "outputs": [ { "internalType": "address", "name": "", "type": "address" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "quote", "outputs": [ { "internalType": "string", "name": "", "type": "string" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "trustedForwarder", "outputs": [ { "internalType": "address", "name": "", "type": "address" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "versionRecipient", "outputs": [ { "internalType": "string", "name": "", "type": "string" } ], "stateMutability": "view", "type": "function" } ]
const init = async () => {
jsonRpcProvider = new ethers.providers.JsonRpcProvider("https://kovan.infura.io/v3/30125eccc47e475b9a9421f0eaf1e19c");
biconomy = new Biconomy(jsonRpcProvider, {
// apiKey: "UoqE4xJwj.6146f43c-07a6-45a7-84f9-edbf9ba19480",
apiKey: "yARl7lxj5.715a8264-060f-41c0-b588-146b42190e0c",
debug: true
});
ethersProvider = new ethers.providers.Web3Provider(biconomy);
signer = new ethers.Wallet(privateKey, jsonRpcProvider);
biconomy.onEvent(biconomy.READY, async () => {
for(let userAddressIndex = 0; userAddressIndex < userAddresses.length; userAddressIndex++) {
let contract = new ethers.Contract(
ethers.utils.getAddress("0x5df74db6377bfd6d81ffa622f9c9c1451249fcf4"),
abi,
biconomy.getSignerByAddress(userAddresses[userAddressIndex])
);
contracts.push(contract);
}
contractInterface = new ethers.utils.Interface(abi);
await executeBatchedTransactionsEIP712();
// await executeBatchedTransactionsPersonalSign();
}).onEvent(biconomy.ERROR, (error, message) => {
// Handle error while initializing mexa
console.log(message);
console.log(error);
});
}
const executeBatchedTransactionsEIP712 = async () => {
try {
let gasPrice = await ethersProvider.getGasPrice();
let forwarder = {address: "0x94Dc33585513129b4b30dAD7Ec2C53cD1F976f47", abi: [ { "inputs": [ { "internalType": "address", "name": "_owner", "type": "address" } ], "stateMutability": "nonpayable", "type": "constructor" }, { "anonymous": false, "inputs": [ { "indexed": true, "internalType": "bytes32", "name": "domainSeparator", "type": "bytes32" }, { "indexed": false, "internalType": "bytes", "name": "domainValue", "type": "bytes" } ], "name": "DomainRegistered", "type": "event" }, { "inputs": [ { "components": [ { "internalType": "address", "name": "from", "type": "address" }, { "internalType": "address", "name": "to", "type": "address" }, { "internalType": "uint256", "name": "txGas", "type": "uint256" }, { "internalType": "uint256", "name": "batchId", "type": "uint256" }, { "internalType": "uint256", "name": "batchNonce", "type": "uint256" }, { "internalType": "uint256", "name": "deadline", "type": "uint256" }, { "internalType": "bytes", "name": "data", "type": "bytes" } ], "internalType": "struct ERC20ForwardRequestTypes.ERC20ForwardRequest[]", "name": "reqs", "type": "tuple[]" }, { "internalType": "bytes32", "name": "domainSeparator", "type": "bytes32" }, { "internalType": "bytes[]", "name": "sigs", "type": "bytes[]" } ], "name": "executeBatchEIP712", "outputs": [ { "internalType": "bytes[]", "name": "results", "type": "bytes[]" } ], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "components": [ { "internalType": "address", "name": "from", "type": "address" }, { "internalType": "address", "name": "to", "type": "address" }, { "internalType": "uint256", "name": "txGas", "type": "uint256" }, { "internalType": "uint256", "name": "batchId", "type": "uint256" }, { "internalType": "uint256", "name": "batchNonce", "type": "uint256" }, { "internalType": "uint256", "name": "deadline", "type": "uint256" }, { "internalType": "bytes", "name": "data", "type": "bytes" } ], "internalType": "struct ERC20ForwardRequestTypes.ERC20ForwardRequest[]", "name": "reqs", "type": "tuple[]" }, { "internalType": "bytes[]", "name": "sigs", "type": "bytes[]" } ], "name": "executeBatchPersonalSign", "outputs": [ { "internalType": "bytes[]", "name": "results", "type": "bytes[]" } ], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "components": [ { "internalType": "address", "name": "from", "type": "address" }, { "internalType": "address", "name": "to", "type": "address" }, { "internalType": "uint256", "name": "txGas", "type": "uint256" }, { "internalType": "uint256", "name": "batchId", "type": "uint256" }, { "internalType": "uint256", "name": "batchNonce", "type": "uint256" }, { "internalType": "uint256", "name": "deadline", "type": "uint256" }, { "internalType": "bytes", "name": "data", "type": "bytes" } ], "internalType": "struct ERC20ForwardRequestTypes.ERC20ForwardRequest", "name": "req", "type": "tuple" }, { "internalType": "bytes32", "name": "domainSeparator", "type": "bytes32" }, { "internalType": "bytes", "name": "sig", "type": "bytes" } ], "name": "executeEIP712", "outputs": [ { "internalType": "bool", "name": "success", "type": "bool" }, { "internalType": "bytes", "name": "ret", "type": "bytes" } ], "stateMutability": "nonpayable", "type": "function" }, { "anonymous": false, "inputs": [ { "indexed": true, "internalType": "address", "name": "previousOwner", "type": "address" }, { "indexed": true, "internalType": "address", "name": "newOwner", "type": "address" } ], "name": "OwnershipTransferred", "type": "event" }, { "inputs": [ { "internalType": "string", "name": "name", "type": "string" }, { "internalType": "string", "name": "version", "type": "string" } ], "name": "registerDomainSeparator", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "renounceOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "newOwner", "type": "address" } ], "name": "transferOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "bytes32", "name": "", "type": "bytes32" } ], "name": "domains", "outputs": [ { "internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "EIP712_DOMAIN_TYPE", "outputs": [ { "internalType": "string", "name": "", "type": "string" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "from", "type": "address" }, { "internalType": "uint256", "name": "batchId", "type": "uint256" } ], "name": "getNonce", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "isOwner", "outputs": [ { "internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "owner", "outputs": [ { "internalType": "address", "name": "", "type": "address" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "REQUEST_TYPEHASH", "outputs": [ { "internalType": "bytes32", "name": "", "type": "bytes32" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "components": [ { "internalType": "address", "name": "from", "type": "address" }, { "internalType": "address", "name": "to", "type": "address" }, { "internalType": "uint256", "name": "txGas", "type": "uint256" }, { "internalType": "uint256", "name": "batchId", "type": "uint256" }, { "internalType": "uint256", "name": "batchNonce", "type": "uint256" }, { "internalType": "uint256", "name": "deadline", "type": "uint256" }, { "internalType": "bytes", "name": "data", "type": "bytes" } ], "internalType": "struct ERC20ForwardRequestTypes.ERC20ForwardRequest", "name": "req", "type": "tuple" }, { "internalType": "bytes32", "name": "domainSeparator", "type": "bytes32" }, { "internalType": "bytes", "name": "sig", "type": "bytes" } ], "name": "verifyEIP712", "outputs": [], "stateMutability": "view", "type": "function" }, { "inputs": [ { "components": [ { "internalType": "address", "name": "from", "type": "address" }, { "internalType": "address", "name": "to", "type": "address" }, { "internalType": "uint256", "name": "txGas", "type": "uint256" }, { "internalType": "uint256", "name": "batchId", "type": "uint256" }, { "internalType": "uint256", "name": "batchNonce", "type": "uint256" }, { "internalType": "uint256", "name": "deadline", "type": "uint256" }, { "internalType": "bytes", "name": "data", "type": "bytes" } ], "internalType": "struct ERC20ForwardRequestTypes.ERC20ForwardRequest", "name": "req", "type": "tuple" }, { "internalType": "bytes", "name": "sig", "type": "bytes" } ], "name": "verifyPersonalSign", "outputs": [], "stateMutability": "view", "type": "function" } ]};
const forwarderContracts = [];
const to = ethers.utils.getAddress("0x5df74db6377bfd6d81ffa622f9c9c1451249fcf4");
const domainSeparator = await getDomainSeperator(42);
const sigs = [];
const reqs = [];
for(let userAddressIndex = 0; userAddressIndex < userAddresses.length; userAddressIndex++) {
let { data } = await contracts[userAddressIndex].populateTransaction.setQuote(`newQuote_${userAddresses[userAddressIndex]}`);
let gasLimit = await ethersProvider.estimateGas({
to: ethers.utils.getAddress("0x5df74db6377bfd6d81ffa622f9c9c1451249fcf4"),
from: userAddresses[userAddressIndex],
data: data,
});
let forwarderContract = new ethers.Contract(
forwarder.address,
forwarder.abi,
biconomy.getSignerByAddress(userAddresses[userAddressIndex])
);
forwarderContracts.push(forwarderContract);
const batchNonce = await forwarderContract.getNonce(userAddresses[userAddressIndex], 0);
const batchId = 0;
const gasLimitNum = Number(gasLimit.toNumber().toString());
const req = await buildForwardTxRequest({
account: (userAddresses[userAddressIndex]),
to,
gasLimitNum,
batchId,
batchNonce,
data,
});
reqs.push(req);
const dataToSign = await getDataToSignForEIP712(req);
console.log("signer", signer);
const sig = await signer._signTypedData(dataToSign.domain, dataToSign.types, dataToSign.message);
console.log("sig", sig);
sigs.push(sig);
console.log("sigs", sigs);
}
sendBatchedTransaction({
sigs,
domainSeparator,
reqs
}, "EIP712_SIGN");
} catch(error) {
console.log(error);
}
}
const executeBatchedTransactionsPersonalSign = async () => {
try {
const sigs = [];
const reqs = [];
let forwarder = {address: "0x94Dc33585513129b4b30dAD7Ec2C53cD1F976f47", abi: [ { "inputs": [ { "internalType": "address", "name": "_owner", "type": "address" } ], "stateMutability": "nonpayable", "type": "constructor" }, { "anonymous": false, "inputs": [ { "indexed": true, "internalType": "bytes32", "name": "domainSeparator", "type": "bytes32" }, { "indexed": false, "internalType": "bytes", "name": "domainValue", "type": "bytes" } ], "name": "DomainRegistered", "type": "event" }, { "inputs": [ { "components": [ { "internalType": "address", "name": "from", "type": "address" }, { "internalType": "address", "name": "to", "type": "address" }, { "internalType": "address", "name": "token", "type": "address" }, { "internalType": "uint256", "name": "txGas", "type": "uint256" }, { "internalType": "uint256", "name": "tokenGasPrice", "type": "uint256" }, { "internalType": "uint256", "name": "batchId", "type": "uint256" }, { "internalType": "uint256", "name": "batchNonce", "type": "uint256" }, { "internalType": "uint256", "name": "deadline", "type": "uint256" }, { "internalType": "bytes", "name": "data", "type": "bytes" } ], "internalType": "struct ERC20ForwardRequestTypes.ERC20ForwardRequest[]", "name": "reqs", "type": "tuple[]" }, { "internalType": "bytes32", "name": "domainSeparator", "type": "bytes32" }, { "internalType": "bytes[]", "name": "sigs", "type": "bytes[]" } ], "name": "executeBatchEIP712", "outputs": [ { "internalType": "bytes[]", "name": "results", "type": "bytes[]" } ], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "components": [ { "internalType": "address", "name": "from", "type": "address" }, { "internalType": "address", "name": "to", "type": "address" }, { "internalType": "address", "name": "token", "type": "address" }, { "internalType": "uint256", "name": "txGas", "type": "uint256" }, { "internalType": "uint256", "name": "tokenGasPrice", "type": "uint256" }, { "internalType": "uint256", "name": "batchId", "type": "uint256" }, { "internalType": "uint256", "name": "batchNonce", "type": "uint256" }, { "internalType": "uint256", "name": "deadline", "type": "uint256" }, { "internalType": "bytes", "name": "data", "type": "bytes" } ], "internalType": "struct ERC20ForwardRequestTypes.ERC20ForwardRequest[]", "name": "reqs", "type": "tuple[]" }, { "internalType": "bytes[]", "name": "sigs", "type": "bytes[]" } ], "name": "executeBatchPersonalSign", "outputs": [ { "internalType": "bytes[]", "name": "results", "type": "bytes[]" } ], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "components": [ { "internalType": "address", "name": "from", "type": "address" }, { "internalType": "address", "name": "to", "type": "address" }, { "internalType": "address", "name": "token", "type": "address" }, { "internalType": "uint256", "name": "txGas", "type": "uint256" }, { "internalType": "uint256", "name": "tokenGasPrice", "type": "uint256" }, { "internalType": "uint256", "name": "batchId", "type": "uint256" }, { "internalType": "uint256", "name": "batchNonce", "type": "uint256" }, { "internalType": "uint256", "name": "deadline", "type": "uint256" }, { "internalType": "bytes", "name": "data", "type": "bytes" } ], "internalType": "struct ERC20ForwardRequestTypes.ERC20ForwardRequest", "name": "req", "type": "tuple" }, { "internalType": "bytes32", "name": "domainSeparator", "type": "bytes32" }, { "internalType": "bytes", "name": "sig", "type": "bytes" } ], "name": "executeEIP712", "outputs": [ { "internalType": "bool", "name": "success", "type": "bool" }, { "internalType": "bytes", "name": "ret", "type": "bytes" } ], "stateMutability": "nonpayable", "type": "function" }, { "anonymous": false, "inputs": [ { "indexed": true, "internalType": "address", "name": "previousOwner", "type": "address" }, { "indexed": true, "internalType": "address", "name": "newOwner", "type": "address" } ], "name": "OwnershipTransferred", "type": "event" }, { "inputs": [ { "internalType": "string", "name": "name", "type": "string" }, { "internalType": "string", "name": "version", "type": "string" } ], "name": "registerDomainSeparator", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "renounceOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "newOwner", "type": "address" } ], "name": "transferOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "bytes32", "name": "", "type": "bytes32" } ], "name": "domains", "outputs": [ { "internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "EIP712_DOMAIN_TYPE", "outputs": [ { "internalType": "string", "name": "", "type": "string" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "from", "type": "address" }, { "internalType": "uint256", "name": "batchId", "type": "uint256" } ], "name": "getNonce", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "isOwner", "outputs": [ { "internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "owner", "outputs": [ { "internalType": "address", "name": "", "type": "address" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "REQUEST_TYPEHASH", "outputs": [ { "internalType": "bytes32", "name": "", "type": "bytes32" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "components": [ { "internalType": "address", "name": "from", "type": "address" }, { "internalType": "address", "name": "to", "type": "address" }, { "internalType": "address", "name": "token", "type": "address" }, { "internalType": "uint256", "name": "txGas", "type": "uint256" }, { "internalType": "uint256", "name": "tokenGasPrice", "type": "uint256" }, { "internalType": "uint256", "name": "batchId", "type": "uint256" }, { "internalType": "uint256", "name": "batchNonce", "type": "uint256" }, { "internalType": "uint256", "name": "deadline", "type": "uint256" }, { "internalType": "bytes", "name": "data", "type": "bytes" } ], "internalType": "struct ERC20ForwardRequestTypes.ERC20ForwardRequest", "name": "req", "type": "tuple" }, { "internalType": "bytes32", "name": "domainSeparator", "type": "bytes32" }, { "internalType": "bytes", "name": "sig", "type": "bytes" } ], "name": "verifyEIP712", "outputs": [], "stateMutability": "view", "type": "function" }, { "inputs": [ { "components": [ { "internalType": "address", "name": "from", "type": "address" }, { "internalType": "address", "name": "to", "type": "address" }, { "internalType": "address", "name": "token", "type": "address" }, { "internalType": "uint256", "name": "txGas", "type": "uint256" }, { "internalType": "uint256", "name": "tokenGasPrice", "type": "uint256" }, { "internalType": "uint256", "name": "batchId", "type": "uint256" }, { "internalType": "uint256", "name": "batchNonce", "type": "uint256" }, { "internalType": "uint256", "name": "deadline", "type": "uint256" }, { "internalType": "bytes", "name": "data", "type": "bytes" } ], "internalType": "struct ERC20ForwardRequestTypes.ERC20ForwardRequest", "name": "req", "type": "tuple" }, { "internalType": "bytes", "name": "sig", "type": "bytes" } ], "name": "verifyPersonalSign", "outputs": [], "stateMutability": "view", "type": "function" } ]};
const to = ethers.utils.getAddress("0x5df74db6377bfd6d81ffa622f9c9c1451249fcf4");
for(let userAddressIndex = 0; userAddressIndex < userAddresses.length; userAddressIndex++) {
let { data } = await contracts[userAddressIndex].populateTransaction.setQuote(`newQuote_${userAddresses[userAddressIndex]}`);
let gasPrice = await ethersProvider.getGasPrice();
let gasLimit = await ethersProvider.estimateGas({
to: config.contract.address,
from: userAddresses[userAddressIndex],
data: data,
});
let forwarderContract = new ethers.Contract(
forwarder.address,
forwarder.abi,
biconomy.getSignerByAddress(userAddresses[userAddressIndex])
);
const batchNonce = await forwarderContract.getNonce(userAddresses[userAddressIndex], userAddressIndex);
const batchId = userAddressIndex;
const gasLimitNum = Number(gasLimit.toNumber().toString());
const req = await buildForwardTxRequest({
account: userAddresses[userAddressIndex],
to,
gasLimitNum,
batchId,
batchNonce,
data,
});
req.push(req);
const hashToSign = getDataToSignForPersonalSign(req);
const sig = signer.signMessage(hashToSign);
sigs.push(sig);
}
} catch (error) {
console.log(error);
}
}
const sendBatchedTransaction = async (batchedTransactionRequests, signatureType) => {
try {
/**
* batchedTransactionRequest = [{userAddress, request, sig, domainSeparator, signatureType}]
*/
let sigs = batchedTransactionRequests.sigs;
let requests = batchedTransactionRequests.reqs;
let domainSeparator = batchedTransactionRequests.domainSeparator;
console.log('Sending request to backend');
const headers = {
"x-api-key": "yARl7lxj5.715a8264-060f-41c0-b588-146b42190e0c",
"Content-Type": "application/json;charset=utf-8",
}
const data = JSON.stringify({
to: "0x5df74db6377bfd6d81ffa622f9c9c1451249fcf4",
apiId: "f0567e06-5f36-4826-bff3-1b8809642d56",
domainSeparator: domainSeparator,
requests: requests,
sigs: sigs,
userAddresses: userAddresses,
signatureType: signatureType
})
axios.post('http://localhost:4000/api/v2/meta-tx/native-batch-transactions', data, {
headers: headers
})
.then((response) => {
console.log('Response from backend')
console.log(response);
})
.catch((error) => {
console.log(error);
})
} catch (error) {
console.log(error);
}
};
const buildForwardTxRequest = async ({account, to, gasLimitNum, batchId, batchNonce, data, deadline}) => {
const req = {
from: account,
to: to,
txGas: gasLimitNum,
batchId: parseInt(batchId),
batchNonce: parseInt(batchNonce),
deadline: deadline || Math.floor(Date.now() / 1000 + 3600),
data: data
};
return req;
};
const getDomainSeperator = async (networkId) => {
const forwarderAddress = ethers.utils.getAddress("0x94Dc33585513129b4b30dAD7Ec2C53cD1F976f47");
let domainData = helperAttributes.biconomyForwarderDomainData;
domainData.salt = ethers.utils.hexZeroPad((ethers.BigNumber.from(networkId)).toHexString(), 32);
domainData.verifyingContract = forwarderAddress;
const domainSeparator = ethers.utils.keccak256(ethers.utils.defaultAbiCoder.encode([
"bytes32",
"bytes32",
"bytes32",
"address",
"bytes32"
], [
ethers.utils.id("EIP712Domain(string name,string version,address verifyingContract,bytes32 salt)"),
ethers.utils.id(domainData.name),
ethers.utils.id(domainData.version),
domainData.verifyingContract,
domainData.salt,
]));
return domainSeparator;
};
const getDataToSignForEIP712 = async (request) => {
const forwarderAddress = ethers.utils.getAddress("0x94Dc33585513129b4b30dAD7Ec2C53cD1F976f47");
let domainData = helperAttributes.biconomyForwarderDomainData;
domainData.salt = ethers.utils.hexZeroPad((ethers.BigNumber.from(42)).toHexString(), 32);
domainData.verifyingContract = forwarderAddress;
const dataToSign = {
types: {
ERC20ForwardRequest: [
{name:'from',type:'address'},
{name:'to',type:'address'},
{name:'txGas',type:'uint256'},
{name:'batchId',type:'uint256'},
{name:'batchNonce',type:'uint256'},
{name:'deadline',type:'uint256'},
{name:'data',type:'bytes'}
]
},
domain: {
name : "Biconomy Forwarder",
version : "1",
salt: ethers.utils.hexZeroPad((ethers.BigNumber.from(42)).toHexString(), 32),
verifyingContract: ethers.utils.getAddress("0x94Dc33585513129b4b30dAD7Ec2C53cD1F976f47")
},
message: request
};
return dataToSign;
}
const getDataToSignForPersonalSign = (request) => {
const hashToSign = abi.soliditySHA3([
"address",
"address",
"uint256",
"uint256",
"uint256",
"bytes32",
], [
request.from,
request.to,
request.txGas,
request.batchId,
request.batchNonce,
ethers.utils.keccak256(request.data),
]);
return hashToSign;
}
init()
// executeBatchedTransactionsEIP712();
// executeBatchedTransactionsPersonalSign();
// excuteTransactionEIP712();
// executeTransactionPersonalSign();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment