npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@shade402/client

v0.0.1

Published

TypeScript HTTP client for X402 payment protocol

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/client

Dependencies

  • @shade402/core: Core X402 protocol implementation
  • @solana/web3.js: Solana wallet operations
  • axios: 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 payments
  • rpcUrl: Optional Solana RPC URL (default: devnet)
  • httpClient: Optional custom Axios instance
  • allowLocal: 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): boolean
parsePaymentRequest

Parse payment request from 402 response.

parsePaymentRequest(response: AxiosResponse): PaymentRequest
createPayment

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 payments
  • rpcUrl: Optional Solana RPC URL (default: devnet)
  • options: Client configuration options
    • maxRetries: Maximum retry attempts (default: 1)
    • autoRetry: Automatically retry after payment (default: true)
    • maxPaymentAmount: Maximum payment amount safety limit
    • allowLocal: 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 URL
  • options: 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 received
  • InsufficientFundsError: If wallet lacks funds
  • PaymentExpiredError: 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 disabled
  • PaymentExpiredError: Payment request has expired
  • InsufficientFundsError: Wallet lacks sufficient funds
  • PaymentVerificationError: Payment verification failed
  • TransactionBroadcastError: Transaction broadcast failed
  • InvalidPaymentRequestError: 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=true only for local development
  • NEVER use allowLocal=true in production deployments
  • Use maxPaymentAmount in 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