x402 icon indicating copy to clipboard operation
x402 copied to clipboard

feat: Extract paywall into modular package

Open apmcdermott opened this issue 2 months ago • 1 comments

Extracts the paywall from the monolithic legacy package into a standalone @x402/paywall package with modular architecture, builder pattern API, and tree-shakeable network-specific imports.

New Package: @x402/paywall

Location: typescript/packages/http/paywall/

Key Features:

  • Standalone paywall package with EVM and Solana support
  • Builder pattern for flexible configuration
  • Subpath exports for tree shaking: /evm and /svm
  • Backwards compatible with legacy x402/paywall API

Bundle Sizes:

  • Full paywall: 3.5 MB (both networks)
  • EVM only: 3.4 MB (probably due to OnchainKit... we should figure out a way to reduce this)
  • Solana only: 1.0 MB

Core Integration

@x402/core:

  • Added PaywallProvider interface
  • Added setPaywallProvider() method to x402HTTPResourceService
  • Auto-detects and uses @x402/paywall if installed, otherwise falls back to basic HTML

@x402/express:

  • Added optional PaywallProvider parameter to paymentMiddleware()

Architecture

@x402/paywall (main)
├── index.ts          - Legacy getPaywallHtml() + builder exports
├── builder.ts        - PaywallBuilder with withNetwork() and withConfig()
├── types.ts          - PaywallProvider, PaywallNetworkHandler interfaces
├── evm/
│   ├── index.ts      - evmPaywall handler
│   ├── EvmPaywall.tsx
│   └── build.ts      - Separate build for EVM-only bundle
└── svm/
    ├── index.ts      - svmPaywall handler
    ├── SolanaPaywall.tsx
    └── build.ts      - Separate build for Solana-only bundle

API

Legacy (Backwards Compatible)

import { getPaywallHtml } from '@x402/paywall';
const html = getPaywallHtml({...});

Builder Pattern

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

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

app.use(paymentMiddleware(routes, facs, schemes, undefined, paywall));

Network-Specific Imports

// EVM only - no Solana dependencies
import { evmPaywall } from '@x402/paywall/evm';

// Solana only - no EVM dependencies
import { svmPaywall } from '@x402/paywall/svm';

Migration Path

From legacy x402/paywall:

// Before
import { getPaywallHtml } from 'x402/paywall';

// After
import { getPaywallHtml } from '@x402/paywall';
// Same API - no code changes needed

Future Work

  • Refactor to use x402Client internally for cleaner architecture
  • Investigate OnchainKit bundle size optimizations

Checklist

  • [x] I have formatted and linted my code
  • [ ] All new and existing tests pass
  • [x] My commits are signed (required for merge) -- you may need to rebase if you initially pushed unsigned commits

apmcdermott avatar Oct 30 '25 23:10 apmcdermott

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
x402 Ready Ready Preview Comment Nov 4, 2025 10:20pm

vercel[bot] avatar Oct 30 '25 23:10 vercel[bot]

saddest rebase in the universe. new branch here: https://github.com/coinbase/x402/pull/600

apmcdermott avatar Nov 06 '25 15:11 apmcdermott