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

v0.0.1

Published

LangGraph.js integration for X402 payment protocol

Readme

@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

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

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

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.

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.

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.

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.

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.

function checkPaymentCompleted(state: PaymentState): string

Returns:

  • 'success': If payment completed successfully
  • 'error': If payment failed

Examples

Simple Payment Flow

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

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

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:

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:

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