Automatic Client

The automatic client (X402AutoClient) automatically handles the X402 payment flow. When it receives a 402 response, it automatically creates a payment and retries the request.

When to Use

Use the automatic client when you want:

  • Simple payment handling

  • Automatic payment flow

  • Less boilerplate code

  • Standard payment behavior

Basic Usage

import { X402AutoClient } from '@shade402/client';
import { Keypair } from '@solana/web3.js';

const wallet = Keypair.generate();
const client = new X402AutoClient(wallet, process.env.SOLANA_RPC_URL, {
  maxPaymentAmount: '1.0',
  autoRetry: true,
});

try {
  // Payment is handled automatically
  const response = await client.get('https://api.example.com/data');
  console.log(response.data);
} finally {
  await client.close();
}

Configuration Options

interface X402AutoClientOptions {
  maxRetries?: number;        // Maximum retry attempts (default: 1)
  autoRetry?: boolean;        // Auto-retry after payment (default: true)
  maxPaymentAmount?: string;  // Maximum payment amount (safety limit)
  allowLocal?: boolean;       // Allow localhost URLs (development only)
}

Maximum Payment Amount

Set a safety limit to prevent overpayment:

const client = new X402AutoClient(wallet, rpcUrl, {
  maxPaymentAmount: '1.0', // Won't pay more than 1.0 tokens
});

Auto Retry

Control automatic retry behavior:

// Auto-retry enabled (default)
const client = new X402AutoClient(wallet, rpcUrl, {
  autoRetry: true,
});

// Auto-retry disabled
const client = new X402AutoClient(wallet, rpcUrl, {
  autoRetry: false,
});

HTTP Methods

All standard HTTP methods are supported:

// GET request
const getResponse = await client.get(url, options);

// POST request
const postResponse = await client.post(url, data, options);

// PUT request
const putResponse = await client.put(url, data, options);

// DELETE request
const deleteResponse = await client.delete(url, options);

// Generic fetch
const response = await client.fetch(url, {
  method: 'GET',
  // ... other options
});

Payment Flow

The automatic client handles the payment flow internally:

  1. Makes initial HTTP request

  2. If 402 received:

    • Parses payment request

    • Validates payment amount (checks maxPaymentAmount)

    • Creates Solana payment transaction

    • Broadcasts transaction

    • Encrypts resource if server public key available

    • Retries request with payment authorization

  3. Returns response

All of this happens automatically without manual intervention.

Error Handling

The automatic client throws errors for payment issues:

import {
  PaymentRequiredError,
  InsufficientFundsError,
  PaymentExpiredError,
} from '@shade402/core';

try {
  const response = await client.get(url);
} catch (error) {
  if (error instanceof PaymentRequiredError) {
    // Payment required but autoRetry is false
    console.log('Payment required:', error.paymentRequest);
  } else if (error instanceof InsufficientFundsError) {
    console.log('Insufficient funds');
  } else if (error instanceof PaymentExpiredError) {
    console.log('Payment expired');
  } else {
    console.error('Other error:', error);
  }
}

Resource Encryption

Resource encryption is handled automatically:

// Client automatically:
// 1. Receives server public key from 402 response
// 2. Encrypts resource field
// 3. Includes encrypted resource in retry request

const response = await client.get(url); // Encryption handled automatically

Override Auto Retry

You can override auto-retry for specific requests:

// Override instance setting
const response = await client.get(url, {
  autoRetry: false, // Don't auto-retry this request
});

// If 402 is received and autoRetry is false, PaymentRequiredError is thrown

Complete Example

import { X402AutoClient } from '@shade402/client';
import { Keypair } from '@solana/web3.js';
import {
  PaymentRequiredError,
  InsufficientFundsError,
} from '@shade402/core';

async function fetchPremiumData(url: string) {
  // Load wallet securely
  const wallet = Keypair.fromSecretKey(
    Buffer.from(process.env.WALLET_SECRET_KEY!, 'base64')
  );

  // Create client with safety limits
  const client = new X402AutoClient(wallet, process.env.SOLANA_RPC_URL, {
    maxPaymentAmount: '1.0',
    autoRetry: true,
  });

  try {
    // Make request - payment handled automatically
    const response = await client.get(url);
    return response.data;
  } catch (error) {
    if (error instanceof PaymentRequiredError) {
      console.error('Payment required but auto-retry disabled');
    } else if (error instanceof InsufficientFundsError) {
      console.error('Insufficient funds:', error.requiredAmount);
    } else {
      console.error('Unexpected error:', error);
    }
    throw error;
  } finally {
    await client.close();
  }
}

Multiple Requests

Reuse the client for multiple requests:

const client = new X402AutoClient(wallet, rpcUrl);

try {
  const response1 = await client.get(url1);
  const response2 = await client.post(url2, data);
  const response3 = await client.get(url3);
  
  // All payments handled automatically
} finally {
  await client.close();
}

Best Practices

  1. Always set maxPaymentAmount as a safety limit

  2. Always close the client when done

  3. Handle errors appropriately

  4. Use autoRetry: false when you need manual control

  5. Store wallet keys securely

  6. Monitor payment amounts and transactions

  7. Reuse client for multiple requests when possible

Comparison with Explicit Client

Automatic Client

  • Simpler API

  • Less boilerplate

  • Automatic payment handling

  • Good for standard use cases

Explicit Client

  • More control

  • Custom payment logic

  • Better for complex scenarios

  • More code required

Choose based on your needs. Use automatic client for simple cases, explicit client for complex scenarios.

Next Steps

Last updated