npm.io
2.17.0 • Published 2d ago

@x402/paywall

Licence
Apache-2.0
Version
2.17.0
Deps
22
Size
52.2 MB
Vulns
0
Weekly
0

@x402/paywall npm version

Modular paywall UI for the x402 payment protocol with support for EVM and Solana networks.

Features

  • Pre-built paywall UI out of the box
  • Wallet connection (MetaMask, Coinbase Wallet, Phantom, etc.)
  • USDC balance checking
  • Multi-network support (EVM + Solana)
  • Tree-shakeable - only bundle what you need
  • Fully customizable via builder pattern

Installation

pnpm add @x402/paywall

Bundle Sizes

Choose the import that matches your needs:

Import Size Networks Use Case
@x402/paywall 3.5MB EVM + Solana Multi-network apps
@x402/paywall/evm 3.4MB EVM only Base, Ethereum, Polygon, etc.
@x402/paywall/svm 1.0MB Solana only Solana apps

Usage

Option 1: EVM Only
import { createPaywall } from '@x402/paywall';
import { evmPaywall } from '@x402/paywall/evm';

const paywall = createPaywall()
  .withNetwork(evmPaywall)
  .withConfig({
    appName: 'My App',
    testnet: true
  })
  .build();

// Use with Express
app.use(paymentMiddleware(routes, facilitators, schemes, undefined, paywall));
Option 2: Solana Only
import { createPaywall } from '@x402/paywall';
import { svmPaywall } from '@x402/paywall/svm';

const paywall = createPaywall()
  .withNetwork(svmPaywall)
  .withConfig({
    appName: 'My Solana App',
    testnet: true
  })
  .build();
Option 3: Multi-Network
import { createPaywall } from '@x402/paywall';
import { evmPaywall } from '@x402/paywall/evm';
import { svmPaywall } from '@x402/paywall/svm';

const paywall = createPaywall()
  .withNetwork(evmPaywall)   // First-match priority
  .withNetwork(svmPaywall)   // Fallback option
  .withConfig({
    appName: 'Multi-chain App',
    testnet: true
  })
  .build();

Configuration

PaywallConfig Options
interface PaywallConfig {
  appName?: string;              // App name shown in wallet connection
  appLogo?: string;              // App logo URL
  currentUrl?: string;           // URL of protected resource
  testnet?: boolean;             // Use testnet (default: true)
}

How It Works

First-Match Selection

When multiple networks are registered, the paywall uses first-match selection:

  1. Iterates through paymentRequired.accepts array
  2. Finds the first payment requirement that has a registered handler
  3. Uses that handler to generate the HTML

Example:

// Server returns multiple options
{
  "accepts": [
    { "network": "solana:5eykt...", ... },  // First
    { "network": "eip155:8453", ... }       // Second
  ]
}

// If both handlers registered, Solana is selected (it's first in accepts)
const paywall = createPaywall()
  .withNetwork(evmPaywall)
  .withNetwork(svmPaywall)
  .build();
Supported Networks

EVM Networks (via evmPaywall):

  • CAIP-2: eip155:* (e.g., eip155:8453 for Base, eip155:84532 for Base Sepolia)

Solana Networks (via svmPaywall):

  • CAIP-2: solana:* (e.g., solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp for mainnet)

With HTTP Middleware

Express
import express from 'express';
import { paymentMiddleware } from '@x402/express';
import { createPaywall } from '@x402/paywall';
import { evmPaywall } from '@x402/paywall/evm';

const app = express();

const paywall = createPaywall()
  .withNetwork(evmPaywall)
  .withConfig({ appName: 'My API' })
  .build();

app.use(paymentMiddleware(
  { "/api/premium": { price: "$0.10", network: "eip155:84532", payTo: "0x..." } },
  facilitators,
  schemes,
  undefined,
  paywall
));
Automatic Detection

If you provide paywallConfig without a custom paywall, @x402/core automatically:

  1. Tries to load @x402/paywall if installed
  2. Falls back to basic HTML if not installed
// Simple usage - auto-detects @x402/paywall
app.use(paymentMiddleware(routes, facilitators, schemes, {
  appName: 'My App',
  testnet: true
}));

Custom Network Handlers

You can create custom handlers for new networks:

import { createPaywall, type PaywallNetworkHandler } from '@x402/paywall';

const suiPaywall: PaywallNetworkHandler = {
  supports: (req) => req.network.startsWith('sui:'),
  generateHtml: (req, paymentRequired, config) => {
    return `<!DOCTYPE html>...`;  // Your custom Sui paywall
  }
};

const paywall = createPaywall()
  .withNetwork(evmPaywall)
  .withNetwork(svmPaywall)
  .withNetwork(suiPaywall)  // Custom handler
  .build();

Development

Build
pnpm build:paywall  # Generate HTML templates
pnpm build          # Build TypeScript
Test
pnpm test           # Run unit tests

Keywords