Handling Native Tokens with 0x Swap API
When using the 0x Swap API to handle native tokens like ETH, the process differs from ERC-20 tokens. This guide explains how to manage native tokens properly and provides context on their representation in the blockchain ecosystem.
Understanding Native Tokens
Native tokens are the foundational currencies of their respective blockchains. Examples include ETH on Ethereum, BNB on Binance Smart Chain, and POL on Polygon. Since native tokens do not inherently have a contract address (unlike ERC-20 tokens), the address 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
is commonly used to represent native tokens in blockchain transactions.
Notes on Native Token Representation
- On Ethereum: This address represents Ether (ETH), as ETH is not an ERC-20 token.
- On Mantle Network: An exception is the native token $MNT, which does have a contract address (
0xdeaddeaddeaddeaddeaddeaddeaddeaddead0000
) for use on the Mantle EVM chain. This address is specific to $MNT on Mantle and does not apply to wrapped or bridged versions of $MNT on other networks. See this guide to understand other differences between Ethereum and Mantle.
For more context on native token addresses:
Steps for Handling Native Tokens
Skip the allowance check: Unlike ERC-20 tokens, native tokens do not require an allowance or approval step. Therefore, you can skip the
approve()
call when preparing to send native tokens.Set the transaction value: Ensure that the
value
field in your transaction parameters accurately reflects the amount of native token (in wei) you intend to send.
⚡️ Quicklink
See a full Swap API headless example that demonstrates how to handle native tokens. See the running instructions here.
Code example
Here's a code snippet of how you can implement the above steps:
import { createWalletClient, http, parseEther, sendTransaction } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { mainnet } from 'viem/chains';
// Create a wallet client using your private key
const account = privateKeyToAccount('YOUR_PRIVATE_KEY');
const client = createWalletClient({
account,
chain: mainnet,
transport: http('https://eth-mainnet.g.alchemy.com/v2/YOUR_ALCHEMY_KEY'), // Provide an authenticated RPC URL to avoid rate-limiting
});
// Check if the sellToken is a native token (ETH) to skip the allowance check
if (eth.address === '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE') {
console.log('Native token detected, no need for an allowance check');
} else {
// Check if allowance is required for non-native tokens
if (price.issues.allowance !== null) {
try {
const { request } = await eth.simulate.approve([price.issues.allowance.spender, maxUint256]);
// Remainder of code...
} catch (error) {
console.error('Error approving token:', error);
}
}
}
// Check if it's a native token (like ETH)
if (eth.address === '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE') {
const nonce = await client.getTransactionCount({
address: client.account.address,
});
// Directly sign and send the native token transaction
const txHash = await client.sendTransaction({
account: client.account,
chain: client.chain,
gas: quote?.transaction.gas ? BigInt(quote.transaction.gas) : undefined,
to: quote?.transaction.to,
data: quote.transaction.data,
value: BigInt(quote.transaction.value), // Ensure value is set for native tokens
gasPrice: quote?.transaction.gasPrice ? BigInt(quote.transaction.gasPrice) : undefined,
nonce: nonce,
});
// Log the transaction hash
console.log('Transaction sent:', txHash);
}
Wrapping and Unwrapping between ETH and WETH
Easily wrap and unwrap between ETH and WETH by requesting a swap quote by setting sellToken
and buyToken
as either the contract address for WETH or ETH. The swap quote returned will provide the calldata to directly interact with the WETH9 contract and not with 0x Settler contract.
Wrap ETH
GET
curl --request GET \
https://api.0x.org/swap/permit2/quote?buyToken=0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2&sellToken=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE&buyAmount=10000000" \
--header '0x-api-key: YOUR_API_KEY'
--header '0x-version: v2'
Unwrap ETH
GET
curl --request GET \
https://api.0x.org/swap/permit2/quote?buyToken=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE&sellToken=0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2&buyAmount=10000000" \
--header '0x-api-key: YOUR_API_KEY'
--header '0x-version: v2'