@x402fly/nextjs
v0.1.0
Published
Next.js middleware and utilities for 402fly payment protocol
Maintainers
Readme
@402fly/nextjs
Next.js middleware and utilities for the X402 payment protocol. This package provides seamless integration of blockchain-based micropayments into your Next.js applications.
Features
- App Router Support - Built for Next.js 13+ App Router
- Payment Verification - Automatic on-chain payment verification
- TypeScript - Full type safety
- Flexible Configuration - Global or per-route configuration
- Easy Integration - Simple higher-order function API
Installation
npm install @402fly/nextjs @402fly/core @solana/web3.jsQuick Start
1. Initialize X402 Configuration
Create a configuration file for your API routes:
// app/api/config.ts
import { Fly402Config, initFly402 } from "@402fly/nextjs";
const config = new Fly402Config({
paymentAddress: process.env.FLY402_PAYMENT_ADDRESS!,
tokenMint: process.env.FLY402_TOKEN_MINT!,
network: "solana-devnet",
rpcUrl: process.env.FLY402_RPC_URL,
});
initFly402(config);
export { config };2. Protect API Routes
Use the withPayment higher-order function to add payment requirements:
// app/api/premium-data/route.ts
import { NextRequest, NextResponse } from "next/server";
import { withPayment } from "@402fly/nextjs";
import "../config"; // Initialize config
export const GET = withPayment(
{
amount: "0.10",
description: "Access to premium data",
},
async (req: NextRequest, context) => {
return NextResponse.json({
data: "Premium content",
payment_id: context.payment?.paymentId,
});
}
);3. Make Client Requests
Use the X402 client to make requests from your frontend:
import { Fly402AutoClient } from "@402fly/client";
import { Keypair } from "@solana/web3.js";
const keypair = Keypair.generate(); // Or use browser wallet
const client = new Fly402AutoClient(keypair, "https://api.devnet.solana.com");
// Payment is handled automatically
const response = await client.get("/api/premium-data");
console.log(response.data);API Reference
Configuration
Fly402Config
Configuration class for X402 settings.
interface Fly402ConfigOptions {
paymentAddress: string; // Solana wallet address to receive payments
tokenMint: string; // SPL token mint address (e.g., USDC)
network?: string; // "solana-mainnet", "solana-devnet", or "solana-testnet"
rpcUrl?: string; // Custom RPC URL (optional)
defaultAmount?: string; // Default payment amount
paymentTimeout?: number; // Payment timeout in seconds (default: 300)
autoVerify?: boolean; // Auto-verify payments on-chain (default: true)
}
const config = new Fly402Config(options);initFly402(config)
Initialize global X402 configuration.
import { initFly402 } from "@402fly/nextjs";
initFly402(config);Middleware
withPayment(options, handler)
Higher-order function that wraps API route handlers with payment verification.
interface PaymentRequiredOptions {
amount: string; // Payment amount required
paymentAddress?: string; // Override global payment address
tokenMint?: string; // Override global token mint
network?: string; // Override global network
description?: string; // Payment description
expiresIn?: number; // Payment expiration in seconds
autoVerify?: boolean; // Override auto-verify setting
}
type X402Handler = (
req: NextRequest,
context: X402HandlerContext
) => Promise<NextResponse> | NextResponse;
const handler = withPayment(options, async (req, context) => {
// Access payment info via context.payment
return NextResponse.json({ data: "..." });
});X402HandlerContext
Context object passed to route handlers.
interface X402HandlerContext {
payment?: PaymentAuthorization; // Payment authorization info (if paid)
}Response Builders
build402Response(options)
Build a 402 Payment Required response.
interface Build402ResponseOptions {
amount: string;
paymentAddress: string;
tokenMint: string;
network: string;
resource: string;
description?: string;
expiresIn?: number;
}
const response = build402Response(options);Examples
Basic Protected Route
// app/api/data/route.ts
import { withPayment } from "@402fly/nextjs";
import { NextRequest, NextResponse } from "next/server";
export const GET = withPayment(
{ amount: "0.10" },
async (req: NextRequest) => {
return NextResponse.json({ data: "Protected content" });
}
);Accessing Payment Details
export const GET = withPayment(
{ amount: "1.00", description: "Premium API access" },
async (req: NextRequest, context) => {
const payment = context.payment;
return NextResponse.json({
data: "Premium content",
payment_id: payment?.paymentId,
transaction_hash: payment?.transactionHash,
amount_paid: payment?.actualAmount,
});
}
);Dynamic Route with Payment
// app/api/content/[id]/route.ts
export const GET = withPayment(
{ amount: "0.05" },
async (req: NextRequest, context) => {
const url = new URL(req.url);
const id = url.pathname.split("/").pop();
return NextResponse.json({
id,
data: `Content for ${id}`,
});
}
);POST Request with Payment
// app/api/process/route.ts
export const POST = withPayment(
{ amount: "0.25", description: "Data processing" },
async (req: NextRequest) => {
const body = await req.json();
return NextResponse.json({
status: "processed",
result: processData(body),
});
}
);Custom Payment Configuration
export const GET = withPayment(
{
amount: "0.50",
paymentAddress: "CUSTOM_WALLET_ADDRESS",
tokenMint: "CUSTOM_TOKEN_MINT",
network: "solana-mainnet",
expiresIn: 600, // 10 minutes
autoVerify: true,
},
async (req: NextRequest) => {
return NextResponse.json({ data: "Custom config content" });
}
);Payment Flow
- Client makes request to protected API endpoint
- Server checks for payment authorization header
- If no payment: Server returns 402 with payment request
- Client creates payment and retries with authorization
- Server verifies payment on-chain (if autoVerify enabled)
- Server returns protected content
Environment Variables
FLY402_PAYMENT_ADDRESS=your_solana_wallet_address
FLY402_TOKEN_MINT=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
FLY402_RPC_URL=https://api.devnet.solana.comTypeScript
Full TypeScript support with type definitions included.
import type {
Fly402Config,
Fly402ConfigOptions,
PaymentRequiredOptions,
X402Handler,
X402HandlerContext,
PaymentRequest,
PaymentAuthorization,
} from "@402fly/nextjs";Error Handling
The middleware automatically handles common errors:
- 400 Bad Request - Invalid payment authorization format
- 402 Payment Required - No payment provided
- 403 Forbidden - Payment verification failed
- 500 Internal Server Error - Server-side errors
Best Practices
- Initialize once: Call
initFly402()in a shared config file - Environment variables: Store sensitive config in environment variables
- Error handling: Wrap client calls in try-catch blocks
- Amount precision: Use string amounts to avoid floating-point issues
- Network matching: Ensure client and server use the same network
- RPC limits: Use paid RPC providers for production (Alchemy, QuickNode)
Testing
For testing without actual payments, set autoVerify: false:
const config = new Fly402Config({
paymentAddress: "TEST_ADDRESS",
tokenMint: "TEST_MINT",
autoVerify: false, // Skip on-chain verification
});Examples
See the Next.js example for a complete working application.
Related Packages
- @402fly/core - Core X402 protocol implementation
- @402fly/client - Client library for making payments
- @402fly/express - Express.js middleware
License
MIT
