Guides
Gasless Transactions

Gasless Transactions

Veridex enables truly gasless transactions — users never need to hold ETH or other gas tokens.

How It Works

  1. User signs a payload with their passkey
  2. Relayer receives the signed payload
  3. Relayer submits the transaction and pays gas
  4. Contract verifies the passkey signature on-chain

Basic Usage

import { createSDK } from '@veridex/sdk';
import { ethers } from 'ethers';
 
const sdk = createSDK('base', {
  network: 'testnet',
  relayerUrl: 'https://relayer.veridex.network', // Veridex relayer
});
 
const { credential } = await sdk.passkey.authenticate();
 
// Gasless cross-chain bridge via relayer
const result = await sdk.bridgeViaRelayer(
  {
    sourceChain: 10004,       // Base Sepolia
    destinationChain: 10005,  // Optimism Sepolia
    token: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',
    recipient: sdk.getVaultAddress(),
    amount: ethers.parseUnits('100', 6),
  },
  (progress) => console.log(progress.message)
);
 
console.log('Gasless bridge complete:', result.transactionHash);

Relayer Configuration

Use Veridex Relayer

const sdk = createSDK('base', {
  network: 'testnet',
  relayerUrl: 'https://relayer.veridex.network',
});

Run Your Own Relayer

// Point to your self-hosted relayer
const sdk = createSDK('base', {
  network: 'testnet',
  relayerUrl: 'http://localhost:3001',
});

See Relayer Setup for self-hosting instructions.

Sponsored Vault Creation

New vaults can be created gaslessly via the GasSponsor:

// User has no ETH, but can still create a vault
const result = await sdk.sponsor.createVault(10005, credential);
 
console.log('Vault created on Optimism:', result.vaultAddress);

For integrators who want to sponsor vault creation for their users, pass a sponsorPrivateKey or integratorSponsorKey in the SDK config:

const sdk = createSDK('base', {
  network: 'testnet',
  relayerUrl: 'https://relayer.veridex.network',
  sponsorPrivateKey: process.env.SPONSOR_KEY,
});

Fee Model

While users don't pay gas, the relayer does. Relayer economics:

ModelDescription
SponsoredRelayer absorbs gas costs (promotional/enterprise)
Protocol FeeSmall fee deducted from transfer amount
SubscriptionUser/app pays monthly for gasless access

Check Bridge Fees

const fees = await sdk.getBridgeFees({
  sourceChain: 10004,
  destinationChain: 10005,
  token: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',
  recipient: sdk.getVaultAddress(),
  amount: 100000000n,
});
 
console.log('Source gas:', fees.sourceGas);
console.log('Message fee:', fees.messageFee);
console.log('Relayer fee:', fees.relayerFee);
console.log('Total:', fees.formattedTotal, fees.currency);

Non-Relayer Fallback

If you want direct on-chain transactions (user pays gas):

import { ethers } from 'ethers';
 
// Connect user's wallet for gas
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();
 
const sdk = createSDK('base', { network: 'testnet' });
 
// Prepare and execute directly (user pays gas)
const prepared = await sdk.prepareTransfer({
  targetChain: 10004,
  token: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',
  recipient: '0x...',
  amount: ethers.parseUnits('100', 6),
});
 
const result = await sdk.executeTransfer(prepared, signer);

Stacks: Native Sponsored Transactions

Stacks has native sponsored transactions — the relayer can pay STX gas fees at the protocol level:

const sdk = createSDK('stacks', {
  network: 'testnet',
  relayerUrl: 'https://relayer.veridex.network',
});
 
// The relayer automatically sponsors Stacks transactions
// Users never need to hold STX for gas

Stacks sponsorship limits:

LimitValue
Per-identity rate50 tx/hour
Per-tx fee cap0.5 STX
Hourly budget50 STX

Agent SDK: Gasless Payments

The Agent SDK handles gasless operations automatically:

