Reference@t402/hono

@t402/hono

Hono middleware for protecting routes with t402 payment requirements. Lightweight and edge-compatible, perfect for Cloudflare Workers, Deno, and Bun.

Installation

npm install @t402/hono @t402/core

Quick Start

import { Hono } from 'hono';
import { paymentMiddleware } from '@t402/hono';
import { t402ResourceServer, createFacilitatorClient } from '@t402/core/server';
import { registerExactEvmScheme } from '@t402/evm/exact/server';
 
const app = new Hono();
 
// Create and configure the t402 server
const facilitator = createFacilitatorClient({ url: 'https://facilitator.t402.io' });
const server = new t402ResourceServer(facilitator);
registerExactEvmScheme(server, {});
 
// Define protected routes
const routes = {
  '/api/premium/*': {
    accepts: {
      scheme: 'exact',
      network: 'eip155:8453',
      payTo: '0xYourAddress',
      price: '$0.01',
    },
    description: 'Premium API access',
  },
};
 
// Apply middleware
app.use('*', paymentMiddleware(routes, server));
 
// Protected route
app.get('/api/premium/data', (c) => {
  return c.json({ data: 'Premium content' });
});
 
export default app;

API Reference

paymentMiddleware

Creates Hono middleware with a pre-configured server instance.

function paymentMiddleware(
  routes: RoutesConfig,
  server: t402ResourceServer,
  paywallConfig?: PaywallConfig,
  paywall?: PaywallProvider,
  syncFacilitatorOnStart?: boolean
): MiddlewareHandler

Parameters

ParameterTypeDescription
routesRoutesConfigRoute configurations for protected endpoints
servert402ResourceServerPre-configured server instance
paywallConfigPaywallConfigOptional paywall UI configuration
paywallPaywallProviderOptional custom paywall provider
syncFacilitatorOnStartbooleanSync with facilitator on startup (default: true)

Example

import { paymentMiddleware } from '@t402/hono';
 
app.use('*', paymentMiddleware(routes, server, {
  title: 'Premium API',
  theme: 'dark',
}));

paymentMiddlewareFromConfig

Creates Hono middleware with simple configuration.

function paymentMiddlewareFromConfig(
  routes: RoutesConfig,
  facilitatorClients?: FacilitatorClient | FacilitatorClient[],
  schemes?: SchemeRegistration[],
  paywallConfig?: PaywallConfig,
  paywall?: PaywallProvider,
  syncFacilitatorOnStart?: boolean
): MiddlewareHandler

Example

import { paymentMiddlewareFromConfig } from '@t402/hono';
import { createExactEvmServer } from '@t402/evm/exact/server';
 
app.use('*', paymentMiddlewareFromConfig(
  routes,
  facilitatorClient,
  [{ network: 'eip155:8453', server: createExactEvmServer({}) }]
));

Edge Runtime Support

Hono runs on edge runtimes. Use appropriate configurations:

// wrangler.toml
// name = "t402-api"
// main = "src/index.ts"
 
import { Hono } from 'hono';
import { paymentMiddleware } from '@t402/hono';
 
const app = new Hono();
 
// Configure for edge environment
const routes = {
  '/api/*': {
    accepts: {
      scheme: 'exact',
      network: 'eip155:8453',
      payTo: '0xYourAddress',
      price: '$0.001',
    },
    description: 'Edge API',
  },
};
 
app.use('*', paymentMiddleware(routes, server));
 
export default app;

Route Configuration

const routes: RoutesConfig = {
  // Exact path match
  '/api/premium': {
    accepts: {
      scheme: 'exact',
      network: 'eip155:8453',
      payTo: '0xRecipient',
      price: '$0.01',
    },
    description: 'Single endpoint',
  },
 
  // Wildcard match
  '/api/data/*': {
    accepts: {
      scheme: 'exact',
      network: 'eip155:8453',
      payTo: '0xRecipient',
      price: '$0.005',
    },
    description: 'All data endpoints',
  },
 
  // Multiple payment options
  '/api/multi': {
    accepts: [
      { scheme: 'exact', network: 'eip155:8453', payTo: '0x...', price: '$0.01' },
      { scheme: 'exact', network: 'ton:mainnet', payTo: 'EQ...', price: '$0.01' },
    ],
    description: 'Multi-chain support',
  },
};

Settlement Flow

The middleware ensures atomic payment settlement:

app.get('/api/premium/data', async (c) => {
  // This handler only runs after payment is verified
  const data = await fetchPremiumData();
 
  // Settlement happens after successful response
  return c.json({ data }); // Status 200 -> Payment settles
});
 
app.get('/api/premium/error', (c) => {
  // Error responses prevent settlement
  return c.json({ error: 'Not found' }, 404); // Status 404 -> No settlement
});

Payment settlement only occurs when your handler returns a successful response (status < 400).

Middleware Ordering

Place the payment middleware appropriately:

import { Hono } from 'hono';
import { cors } from 'hono/cors';
import { logger } from 'hono/logger';
import { paymentMiddleware } from '@t402/hono';
 
const app = new Hono();
 
// 1. CORS first
app.use('*', cors());
 
// 2. Logging
app.use('*', logger());
 
// 3. Payment middleware
app.use('*', paymentMiddleware(routes, server));
 
// 4. Routes
app.get('/api/premium/data', (c) => c.json({ data: 'Premium' }));

Group-Based Protection

Protect route groups:

const app = new Hono();
 
// Public routes
app.get('/api/public', (c) => c.json({ public: true }));
 
// Premium route group
const premium = new Hono();
premium.use('*', paymentMiddleware(routes, server));
premium.get('/data', (c) => c.json({ premium: true }));
premium.get('/analytics', (c) => c.json({ analytics: [] }));
 
app.route('/api/premium', premium);

Custom Paywall

import { PaywallProvider } from '@t402/core/server';
 
const customPaywall: PaywallProvider = {
  render: (paymentRequired, config) => {
    return `
      <!DOCTYPE html>
      <html>
        <head><title>${config?.title || 'Pay'}</title></head>
        <body>
          <h1>Payment Required</h1>
          <p>Amount: ${paymentRequired.requirements[0].maxAmountRequired}</p>
        </body>
      </html>
    `;
  },
};
 
app.use('*', paymentMiddleware(routes, server, paywallConfig, customPaywall));

Type Exports

// Server types
export { t402ResourceServer, t402HTTPResourceServer } from '@t402/core/server';
export type { PaywallProvider, PaywallConfig } from '@t402/core/server';
export { RouteConfigurationError } from '@t402/core/server';
 
// Protocol types
export type {
  PaymentRequired,
  PaymentRequirements,
  PaymentPayload,
  Network,
  SchemeNetworkServer,
} from '@t402/core/types';
 
// Adapter
export { HonoAdapter } from '@t402/hono';