@shade402/client
v0.0.1
Published
TypeScript HTTP client for X402 payment protocol
Maintainers
Readme
@shade402/client
TypeScript HTTP client library for making X402 payment protocol requests. Supports both explicit (manual) and automatic payment handling.
Overview
The client package provides HTTP client functionality for consuming X402-protected APIs. It handles payment requests, authorization, and retry logic. Two client types are available: explicit client for manual control and automatic client for simplified workflows.
Features
- Explicit client for manual payment flow control
- Automatic client for simplified payment handling
- Automatic payment detection and processing
- Payment retry logic with configurable limits
- Resource encryption support
- Localhost URL support for development
- Full TypeScript support
- Axios-based HTTP client
Installation
npm install @shade402/client
# or
pnpm add @shade402/client
# or
yarn add @shade402/clientDependencies
@shade402/core: Core X402 protocol implementation@solana/web3.js: Solana wallet operationsaxios: HTTP client library
Usage
Explicit Client
The explicit client gives you full control over the payment flow. Use this when you need fine-grained control or want to handle payment errors manually.
import { X402Client } from '@shade402/client';
import { Keypair } from '@solana/web3.js';
const wallet = Keypair.generate();
const client = new X402Client(
wallet,
'https://api.devnet.solana.com', // RPC URL
undefined, // Optional custom Axios instance
false // allowLocal (set to true for localhost in development)
);
try {
// Make initial request
let response = await client.get('https://api.example.com/premium-data');
// Check if payment required
if (client.paymentRequired(response)) {
// Parse payment request from 402 response
const paymentRequest = client.parsePaymentRequest(response);
// Create payment
const authorization = await client.createPayment(paymentRequest);
// Retry request with payment authorization
response = await client.get('https://api.example.com/premium-data', {
payment: authorization
});
}
// Use response data
console.log(response.data);
} finally {
// Always close client to cleanup connections
await client.close();
}Automatic Client
The automatic client handles payment flow automatically. Use this for simpler workflows where you want payment handling to be transparent.
import { X402AutoClient } from '@shade402/client';
import { Keypair } from '@solana/web3.js';
const wallet = Keypair.generate();
const client = new X402AutoClient(
wallet,
'https://api.devnet.solana.com',
{
maxRetries: 1,
autoRetry: true,
maxPaymentAmount: '1.0', // Safety limit
allowLocal: false // Set to true for localhost in development
}
);
try {
// Payment is handled automatically
const response = await client.fetch('https://api.example.com/premium-data');
console.log(response.data);
} finally {
await client.close();
}API Reference
X402Client
Explicit client for manual payment control.
Constructor
new X402Client(
walletKeypair: Keypair,
rpcUrl?: string,
httpClient?: AxiosInstance,
allowLocal?: boolean
)Parameters:
walletKeypair: Solana wallet keypair for making paymentsrpcUrl: Optional Solana RPC URL (default: devnet)httpClient: Optional custom Axios instanceallowLocal: Allow localhost URLs (default: false, use true for development)
Methods
get
Make GET request with optional payment authorization.
async get(url: string, options?: { payment?: PaymentAuthorization }): Promise<AxiosResponse>post
Make POST request with optional payment authorization.
async post(url: string, data?: any, options?: { payment?: PaymentAuthorization }): Promise<AxiosResponse>put
Make PUT request with optional payment authorization.
async put(url: string, data?: any, options?: { payment?: PaymentAuthorization }): Promise<AxiosResponse>delete
Make DELETE request with optional payment authorization.
async delete(url: string, options?: { payment?: PaymentAuthorization }): Promise<AxiosResponse>paymentRequired
Check if response indicates payment is required.
paymentRequired(response: AxiosResponse): booleanparsePaymentRequest
Parse payment request from 402 response.
parsePaymentRequest(response: AxiosResponse): PaymentRequestcreatePayment
Create payment transaction and return authorization.
async createPayment(paymentRequest: PaymentRequest): Promise<PaymentAuthorization>close
Close client and cleanup connections.
async close(): Promise<void>X402AutoClient
Automatic client for simplified payment handling.
Constructor
new X402AutoClient(
walletKeypair: Keypair,
rpcUrl?: string,
options?: {
maxRetries?: number;
autoRetry?: boolean;
maxPaymentAmount?: string;
allowLocal?: boolean;
}
)Parameters:
walletKeypair: Solana wallet keypair for making paymentsrpcUrl: Optional Solana RPC URL (default: devnet)options: Client configuration optionsmaxRetries: Maximum retry attempts (default: 1)autoRetry: Automatically retry after payment (default: true)maxPaymentAmount: Maximum payment amount safety limitallowLocal: Allow localhost URLs (default: false)
Methods
fetch
Make HTTP request with automatic payment handling.
async fetch(
url: string,
options?: AxiosRequestConfig & {
method?: string;
autoRetry?: boolean;
}
): Promise<AxiosResponse>Parameters:
url: Request URLoptions: Axios request options plus:method: HTTP method (default: 'GET')autoRetry: Override instance autoRetry setting
Returns: Response after payment (if required)
Throws:
PaymentRequiredError: If autoRetry is false and 402 receivedInsufficientFundsError: If wallet lacks fundsPaymentExpiredError: If payment request expired
close
Close client and cleanup connections.
async close(): Promise<void>Examples
Explicit Client with Error Handling
import { X402Client } from '@shade402/client';
import {
PaymentExpiredError,
InsufficientFundsError,
PaymentVerificationError
} from '@shade402/core';
import { Keypair } from '@solana/web3.js';
const wallet = Keypair.generate();
const client = new X402Client(wallet);
try {
let response = await client.get('https://api.example.com/data');
if (client.paymentRequired(response)) {
const paymentRequest = client.parsePaymentRequest(response);
try {
const authorization = await client.createPayment(paymentRequest);
response = await client.get('https://api.example.com/data', {
payment: authorization
});
} catch (error) {
if (error instanceof PaymentExpiredError) {
console.error('Payment request expired');
} else if (error instanceof InsufficientFundsError) {
console.error('Insufficient funds');
} else if (error instanceof PaymentVerificationError) {
console.error('Payment verification failed');
}
throw error;
}
}
console.log(response.data);
} finally {
await client.close();
}Automatic Client with Safety Limits
import { X402AutoClient } from '@shade402/client';
import { Keypair } from '@solana/web3.js';
const wallet = Keypair.generate();
const client = new X402AutoClient(wallet, undefined, {
maxRetries: 2,
autoRetry: true,
maxPaymentAmount: '5.0', // Prevent payments over $5
allowLocal: false
});
try {
const response = await client.fetch('https://api.example.com/data', {
method: 'POST',
data: { query: 'example' }
});
console.log(response.data);
} catch (error) {
if (error.message.includes('exceeds max allowed')) {
console.error('Payment amount exceeds safety limit');
} else {
console.error('Request failed:', error);
}
} finally {
await client.close();
}Local Development Setup
For local development with localhost URLs:
import { X402AutoClient } from '@shade402/client';
import { Keypair } from '@solana/web3.js';
const wallet = Keypair.generate();
const client = new X402AutoClient(
wallet,
'http://localhost:8899', // Local Solana validator
{ allowLocal: true } // Enable localhost URLs
);
try {
const response = await client.fetch('http://localhost:3000/api/data');
console.log(response.data);
} finally {
await client.close();
}Using with Custom Axios Instance
import { X402Client } from '@shade402/client';
import axios from 'axios';
import { Keypair } from '@solana/web3.js';
const customAxios = axios.create({
timeout: 10000,
headers: {
'User-Agent': 'MyApp/1.0'
}
});
const wallet = Keypair.generate();
const client = new X402Client(
wallet,
undefined,
customAxios
);
try {
const response = await client.get('https://api.example.com/data');
console.log(response.data);
} finally {
await client.close();
}Error Handling
The client throws various error types from @shade402/core:
PaymentRequiredError: Payment required but autoRetry disabledPaymentExpiredError: Payment request has expiredInsufficientFundsError: Wallet lacks sufficient fundsPaymentVerificationError: Payment verification failedTransactionBroadcastError: Transaction broadcast failedInvalidPaymentRequestError: Invalid payment request data
Always handle these errors appropriately in your application.
Security Considerations
- Always call
close()when done to cleanup connections - Private keys are held in memory - ensure proper disposal
- Only use URLs from trusted sources to prevent SSRF attacks
- Use mainnet RPC URL for production
- Set
allowLocal=trueonly for local development - NEVER use
allowLocal=truein production deployments - Use
maxPaymentAmountin automatic client to prevent excessive payments - Validate payment amounts before processing
TypeScript Support
The package is written in TypeScript and provides full type definitions. All types are exported:
import type {
PaymentRequest,
PaymentAuthorization
} from '@shade402/client';License
MIT
