Pay Gas in ERC20
In this tutorial, we'll learn how to pay gas in ERC20 using Sequence Kit's hooks.
Step by Step Guide
Setup Sequence Kit
Go to the Getting Started page to learn how to setup Sequence Kit if you haven't already.
Pay gas in native currency
Next, we'll create a simple page that allows users to send an unsponsored transaction using their smart wallet's native currency.
import React, { useState, useEffect } from 'react';
import { Box, Button, Card, Select, Text } from '@0xsequence/design-system';
import { useWaasFeeOptions } from '@0xsequence/kit';
import { formatUnits } from 'viem';
import { useAccount, useSendTransaction } from 'wagmi';
export const ERC20GasPaymentExample = () => {
const { address } = useAccount();
const {
sendTransaction,
isPending,
isSuccess,
data: txHash
} = useSendTransaction();
const sendUnsponsored = () => {
if (!address) return;
// Send a simple 0 value transaction to yourself
sendTransaction({
to: address,
value: BigInt(0),
gas: null
});
};
return (
<>
<Box>
<Text>Address: {address}</Text>
<Button onClick={sendUnsponsored}>Send Unsponsored</Button>
{isPending && <Text>Pending...</Text>}
{isSuccess && <Text>Success! Tx Hash: {txHash}</Text>}
</Box>
</>
)
}Pay gas in ERC20
Next, we'll use the useWaasFeeOptions hook to allow users to pay gas in ERC20.
How this works
Behind the scenes, the WaaS connector intercepts this transaction request and triggers the fee confirmation flow.
Now that we declared the useWaasFeeOptions hook, it has set up an effect that overrides the default feeConfirmationHandler of the WaaS provider adding the possibility to pay with ERC20 tokens, you do not have to do anything else.
import React, { useState, useEffect } from 'react';
import { Box, Button, Card, Select, Text } from '@0xsequence/design-system';
import { useWaasFeeOptions } from '@0xsequence/kit';
import { formatUnits } from 'viem';
import { useAccount, useSendTransaction } from 'wagmi';
export const ERC20GasPaymentExample = () => {
const { address } = useAccount();
const [pendingFeeOptionConfirmation, confirmPendingFeeOption] = useWaasFeeOptions();
const {
sendTransaction,
isPending,
isSuccess,
data: txHash
} = useSendTransaction();
const [selectedFeeTokenName, setSelectedFeeTokenName] = useState<string>();
useEffect(() => {
if (pendingFeeOptionConfirmation && pendingFeeOptionConfirmation.options.length > 0) {
setSelectedFeeTokenName(pendingFeeOptionConfirmation.options[0].token.name);
}
}, [pendingFeeOptionConfirmation]);
const sendUnsponsored = () => {
if (!address) return;
// Send a simple 0 value transaction to yourself
sendTransaction({
to: address,
value: BigInt(0),
gas: null
});
};
return (
<>
<Box>
<Text>Address: {address}</Text>
<Button onClick={sendUnsponsored}>Send Unsponsored</Button>
{isPending && <Text>Pending...</Text>}
{isSuccess && <Text>Success! Tx Hash: {txHash}</Text>}
</Box>
</>
)
}Add a fee token selector (UI)
Next, we'll add a fee token selector to allow users to choose the fee token they want to pay with.
import React, { useState, useEffect } from 'react';
import { Box, Button, Card, Select, Text } from '@0xsequence/design-system';
import { useWaasFeeOptions } from '@0xsequence/kit';
import { formatUnits } from 'viem';
import { useAccount, useSendTransaction } from 'wagmi';
export const ERC20GasPaymentExample = () => {
const { address } = useAccount();
// 1. Set up the fee options hook
const [pendingFeeOptionConfirmation, confirmPendingFeeOption, rejectPendingFeeOption] = useWaasFeeOptions();
// 2. Set up transaction state
const {
sendTransaction,
isPending,
isSuccess,
data: txHash
} = useSendTransaction();
// 3. Track selected fee token
const [selectedFeeTokenName, setSelectedFeeTokenName] = useState<string>();
// 4. Initialize with first option when fee options become available
useEffect(() => {
if (pendingFeeOptionConfirmation && pendingFeeOptionConfirmation.options.length > 0) {
setSelectedFeeTokenName(pendingFeeOptionConfirmation.options[0].token.name);
}
}, [pendingFeeOptionConfirmation]);
// 5. Function to send an unsponsored transaction
const sendUnsponsored = () => {
if (!address) return;
// Send a simple 0 value transaction to yourself
sendTransaction({
to: address,
value: BigInt(0),
gas: null
});
};
return (
<Box padding="4" flexDirection="column" gap="4" maxWidth="500px" margin="0 auto">
<Card padding="4">
<Text variant="large" fontWeight="bold" marginBottom="4">
ERC20 Gas Payment Example
</Text>
<Button
onClick={sendUnsponsored}
label="Send Unsponsored Transaction"
variant="primary"
isLoading={isPending}
disabled={isPending}
marginBottom="4"
/>
{isSuccess && txHash && (
<Box marginY="4" padding="3" background="positive" borderRadius="md">
<Text>Transaction successful! Hash: {txHash}</Text>
</Box>
)}
{/* Fee selection UI appears when needed */}
{pendingFeeOptionConfirmation && (
<Box marginTop="4" flexDirection="column" gap="3">
<Text fontWeight="semibold">
Select Token to Pay Gas Fees
</Text>
<Select
name="feeOption"
labelLocation="top"
label="Available Fee Options"
value={selectedFeeTokenName}
onValueChange={(value) => setSelectedFeeTokenName(value)}
options={pendingFeeOptionConfirmation.options.map(option => ({
label: (
<Box flexDirection="column" gap="1">
<Text>{option.token.name}</Text>
<Box flexDirection="row" gap="1">
<Text variant="small" color="text50">Fee:</Text>
<Text variant="small">
{formatUnits(BigInt(option.value), option.token.decimals || 18)} {option.token.symbol}
</Text>
</Box>
{option.hasEnoughBalanceForFee !== undefined && (
<Text
variant="small"
color={option.hasEnoughBalanceForFee ? "positive" : "negative"}
>
{option.hasEnoughBalanceForFee ? "Sufficient balance" : "Insufficient balance"}
</Text>
)}
</Box>
),
value: option.token.name
}))}
/>
<Box flexDirection="row" gap="2" justifyContent="flex-end">
<Button
variant="secondary"
label="Cancel"
onClick={() => rejectPendingFeeOption(pendingFeeOptionConfirmation.id)}
/>
<Button
variant="primary"
label="Confirm"
onClick={() => {
const selected = pendingFeeOptionConfirmation.options.find(
option => option.token.name === selectedFeeTokenName
);
if (selected) {
confirmPendingFeeOption(
pendingFeeOptionConfirmation.id,
selected.token.contractAddress
);
}
}}
/>
</Box>
</Box>
)}
</Card>
</Box>
);
};Congratulations! You've just learned how to pay gas in ERC20 using Sequence Kit.