@x402/paywall
v2.1.0
Published
x402 Payment Protocol Paywall UI
Readme
@x402/paywall
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/paywallBundle 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:
- Iterates through
paymentRequired.acceptsarray - Finds the first payment requirement that has a registered handler
- 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:8453for Base,eip155:84532for Base Sepolia)
Solana Networks (via svmPaywall):
- CAIP-2:
solana:*(e.g.,solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpfor 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:
- Tries to load
@x402/paywallif installed - 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 TypeScriptTest
pnpm test # Run unit tests