npm package: @shade402/langgraph
Description: LangGraph.js integration for X402 payment protocol
Author: shade402
Latest version: 0.0.1

# @shade402/langgraph

LangGraph.js integration for X402 payment protocol. Provides reusable nodes and utilities for handling X402 payments in LangGraph workflows.

## Overview

The LangGraph package provides payment nodes and helper functions that can be integrated into LangGraph state machine workflows. This enables complex AI agent workflows to automatically handle payments for API access as part of their execution graph.

## Features

- Reusable payment nodes for LangGraph workflows
- Payment state management
- Conditional edges for payment flow control
- Automatic payment handling in workflow steps
- Support for all HTTP methods
- Full TypeScript support
- Seamless integration with LangGraph state machines

## Installation

```bash
npm install @shade402/langgraph
# or
pnpm add @shade402/langgraph
# or
yarn add @shade402/langgraph
```

## Dependencies

- `@shade402/core`: Core X402 protocol implementation
- `@shade402/client`: X402 HTTP client
- `@solana/web3.js`: Solana wallet operations
- `@langchain/langgraph`: LangGraph.js framework

## Usage

### Basic Workflow Setup

```typescript
import { StateGraph } from '@langchain/langgraph';
import {
  paymentNode,
  fetchWithPaymentNode,
  checkPaymentRequired,
  checkPaymentCompleted,
  PaymentState
} from '@shade402/langgraph';
import { Keypair } from '@solana/web3.js';

// Create wallet for payments
const wallet = Keypair.generate();

// Define workflow
const workflow = new StateGraph<PaymentState>({
  channels: {
    wallet_keypair: null,
    api_url: null,
    api_response: null,
    payment_completed: null,
    payment_error: null,
    payment_required: null,
    max_payment_amount: null,
    http_method: null,
    allow_local: null,
    rpc_url: null
  }
});

// Add nodes
workflow.addNode('fetch_api', fetchWithPaymentNode);
workflow.addNode('make_payment', paymentNode);
workflow.addNode('process_response', async (state: PaymentState) => {
  return {
    ...state,
    processed: true,
    result: state.api_response
  };
});

// Add edges
workflow.setEntryPoint('fetch_api');

workflow.addConditionalEdges(
  'fetch_api',
  checkPaymentRequired,
  {
    payment_required: 'make_payment',
    success: 'process_response'
  }
);

workflow.addEdge('make_payment', 'fetch_api'); // Retry after payment

// Compile and run
const app = workflow.compile();

const result = await app.invoke({
  wallet_keypair: wallet,
  api_url: 'https://api.example.com/premium-data',
  max_payment_amount: '1.0',
  rpc_url: 'https://api.devnet.solana.com'
});
```

### Advanced Workflow with Error Handling

```typescript
import { StateGraph } from '@langchain/langgraph';
import {
  paymentNode,
  fetchWithPaymentNode,
  checkPaymentRequired,
  checkPaymentCompleted,
  PaymentState
} from '@shade402/langgraph';
import { Keypair } from '@solana/web3.js';

const wallet = Keypair.generate();

const workflow = new StateGraph<PaymentState>({
  channels: {
    wallet_keypair: null,
    api_url: null,
    api_response: null,
    payment_completed: null,
    payment_error: null,
    payment_required: null,
    max_payment_amount: null,
    http_method: null,
    allow_local: null,
    rpc_url: null,
    retry_count: null
  }
});

// Add nodes
workflow.addNode('fetch_api', fetchWithPaymentNode);
workflow.addNode('make_payment', paymentNode);
workflow.addNode('handle_error', async (state: PaymentState) => {
  return {
    ...state,
    error_handled: true
  };
});
workflow.addNode('process_response', async (state: PaymentState) => {
  return {
    ...state,
    processed: true
  };
});

// Entry point
workflow.setEntryPoint('fetch_api');

// Conditional routing
workflow.addConditionalEdges(
  'fetch_api',
  checkPaymentRequired,
  {
    payment_required: 'make_payment',
    success: 'process_response',
    error: 'handle_error'
  }
);

workflow.addConditionalEdges(
  'make_payment',
  checkPaymentCompleted,
  {
    success: 'fetch_api', // Retry after payment
    error: 'handle_error'
  }
);

const app = workflow.compile();
```

## API Reference

### PaymentState

Interface for payment-related state in LangGraph workflows.

```typescript
interface PaymentState {
  wallet_keypair?: Keypair;
  api_url?: string;
  api_response?: string;
  payment_completed?: boolean;
  payment_error?: string | null;
  payment_required?: boolean;
  max_payment_amount?: string;
  http_method?: string;
  allow_local?: boolean;
  rpc_url?: string;
  [key: string]: any;
}
```

### paymentNode

Node that handles X402 payment and retries the API request.

```typescript
async function paymentNode(state: PaymentState): Promise<PaymentState>
```

**Required State:**
- `wallet_keypair`: Keypair for making payments
- `api_url`: URL to fetch after payment

**Optional State:**
- `rpc_url`: Solana RPC URL
- `allow_local`: Allow localhost URLs
- `max_payment_amount`: Maximum payment amount

**Returns State:**
- `api_response`: API response text
- `payment_completed`: boolean indicating success
- `payment_error`: Error message if payment failed

### fetchWithPaymentNode

Node that fetches an API endpoint and handles payment if required.

```typescript
async function fetchWithPaymentNode(state: PaymentState): Promise<PaymentState>
```

**Required State:**
- `wallet_keypair`: Keypair for making payments
- `api_url`: URL to fetch

**Optional State:**
- `rpc_url`: Solana RPC URL
- `allow_local`: Allow localhost URLs
- `http_method`: HTTP method (default: 'GET')
- `max_payment_amount`: Maximum payment amount

