Send Hello World transactions using Gelato MetaBox SDK
- Check metabox-sdk npm package page to know more about how to use the Gelato's MetaBox relayer
- Install project dependencies:
yarn install
- Create a
.env
file to use onmumbai
network:
CHAIN_ID=80001
PROVIDER_URL="https://rpc-mumbai.maticvigil.com/"
USER_PK=""
SPONSOR_PK=""
-
USER_PK
refers to private key of the Hello World application user. We only use it in this tutorial to produce a dApp's user signature, while in reality the signature would have been obtained in a safe way! -
SPONSOR_PK
refers to the EOA that will pay transaction fee. Can be same asUSER_PK
. Note: On testnets likemumbai
Gelato will pay transaction fees. But on production networksSPONSOR
is expected to already hold a balance with Gelato.
- First, use
MetaBoxSDK.isChainSupported
to verify that your network is supported by Gelato MetaBox:
if (!process.env.CHAIN_ID) {
throw new Error("chainId is missing");
}
const chainId = parseInt(process.env.CHAIN_ID);
const isChainSupported = await MetaBoxSDK.isChainSupported(chainId);
if (!isChainSupported) {
console.log("ChainId not supported");
return;
}
- Then, use
MetaBoxSDK.metaBoxRequest
to build the necessary data to be signed and submitted:
// address of HelloWorld's user (may be same EOA as sponsor)
const userAddress = await user.getAddress();
const { address, abi } = MetaBoxSDK.getMetaBoxAddressAndABI(chainId);
const gelatoMetaBox = new Contract(address, abi, provider);
// user's smart contract nonce (to prevent replay attacks)
const nonce: number = parseInt(await gelatoMetaBox.nonce(userAddress));
// HelloWorld uses EIP-2771 for compatability with meta transactions:
// msg.sender will safely be interpreted as userAddress
const isEIP2771 = true;
const request = MetaBoxSDK.metaBoxRequest(
chainId,
// target contract to call
HELLO_WORLD,
data,
// feeToken
ETH,
userAddress,
nonce,
isEIP2771
);
- Compute
digest
by hashing request data, and then sign with each private key to produceuserSignature
andsponsorSignature
:
// Distill request data into a hash
const digest = MetaBoxSDK.getDigestToSign(request);
// user signs digest
const userSignature = utils.joinSignature(
await user._signingKey().signDigest(digest)
);
// sponsor signs digest
// Sponsor commits to paying transaction fee
// by having its balance deducted from Gelato Diamond SponsorFacet
let sponsorSignature: string | undefined = undefined;
if (sponsorPK && sponsorPK.length > 0) {
const sponsor = new Wallet(sponsorPK);
sponsorSignature = utils.joinSignature(
await sponsor._signingKey().signDigest(digest)
);
}
If user
is interacting with a UI using a wallet,
consider using MetaBoxSDK.getWalletPayloadToSign(request)
,
and then call rpc method eth_signTypedData_v4
to get userSignature
.
- Finally, use
MetaBoxSDK.sendMetaBoxTransaction
to send transaction payload to Gelato MetaBox relayer:
const taskId = await MetaBoxSDK.sendMetaBoxTransaction(
request,
userSignature,
sponsorSignature
);
Check this transaction
for an example. Notice how the user address is not msg.sender
but rather request.user
, due to the fact that req.isEIP2771
was set as true
.
By inheriting the ERC2771Context
contract as we did in HelloWorld
, and replacing all occurrences of msg.sender
by _msgSender()
, dApps can ensure that GelatoMetaBox safely passes on the original user's address whenever required.
Alternatively, for dApps whose logic does not rely on who msg.sender
or _msgSender()
is, request.isEIP2771
should be set as false
and no smart contract changes are required.
- Check the example source code
send-tx.ts
and try it yourself using:
yarn send-tx