solana-pay-qr-code-x402-express
v0.2.0
Published
An Express middleware that combines x402 payment requests with a Solana Pay QR code paywall.
Maintainers
Readme
Solana Pay x402 Middleware
A drop-in replacement for the x402-express paymentMiddleware that automatically generates a beautiful, user-friendly Solana Pay QR code paywall.
This middleware intercepts 402 Payment Required responses for Solana-configured routes and replaces the default response with a custom HTML page displaying a Solana Pay QR code. It's designed to be a seamless upgrade for developers already using the x402 protocol.
Features
- Drop-in Replacement: Call it exactly like you would call
paymentMiddlewarefromx402-express. - QR Code Paywall: Automatically generates and displays a Solana Pay QR code for a superior user experience.
- Mobile Friendly: Includes a direct payment link (
solana:) for a one-click experience on mobile wallets. - No
async/awaitNeeded: Integrates synchronously during server setup for clean, simple, and familiar code. - TypeScript Ready: Fully typed for a great developer experience.
Installation
npm install solana-pay-x402-middleware @solana/web3.js expressHow to Use
Simply import solanaPayQRMiddleware and use it in place of paymentMiddleware. The function signature is identical, making migration trivial.
Here is a complete example of an Express server:
// server/index.ts
import express from "express";
import { facilitator } from "@coinbase/x402"; // Or your preferred facilitator
import { solanaPayQRMiddleware } from "solana-pay-x402-middleware";
// --- 1. Server Setup ---
const app = express();
const PORT = process.env.PORT || 3000;
const MERCHANT_WALLET =
process.env.MERCHANT_SOLANA_ADDRESS || "REPLACE_WITH_YOUR_SOLANA_ADDRESS";
if (MERCHANT_WALLET === "REPLACE_WITH_YOUR_SOLANA_ADDRESS") {
console.warn(
"⚠️ WARNING: Please replace the placeholder Solana address in your environment or code."
);
}
// --- 2. x402 Configuration ---
// Define which routes require payment.
const routeConfigs = {
// Protect this route with a 0.01 SOL payment
"GET /api/premium-content": {
// NOTE: For the solana network, this price is treated as SOL.
price: "$0.01",
network: "solana" as const,
},
// This ethereum route will function normally without a QR code
"GET /api/other-content": {
price: "$0.05",
network: "ethereum" as const,
},
// This route remains free
"GET /api/free-content": {
price: "$0.00",
},
};
// --- 3. Apply Middleware ---
// The call is synchronous and identical to the original paymentMiddleware.
// It replaces the standard 402 error with the Solana Pay UI for Solana routes.
app.use(solanaPayQRMiddleware(MERCHANT_WALLET, routeConfigs, facilitator));
// --- 4. Define Your API Routes ---
app.get("/api/premium-content", (req, res) => {
res.send({
message: "This is top-secret premium content, unlocked with Solana!",
timestamp: new Date().toISOString(),
});
});
app.get("/api/free-content", (req, res) => {
res.send({ message: "This content is free for everyone to access." });
});
app.get("/api/other-content", (req, res) => {
res.send({ message: "This content was paid for on another chain." });
});
// --- 5. Start Server ---
app.listen(PORT, () => {
console.log(`🚀 Server running at http://localhost:${PORT}`);
console.log(
`💎 Protected Solana route: http://localhost:${PORT}/api/premium-content`
);
});Paywall Preview
When a user accesses a protected Solana route without a valid payment, they will see this page instead of a plain error:
Important Note on Price
For any route configured with "network": "solana", this middleware assumes the price field is denominated in SOL, not USD. It will strip the $ sign for compatibility, but the numeric value is treated as SOL.
In a full production application, you should integrate a price oracle (like Pyth or Chainlink) to dynamically convert a USD price to the correct amount of SOL before passing the configuration to the middleware.
License
This project is licensed under the MIT License.