**Returns State:**
- `api_response`: API response text if successful
- `payment_required`: boolean indicating if payment is needed
- `payment_error`: Error message if fetch failed

### checkPaymentRequired

Conditional edge function to check if payment is required.

```typescript
function checkPaymentRequired(state: PaymentState): string
```

**Returns:**
- `'payment_required'`: If payment is needed
- `'success'`: If request succeeded
- `'error'`: If request failed

### checkPaymentCompleted

Conditional edge function to check if payment was completed successfully.

```typescript
function checkPaymentCompleted(state: PaymentState): string
```

**Returns:**
- `'success'`: If payment completed successfully
- `'error'`: If payment failed

## Examples

### Simple Payment Flow

```typescript
import { StateGraph } from '@langchain/langgraph';
import {
  paymentNode,
  fetchWithPaymentNode,
  checkPaymentRequired,
  PaymentState
} from '@shade402/langgraph';
import { Keypair } from '@solana/web3.js';

const wallet = Keypair.generate();

const workflow = new StateGraph<PaymentState>({
  channels: {
    wallet_keypair: null,
    api_url: null,
    api_response: null,
    payment_completed: null,
    payment_error: null,
    payment_required: null
  }
});

workflow.addNode('fetch', fetchWithPaymentNode);
workflow.addNode('pay', paymentNode);
workflow.addNode('done', (state) => ({ ...state, done: true }));

workflow.setEntryPoint('fetch');

workflow.addConditionalEdges('fetch', checkPaymentRequired, {
  payment_required: 'pay',
  success: 'done'
});

workflow.addEdge('pay', 'fetch'); // Retry after payment

const app = workflow.compile();

const result = await app.invoke({
  wallet_keypair: wallet,
  api_url: 'https://api.example.com/data'
});
```

### Multi-Step Workflow

```typescript
import { StateGraph } from '@langchain/langgraph';
import {
  paymentNode,
  fetchWithPaymentNode,
  checkPaymentRequired,
  checkPaymentCompleted,
  PaymentState
} from '@shade402/langgraph';
import { Keypair } from '@solana/web3.js';

const wallet = Keypair.generate();

const workflow = new StateGraph<PaymentState>({
  channels: {
    wallet_keypair: null,
    api_url: null,
    api_response: null,
    payment_completed: null,
    payment_error: null,
    payment_required: null,
    step: null
  }
});

// Step 1: Fetch initial data
workflow.addNode('step1', async (state: PaymentState) => {
  return {
    ...state,
    api_url: 'https://api.example.com/data',
    step: 1
  };
});

// Step 2: Fetch with payment
workflow.addNode('fetch', fetchWithPaymentNode);

// Step 3: Make payment if needed
workflow.addNode('pay', paymentNode);

// Step 4: Process response
workflow.addNode('process', async (state: PaymentState) => {
  return {
    ...state,
    processed: true,
    result: JSON.parse(state.api_response || '{}')
  };
});

workflow.setEntryPoint('step1');
workflow.addEdge('step1', 'fetch');

workflow.addConditionalEdges('fetch', checkPaymentRequired, {
  payment_required: 'pay',
  success: 'process'
});

workflow.addConditionalEdges('pay', checkPaymentCompleted, {
  success: 'fetch',
  error: 'process'
});

const app = workflow.compile();
```

### Error Handling Workflow

```typescript
import { StateGraph } from '@langchain/langgraph';
import {
  paymentNode,
  fetchWithPaymentNode,
  checkPaymentRequired,
  PaymentState
} from '@shade402/langgraph';
import { Keypair } from '@solana/web3.js';

const wallet = Keypair.generate();

const workflow = new StateGraph<PaymentState>({
  channels: {
    wallet_keypair: null,
    api_url: null,
    api_response: null,
    payment_completed: null,
    payment_error: null,
    payment_required: null,
    retry_count: null
  }
});

workflow.addNode('fetch', fetchWithPaymentNode);
workflow.addNode('pay', paymentNode);
workflow.addNode('handle_error', async (state: PaymentState) => {
  const retryCount = (state.retry_count || 0) + 1;
  
  if (retryCount > 3) {
    return {
      ...state,
      retry_count: retryCount,
      failed: true
    };
  }
  
  return {
    ...state,
    retry_count: retryCount
  };
});

workflow.setEntryPoint('fetch');

workflow.addConditionalEdges('fetch', (state: PaymentState) => {
  if (state.payment_error) return 'error';
  if (state.payment_required) return 'payment_required';
  return 'success';
}, {
  payment_required: 'pay',
  success: 'done',
  error: 'handle_error'
});

workflow.addConditionalEdges('pay', (state: PaymentState) => {
  return state.payment_completed ? 'success' : 'error';
}, {
  success: 'fetch',
  error: 'handle_error'
});
```

## State Management

The payment nodes work with LangGraph state channels. You can extend the state with additional fields:

```typescript
interface ExtendedPaymentState extends PaymentState {
  user_id?: string;
  session_id?: string;
  metadata?: Record<string, any>;
}
```

## Security Considerations

- Store wallet keys securely (environment variables, key management service)
- Use `max_payment_amount` to prevent excessive payments
- Set `allow_local: false` in production
- Monitor workflow execution and payment patterns
- Use mainnet RPC endpoints for production
- Implement proper error handling and retry limits
- Validate API URLs to prevent SSRF attacks

## TypeScript Support

The package is written in TypeScript and provides full type definitions:

```typescript
import type {
  PaymentState
} from '@shade402/langgraph';
```

## Integration with LangGraph

This package is designed to work seamlessly with LangGraph.js state machines. The nodes are regular async functions that take and return state, making them compatible with LangGraph's execution model.

## License

MIT