@nano402/express
v0.0.14
Published
Express middleware for nano402 - HTTP 402 payments with Nano cryptocurrency
Maintainers
Readme
@nano402/express
Express.js middleware for HTTP 402 payments with Nano cryptocurrency.
Installation
npm install @nano402/express
# or
pnpm add @nano402/express
# or
yarn add @nano402/expressPeer Dependencies:
npm install expressOverview
@nano402/express provides Express.js middleware that makes it easy to protect routes with HTTP 402 payments. It includes all functionality from nano402 plus Express-specific middleware.
Quick Start
import express from "express";
import { Nano402, nano402Guard } from "@nano402/express";
const app = express();
app.use(express.json());
// Initialize Nano402
const nano402 = new Nano402({
walletSeed: process.env.NANO_SEED!,
nanoRpcUrl: process.env.NANO_RPC_URL || "https://node.somenano.com/proxy",
});
// Protect a route with 402 payment
app.get(
"/api/protected",
nano402Guard(nano402, {
amount_xno: "0.00001",
ttlSeconds: 3600,
description: "Access to premium content",
}),
(req, res) => {
res.json({ data: "Protected content" });
}
);
app.listen(3000);Usage
Basic Middleware
import { nano402Guard } from "@nano402/express";
app.get(
"/api/premium",
nano402Guard(nano402, {
amount_xno: "0.00001",
}),
(req, res) => {
res.json({ secret: "Premium data" });
}
);Middleware Options
interface Nano402GuardOptions {
amount_xno: string; // Required: Payment amount in XNO
ttlSeconds?: number; // Optional: Invoice TTL in seconds (default: 3600)
description?: string; // Optional: Human-readable description
trackByIp?: boolean; // Optional: Track by IP for seamless access (default: false)
sessionDuration?: number; // Optional: Access duration in seconds
maxUsage?: number; // Optional: Maximum accesses per invoice
makeItPublic?: boolean; // Optional: Make content public after payment (default: false)
}IP-Based Tracking
Enable seamless access by tracking payments by IP address:
app.get(
"/api/content",
nano402Guard(nano402, {
amount_xno: "0.00001",
trackByIp: true, // Enable IP-based tracking
sessionDuration: 3600, // 1 hour access
}),
(req, res) => {
res.json({ data: "Content" });
}
);After payment, users can access from the same IP without providing payment proof headers.
Session Management
Control access duration and usage limits:
app.get(
"/api/limited",
nano402Guard(nano402, {
amount_xno: "0.00001",
sessionDuration: 3600, // Access valid for 1 hour
maxUsage: 5, // Maximum 5 accesses
}),
(req, res) => {
res.json({ data: "Limited access content" });
}
);Public Access After Payment
Make content publicly accessible after first payment:
app.get(
"/api/public-after-payment",
nano402Guard(nano402, {
amount_xno: "0.00001",
makeItPublic: true, // Content becomes public after payment
sessionDuration: 86400, // Public for 24 hours
}),
(req, res) => {
res.json({ data: "Public content after payment" });
}
);Manual Payment Verification
For more control, you can implement the payment flow manually:
import { Nano402 } from "@nano402/express";
app.get("/api/manual", async (req, res) => {
const invoice = await nano402.createInvoice({
resource: "/api/manual",
amount_xno: "0.00001",
ttlSeconds: 3600,
});
// Check for payment proof headers
const requestId = req.headers["x-402-request-id"] as string;
const proof = req.headers["x-402-proof"] as string;
if (requestId && proof) {
const isValid = await nano402.verifyPayment(requestId, proof);
if (isValid) {
return res.json({ data: "Content" });
}
}
// Return 402 Payment Required
const nanoUri = nano402.generateNanoUri(invoice);
return res.status(402).json({
request_id: invoice.id,
nano_account: invoice.nano_account,
amount_xno: invoice.amount_xno,
amount_raw: invoice.amount_raw,
nano_uri: nanoUri,
expires_at: invoice.expires_at,
});
});How It Works
First Request - Client requests protected route without payment proof
- Middleware returns
402 Payment Requiredwith invoice details - Response includes payment address, amount, and Nano URI
- Middleware returns
Payment - Client pays the invoice using a Nano wallet
Second Request - Client retries with payment proof headers:
X-402-Request-Id: <invoice_id> X-402-Proof: <transaction_hash>- Middleware verifies payment via Nano RPC
- If valid, request proceeds to route handler
- If invalid, returns 402 again
Response Format
402 Payment Required Response
{
"request_id": "invoice-id",
"nano_account": "nano_...",
"amount_xno": "0.00001",
"amount_raw": "1000000000000000000000000",
"nano_uri": "nano:nano_...?amount=1000000000000000000000000",
"expires_at": "2024-01-01T00:00:00Z",
"description": "Access to premium content"
}Core Library Access
This package re-exports everything from nano402, so you can use all core functionality:
import {
Nano402,
SqliteInvoiceStore,
MemoryInvoiceStore,
// ... all core exports
} from "@nano402/express";Examples
See the examples directory in the main repository for complete examples.
Requirements
- Node.js >= 18.0.0
- Express >= 4.18.0
- Nano wallet seed (64-character hexadecimal string)
- Nano RPC node (public or self-hosted)
Documentation
For complete documentation, see the main repository.
License
MIT
Repository
Donations
If you find this project useful, consider supporting its development:
Nano Address: nano_366td9nfbxns1tkq3u1ryoaazdzjc5ah3duipw5s7dah4nqna41a6hef3i7x
