Architecture
The example consists of two parts:- Server (
apps/server): Hono middleware server that issues x402 payment requirements - Browser App (
apps/browser-app): React/Vite frontend that handles wallet connection and payments
Quick Start
Prerequisites
- pnpm installed
- Phantom wallet installed in your browser
- USDC on Solana devnet in your Phantom wallet
Step 1: Install Dependencies
Step 2: Run the Server
SOLANA_PAYTO_ADDRESS to the Solana address that will receive payments.
Step 3: Run the Browser App
Step 4: Open in Browser
Openhttp://localhost:5173 in a browser with Phantom wallet installed.
Step 5: Make a Payment
- Click the “Make Request” button
- Phantom wallet will prompt you to connect (if not already connected)
- Phantom will prompt you to authorize the payment transaction
- After approval, you should see:
Full Example Code
Server (Hono Middleware)
The server uses@faremeter/middleware to protect routes with x402 payments:
Facilitator Setup
The facilitator service handles payment requirements and settlement. It needs to be running separately:Browser App (React/Vite)
The browser app connects to Phantom and handles payments:Facilitator Interactions
The facilitator is a separate service that orchestrates payment flows. The middleware communicates with it at two key points:1. Getting Payment Requirements (POST /accepts)
When a client first requests a protected resource:
-
Middleware calls facilitator: The middleware sends the desired payment requirements to
POST /facilitator/accepts -
Facilitator enriches requirements: The facilitator handler adds network-specific details:
-
Middleware returns 402: The middleware sends this enriched response to the client as a
402 Payment Requiredresponse.
2. Settling Payments (POST /settle)
After the client creates and submits a payment:
-
Client retries with payment proof: The browser app includes the payment transaction in the
X-PAYMENTheader: -
Middleware forwards to facilitator: The middleware sends the payment payload to
POST /facilitator/settle: -
Facilitator validates and executes: The facilitator handler:
- Validates the transaction structure
- Verifies the payment amount and destination
- Partially signs with the fee payer keypair
- Submits the transaction to the Solana network
- Polls for confirmation
-
Settlement response: If successful, the facilitator returns:
- Request proceeds: The middleware allows the original request to continue, returning the protected resource.
Step-by-Step Breakdown
1. Check Phantom Installation
2. Connect to Phantom
3. Create Wallet Interface
- Exposes the connected Phantom wallet’s public key
- Signs transactions through Phantom’s
signTransactionmethod - Matches the interface expected by
@faremeter/payment-solana
4. Create Payment Handler
- Intercept 402 Payment Required responses
- Create Solana SPL token transfer transactions
- Sign them using Phantom
- Submit them to the network
5. Make Payment
- The payment handler creates a transaction
- Phantom prompts the user to sign
- The transaction is submitted
- The request is retried with payment proof
- The server responds with 200 OK
Phantom Wallet Integration
Required Methods
Phantom wallet must implement:connect(): Connect to the walletsignTransaction(tx): Sign a Solana transactionpublicKey: The wallet’s public key
Transaction Signing
When a payment is required, Phantom will prompt the user to:- Review the transaction details
- Approve the USDC transfer
- Confirm the transaction
- Phantom wallet installed and unlocked
- USDC in their wallet on the correct network (devnet/mainnet)
- Sufficient balance for the payment amount
Environment Variables
Server (Middleware)
SOLANA_PAYTO_ADDRESS: Solana address that receives payments (required)
Facilitator Service
FEE_PAYER_KEYPAIR: Secret key for the fee payer account (required)SOLANA_RPC_URL: Optional custom RPC endpoint (defaults to public devnet)
Browser App
- No environment variables needed (uses browser’s Phantom wallet)
Running the Complete Stack
To run the full example, you need three services:1. Start the Facilitator
http://localhost:3000/facilitator.
2. Start the Middleware Server
http://localhost:3000 and call the facilitator at http://localhost:3000/facilitator.
3. Start the Browser App
http://localhost:5173.
Common Issues
”Phantom wallet not installed”
- Install Phantom wallet extension
- Make sure it’s enabled in your browser
”Insufficient USDC balance”
- Get devnet USDC from a faucet
- Make sure you’re connected to the correct network (devnet/mainnet)
“Transaction rejected”
- Check that you approved the transaction in Phantom
- Verify the payment amount matches what you expect
”Connection refused”
- Make sure the server is running on port 3000
- Check that the browser app is pointing to the correct server URL
Debugging
Open browser developer tools (F12) to see:- Console errors
- Network requests (including 402 responses)
- Transaction signatures
- Payment flow logs
Comparison: Browser vs Node.js
- Browser: User-friendly, no server-side key management, requires wallet extension
- Node.js: Automated, full control, but requires private key management
Related Resources
- examples-browser Repository - Full working example
- Solana Exact Payment - Node.js example
- Package Reference - Payment handler documentation
- Phantom Wallet Docs - Phantom integration guide