import 'dotenv/config';
import { Hono } from 'hono';
import { serve } from '@hono/node-server';
import { HTTPFacilitatorClient } from '@x402/core/server';
import { paymentMiddleware, x402ResourceServer } from '@x402/hono';
import { ExactEvmScheme } from '@x402/evm/exact/server';
const required = (name: string) => {
const value = process.env[name];
if (!value) throw new Error(`Missing environment variable: ${name}`);
return value;
};
const apiKey = required('FACILITATOR_API_KEY');
const payTo = required('PAY_TO');
const network = required('NETWORK') as `${string}:${string}`;
const facilitator = new HTTPFacilitatorClient({
url: process.env.FACILITATOR_URL ?? 'https://api.x402go.online',
createAuthHeaders: async () => {
const headers = { 'x-api-key': apiKey };
return { verify: headers, settle: headers, supported: headers };
},
});
const resourceServer = new x402ResourceServer(facilitator).register(network, new ExactEvmScheme());
// Amounts are in the token's smallest unit (10000 = 0.01 for a 6-decimal token).
const price = (amount: string) => ({
amount,
asset: required('ASSET'),
extra: {
name: required('ASSET_NAME'),
version: required('ASSET_VERSION'),
...(process.env.METHOD === 'permit2' ? { assetTransferMethod: 'permit2' } : {}),
},
});
const app = new Hono();
app.use(
paymentMiddleware(
{
'GET /premium': {
accepts: [{ scheme: 'exact', network, payTo, price: price('10000') }],
description: 'Premium content',
mimeType: 'application/json',
},
'GET /reports': {
accepts: [{ scheme: 'exact', network, payTo, price: price('50000') }],
description: 'Detailed reports',
mimeType: 'application/json',
},
},
resourceServer,
),
);
app.get('/premium', (c) => c.json({ content: 'This resource requires payment.' }));
app.get('/reports', (c) => c.json({ report: 'Your paid report.' }));
// Routes not listed in the middleware config stay free.
app.get('/health', (c) => c.json({ ok: true }));
const port = Number(process.env.PORT) || 3000;
serve({ fetch: app.fetch, port }, () => {
console.log(`Listening on http://localhost:${port}`);
});