UNPKG

solana-pay-qr-code-x402-express

Version:

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

80 lines (79 loc) 3.67 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.solanaPayQRMiddleware = solanaPayQRMiddleware; const x402_express_1 = require("x402-express"); const pay_1 = require("@solana/pay"); const web3_js_1 = require("@solana/web3.js"); const bignumber_js_1 = __importDefault(require("bignumber.js")); const qrcode_1 = __importDefault(require("qrcode")); function solanaPayQRMiddleware(payTo, routes, facilitator, paywall) { const configsWithPaywall = JSON.parse(JSON.stringify(routes)); const recipient = new web3_js_1.PublicKey(payTo); const qrCodeCache = {}; for (const route in configsWithPaywall) { const config = configsWithPaywall[route]; if (config.network === "solana") { const amount = new bignumber_js_1.default(config.price.replace("$", "")); const reference = new web3_js_1.Keypair().publicKey; const label = "API Access"; const message = `Payment for ${route}`; const paymentUrl = (0, pay_1.encodeURL)({ recipient, amount, reference, label, message, }); const generateQRCode = async () => { if (!qrCodeCache[route]) { qrCodeCache[route] = await qrcode_1.default.toString(paymentUrl.toString(), { type: "svg", margin: 2, width: 250, color: { dark: "#000000", light: "#FFFFFF", }, }); } return qrCodeCache[route]; }; const originalCustomPaywallHtml = config.customPaywallHtml; config.customPaywallHtml = async () => { const qrCodeSvg = await generateQRCode(); return ` <html lang="en"> <head> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>402 Payment Required</title> <style> body { display: flex; flex-direction: column; justify-content: center; align-items: center; height: 100vh; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; background-color: #f4f4f7; color: #333; margin: 0; } .container { text-align: center; background: white; padding: 40px; border-radius: 12px; box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1); } h1 { font-size: 24px; margin-bottom: 10px; } p { margin: 0; color: #666; } .qr-code { margin-top: 25px; } .payment-link { margin-top: 25px; font-size: 16px; } a { color: #007bff; text-decoration: none; } a:hover { text-decoration: underline; } </style> </head> <body> <div class="container"> <h1>Payment Required</h1> <p>Scan with a Solana wallet to pay ${amount.toString()} SOL</p> <div class="qr-code">${qrCodeSvg}</div> <p class="payment-link"> <a href="${paymentUrl.toString()}">Click here to open in your wallet</a> </p> </div> </body> </html> `; }; } } return (0, x402_express_1.paymentMiddleware)(payTo, configsWithPaywall, facilitator, paywall); }