import { createAgentWallet } from '@veridex/agentic-payments';
 
const agent = await createAgentWallet({
  masterCredential: { /* ... */ },
  session: {
    dailyLimitUSD: 50,
    perTransactionLimitUSD: 10,
    expiryHours: 24,
    allowedChains: [10004],
  },
  relayerUrl: 'https://relayer.veridex.network',
});
 
// All agent payments are gasless via the relayer
const receipt = await agent.pay({
  chain: 10004,
  token: 'USDC',
  amount: '1000000',
  recipient: '0x...',
});
 
// x402 payments are also gasless
const response = await agent.fetch('https://paid-api.example.com/data');

React Integration

import { useState } from 'react';
import { createSDK } from '@veridex/sdk';
import { ethers } from 'ethers';
 
const sdk = createSDK('base', {
  network: 'testnet',
  relayerUrl: 'https://relayer.veridex.network',
});
 
export function GaslessBridge() {
  const [targetChain, setTargetChain] = useState('10005');
  const [amount, setAmount] = useState('');
  const [loading, setLoading] = useState(false);
  const [progress, setProgress] = useState<string | null>(null);
 
  const handleBridge = async () => {
    setLoading(true);
    try {
      const result = await sdk.bridgeViaRelayer(
        {
          sourceChain: 10004,
          destinationChain: parseInt(targetChain),
          token: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',
          recipient: sdk.getVaultAddress(),
          amount: ethers.parseUnits(amount, 6),
        },
        (p) => setProgress(`Step ${p.step}: ${p.message}`)
      );
      setProgress(`Done! Tx: ${result.transactionHash}`);
    } catch (error: any) {
      setProgress(`Error: ${error.message}`);
    }
    setLoading(false);
  };
 
  return (
    <div className="space-y-4">
      <div className="bg-blue-50 p-4 rounded-lg">
        <p className="text-blue-800 font-medium">Gasless Bridge</p>
        <p className="text-blue-600 text-sm">
          You don't need ETH — the relayer pays gas fees
        </p>
      </div>
 
      <select
        value={targetChain}
        onChange={(e) => setTargetChain(e.target.value)}
        className="block w-full rounded-md border p-2"
      >
        <option value="10005">Optimism Sepolia</option>
        <option value="10003">Arbitrum Sepolia</option>
        <option value="50003">Stacks Testnet</option>
      </select>
 
      <input
        type="number"
        value={amount}
        onChange={(e) => setAmount(e.target.value)}
        placeholder="Amount (USDC)"
        className="block w-full rounded-md border p-2"
      />
 
      <button
        onClick={handleBridge}
        disabled={loading}
        className="w-full bg-green-600 text-white py-2 rounded-lg"
      >
        {loading ? 'Bridging...' : 'Bridge (Gasless)'}
      </button>
 
      {progress && <p className="text-sm text-gray-600">{progress}</p>}
    </div>
  );
}

Relayer Health Check

Check relayer status via the REST API:

// Direct health check via fetch
const response = await fetch('https://relayer.veridex.network/health');
const health = await response.json();
 
console.log('Status:', health.status);
console.log('Chains:', health.chains);

See Relayer API Reference for all endpoints.

Error Handling

try {
  await sdk.bridgeViaRelayer(params, onProgress);
} catch (error: any) {
  if (error.message?.includes('relayer')) {
    // Fallback to direct transaction
    console.log('Relayer unavailable, user needs gas');
    const prepared = await sdk.prepareBridge(params);
    const result = await sdk.executeBridge(prepared, signer);
  } else if (error.message?.includes('rate')) {
    console.log('Rate limited, try again later');
  } else {
    console.error('Bridge failed:', error);
  }
}

Benefits

BenefitDescription
Zero gas UXUsers never see "insufficient ETH" errors
Lower frictionNo need to acquire gas tokens first
Cross-chain readyGasless on all supported chains
Enterprise friendlyPredictable costs for sponsors

Next Steps