npm package: @shade402/client
Description: TypeScript HTTP client for X402 payment protocol
Author: shade402
Latest version: 0.0.1

# @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

```bash
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.

```typescript
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.

```typescript
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

```typescript
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.

```typescript
async get(url: string, options?: { payment?: PaymentAuthorization }): Promise<AxiosResponse>
```

##### post

Make POST request with optional payment authorization.

```typescript
async post(url: string, data?: any, options?: { payment?: PaymentAuthorization }): Promise<AxiosResponse>
```

##### put

Make PUT request with optional payment authorization.

```typescript
async put(url: string, data?: any, options?: { payment?: PaymentAuthorization }): Promise<AxiosResponse>
```

##### delete

Make DELETE request with optional payment authorization.

```typescript
async delete(url: string, options?: { payment?: PaymentAuthorization }): Promise<AxiosResponse>
```

##### paymentRequired

Check if response indicates payment is required.

```typescript
paymentRequired(response: AxiosResponse): boolean
```

##### parsePaymentRequest

Parse payment request from 402 response.

```typescript
parsePaymentRequest(response: AxiosResponse): PaymentRequest
```

##### createPayment

Create payment transaction and return authorization.

```typescript
async createPayment(paymentRequest: PaymentRequest): Promise<PaymentAuthorization>
```

##### close

Close client and cleanup connections.

```typescript
async close(): Promise<void>
```

### X402AutoClient

Automatic client for simplified payment handling.

#### Constructor

```typescript
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.

```typescript
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.

```typescript
async close(): Promise<void>
```

## Examples

### Explicit Client with Error Handling

```typescript
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

```typescript
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:

```typescript
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

```typescript
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:

```typescript
import type {
  PaymentRequest,
  PaymentAuthorization
} from '@shade402/client';
```

## License

MIT