agentgate / tree / examples/demo.js ยท raw (this view has old GitHub links rewritten for the mirror; raw is byte-exact)
// Runnable demo: an Express API with one paid route gated by AgentGate.
//   npm run demo        -> offline, MockProvider + mock paywall (no network, no funds)
//   npm run demo:live   -> real Concordium mainnet registry lookups via the public badge-check API
//                          (payment step is still the MOCK paywall; no funds are moved)
import express from 'express';
import { agentGate, MockProvider, ConcordiumPublicProvider, encodeHeader, decodeHeader } from '../src/index.js';
import { mockPaywall } from './mock-paywall.js';

const live = process.argv.includes('--live');
const provider = live ? new ConcordiumPublicProvider() : new MockProvider();
const network = live ? 'mainnet' : 'testnet';

export function createApp() {
  const app = express();
  app.get('/free', (_req, res) => res.json({ ok: true }));
  app.get('/paid/quote', agentGate({ provider, network, bindPayer: !live }), mockPaywall(), (req, res) => {
    res.json({ quote: 'CCD/EUR 0.0123 (demo data)', servedTo: req.agentGate.tokenAddress, source: req.agentGate.source });
  });
  return app;
}

async function main() {
  const app = createApp();
  const server = app.listen(0);
  const base = `http://127.0.0.1:${server.address().port}`;
  const good = live ? 'Mf22soLh1NuZYFgBK8iSs' : 'MockVerifiedAgent1111'; // live: a real public mainnet agent (TippingService)
  const bad = live ? '4DDvjwdcLmTy1Ar9FCKKPMiABrS261TvyXJGr4n4ypuuogXeFX' : 'MockRevokedAgent22222';
  console.log(`AgentGate demo (${live ? 'LIVE Concordium mainnet registry' : 'MOCK provider, offline'}) on ${base}\n`);

  const show = async (label, headers = {}) => {
    const r = await fetch(`${base}/paid/quote`, { headers });
    const body = await r.json();
    console.log(`- ${label}\n  -> HTTP ${r.status} ${body.error || ''}${body.quote ? ' ' + JSON.stringify(body) : ''}`);
    return r;
  };
  await show('no badge header');
  await show(`unregistered/revoked agent (${bad})`, { 'X-Agent-Badge': bad });
  const r402 = await show(`verified agent (${good}), no payment yet`, { 'X-Agent-Badge': good });
  const reqs = decodeHeader(r402.headers.get('PAYMENT-REQUIRED'));
  if (reqs) {
    const accepted = reqs.accepts[0];
    const payer = live ? undefined : 'MOCK-WALLET-1';
    const sig = encodeHeader({ x402Version: 2, accepted, payload: { payer, mock: true } });
    await show(`verified agent pays (MOCK payment)`, { 'X-Agent-Badge': good, 'PAYMENT-SIGNATURE': sig });
  }
  server.close();
}

if (import.meta.url === `file://${process.argv[1]}`) main().catch((e) => { console.error(e); process.exit(1); });

agentgate-source: code mirror on Cloudflare Pages. All repos