Skip to main content
Trade without holding any native gas token. The user signs a permit and an intent instead of a transaction, and DZap’s relayer sends the transaction and pays the gas, charging its fee in the source token. Gasless is EVM-only. Pick Swap or Bridge in any tab, and the rest of the page switches with it.

Setup

This example swaps 100 USDC for WETH on Arbitrum from a wallet with no ETH, signing with walletClient, a viem wallet client built from the private key in PRIVATE_KEY. Amounts are strings in the token’s smallest unit, and no API key is needed.

Steps

1

Quote

getTradeQuotes with gasless: true prices the swap as a gasless trade. pair.quoteRates lists every route and recommendedSource names DZap’s pick. The gasless fee is charged in USDC and already taken out of destAmount: fee.protocolFee shows an estimate, and the build sets the final fee. Pairs under $1 return an error instead of routes.
2

Sign the permit

The user signs an EIP-2612 permit that lets the DZap router move the USDC. It’s a signature, not a transaction, so it costs no gas, and it’s valid for 30 minutes. sign() throws if the token doesn’t support EIP-2612.
3

Execute

tradeGasless() builds the transaction, has the user sign an intent that lets DZap execute exactly this trade once before a deadline, and submits both signatures. DZap’s relayer then sends the transaction and pays the gas. If DZap’s check of the trade fails, nothing is sent and result.status is error.
4

Status

result.txnHash is the relayer’s transaction. Poll getTradeTxnStatus with it until the status leaves PENDING; COMPLETED means the swap went through, and status.gasless is true. DZap answers 404 until it sees the transaction, and 429 once the keyless limit of 5 requests a minute is used up, so the catch skips only those two and rethrows anything else. The loop gives up after 5 minutes, and the check after it throws unless the status is COMPLETED.

End-to-end

API usage

The same flow over REST. The gasless build returns hashes to sign instead of a transaction, and the signed result goes to Execute.
Before Execute, the user signs an EIP-2612 permit for the USDC and an EIP-712 intent over the build’s txId and hashes; the SDK’s sign() and tradeGasless() do this for you. Full reference: Quote, Build Tx, Execute, Status.

Fees

The gasless fee covers the gas DZap’s relayer pays, so it depends on the source chain. It’s charged in the source token and already taken out of the quoted output (included: true), so don’t subtract it again. On a gasless quote, fee.gasFee is empty. The two can differ noticeably, so show the build’s number on the confirmation screen.

Other ways to authorize

Tokens without EIP-2612 can still go gasless after an on-chain approval, which needs gas:

What can go wrong

  • **Under 1∗∗:thepaircomesbackwith‘status:′error′‘and‘Minimum1**: the pair comes back with `status: 'error'` and `Minimum 1 per pair required for gasless` instead of routes.
  • Token without EIP-2612: quotes don’t check this, but sign() throws Token does not support EIP-2612 permits. Call checkEIP2612PermitSupport({ chainId, address, owner }) before offering gasless, or use one of the approvals above.
  • Simulation Failed from tradeGasless(): DZap’s check of the trade failed. Make sure the wallet holds the amount and that the permit or approval covers it; over REST, the Execute response’s error.message and error.action say which.
  • Not completed: no status: DZap never returned a status, usually because the transaction failed on-chain. Check the hash in a block explorer.
  • HTTP 429: without an API key, the trade API allows 5 requests a minute in total, shared by every endpoint, and retryAfter says how many seconds to wait. The status loop skips 429s and polls again.
See Error codes for the full catalog.
Last modified on October 1, 2026