Examples

Real-world code examples for common use cases.


Node.js Backend Payment

Make payments from a Node.js backend using a private key:

import { createPublicClient, createWalletClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import {
  FacilitatorClient,
  AgentPaymentClient,
  FacilitatorError,
  APECHAIN,
  APECHAIN_USDC,
  DEFAULT_FACILITATOR_URL,
  DEFAULT_SETTLEMENT_ADDRESS,
  toTokenUnits
} from '@x402apechain/sdk';

async function makePayment() {
  // Setup wallet from private key
  const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
  const transport = http(APECHAIN.rpcUrls.default.http[0]);
  
  const publicClient = createPublicClient({ chain: APECHAIN, transport });
  const walletClient = createWalletClient({ account, chain: APECHAIN, transport });

  // Create clients
  const facilitator = new FacilitatorClient({
    baseUrl: DEFAULT_FACILITATOR_URL,
    chainId: APECHAIN.id,
    settlementAddress: DEFAULT_SETTLEMENT_ADDRESS
  });

  const agent = new AgentPaymentClient({
    facilitator,
    publicClient,
    walletClient
  });

  // Make payment
  try {
    const receipt = await agent.pay({
      invoice: {
        chainId: APECHAIN.id,
        tokenAddress: APECHAIN_USDC,
        recipient: '0xMerchantAddress...',
        amount: toTokenUnits('5.00', 6) // 5 USDC
      }
    });
    
    console.log('Payment successful!', receipt.txHash);
  } catch (error) {
    if (error instanceof FacilitatorError) {
      if (error.isInsufficientFunds()) {
        console.error('Not enough USDC balance');
      } else {
        console.error('Payment failed:', error.message);
      }
    }
  }
}

makePayment();

React Hook for Payments

A reusable React hook for making payments with wallet providers:

'use client';
import { useMemo, useCallback, useState } from 'react';
import { createPublicClient, createWalletClient, custom, http } from 'viem';
import {
  FacilitatorClient,
  AgentPaymentClient,
  APECHAIN,
  APECHAIN_USDC,
  DEFAULT_FACILITATOR_URL,
  DEFAULT_SETTLEMENT_ADDRESS,
  toTokenUnits
} from '@x402apechain/sdk';

export function usePayment(walletProvider: any, account: string) {
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const { agent } = useMemo(() => {
    const publicClient = createPublicClient({
      chain: APECHAIN,
      transport: http()
    });
    
    const walletClient = createWalletClient({
      account: account as `0x${string}`,
      chain: APECHAIN,
      transport: custom(walletProvider)
    });

    const facilitator = new FacilitatorClient({
      baseUrl: DEFAULT_FACILITATOR_URL,
      chainId: APECHAIN.id,
      settlementAddress: DEFAULT_SETTLEMENT_ADDRESS
    });

    const agent = new AgentPaymentClient({
      facilitator,
      publicClient,
      walletClient
    });

    return { agent };
  }, [walletProvider, account]);

  const pay = useCallback(async (
    recipient: string, 
    amountUsdc: string
  ) => {
    setLoading(true);
    setError(null);
    
    try {
      const receipt = await agent.pay({
        invoice: {
          chainId: APECHAIN.id,
          tokenAddress: APECHAIN_USDC,
          recipient: recipient as `0x${string}`,
          amount: toTokenUnits(amountUsdc, 6)
        }
      });
      return receipt;
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Payment failed');
      throw err;
    } finally {
      setLoading(false);
    }
  }, [agent]);

  return { pay, loading, error };
}

Using the Hook

function PaymentButton({ recipient }: { recipient: string }) {
  const { provider, address } = useWallet(); // Your wallet hook
  const { pay, loading, error } = usePayment(provider, address);

  const handlePay = async () => {
    const receipt = await pay(recipient, '1.00');
    alert(`Paid! TX: ${receipt.txHash}`);
  };

  return (
    <button onClick={handlePay} disabled={loading}>
      {loading ? 'Processing...' : 'Pay 1 USDC'}
    </button>
  );
}

Express.js Payment Endpoint

Create a payment endpoint in an Express.js server:

import express from 'express';
import { createPublicClient, createWalletClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import {
  FacilitatorClient,
  AgentPaymentClient,
  APECHAIN,
  APECHAIN_USDC,
  toTokenUnits
} from '@x402apechain/sdk';

const app = express();
app.use(express.json());

// Initialize once at startup
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const transport = http();

const publicClient = createPublicClient({ chain: APECHAIN, transport });
const walletClient = createWalletClient({ account, chain: APECHAIN, transport });

const facilitator = new FacilitatorClient({
  baseUrl: 'https://x402apes-production.up.railway.app',
  chainId: APECHAIN.id,
  settlementAddress: '0xe24a8dbf205ee116c991f60686f778a2337a844f'
});

const agent = new AgentPaymentClient({
  facilitator,
  publicClient,
  walletClient
});

// Payment endpoint
app.post('/api/pay', async (req, res) => {
  const { recipient, amount } = req.body;

  try {
    const receipt = await agent.pay({
      invoice: {
        id: `order-${Date.now()}`,
        chainId: APECHAIN.id,
        tokenAddress: APECHAIN_USDC,
        recipient,
        amount: toTokenUnits(amount, 6)
      }
    });

    res.json({
      success: true,
      txHash: receipt.txHash,
      settledAt: receipt.settledAt
    });
  } catch (error) {
    res.status(400).json({
      success: false,
      error: error instanceof Error ? error.message : 'Payment failed'
    });
  }
});

app.listen(3000);

Check Facilitator Health

Monitor the facilitator service status:

import { FacilitatorClient } from '@x402apechain/sdk';

const facilitator = new FacilitatorClient({
  baseUrl: 'https://x402apes-production.up.railway.app',
  chainId: 33139,
  settlementAddress: '0xe24a8dbf205ee116c991f60686f778a2337a844f'
});

async function checkHealth() {
  const health = await facilitator.health();
  
  console.log('Status:', health.status);
  console.log('Redis:', health.redis);
  console.log('RPC:', health.rpc);
  console.log('Time:', health.timestamp);
  
  if (health.status !== 'ok') {
    console.warn('Facilitator is not healthy!');
  }
}

checkHealth();

Get Transaction Stats

Fetch facilitator statistics for dashboards:

import { FacilitatorClient } from '@x402apechain/sdk';

const facilitator = new FacilitatorClient({
  baseUrl: 'https://x402apes-production.up.railway.app',
  chainId: 33139,
  settlementAddress: '0xe24a8dbf205ee116c991f60686f778a2337a844f'
});

async function getStats() {
  const stats = await facilitator.stats();
  
  console.log('Total Transactions:', stats.totalTransactions);
  console.log('Total Volume (USDC):', stats.totalVolumeUSDC);
  console.log('Recent transactions:', stats.recent.length);
  
  // Daily breakdown
  for (const [date, data] of Object.entries(stats.daily)) {
    console.log(`${date}: ${data.txs} txs, $${data.volume} USDC`);
  }
}

getStats();

More Examples

Check out the SDK package on npm for additional examples and the full source code.