Gas Sponsor (Paymaster)¶
A paymaster is a smart contract that pays gas fees on behalf of users. This lets you build dapps where users never need to hold DILI for gas -- the sponsor contract covers the cost.
How It Works¶
- Your dapp passes a
paymasteraddress in theTxOptionsof any transactional function. - The wallet includes the paymaster address in the signed transaction.
- The network charges gas to the paymaster contract instead of the user's account.
The paymaster contract must be pre-funded and must accept the transaction (paymasters can implement allowlists, rate limits, etc.).
Supported Functions¶
The following wallet functions accept a paymaster option via TxOptions:
| Function | Description |
|---|---|
signPayload |
Sign a structured payload |
sendTransaction |
Submit a pre-built transaction |
callContract |
Build and submit a contract call |
transfer |
Transfer DILI tokens |
shieldedDeposit |
Deposit into the shielded pool |
shieldedWithdraw |
Withdraw from the shielded pool |
Example: Sponsored Transfer¶
import { connect, transfer, createChainClient } from "@dilithia/browser-sdk";
const SPONSOR = "dili1myappsponsor";
const session = await connect();
const chain = createChainClient(session.rpcUrl);
// User pays no gas -- the sponsor contract covers it
const tx = await transfer("dili1bob", 100, { paymaster: SPONSOR });
const receipt = await chain.waitForReceipt(tx.txHash);
console.log("Status:", receipt.status);
console.log("Fee paid by sponsor:", receipt.feePaid, "DILI");
Example: Sponsored Contract Call¶
import { callContract, createChainClient, connect } from "@dilithia/browser-sdk";
const SPONSOR = "dili1myappsponsor";
const session = await connect();
const chain = createChainClient(session.rpcUrl);
const tx = await callContract(
"dili1nftcontract",
"mint",
{ tokenId: 42, metadata: "ipfs://Qm..." },
{ paymaster: SPONSOR },
);
const receipt = await chain.waitForReceipt(tx.txHash);
console.log("Minted! Block:", receipt.blockHeight);
Example: Sponsored Shielded Deposit¶
import { shieldedDeposit, createChainClient, connect } from "@dilithia/browser-sdk";
const SPONSOR = "dili1myappsponsor";
const session = await connect();
const chain = createChainClient(session.rpcUrl);
// Deposit into the shielded pool with sponsored gas
const deposit = await shieldedDeposit(500, { paymaster: SPONSOR });
console.log("Commitment:", deposit.commitment);
const receipt = await chain.waitForReceipt(deposit.txHash);
console.log("Deposit confirmed at block", receipt.blockHeight);
Tips¶
Paymaster funding
Make sure your paymaster contract has enough DILI to cover gas for your users. Monitor its balance with chain.getBalance("dili1myappsponsor").
Combine with shielded withdrawals
You can sponsor shielded withdrawals too. This is useful when the recipient has no public balance to pay gas:
Paymaster rejection
If the paymaster contract rejects the transaction (e.g., the user is not on its allowlist), the wallet will throw an error. Handle it with try/catch.