UNPKG

solana-pay-qr-code-x402-express

Version:

An Express middleware that combines x402 payment requests with a Solana Pay QR code paywall.

113 lines (85 loc) 4.29 kB
# Solana Pay x402 Middleware [![NPM version](https://img.shields.io/npm/v/solana-pay-x402-middleware.svg)](https://www.npmjs.com/package/solana-pay-x402-middleware) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) 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 `paymentMiddleware` from `x402-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/await` Needed:** Integrates synchronously during server setup for clean, simple, and familiar code. - **TypeScript Ready:** Fully typed for a great developer experience. ## Installation ```bash npm install solana-pay-x402-middleware @solana/web3.js express ``` ## How 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: ```typescript // 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](LICENSE).