x402-storefront

A self-hosted store with x402 checkout. Digital goods delivered in the paid response; physical goods confirmed with signed fulfillment records. Pay in USDC on Base or Solana — your client picks the rail. No accounts.

git clone https://github.com/nirholas/x402-storefront && cd x402-storefront && npm install && npm run dev

Pricing

RoutePriceYou get back
GET /catalogfreeItems, prices, buy routes
GET /buy/guide-agentic-commerce$0.05Signed download grant + license (markdown guide)
GET /buy/dataset-http-402$0.02Signed download grant + license (JSON dataset)
GET /buy/art-payment-required$0.01Signed download grant + license (SVG art)
GET /buy/stickers-x402$0.10Signed order confirmation + fulfillment record
GET /buy/tee-pay-per-call$0.25Signed order confirmation + fulfillment record
GET /download/:tokenfreePurchased bytes (from a digital purchase)
GET /verifyfreeSignature check for any artifact

All items and prices are configured in config/catalog.json — paid routes are generated from it.

Two rails, one challenge

Every 402 lists both networks. A buyer holding USDC on Base pays on Base; a buyer holding USDC on Solana pays on Solana. Same route, same artifact, same price.

EVM

USDC on Base

base-sepolia by default, base for mainnet. EIP-3009 transfer authorization.

0x40252CFDF8B20Ed757D61ff157719F33Ec332402
SVM

USDC on Solana

solana mainnet by default, solana-devnet for testing. SPL transfer.

WwwuGbqHrwF5RG89KhUbmRWEvjnRH9k5kVM5p7T3WwW

How a purchase flows

402quote in USDC on
Base and Solana
signclient picks a rail
and signs
retrysame request +
X-PAYMENT
200artifact in body,
receipt in header

Quickstart

# 1. Run the store
cp .env.example .env       # ships with working payTo addresses for both rails
npm run dev                # http://localhost:4021

# 2. See the dual-rail 402 quote (no wallet needed)
curl -s http://localhost:4021/buy/art-payment-required \
  | jq '.accepts[] | {network, payTo, maxAmountRequired}'

# 3. Buy for real on Base Sepolia (free test USDC: faucet.circle.com)
export PRIVATE_KEY=0x…
npm run client             # pays, verifies signature, downloads the asset

Human checkout demo

The store ships a one-page checkout at / (see public/index.html) built on the drop-in @three-ws/x402-payment-modal: every item gets a Pay & buy button, and the signed artifact renders in-page after payment. The modal reads both rails from the 402 challenge — Phantom for Solana, an injected wallet for Base — and ships SIWX re-entry plus per-site spending caps. Run npm run dev and open localhost:4021.