Hono Middleware
Add x402 payment verification to your Hono API with the Dunmore SDK.
The @dunmore/hono package adds x402 payment verification to Hono APIs with a single middleware function.
Installation
npm install @dunmore/hono
Quick Start
import { Hono } from "hono";
import { serve } from "@hono/node-server";
import { dunmorePaywall } from "@dunmore/hono";
const app = new Hono();
app.get(
"/api/weather",
dunmorePaywall({
apiUrl: "https://api.dunmore.xyz",
apiKey: "gf_live_...",
projectId: "proj_...",
priceUsd: "0.001",
payTo: "0x...",
}),
(c) => {
return c.json({ temperature: 72, city: "San Francisco" });
}
);
serve({ fetch: app.fetch, port: 3000 }, () => {
console.log("Running on http://localhost:3000");
});
Step-by-Step Guide
1. Create a Dunmore Project
Sign in at console.dunmore.xyz and create a project. Note your project ID (proj_...) and generate an API key (gf_live_...).
2. Install the Package
npm install @dunmore/hono hono @hono/node-server
3. Configure the Paywall
Create a config object with your Dunmore credentials and pricing:
import { dunmorePaywall } from "@dunmore/hono";
const paywallConfig = {
apiUrl: "https://api.dunmore.xyz",
apiKey: process.env.DUNMORE_API_KEY!,
projectId: process.env.DUNMORE_PROJECT_ID!,
priceUsd: "0.001",
payTo: "0xYourWalletAddress",
};
4. Apply to Routes
Add dunmorePaywall() as middleware on any route you want to monetize:
import { Hono } from "hono";
import { serve } from "@hono/node-server";
const app = new Hono();
// This route requires payment
app.get("/api/weather", dunmorePaywall(paywallConfig), (c) => {
return c.json({ temperature: 72, unit: "F" });
});
// This route is free
app.get("/api/health", (c) => {
return c.json({ status: "ok" });
});
serve({ fetch: app.fetch, port: 3000 });
5. Access Payment Info
After verification, payment metadata is available via c.get("dunmore"):
app.get("/api/weather", dunmorePaywall(paywallConfig), (c) => {
const { paymentId, verified } = c.get("dunmore");
console.log(`Payment ${paymentId} verified: ${verified}`);
return c.json({ temperature: 72, unit: "F" });
});
6. Use Testnet for Development
Set network to Base Sepolia during development:
const testConfig = {
...paywallConfig,
network: "eip155:84532", // Base Sepolia testnet
};
How It Works
- No
Payment-Signatureheader — Returns402 Payment Requiredwith x402 v2 payment requirements (acceptsarray with scheme, network, USDC asset address, amount, payTo). - Has
Payment-Signatureheader — Decodes the base64 payment payload and sends it to the Dunmore facilitator for on-chain verification. - Verification passes — Attaches payment info to the Hono context, fires off settlement asynchronously, and calls your handler.
- Verification fails — Returns
402with an error describing why the payment was invalid.
Configuration Options
| Option | Type | Required | Default | Description |
|---|---|---|---|---|
apiUrl | string | Yes | — | Dunmore API base URL |
apiKey | string | Yes | — | Your gf_live_... API key |
projectId | string | Yes | — | Your proj_... project ID |
priceUsd | string | Yes | — | Price per request in USD (e.g. "0.001") |
payTo | string | Yes | — | Wallet address to receive USDC payments |
network | string | No | eip155:8453 | Chain ID. Use eip155:84532 for Base Sepolia testnet |
Error Responses
| Status | Code | When |
|---|---|---|
402 | PAYMENT_REQUIRED | No Payment-Signature header provided |
400 | INVALID_PAYMENT | Payment header is not valid base64 JSON |
402 | PAYMENT_INVALID | Payment failed on-chain verification |
500 | GATEWAY_ERROR | Dunmore facilitator is unreachable |