@t2000/serve 10.21.0 → 10.21.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -51,6 +51,7 @@ npm install @t2000/serve
51
51
  |---|---|---|
52
52
  | `T2000_PAY_TO` | yes | Your Sui address — payments settle here (`t2 address` prints it) |
53
53
  | `T2000_NETWORK` | no | `mainnet` (default) or `testnet` |
54
+ | `T2000_ACTIVITY_REPORT_URL` | no | Fire-and-forget `x402.paid` reports after each successful settle (chain-verified server-side; never affects buyer responses). **Default-on for `createServeFromEnv`**: unset → `https://t2000.ai/api/activity/x402`, so your sold routes appear on the [t2000.ai](https://t2000.ai/activity) activity tape. Opt out with `false` \| `0` \| `off` \| `none`, or set a custom URL. Code-constructed `new Serve({...})` stays silent unless you pass `activityReportUrl`. |
54
55
  | `T2000_BASE_URL` | no | Public URL of the deployed app (used in challenges + discovery) |
55
56
  | `KV_REST_API_URL` / `KV_REST_API_TOKEN` | serverless: yes | Upstash-compatible KV for durable replay protection. Without it the store is in-memory (fine for one long-lived process, wrong for serverless). |
56
57
 
package/dist/index.cjs CHANGED
@@ -369,6 +369,12 @@ var RouteBuilder = class {
369
369
  await runtime.store.set(challengeKey);
370
370
  } catch {
371
371
  }
372
+ reportActivity(runtime, {
373
+ digest: settle.transaction,
374
+ payer: settle.payer,
375
+ priceUsdc,
376
+ resource
377
+ });
372
378
  const headers = new Headers(served.headers);
373
379
  headers.set(suiX402.X402_PAYMENT_RESPONSE_HEADER, suiX402.encodeX402Response(settle));
374
380
  return new Response(served.body, { status: served.status, headers });
@@ -385,6 +391,27 @@ var RouteBuilder = class {
385
391
  return route;
386
392
  }
387
393
  };
394
+ function reportActivity(runtime, args) {
395
+ const url = runtime.activityReportUrl;
396
+ if (!url) return;
397
+ try {
398
+ void fetch(url, {
399
+ method: "POST",
400
+ headers: { "content-type": "application/json" },
401
+ body: JSON.stringify({
402
+ digest: args.digest,
403
+ payTo: runtime.payTo,
404
+ payer: args.payer,
405
+ amountMicroUsdc: Math.round(Number(args.priceUsdc) * 1e6),
406
+ network: `sui:${runtime.network}`,
407
+ route: args.resource,
408
+ source: "serve"
409
+ }),
410
+ signal: AbortSignal.timeout(1500)
411
+ }).catch(() => void 0);
412
+ } catch {
413
+ }
414
+ }
388
415
  async function respond402(runtime, args) {
389
416
  try {
390
417
  const { chain, epoch } = await getChainInfo(runtime.network, runtime.rpcUrl);
@@ -462,6 +489,8 @@ var UpstashDigestStore = class {
462
489
  };
463
490
 
464
491
  // src/serve.ts
492
+ var DEFAULT_ACTIVITY_REPORT_URL = "https://t2000.ai/api/activity/x402";
493
+ var REPORT_OPT_OUT = /* @__PURE__ */ new Set(["false", "0", "off", "none"]);
465
494
  var Serve = class {
466
495
  runtime;
467
496
  /** Every route built through this instance, keyed by path (discovery). */
@@ -471,6 +500,8 @@ var Serve = class {
471
500
  name;
472
501
  description;
473
502
  baseUrl;
503
+ /** Where settled payments are reported (B2) — undefined = no report. */
504
+ activityReportUrl;
474
505
  constructor(config) {
475
506
  if (!config.payTo || !utils.isValidSuiAddress(config.payTo)) {
476
507
  throw new Error(
@@ -482,6 +513,7 @@ var Serve = class {
482
513
  this.name = config.name;
483
514
  this.description = config.description;
484
515
  this.baseUrl = config.baseUrl?.replace(/\/$/, "");
516
+ this.activityReportUrl = config.activityReportUrl;
485
517
  const currency = this.network === "testnet" ? suiX402.USDC_TESTNET : suiX402.USDC;
486
518
  this.runtime = {
487
519
  payTo: this.payTo,
@@ -489,7 +521,8 @@ var Serve = class {
489
521
  currency,
490
522
  store: config.store ?? new suiX402.InMemoryDigestStore(),
491
523
  baseUrl: this.baseUrl,
492
- rpcUrl: config.rpcUrl
524
+ rpcUrl: config.rpcUrl,
525
+ activityReportUrl: this.activityReportUrl
493
526
  };
494
527
  }
495
528
  /** Start building a route. Chain `.paid()` / `.body()` / `.handler()`. */
@@ -597,9 +630,15 @@ function createServeFromEnv(env = process.env) {
597
630
  baseUrl: read("T2000_BASE_URL"),
598
631
  name: read("T2000_NAME"),
599
632
  description: read("T2000_DESCRIPTION"),
633
+ activityReportUrl: resolveReportUrlFromEnv(read("T2000_ACTIVITY_REPORT_URL")),
600
634
  store
601
635
  });
602
636
  }
637
+ function resolveReportUrlFromEnv(raw) {
638
+ if (raw === void 0) return DEFAULT_ACTIVITY_REPORT_URL;
639
+ if (REPORT_OPT_OUT.has(raw.toLowerCase())) return void 0;
640
+ return raw;
641
+ }
603
642
 
604
643
  // src/next.ts
605
644
  function asNextRoute(route) {
@@ -610,6 +649,7 @@ Object.defineProperty(exports, "InMemoryDigestStore", {
610
649
  enumerable: true,
611
650
  get: function () { return suiX402.InMemoryDigestStore; }
612
651
  });
652
+ exports.DEFAULT_ACTIVITY_REPORT_URL = DEFAULT_ACTIVITY_REPORT_URL;
613
653
  exports.RouteBuilder = RouteBuilder;
614
654
  exports.Serve = Serve;
615
655
  exports.UpstashDigestStore = UpstashDigestStore;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/discovery.ts","../src/chain.ts","../src/route.ts","../src/store.ts","../src/serve.ts","../src/next.ts"],"names":["USDC_TESTNET","USDC","SuiGrpcClient","X402_PAYMENT_HEADER","X402_PAYMENT_RESPONSE_HEADER","result","isX402EscrowHeader","parseX402Header","verifyX402Payment","settleX402Payment","encodeX402Response","createX402Requirements","X402_VERSION","isValidSuiAddress","normalizeSuiAddress","InMemoryDigestStore"],"mappings":"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","file":"index.cjs","sourcesContent":["import { USDC, USDC_TESTNET } from '@t2000/sui-x402';\nimport type { Serve } from './serve.js';\n\n// ---------------------------------------------------------------------------\n// Discovery docs — /openapi.json + /llms.txt.\n//\n// The shapes here are what the on-chain listing probe grades (the check\n// behind `t2 agent sell`) (was: apps/gateway/lib/\n// catalog-ingest.ts `gradeListing`): a warning-free listing needs info.title,\n// a one-paragraph info.description, a flat string `x-payment-info.price` per\n// paid operation, and an application/json requestBody schema with typed\n// properties. Everything serve can derive is emitted automatically; the JSON\n// request schema comes from the route's `inputSchema` (zod v4 users:\n// `z.toJSONSchema(schema)`).\n// ---------------------------------------------------------------------------\n\nexport function buildOpenApiDocument(serve: Serve, origin?: string): Record<string, unknown> {\n const base = serve.baseUrl ?? origin;\n const paths: Record<string, unknown> = {};\n\n for (const route of serve.routes.values()) {\n const { path, priceUsdc, description, inputSchema, outputSchema } = route.meta;\n const operation: Record<string, unknown> = {\n operationId: path.replace(/[^a-zA-Z0-9]+/g, '_'),\n summary: description ?? path,\n responses: {\n '200': outputSchema\n ? {\n description: 'Success',\n content: { 'application/json': { schema: outputSchema } },\n }\n : { description: 'Success' },\n ...(priceUsdc\n ? {\n '402': {\n description:\n 'Payment required — the body carries an x402 accepts[] envelope (scheme \"exact\", network sui). Sign it and retry with the X-PAYMENT header.',\n },\n }\n : {}),\n '422': { description: 'Invalid request body — never charged' },\n },\n };\n if (priceUsdc) {\n // Same shape the gateway's own /openapi.json emits: 'mpp' is the\n // protocol family, 'x402' the dialect; the x402 block mirrors the\n // static half of the live accepts[] entry (dynamic fields ride the 402).\n operation['x-payment-info'] = {\n pricingMode: 'fixed',\n price: priceUsdc,\n currency: 'USDC',\n protocols: ['mpp', 'x402'],\n x402: {\n scheme: 'exact',\n network: `sui:${serve.network}`,\n asset: (serve.network === 'testnet' ? USDC_TESTNET : USDC).type,\n payTo: serve.payTo,\n },\n };\n }\n if (inputSchema) {\n operation.requestBody = {\n required: true,\n content: { 'application/json': { schema: inputSchema } },\n };\n }\n paths[`/${path}`] = { post: operation };\n }\n\n return {\n openapi: '3.1.0',\n info: {\n title: serve.name ?? 'Paid API',\n version: '1.0.0',\n description:\n serve.description ??\n 'Agent-payable API. Every paid endpoint answers 402 with an x402 accepts[] envelope; payment settles in USDC on Sui.',\n },\n ...(base ? { servers: [{ url: base }] } : {}),\n paths,\n };\n}\n\nexport function buildLlmsTxt(serve: Serve, origin?: string): string {\n const base = serve.baseUrl ?? origin ?? '';\n const lines: string[] = [];\n lines.push(`# ${serve.name ?? 'Paid API'}`);\n lines.push('');\n if (serve.description) {\n lines.push(serve.description);\n lines.push('');\n }\n lines.push('## How to pay');\n lines.push('');\n lines.push(\n 'Endpoints below are paid per call in USDC on Sui (x402). An unpaid request returns',\n 'HTTP 402 with an `accepts[]` envelope; sign it and retry with the `X-PAYMENT` header.',\n 'Invalid input returns 422 before any payment is taken. A failed call is never charged.',\n '',\n 'Easiest client: `npm i -g @t2000/cli` then `t2 pay <url> --data \\'{...}\\'`,',\n 'or the t2000 MCP server (`t2000_pay`), or `@t2000/sdk` `pay()`.',\n '',\n );\n lines.push('## Endpoints');\n lines.push('');\n for (const route of serve.routes.values()) {\n const { path, priceUsdc, description, inputSchema, outputSchema } = route.meta;\n const price = priceUsdc ? `${priceUsdc} USDC per call` : 'free';\n lines.push(`### POST ${base}/${path} — ${price}`);\n if (description) lines.push(description);\n if (inputSchema) {\n lines.push('Request body (JSON Schema):');\n lines.push('```json');\n lines.push(JSON.stringify(inputSchema, null, 2));\n lines.push('```');\n }\n if (outputSchema) {\n lines.push('Response (JSON Schema — contentMediaType/format annotations name the deliverable types):');\n lines.push('```json');\n lines.push(JSON.stringify(outputSchema, null, 2));\n lines.push('```');\n }\n lines.push('');\n }\n lines.push(`Discovery: ${base}/openapi.json`);\n return lines.join('\\n');\n}\n","import { SuiGrpcClient } from '@mysten/sui/grpc';\nimport type { ServeNetwork } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Chain plumbing — same shape as the gateway's x402-dialect.ts (the reference\n// composition). All reads are gRPC; this package never touches JSON-RPC.\n//\n// Cache policy: the chain identifier (genesis digest) is immutable per\n// network — cached forever. The epoch advances ~daily and x402 requirements\n// are valid for [epoch, epoch+1], so a 10-minute TTL is conservatively fresh.\n// ---------------------------------------------------------------------------\n\nconst FULLNODE_URLS: Record<ServeNetwork, string> = {\n mainnet: 'https://fullnode.mainnet.sui.io:443',\n testnet: 'https://fullnode.testnet.sui.io:443',\n};\n\nconst EPOCH_TTL_MS = 10 * 60 * 1000;\n\nexport interface ChainInfo {\n chain: string;\n epoch: string;\n}\n\ninterface ChainState {\n client?: SuiGrpcClient;\n chainId?: string;\n epoch?: { value: string; fetchedAt: number };\n}\n\nconst state: Partial<Record<ServeNetwork, ChainState>> = {};\n\nexport function getGrpcClient(network: ServeNetwork, rpcUrl?: string): SuiGrpcClient {\n const s = (state[network] ??= {});\n if (!s.client) {\n s.client = new SuiGrpcClient({\n baseUrl: rpcUrl ?? FULLNODE_URLS[network],\n network,\n });\n }\n return s.client;\n}\n\nexport async function getChainInfo(network: ServeNetwork, rpcUrl?: string): Promise<ChainInfo> {\n const client = getGrpcClient(network, rpcUrl);\n const s = (state[network] ??= {});\n if (!s.chainId) {\n const res = await client.core.getChainIdentifier();\n s.chainId = res.chainIdentifier;\n }\n if (!s.epoch || Date.now() - s.epoch.fetchedAt > EPOCH_TTL_MS) {\n const res = await client.core.getCurrentSystemState();\n s.epoch = { value: String(res.systemState.epoch), fetchedAt: Date.now() };\n }\n return { chain: s.chainId, epoch: s.epoch.value };\n}\n\n/** Test seam — reset module caches between cases. */\nexport function __resetChainCaches(): void {\n delete state.mainnet;\n delete state.testnet;\n}\n\n/** Test seam — pre-seed chain info so tests never hit the network. */\nexport function __seedChainInfo(network: ServeNetwork, chain: string, epoch: string): void {\n const s = (state[network] ??= {});\n s.chainId = chain;\n s.epoch = { value: epoch, fetchedAt: Date.now() };\n}\n","import type { Currency, DigestStore } from '@t2000/sui-x402';\nimport {\n createX402Requirements,\n encodeX402Response,\n isX402EscrowHeader,\n parseX402Header,\n settleX402Payment,\n verifyX402Payment,\n X402_PAYMENT_HEADER,\n X402_PAYMENT_RESPONSE_HEADER,\n X402_VERSION,\n type X402SettleResponse,\n} from '@t2000/sui-x402';\nimport { getChainInfo, getGrpcClient } from './chain.js';\nimport type {\n BuiltRoute,\n HandlerContext,\n HandlerResult,\n ServeNetwork,\n ServeSchema,\n StandardSchemaLike,\n} from './types.js';\n\n// ---------------------------------------------------------------------------\n// The paid-request lifecycle (SPEC_T2000_SERVE §3 — sign-then-settle,\n// handler-then-settle):\n//\n// no X-PAYMENT → 402 with the accepts[] envelope (never a charge;\n// the catalog probe and every discovery tool read\n// this, so it fires BEFORE body validation)\n// X-PAYMENT present:\n// 1. parse + STRUCTURAL verify (right amount/recipient/nonce — no RPC)\n// 2. challenge-once check (a signed payload is single-use)\n// 3. validate the body — invalid → 422, payment NEVER submitted\n// (the JMPR paid-422 class is impossible: the buyer keeps their money)\n// 4. run the handler — throws → 500, payment NEVER submitted\n// 5. settle (submit the buyer-signed gasless bytes; digest-once inside)\n// 6. consume the challenge, attach the X-PAYMENT-RESPONSE receipt\n//\n// Money only moves at step 5, after the seller has already produced the\n// result. A forged payload can waste seller compute (signature authority is\n// the chain at settle time), never buyer money.\n// ---------------------------------------------------------------------------\n\nexport interface RouteRuntime {\n payTo: string;\n network: ServeNetwork;\n currency: Currency;\n store: DigestStore;\n baseUrl?: string;\n rpcUrl?: string;\n}\n\nexport interface RouteOptions {\n path: string;\n description?: string;\n}\n\n/** Sanity cap on a per-call price — above this, the work is job-shaped\n * (escrow) rather than a per-call x402 Service. */\nconst CATALOG_PRICE_CAP_USDC = 5;\n\nconst CORS_HEADERS: Record<string, string> = {\n 'access-control-allow-origin': '*',\n 'access-control-allow-methods': 'GET, POST, PUT, DELETE, OPTIONS',\n 'access-control-allow-headers': `content-type, ${X402_PAYMENT_HEADER}`,\n 'access-control-expose-headers': `${X402_PAYMENT_RESPONSE_HEADER}, WWW-Authenticate`,\n};\n\nfunction withCors(response: Response): Response {\n const headers = new Headers(response.headers);\n for (const [k, v] of Object.entries(CORS_HEADERS)) headers.set(k, v);\n return new Response(response.body, { status: response.status, headers });\n}\n\nfunction json(status: number, body: unknown, headers?: Record<string, string>): Response {\n return withCors(\n new Response(JSON.stringify(body), {\n status,\n headers: { 'content-type': 'application/json', ...headers },\n }),\n );\n}\n\nfunction isStandardSchema(schema: ServeSchema): schema is StandardSchemaLike {\n return typeof schema === 'object' && schema !== null && '~standard' in schema;\n}\n\nasync function validateBody(\n schema: ServeSchema,\n value: unknown,\n): Promise<{ ok: true; data: unknown } | { ok: false; message: string }> {\n if (isStandardSchema(schema)) {\n const result = await schema['~standard'].validate(value);\n if (result.issues) {\n // Name the failing field — bare \"Invalid input\" ×N gives a paying\n // buyer's agent nothing to self-correct with.\n const message = result.issues\n .map((i) => {\n const path = (i.path ?? [])\n .map((seg) => (typeof seg === 'object' ? String(seg.key) : String(seg)))\n .join('.');\n return path ? `${path}: ${i.message}` : i.message;\n })\n .join('; ');\n return { ok: false, message };\n }\n return { ok: true, data: result.value };\n }\n const result = schema.safeParse(value);\n if (!result.success) {\n return { ok: false, message: result.error.message ?? 'invalid body' };\n }\n return { ok: true, data: result.data };\n}\n\n/** Positive decimal USDC string, max 6dp (atomic precision). */\nfunction assertValidPrice(price: string, path: string): void {\n if (!/^\\d+(\\.\\d{1,6})?$/.test(price) || Number(price) <= 0) {\n throw new Error(\n `[serve] Route \"${path}\": price must be a positive decimal USDC string with up to 6 decimals, got \"${price}\"`,\n );\n }\n if (Number(price) > CATALOG_PRICE_CAP_USDC) {\n console.warn(\n `[serve] Route \"${path}\": price ${price} USDC is above the ${CATALOG_PRICE_CAP_USDC} USDC listing cap — ` +\n 'the route works, but per-call x402 is the wrong shape for it. Job-class work belongs in `t2 service create` (escrow).',\n );\n }\n}\n\nexport class RouteBuilder<TBody = undefined> {\n private priceUsdc?: string;\n private bodySchema?: ServeSchema;\n private inputSchema?: Record<string, unknown>;\n private outputSchema?: Record<string, unknown>;\n private isFree = false;\n\n constructor(\n private readonly runtime: RouteRuntime,\n private readonly options: RouteOptions,\n private readonly register: (route: BuiltRoute) => void,\n ) {}\n\n /** Charge this many USDC per call (human units, e.g. \"0.01\"). */\n paid(priceUsdc: string): this {\n assertValidPrice(priceUsdc, this.options.path);\n this.priceUsdc = priceUsdc;\n this.isFree = false;\n return this;\n }\n\n /** Serve without payment (health checks, previews, docs). */\n unprotected(): this {\n this.isFree = true;\n this.priceUsdc = undefined;\n return this;\n }\n\n /**\n * Validate the JSON request body. zod v4 / valibot / arktype / anything\n * Standard-Schema, or anything with a zod-style safeParse.\n *\n * Pass the JSON Schema as the second argument to publish it in\n * /openapi.json + /llms.txt (zod v4: `z.toJSONSchema(schema)`) — buyers'\n * agents build request bodies from it, and the catalog grades listings\n * without one.\n */\n body<T>(schema: ServeSchema<T>, jsonSchema?: Record<string, unknown>): RouteBuilder<T> {\n this.bodySchema = schema;\n this.inputSchema = jsonSchema;\n return this as unknown as RouteBuilder<T>;\n }\n\n /**\n * Declare the 200 response's JSON Schema (zod v4: `z.toJSONSchema(schema)`).\n * Published in /openapi.json + /llms.txt so buyer agents know what they're\n * buying and buyer UIs can render the deliverable by TYPE instead of\n * sniffing it — annotate with `contentMediaType` (e.g. \"image/svg+xml\",\n * \"text/markdown\") and `format: \"color\"` where they apply. Declaration\n * only; responses are never validated at runtime.\n */\n response(jsonSchema: Record<string, unknown>): this {\n this.outputSchema = jsonSchema;\n return this;\n }\n\n handler(fn: (ctx: HandlerContext<TBody>) => HandlerResult | Promise<HandlerResult>): BuiltRoute {\n if (!this.isFree && !this.priceUsdc) {\n throw new Error(\n `[serve] Route \"${this.options.path}\": call .paid('<usdc>') or .unprotected() before .handler()`,\n );\n }\n const runtime = this.runtime;\n const { path, description } = this.options;\n const priceUsdc = this.priceUsdc;\n const bodySchema = this.bodySchema;\n\n const route = (async (req: Request): Promise<Response> => {\n if (req.method === 'OPTIONS') {\n return withCors(new Response(null, { status: 204 }));\n }\n\n // Read + parse the body once, up front. A missing/empty body on a\n // schema-less route is fine; JSON parse failures only matter when a\n // paid request must be validated (the unpaid 402 fires regardless).\n let parsedBody: unknown;\n let bodyParseError: string | undefined;\n if (req.method !== 'GET' && req.method !== 'HEAD') {\n const text = await req.text();\n if (text.trim().length > 0) {\n try {\n parsedBody = JSON.parse(text);\n } catch {\n bodyParseError = 'request body is not valid JSON';\n }\n }\n }\n\n const resource = (runtime.baseUrl ?? new URL(req.url).origin).replace(/\\/$/, '') + `/${path}`;\n\n const runHandler = async (payer?: string): Promise<Response> => {\n let validated: unknown = parsedBody;\n if (bodySchema) {\n // `paid: false` is machine-readable charge honesty — a 422 fires\n // BEFORE settlement, so the buyer always keeps their money.\n if (bodyParseError) {\n return json(422, { error: bodyParseError, paid: false });\n }\n const result = await validateBody(bodySchema, parsedBody ?? {});\n if (!result.ok) {\n return json(422, { error: result.message, paid: false });\n }\n validated = result.data;\n }\n const out = await fn({ body: validated as TBody, req, payer });\n if (out instanceof Response) return withCors(out);\n return json(200, out);\n };\n\n // Free route — no payment machinery at all.\n if (!priceUsdc) {\n try {\n return await runHandler();\n } catch (err) {\n console.error(`[serve] Route \"${path}\" handler failed:`, err);\n return json(500, { error: 'internal error' });\n }\n }\n\n const paymentHeader = req.headers.get(X402_PAYMENT_HEADER);\n\n // Unpaid → 402 with the accepts[] envelope. This fires before body\n // validation on purpose: the catalog probe (and every discovery tool)\n // POSTs `{}` and must see the challenge, and an unpaid request can\n // never be charged, so there is nothing to protect yet.\n if (!paymentHeader) {\n return await respond402(runtime, { resource, priceUsdc });\n }\n\n if (isX402EscrowHeader(paymentHeader)) {\n return await respond402(runtime, {\n resource,\n priceUsdc,\n error:\n 'this endpoint sells instant per-call work (settle-then-serve), not escrow jobs — retry with a signed x402 payment',\n });\n }\n\n // 1. Parse + structural verify — right terms, right recipient, right\n // nonce. No RPC, no state. Wrong-terms payloads never reach the\n // handler.\n let payment: ReturnType<typeof parseX402Header>;\n try {\n payment = parseX402Header(paymentHeader);\n verifyX402Payment({\n payment,\n expected: {\n challengeId: payment.payload.challengeId,\n amount: priceUsdc,\n currency: runtime.currency,\n recipient: runtime.payTo,\n network: runtime.network,\n },\n });\n } catch (err) {\n return await respond402(runtime, {\n resource,\n priceUsdc,\n error: `invalid payment: ${err instanceof Error ? err.message : String(err)}`,\n });\n }\n\n // 2. Challenge-once — a signed payload is single-use even before it\n // settles (the settled digest is separately consumed inside\n // settleX402Payment, digest-once).\n const challengeKey = `challenge:${payment.payload.challengeId}`;\n if (await runtime.store.has(challengeKey)) {\n return await respond402(runtime, {\n resource,\n priceUsdc,\n error: 'payment challenge already used — sign a fresh payment',\n });\n }\n\n // 3 + 4. Validate, then compute the result. Any failure here returns\n // WITHOUT settling — the buyer-signed bytes are never submitted.\n let served: Response;\n try {\n served = await runHandler(payment.payload.senderAddress);\n } catch (err) {\n console.error(`[serve] Route \"${path}\" handler failed (payment NOT settled):`, err);\n return json(500, { error: 'internal error — you were not charged' });\n }\n if (served.status >= 400) return served; // 422 etc. — not charged\n\n // 5. Settle — submit the buyer-signed gasless bytes, confirm the\n // on-chain balance change, record the digest (digest-once).\n let settle: X402SettleResponse;\n try {\n settle = await settleX402Payment({\n payment,\n client: getGrpcClient(runtime.network, runtime.rpcUrl),\n store: runtime.store,\n expected: {\n challengeId: payment.payload.challengeId,\n amount: priceUsdc,\n currency: runtime.currency,\n recipient: runtime.payTo,\n network: runtime.network,\n },\n });\n } catch (err) {\n return await respond402(runtime, {\n resource,\n priceUsdc,\n error: `settlement failed: ${err instanceof Error ? err.message : String(err)}`,\n });\n }\n\n // 6. Consume the challenge + attach the receipt.\n try {\n await runtime.store.set(challengeKey);\n } catch {\n // Digest-once already holds; challenge-once is defense in depth.\n }\n\n const headers = new Headers(served.headers);\n headers.set(X402_PAYMENT_RESPONSE_HEADER, encodeX402Response(settle));\n return new Response(served.body, { status: served.status, headers });\n }) as BuiltRoute;\n\n route.meta = {\n path,\n priceUsdc,\n description,\n bodySchema,\n inputSchema: this.inputSchema,\n outputSchema: this.outputSchema,\n };\n this.register(route);\n return route;\n }\n}\n\nasync function respond402(\n runtime: RouteRuntime,\n args: { resource: string; priceUsdc: string; error?: string },\n): Promise<Response> {\n try {\n const { chain, epoch } = await getChainInfo(runtime.network, runtime.rpcUrl);\n const requirements = createX402Requirements({\n challengeId: crypto.randomUUID(),\n amount: args.priceUsdc,\n currency: runtime.currency,\n recipient: runtime.payTo,\n resource: args.resource,\n network: runtime.network,\n chain,\n currentEpoch: epoch,\n });\n // Belt-and-suspenders for pre-0.2.2 discovery clients and dual-dialect\n // consumers: mirror the challenge into the MPP WWW-Authenticate shape.\n // The accepts[] body stays the authoritative envelope — the header carries\n // the same recipient/currency and the DECIMAL amount that dialect uses.\n const host = (() => {\n try {\n return new URL(args.resource).hostname;\n } catch {\n return undefined;\n }\n })();\n const wwwAuth = `Payment realm=\"${host ?? 'x402'}\", recipient=\"${runtime.payTo}\", currency=\"${runtime.currency}\", amount=\"${args.priceUsdc}\"`;\n return json(\n 402,\n {\n x402Version: X402_VERSION,\n error: args.error ?? 'Payment required',\n accepts: [requirements],\n },\n { 'WWW-Authenticate': wwwAuth },\n );\n } catch (err) {\n // Chain info unreachable — a 402 without the envelope is unpayable, so\n // be honest about the outage instead of serving a dead challenge.\n console.error('[serve] failed to build 402 challenge:', err);\n return json(503, { error: 'payment challenge temporarily unavailable' });\n }\n}\n\n","import type { DigestStore } from '@t2000/sui-x402';\n\nexport { InMemoryDigestStore } from '@t2000/sui-x402';\nexport type { DigestStore } from '@t2000/sui-x402';\n\n// ---------------------------------------------------------------------------\n// Upstash-REST digest store — the production replay store for serverless\n// hosts. Mirrors the gateway's upstash-digest-store.ts but speaks the\n// Upstash REST API over plain fetch (no @upstash/redis dependency).\n//\n// TTL: 72h. x402 payments are chain-valid for the whole ValidDuring window\n// ([minEpoch, minEpoch+1] ≈ up to ~48h on mainnet). Sui resubmission of an\n// executed tx is idempotent, so if the digest/challenge keys expired BEFORE\n// the window closed, a replayed X-PAYMENT would re-settle \"successfully\"\n// and serve again on a single payment. 72h > max window + drift.\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_TTL_SECONDS = 72 * 60 * 60;\nconst PREFIX = 'serve:digest:';\n\nexport interface UpstashDigestStoreOptions {\n url: string;\n token: string;\n /** Key TTL in seconds. Default 72h — do not lower below ~50h (see above). */\n ttlSeconds?: number;\n}\n\nexport class UpstashDigestStore implements DigestStore {\n private readonly url: string;\n private readonly token: string;\n private readonly ttlSeconds: number;\n\n constructor(options: UpstashDigestStoreOptions) {\n this.url = options.url.replace(/\\/$/, '');\n this.token = options.token;\n this.ttlSeconds = options.ttlSeconds ?? DEFAULT_TTL_SECONDS;\n }\n\n private async command(segments: string[]): Promise<unknown> {\n const res = await fetch(`${this.url}/${segments.map(encodeURIComponent).join('/')}`, {\n headers: { authorization: `Bearer ${this.token}` },\n });\n if (!res.ok) {\n throw new Error(`Upstash command failed: ${res.status} ${await res.text()}`);\n }\n const body = (await res.json()) as { result?: unknown; error?: string };\n if (body.error) throw new Error(`Upstash error: ${body.error}`);\n return body.result;\n }\n\n async has(digest: string): Promise<boolean> {\n const result = await this.command(['GET', PREFIX + digest]);\n return result !== null && result !== undefined;\n }\n\n async set(digest: string): Promise<void> {\n // SET key 1 EX <ttl> NX — atomic set-if-absent. A null result means the\n // key already existed: the digest (or challenge) was already consumed.\n const result = await this.command([\n 'SET',\n PREFIX + digest,\n '1',\n 'EX',\n String(this.ttlSeconds),\n 'NX',\n ]);\n if (result === null || result === undefined) {\n throw new Error(`Digest already used: ${digest}`);\n }\n }\n}\n","import { isValidSuiAddress, normalizeSuiAddress } from '@mysten/sui/utils';\nimport { InMemoryDigestStore, USDC, USDC_TESTNET, type Currency } from '@t2000/sui-x402';\nimport { buildLlmsTxt, buildOpenApiDocument } from './discovery.js';\nimport { RouteBuilder, type RouteOptions, type RouteRuntime } from './route.js';\nimport { UpstashDigestStore } from './store.js';\nimport type { BuiltRoute, ServeConfig, ServeNetwork } from './types.js';\n\nexport class Serve {\n private readonly runtime: RouteRuntime;\n /** Every route built through this instance, keyed by path (discovery). */\n readonly routes = new Map<string, BuiltRoute>();\n\n readonly payTo: string;\n readonly network: ServeNetwork;\n readonly name?: string;\n readonly description?: string;\n readonly baseUrl?: string;\n\n constructor(config: ServeConfig) {\n if (!config.payTo || !isValidSuiAddress(config.payTo)) {\n throw new Error(\n `[serve] payTo must be a valid Sui address (the wallet your payments settle to), got \"${config.payTo}\"`,\n );\n }\n this.payTo = normalizeSuiAddress(config.payTo);\n this.network = config.network ?? 'mainnet';\n this.name = config.name;\n this.description = config.description;\n this.baseUrl = config.baseUrl?.replace(/\\/$/, '');\n\n const currency: Currency = this.network === 'testnet' ? USDC_TESTNET : USDC;\n this.runtime = {\n payTo: this.payTo,\n network: this.network,\n currency,\n store: config.store ?? new InMemoryDigestStore(),\n baseUrl: this.baseUrl,\n rpcUrl: config.rpcUrl,\n };\n }\n\n /** Start building a route. Chain `.paid()` / `.body()` / `.handler()`. */\n route(options: RouteOptions): RouteBuilder {\n const path = options.path.replace(/^\\/+/, '').replace(/\\/+$/, '');\n if (!path) throw new Error('[serve] route path must be non-empty');\n return new RouteBuilder({ ...this.runtime }, { ...options, path }, (route) => {\n this.routes.set(path, route);\n });\n }\n\n /**\n * Discovery: GET handler for /openapi.json. OpenAPI 3.1 with the\n * `x-payment-info` pricing extension on every paid operation — the shape\n * x402 tooling (and any catalog built on it) indexes.\n *\n * export const GET = serve.openapi(); // app/openapi.json/route.ts\n */\n openapi(): (req: Request) => Response {\n return (req: Request) =>\n new Response(JSON.stringify(buildOpenApiDocument(this, new URL(req.url).origin), null, 2), {\n headers: { 'content-type': 'application/json', 'access-control-allow-origin': '*' },\n });\n }\n\n /**\n * Discovery: GET handler for /llms.txt — plain-text guidance agents read\n * to understand what the API sells, what it costs, and how to pay.\n *\n * export const GET = serve.llms(); // app/llms.txt/route.ts\n */\n llms(): (req: Request) => Response {\n return (req: Request) =>\n new Response(buildLlmsTxt(this, new URL(req.url).origin), {\n headers: { 'content-type': 'text/plain; charset=utf-8', 'access-control-allow-origin': '*' },\n });\n }\n\n /**\n * One fetch handler for the whole app — routes + discovery docs. For\n * fetch-native runtimes (Bun.serve, Deno.serve, Hono, Cloudflare Workers):\n *\n * Bun.serve({ fetch: serve.fetch });\n * app.all('*', (c) => serve.fetch(c.req.raw)); // Hono\n *\n * Next.js apps can skip this and export route handlers directly.\n */\n readonly fetch = async (req: Request): Promise<Response> => {\n const pathname = new URL(req.url).pathname.replace(/^\\/+/, '').replace(/\\/+$/, '');\n if (pathname === 'openapi.json') return this.openapi()(req);\n if (pathname === 'llms.txt') return this.llms()(req);\n const route = this.routes.get(pathname);\n if (route) return route(req);\n return new Response(\n JSON.stringify({ error: 'not found', discovery: ['/openapi.json', '/llms.txt'] }),\n { status: 404, headers: { 'content-type': 'application/json' } },\n );\n };\n\n /**\n * The command that sells this API as an x402 Service on your Agent ID,\n * once it is deployed. Listing is a separate, explicit step: the endpoint\n * is live-probed (it must answer 402 with a Sui challenge that pays YOUR\n * wallet) and then recorded on-chain, sponsored and gasless.\n *\n * This used to emit curls against the hosted mpp.t2000.ai catalog. That\n * proxy mall was purged 2026-08-01 (SPEC_T2_CLEANUP_USDC_ONLY) — there is\n * no central catalog to submit to. Your Agent ID IS the listing, and\n * buyers find it with `t2 services`.\n */\n catalogSubmitCommand(deployedUrl?: string): string {\n const base = (deployedUrl ?? this.baseUrl ?? 'https://<your-deployed-app>').replace(/\\/$/, '');\n const paidPaths = [...this.routes.values()].filter((r) => r.meta.priceUsdc);\n const example = paidPaths[0]?.meta.path ?? '<route>';\n return [\n '# Sell it as an x402 Service on your Agent ID (live-probed, gasless):',\n `npx @t2000/cli agent sell ${base}/${example}`,\n '# Buyers then find it with `t2 services` and pay per call with `t2 pay`.',\n ].join('\\n');\n }\n}\n\nexport function createServe(config: ServeConfig): Serve {\n return new Serve(config);\n}\n\n/**\n * Build a Serve from environment variables — the template-app path where\n * config lives in the host's env UI, not code.\n *\n * T2000_PAY_TO required — the seller's Sui address\n * T2000_NETWORK optional — 'mainnet' (default) | 'testnet'\n * T2000_BASE_URL optional — public URL of the deployed app\n * T2000_NAME optional — service name for discovery docs\n * T2000_DESCRIPTION optional — one-liner for discovery docs\n * KV_REST_API_URL / KV_REST_API_TOKEN\n * optional — enables the durable Upstash replay store\n * (REQUIRED in serverless production; without it replay\n * state is per-instance memory)\n *\n * Empty strings are treated as unset (the Vercel empty-env bug class).\n */\nexport function createServeFromEnv(env: Record<string, string | undefined> = process.env): Serve {\n const read = (key: string): string | undefined => {\n const v = env[key]?.trim();\n return v && v.length > 0 ? v : undefined;\n };\n\n const payTo = read('T2000_PAY_TO');\n if (!payTo) {\n throw new Error(\n '[serve] T2000_PAY_TO is not set (or is empty). Set it to the Sui address your payments should settle to — `t2 address` prints yours.',\n );\n }\n\n const network = read('T2000_NETWORK');\n if (network && network !== 'mainnet' && network !== 'testnet') {\n throw new Error(`[serve] T2000_NETWORK must be 'mainnet' or 'testnet', got \"${network}\"`);\n }\n\n const kvUrl = read('KV_REST_API_URL');\n const kvToken = read('KV_REST_API_TOKEN');\n const store =\n kvUrl && kvToken ? new UpstashDigestStore({ url: kvUrl, token: kvToken }) : undefined;\n\n if (!store) {\n console.warn(\n '[serve] No KV_REST_API_URL/KV_REST_API_TOKEN — using the in-memory replay store. ' +\n 'Fine for a single long-lived process; on serverless hosts set both so replay protection is durable.',\n );\n }\n\n return new Serve({\n payTo,\n network: (network as ServeNetwork | undefined) ?? 'mainnet',\n baseUrl: read('T2000_BASE_URL'),\n name: read('T2000_NAME'),\n description: read('T2000_DESCRIPTION'),\n store,\n });\n}\n","import type { BuiltRoute } from './types.js';\n\n/**\n * Export a built route the way Next.js App Router needs it.\n *\n * Next dispatches ONLY the methods a route.ts exports — serve's own CORS\n * handling (OPTIONS → 204 with the ACAO headers) never runs if the file\n * exports just `POST`: the browser preflight gets Next's bare 204 with no\n * CORS headers, and every browser buyer (Passport, the store's Try it)\n * fails while CLI/server buyers — who never preflight — work fine. Fetch\n * runtimes mounted via a single handler (`serve.fetch`-style) don't have\n * this hole; it is a Next export contract, not a serve one.\n *\n * export const { POST, OPTIONS } = asNextRoute(\n * serve.route({ path: 'haiku' }).paid('0.01').handler(fn),\n * );\n */\nexport function asNextRoute(route: BuiltRoute): {\n POST: BuiltRoute;\n OPTIONS: BuiltRoute;\n} {\n return { POST: route, OPTIONS: route };\n}\n"]}
1
+ {"version":3,"sources":["../src/discovery.ts","../src/chain.ts","../src/route.ts","../src/store.ts","../src/serve.ts","../src/next.ts"],"names":["USDC_TESTNET","USDC","SuiGrpcClient","X402_PAYMENT_HEADER","X402_PAYMENT_RESPONSE_HEADER","result","isX402EscrowHeader","parseX402Header","verifyX402Payment","settleX402Payment","encodeX402Response","createX402Requirements","X402_VERSION","isValidSuiAddress","normalizeSuiAddress","InMemoryDigestStore"],"mappings":"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","file":"index.cjs","sourcesContent":["import { USDC, USDC_TESTNET } from '@t2000/sui-x402';\nimport type { Serve } from './serve.js';\n\n// ---------------------------------------------------------------------------\n// Discovery docs — /openapi.json + /llms.txt.\n//\n// The shapes here are what the on-chain listing probe grades (the check\n// behind `t2 agent sell`) (was: apps/gateway/lib/\n// catalog-ingest.ts `gradeListing`): a warning-free listing needs info.title,\n// a one-paragraph info.description, a flat string `x-payment-info.price` per\n// paid operation, and an application/json requestBody schema with typed\n// properties. Everything serve can derive is emitted automatically; the JSON\n// request schema comes from the route's `inputSchema` (zod v4 users:\n// `z.toJSONSchema(schema)`).\n// ---------------------------------------------------------------------------\n\nexport function buildOpenApiDocument(serve: Serve, origin?: string): Record<string, unknown> {\n const base = serve.baseUrl ?? origin;\n const paths: Record<string, unknown> = {};\n\n for (const route of serve.routes.values()) {\n const { path, priceUsdc, description, inputSchema, outputSchema } = route.meta;\n const operation: Record<string, unknown> = {\n operationId: path.replace(/[^a-zA-Z0-9]+/g, '_'),\n summary: description ?? path,\n responses: {\n '200': outputSchema\n ? {\n description: 'Success',\n content: { 'application/json': { schema: outputSchema } },\n }\n : { description: 'Success' },\n ...(priceUsdc\n ? {\n '402': {\n description:\n 'Payment required — the body carries an x402 accepts[] envelope (scheme \"exact\", network sui). Sign it and retry with the X-PAYMENT header.',\n },\n }\n : {}),\n '422': { description: 'Invalid request body — never charged' },\n },\n };\n if (priceUsdc) {\n // Same shape the gateway's own /openapi.json emits: 'mpp' is the\n // protocol family, 'x402' the dialect; the x402 block mirrors the\n // static half of the live accepts[] entry (dynamic fields ride the 402).\n operation['x-payment-info'] = {\n pricingMode: 'fixed',\n price: priceUsdc,\n currency: 'USDC',\n protocols: ['mpp', 'x402'],\n x402: {\n scheme: 'exact',\n network: `sui:${serve.network}`,\n asset: (serve.network === 'testnet' ? USDC_TESTNET : USDC).type,\n payTo: serve.payTo,\n },\n };\n }\n if (inputSchema) {\n operation.requestBody = {\n required: true,\n content: { 'application/json': { schema: inputSchema } },\n };\n }\n paths[`/${path}`] = { post: operation };\n }\n\n return {\n openapi: '3.1.0',\n info: {\n title: serve.name ?? 'Paid API',\n version: '1.0.0',\n description:\n serve.description ??\n 'Agent-payable API. Every paid endpoint answers 402 with an x402 accepts[] envelope; payment settles in USDC on Sui.',\n },\n ...(base ? { servers: [{ url: base }] } : {}),\n paths,\n };\n}\n\nexport function buildLlmsTxt(serve: Serve, origin?: string): string {\n const base = serve.baseUrl ?? origin ?? '';\n const lines: string[] = [];\n lines.push(`# ${serve.name ?? 'Paid API'}`);\n lines.push('');\n if (serve.description) {\n lines.push(serve.description);\n lines.push('');\n }\n lines.push('## How to pay');\n lines.push('');\n lines.push(\n 'Endpoints below are paid per call in USDC on Sui (x402). An unpaid request returns',\n 'HTTP 402 with an `accepts[]` envelope; sign it and retry with the `X-PAYMENT` header.',\n 'Invalid input returns 422 before any payment is taken. A failed call is never charged.',\n '',\n 'Easiest client: `npm i -g @t2000/cli` then `t2 pay <url> --data \\'{...}\\'`,',\n 'or the t2000 MCP server (`t2000_pay`), or `@t2000/sdk` `pay()`.',\n '',\n );\n lines.push('## Endpoints');\n lines.push('');\n for (const route of serve.routes.values()) {\n const { path, priceUsdc, description, inputSchema, outputSchema } = route.meta;\n const price = priceUsdc ? `${priceUsdc} USDC per call` : 'free';\n lines.push(`### POST ${base}/${path} — ${price}`);\n if (description) lines.push(description);\n if (inputSchema) {\n lines.push('Request body (JSON Schema):');\n lines.push('```json');\n lines.push(JSON.stringify(inputSchema, null, 2));\n lines.push('```');\n }\n if (outputSchema) {\n lines.push('Response (JSON Schema — contentMediaType/format annotations name the deliverable types):');\n lines.push('```json');\n lines.push(JSON.stringify(outputSchema, null, 2));\n lines.push('```');\n }\n lines.push('');\n }\n lines.push(`Discovery: ${base}/openapi.json`);\n return lines.join('\\n');\n}\n","import { SuiGrpcClient } from '@mysten/sui/grpc';\nimport type { ServeNetwork } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Chain plumbing — same shape as the gateway's x402-dialect.ts (the reference\n// composition). All reads are gRPC; this package never touches JSON-RPC.\n//\n// Cache policy: the chain identifier (genesis digest) is immutable per\n// network — cached forever. The epoch advances ~daily and x402 requirements\n// are valid for [epoch, epoch+1], so a 10-minute TTL is conservatively fresh.\n// ---------------------------------------------------------------------------\n\nconst FULLNODE_URLS: Record<ServeNetwork, string> = {\n mainnet: 'https://fullnode.mainnet.sui.io:443',\n testnet: 'https://fullnode.testnet.sui.io:443',\n};\n\nconst EPOCH_TTL_MS = 10 * 60 * 1000;\n\nexport interface ChainInfo {\n chain: string;\n epoch: string;\n}\n\ninterface ChainState {\n client?: SuiGrpcClient;\n chainId?: string;\n epoch?: { value: string; fetchedAt: number };\n}\n\nconst state: Partial<Record<ServeNetwork, ChainState>> = {};\n\nexport function getGrpcClient(network: ServeNetwork, rpcUrl?: string): SuiGrpcClient {\n const s = (state[network] ??= {});\n if (!s.client) {\n s.client = new SuiGrpcClient({\n baseUrl: rpcUrl ?? FULLNODE_URLS[network],\n network,\n });\n }\n return s.client;\n}\n\nexport async function getChainInfo(network: ServeNetwork, rpcUrl?: string): Promise<ChainInfo> {\n const client = getGrpcClient(network, rpcUrl);\n const s = (state[network] ??= {});\n if (!s.chainId) {\n const res = await client.core.getChainIdentifier();\n s.chainId = res.chainIdentifier;\n }\n if (!s.epoch || Date.now() - s.epoch.fetchedAt > EPOCH_TTL_MS) {\n const res = await client.core.getCurrentSystemState();\n s.epoch = { value: String(res.systemState.epoch), fetchedAt: Date.now() };\n }\n return { chain: s.chainId, epoch: s.epoch.value };\n}\n\n/** Test seam — reset module caches between cases. */\nexport function __resetChainCaches(): void {\n delete state.mainnet;\n delete state.testnet;\n}\n\n/** Test seam — pre-seed chain info so tests never hit the network. */\nexport function __seedChainInfo(network: ServeNetwork, chain: string, epoch: string): void {\n const s = (state[network] ??= {});\n s.chainId = chain;\n s.epoch = { value: epoch, fetchedAt: Date.now() };\n}\n","import type { Currency, DigestStore } from '@t2000/sui-x402';\nimport {\n createX402Requirements,\n encodeX402Response,\n isX402EscrowHeader,\n parseX402Header,\n settleX402Payment,\n verifyX402Payment,\n X402_PAYMENT_HEADER,\n X402_PAYMENT_RESPONSE_HEADER,\n X402_VERSION,\n type X402SettleResponse,\n} from '@t2000/sui-x402';\nimport { getChainInfo, getGrpcClient } from './chain.js';\nimport type {\n BuiltRoute,\n HandlerContext,\n HandlerResult,\n ServeNetwork,\n ServeSchema,\n StandardSchemaLike,\n} from './types.js';\n\n// ---------------------------------------------------------------------------\n// The paid-request lifecycle (SPEC_T2000_SERVE §3 — sign-then-settle,\n// handler-then-settle):\n//\n// no X-PAYMENT → 402 with the accepts[] envelope (never a charge;\n// the catalog probe and every discovery tool read\n// this, so it fires BEFORE body validation)\n// X-PAYMENT present:\n// 1. parse + STRUCTURAL verify (right amount/recipient/nonce — no RPC)\n// 2. challenge-once check (a signed payload is single-use)\n// 3. validate the body — invalid → 422, payment NEVER submitted\n// (the JMPR paid-422 class is impossible: the buyer keeps their money)\n// 4. run the handler — throws → 500, payment NEVER submitted\n// 5. settle (submit the buyer-signed gasless bytes; digest-once inside)\n// 6. consume the challenge, attach the X-PAYMENT-RESPONSE receipt\n//\n// Money only moves at step 5, after the seller has already produced the\n// result. A forged payload can waste seller compute (signature authority is\n// the chain at settle time), never buyer money.\n// ---------------------------------------------------------------------------\n\nexport interface RouteRuntime {\n payTo: string;\n network: ServeNetwork;\n currency: Currency;\n store: DigestStore;\n baseUrl?: string;\n rpcUrl?: string;\n /** B2 attributed reporting — unset = no report (see ServeConfig). */\n activityReportUrl?: string;\n}\n\nexport interface RouteOptions {\n path: string;\n description?: string;\n}\n\n/** Sanity cap on a per-call price — above this, the work is job-shaped\n * (escrow) rather than a per-call x402 Service. */\nconst CATALOG_PRICE_CAP_USDC = 5;\n\nconst CORS_HEADERS: Record<string, string> = {\n 'access-control-allow-origin': '*',\n 'access-control-allow-methods': 'GET, POST, PUT, DELETE, OPTIONS',\n 'access-control-allow-headers': `content-type, ${X402_PAYMENT_HEADER}`,\n 'access-control-expose-headers': `${X402_PAYMENT_RESPONSE_HEADER}, WWW-Authenticate`,\n};\n\nfunction withCors(response: Response): Response {\n const headers = new Headers(response.headers);\n for (const [k, v] of Object.entries(CORS_HEADERS)) headers.set(k, v);\n return new Response(response.body, { status: response.status, headers });\n}\n\nfunction json(status: number, body: unknown, headers?: Record<string, string>): Response {\n return withCors(\n new Response(JSON.stringify(body), {\n status,\n headers: { 'content-type': 'application/json', ...headers },\n }),\n );\n}\n\nfunction isStandardSchema(schema: ServeSchema): schema is StandardSchemaLike {\n return typeof schema === 'object' && schema !== null && '~standard' in schema;\n}\n\nasync function validateBody(\n schema: ServeSchema,\n value: unknown,\n): Promise<{ ok: true; data: unknown } | { ok: false; message: string }> {\n if (isStandardSchema(schema)) {\n const result = await schema['~standard'].validate(value);\n if (result.issues) {\n // Name the failing field — bare \"Invalid input\" ×N gives a paying\n // buyer's agent nothing to self-correct with.\n const message = result.issues\n .map((i) => {\n const path = (i.path ?? [])\n .map((seg) => (typeof seg === 'object' ? String(seg.key) : String(seg)))\n .join('.');\n return path ? `${path}: ${i.message}` : i.message;\n })\n .join('; ');\n return { ok: false, message };\n }\n return { ok: true, data: result.value };\n }\n const result = schema.safeParse(value);\n if (!result.success) {\n return { ok: false, message: result.error.message ?? 'invalid body' };\n }\n return { ok: true, data: result.data };\n}\n\n/** Positive decimal USDC string, max 6dp (atomic precision). */\nfunction assertValidPrice(price: string, path: string): void {\n if (!/^\\d+(\\.\\d{1,6})?$/.test(price) || Number(price) <= 0) {\n throw new Error(\n `[serve] Route \"${path}\": price must be a positive decimal USDC string with up to 6 decimals, got \"${price}\"`,\n );\n }\n if (Number(price) > CATALOG_PRICE_CAP_USDC) {\n console.warn(\n `[serve] Route \"${path}\": price ${price} USDC is above the ${CATALOG_PRICE_CAP_USDC} USDC listing cap — ` +\n 'the route works, but per-call x402 is the wrong shape for it. Job-class work belongs in `t2 service create` (escrow).',\n );\n }\n}\n\nexport class RouteBuilder<TBody = undefined> {\n private priceUsdc?: string;\n private bodySchema?: ServeSchema;\n private inputSchema?: Record<string, unknown>;\n private outputSchema?: Record<string, unknown>;\n private isFree = false;\n\n constructor(\n private readonly runtime: RouteRuntime,\n private readonly options: RouteOptions,\n private readonly register: (route: BuiltRoute) => void,\n ) {}\n\n /** Charge this many USDC per call (human units, e.g. \"0.01\"). */\n paid(priceUsdc: string): this {\n assertValidPrice(priceUsdc, this.options.path);\n this.priceUsdc = priceUsdc;\n this.isFree = false;\n return this;\n }\n\n /** Serve without payment (health checks, previews, docs). */\n unprotected(): this {\n this.isFree = true;\n this.priceUsdc = undefined;\n return this;\n }\n\n /**\n * Validate the JSON request body. zod v4 / valibot / arktype / anything\n * Standard-Schema, or anything with a zod-style safeParse.\n *\n * Pass the JSON Schema as the second argument to publish it in\n * /openapi.json + /llms.txt (zod v4: `z.toJSONSchema(schema)`) — buyers'\n * agents build request bodies from it, and the catalog grades listings\n * without one.\n */\n body<T>(schema: ServeSchema<T>, jsonSchema?: Record<string, unknown>): RouteBuilder<T> {\n this.bodySchema = schema;\n this.inputSchema = jsonSchema;\n return this as unknown as RouteBuilder<T>;\n }\n\n /**\n * Declare the 200 response's JSON Schema (zod v4: `z.toJSONSchema(schema)`).\n * Published in /openapi.json + /llms.txt so buyer agents know what they're\n * buying and buyer UIs can render the deliverable by TYPE instead of\n * sniffing it — annotate with `contentMediaType` (e.g. \"image/svg+xml\",\n * \"text/markdown\") and `format: \"color\"` where they apply. Declaration\n * only; responses are never validated at runtime.\n */\n response(jsonSchema: Record<string, unknown>): this {\n this.outputSchema = jsonSchema;\n return this;\n }\n\n handler(fn: (ctx: HandlerContext<TBody>) => HandlerResult | Promise<HandlerResult>): BuiltRoute {\n if (!this.isFree && !this.priceUsdc) {\n throw new Error(\n `[serve] Route \"${this.options.path}\": call .paid('<usdc>') or .unprotected() before .handler()`,\n );\n }\n const runtime = this.runtime;\n const { path, description } = this.options;\n const priceUsdc = this.priceUsdc;\n const bodySchema = this.bodySchema;\n\n const route = (async (req: Request): Promise<Response> => {\n if (req.method === 'OPTIONS') {\n return withCors(new Response(null, { status: 204 }));\n }\n\n // Read + parse the body once, up front. A missing/empty body on a\n // schema-less route is fine; JSON parse failures only matter when a\n // paid request must be validated (the unpaid 402 fires regardless).\n let parsedBody: unknown;\n let bodyParseError: string | undefined;\n if (req.method !== 'GET' && req.method !== 'HEAD') {\n const text = await req.text();\n if (text.trim().length > 0) {\n try {\n parsedBody = JSON.parse(text);\n } catch {\n bodyParseError = 'request body is not valid JSON';\n }\n }\n }\n\n const resource = (runtime.baseUrl ?? new URL(req.url).origin).replace(/\\/$/, '') + `/${path}`;\n\n const runHandler = async (payer?: string): Promise<Response> => {\n let validated: unknown = parsedBody;\n if (bodySchema) {\n // `paid: false` is machine-readable charge honesty — a 422 fires\n // BEFORE settlement, so the buyer always keeps their money.\n if (bodyParseError) {\n return json(422, { error: bodyParseError, paid: false });\n }\n const result = await validateBody(bodySchema, parsedBody ?? {});\n if (!result.ok) {\n return json(422, { error: result.message, paid: false });\n }\n validated = result.data;\n }\n const out = await fn({ body: validated as TBody, req, payer });\n if (out instanceof Response) return withCors(out);\n return json(200, out);\n };\n\n // Free route — no payment machinery at all.\n if (!priceUsdc) {\n try {\n return await runHandler();\n } catch (err) {\n console.error(`[serve] Route \"${path}\" handler failed:`, err);\n return json(500, { error: 'internal error' });\n }\n }\n\n const paymentHeader = req.headers.get(X402_PAYMENT_HEADER);\n\n // Unpaid → 402 with the accepts[] envelope. This fires before body\n // validation on purpose: the catalog probe (and every discovery tool)\n // POSTs `{}` and must see the challenge, and an unpaid request can\n // never be charged, so there is nothing to protect yet.\n if (!paymentHeader) {\n return await respond402(runtime, { resource, priceUsdc });\n }\n\n if (isX402EscrowHeader(paymentHeader)) {\n return await respond402(runtime, {\n resource,\n priceUsdc,\n error:\n 'this endpoint sells instant per-call work (settle-then-serve), not escrow jobs — retry with a signed x402 payment',\n });\n }\n\n // 1. Parse + structural verify — right terms, right recipient, right\n // nonce. No RPC, no state. Wrong-terms payloads never reach the\n // handler.\n let payment: ReturnType<typeof parseX402Header>;\n try {\n payment = parseX402Header(paymentHeader);\n verifyX402Payment({\n payment,\n expected: {\n challengeId: payment.payload.challengeId,\n amount: priceUsdc,\n currency: runtime.currency,\n recipient: runtime.payTo,\n network: runtime.network,\n },\n });\n } catch (err) {\n return await respond402(runtime, {\n resource,\n priceUsdc,\n error: `invalid payment: ${err instanceof Error ? err.message : String(err)}`,\n });\n }\n\n // 2. Challenge-once — a signed payload is single-use even before it\n // settles (the settled digest is separately consumed inside\n // settleX402Payment, digest-once).\n const challengeKey = `challenge:${payment.payload.challengeId}`;\n if (await runtime.store.has(challengeKey)) {\n return await respond402(runtime, {\n resource,\n priceUsdc,\n error: 'payment challenge already used — sign a fresh payment',\n });\n }\n\n // 3 + 4. Validate, then compute the result. Any failure here returns\n // WITHOUT settling — the buyer-signed bytes are never submitted.\n let served: Response;\n try {\n served = await runHandler(payment.payload.senderAddress);\n } catch (err) {\n console.error(`[serve] Route \"${path}\" handler failed (payment NOT settled):`, err);\n return json(500, { error: 'internal error — you were not charged' });\n }\n if (served.status >= 400) return served; // 422 etc. — not charged\n\n // 5. Settle — submit the buyer-signed gasless bytes, confirm the\n // on-chain balance change, record the digest (digest-once).\n let settle: X402SettleResponse;\n try {\n settle = await settleX402Payment({\n payment,\n client: getGrpcClient(runtime.network, runtime.rpcUrl),\n store: runtime.store,\n expected: {\n challengeId: payment.payload.challengeId,\n amount: priceUsdc,\n currency: runtime.currency,\n recipient: runtime.payTo,\n network: runtime.network,\n },\n });\n } catch (err) {\n return await respond402(runtime, {\n resource,\n priceUsdc,\n error: `settlement failed: ${err instanceof Error ? err.message : String(err)}`,\n });\n }\n\n // 6. Consume the challenge + attach the receipt.\n try {\n await runtime.store.set(challengeKey);\n } catch {\n // Digest-once already holds; challenge-once is defense in depth.\n }\n\n // B2: attributed activity report — AFTER a successful settle only,\n // strictly fire-and-forget (a dead report can never change the\n // buyer's 200 or the settle; SPEC_T2_ACTIVITY_X402 §7 lock 6).\n reportActivity(runtime, {\n digest: settle.transaction,\n payer: settle.payer,\n priceUsdc,\n resource,\n });\n\n const headers = new Headers(served.headers);\n headers.set(X402_PAYMENT_RESPONSE_HEADER, encodeX402Response(settle));\n return new Response(served.body, { status: served.status, headers });\n }) as BuiltRoute;\n\n route.meta = {\n path,\n priceUsdc,\n description,\n bodySchema,\n inputSchema: this.inputSchema,\n outputSchema: this.outputSchema,\n };\n this.register(route);\n return route;\n }\n}\n\n/** Fire-and-forget x402.paid report (B2). Never awaited into the response\n * path; short timeout; every failure swallowed. The report endpoint\n * chain-verifies the digest, so this carries claims, not trust. */\nfunction reportActivity(\n runtime: RouteRuntime,\n args: { digest: string; payer: string; priceUsdc: string; resource: string },\n): void {\n const url = runtime.activityReportUrl;\n if (!url) return;\n try {\n void fetch(url, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n digest: args.digest,\n payTo: runtime.payTo,\n payer: args.payer,\n amountMicroUsdc: Math.round(Number(args.priceUsdc) * 1_000_000),\n network: `sui:${runtime.network}`,\n route: args.resource,\n source: 'serve',\n }),\n signal: AbortSignal.timeout(1500),\n }).catch(() => undefined);\n } catch {\n // even a sync throw (bad URL) must not touch the buyer's response\n }\n}\n\nasync function respond402(\n runtime: RouteRuntime,\n args: { resource: string; priceUsdc: string; error?: string },\n): Promise<Response> {\n try {\n const { chain, epoch } = await getChainInfo(runtime.network, runtime.rpcUrl);\n const requirements = createX402Requirements({\n challengeId: crypto.randomUUID(),\n amount: args.priceUsdc,\n currency: runtime.currency,\n recipient: runtime.payTo,\n resource: args.resource,\n network: runtime.network,\n chain,\n currentEpoch: epoch,\n });\n // Belt-and-suspenders for pre-0.2.2 discovery clients and dual-dialect\n // consumers: mirror the challenge into the MPP WWW-Authenticate shape.\n // The accepts[] body stays the authoritative envelope — the header carries\n // the same recipient/currency and the DECIMAL amount that dialect uses.\n const host = (() => {\n try {\n return new URL(args.resource).hostname;\n } catch {\n return undefined;\n }\n })();\n const wwwAuth = `Payment realm=\"${host ?? 'x402'}\", recipient=\"${runtime.payTo}\", currency=\"${runtime.currency}\", amount=\"${args.priceUsdc}\"`;\n return json(\n 402,\n {\n x402Version: X402_VERSION,\n error: args.error ?? 'Payment required',\n accepts: [requirements],\n },\n { 'WWW-Authenticate': wwwAuth },\n );\n } catch (err) {\n // Chain info unreachable — a 402 without the envelope is unpayable, so\n // be honest about the outage instead of serving a dead challenge.\n console.error('[serve] failed to build 402 challenge:', err);\n return json(503, { error: 'payment challenge temporarily unavailable' });\n }\n}\n\n","import type { DigestStore } from '@t2000/sui-x402';\n\nexport { InMemoryDigestStore } from '@t2000/sui-x402';\nexport type { DigestStore } from '@t2000/sui-x402';\n\n// ---------------------------------------------------------------------------\n// Upstash-REST digest store — the production replay store for serverless\n// hosts. Mirrors the gateway's upstash-digest-store.ts but speaks the\n// Upstash REST API over plain fetch (no @upstash/redis dependency).\n//\n// TTL: 72h. x402 payments are chain-valid for the whole ValidDuring window\n// ([minEpoch, minEpoch+1] ≈ up to ~48h on mainnet). Sui resubmission of an\n// executed tx is idempotent, so if the digest/challenge keys expired BEFORE\n// the window closed, a replayed X-PAYMENT would re-settle \"successfully\"\n// and serve again on a single payment. 72h > max window + drift.\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_TTL_SECONDS = 72 * 60 * 60;\nconst PREFIX = 'serve:digest:';\n\nexport interface UpstashDigestStoreOptions {\n url: string;\n token: string;\n /** Key TTL in seconds. Default 72h — do not lower below ~50h (see above). */\n ttlSeconds?: number;\n}\n\nexport class UpstashDigestStore implements DigestStore {\n private readonly url: string;\n private readonly token: string;\n private readonly ttlSeconds: number;\n\n constructor(options: UpstashDigestStoreOptions) {\n this.url = options.url.replace(/\\/$/, '');\n this.token = options.token;\n this.ttlSeconds = options.ttlSeconds ?? DEFAULT_TTL_SECONDS;\n }\n\n private async command(segments: string[]): Promise<unknown> {\n const res = await fetch(`${this.url}/${segments.map(encodeURIComponent).join('/')}`, {\n headers: { authorization: `Bearer ${this.token}` },\n });\n if (!res.ok) {\n throw new Error(`Upstash command failed: ${res.status} ${await res.text()}`);\n }\n const body = (await res.json()) as { result?: unknown; error?: string };\n if (body.error) throw new Error(`Upstash error: ${body.error}`);\n return body.result;\n }\n\n async has(digest: string): Promise<boolean> {\n const result = await this.command(['GET', PREFIX + digest]);\n return result !== null && result !== undefined;\n }\n\n async set(digest: string): Promise<void> {\n // SET key 1 EX <ttl> NX — atomic set-if-absent. A null result means the\n // key already existed: the digest (or challenge) was already consumed.\n const result = await this.command([\n 'SET',\n PREFIX + digest,\n '1',\n 'EX',\n String(this.ttlSeconds),\n 'NX',\n ]);\n if (result === null || result === undefined) {\n throw new Error(`Digest already used: ${digest}`);\n }\n }\n}\n","import { isValidSuiAddress, normalizeSuiAddress } from '@mysten/sui/utils';\nimport { InMemoryDigestStore, USDC, USDC_TESTNET, type Currency } from '@t2000/sui-x402';\nimport { buildLlmsTxt, buildOpenApiDocument } from './discovery.js';\nimport { RouteBuilder, type RouteOptions, type RouteRuntime } from './route.js';\nimport { UpstashDigestStore } from './store.js';\nimport type { BuiltRoute, ServeConfig, ServeNetwork } from './types.js';\n\n/** The t2000.ai attributed-activity report endpoint — ONE canonical string\n * (matches the sdk's DEFAULT_ACTIVITY_REPORT_URL; tests assert equality). */\nexport const DEFAULT_ACTIVITY_REPORT_URL = 'https://t2000.ai/api/activity/x402';\n\n/** Explicit opt-out tokens for T2000_ACTIVITY_REPORT_URL (case-insensitive). */\nconst REPORT_OPT_OUT = new Set(['false', '0', 'off', 'none']);\n\nexport class Serve {\n private readonly runtime: RouteRuntime;\n /** Every route built through this instance, keyed by path (discovery). */\n readonly routes = new Map<string, BuiltRoute>();\n\n readonly payTo: string;\n readonly network: ServeNetwork;\n readonly name?: string;\n readonly description?: string;\n readonly baseUrl?: string;\n /** Where settled payments are reported (B2) — undefined = no report. */\n readonly activityReportUrl?: string;\n\n constructor(config: ServeConfig) {\n if (!config.payTo || !isValidSuiAddress(config.payTo)) {\n throw new Error(\n `[serve] payTo must be a valid Sui address (the wallet your payments settle to), got \"${config.payTo}\"`,\n );\n }\n this.payTo = normalizeSuiAddress(config.payTo);\n this.network = config.network ?? 'mainnet';\n this.name = config.name;\n this.description = config.description;\n this.baseUrl = config.baseUrl?.replace(/\\/$/, '');\n this.activityReportUrl = config.activityReportUrl;\n\n const currency: Currency = this.network === 'testnet' ? USDC_TESTNET : USDC;\n this.runtime = {\n payTo: this.payTo,\n network: this.network,\n currency,\n store: config.store ?? new InMemoryDigestStore(),\n baseUrl: this.baseUrl,\n rpcUrl: config.rpcUrl,\n activityReportUrl: this.activityReportUrl,\n };\n }\n\n /** Start building a route. Chain `.paid()` / `.body()` / `.handler()`. */\n route(options: RouteOptions): RouteBuilder {\n const path = options.path.replace(/^\\/+/, '').replace(/\\/+$/, '');\n if (!path) throw new Error('[serve] route path must be non-empty');\n return new RouteBuilder({ ...this.runtime }, { ...options, path }, (route) => {\n this.routes.set(path, route);\n });\n }\n\n /**\n * Discovery: GET handler for /openapi.json. OpenAPI 3.1 with the\n * `x-payment-info` pricing extension on every paid operation — the shape\n * x402 tooling (and any catalog built on it) indexes.\n *\n * export const GET = serve.openapi(); // app/openapi.json/route.ts\n */\n openapi(): (req: Request) => Response {\n return (req: Request) =>\n new Response(JSON.stringify(buildOpenApiDocument(this, new URL(req.url).origin), null, 2), {\n headers: { 'content-type': 'application/json', 'access-control-allow-origin': '*' },\n });\n }\n\n /**\n * Discovery: GET handler for /llms.txt — plain-text guidance agents read\n * to understand what the API sells, what it costs, and how to pay.\n *\n * export const GET = serve.llms(); // app/llms.txt/route.ts\n */\n llms(): (req: Request) => Response {\n return (req: Request) =>\n new Response(buildLlmsTxt(this, new URL(req.url).origin), {\n headers: { 'content-type': 'text/plain; charset=utf-8', 'access-control-allow-origin': '*' },\n });\n }\n\n /**\n * One fetch handler for the whole app — routes + discovery docs. For\n * fetch-native runtimes (Bun.serve, Deno.serve, Hono, Cloudflare Workers):\n *\n * Bun.serve({ fetch: serve.fetch });\n * app.all('*', (c) => serve.fetch(c.req.raw)); // Hono\n *\n * Next.js apps can skip this and export route handlers directly.\n */\n readonly fetch = async (req: Request): Promise<Response> => {\n const pathname = new URL(req.url).pathname.replace(/^\\/+/, '').replace(/\\/+$/, '');\n if (pathname === 'openapi.json') return this.openapi()(req);\n if (pathname === 'llms.txt') return this.llms()(req);\n const route = this.routes.get(pathname);\n if (route) return route(req);\n return new Response(\n JSON.stringify({ error: 'not found', discovery: ['/openapi.json', '/llms.txt'] }),\n { status: 404, headers: { 'content-type': 'application/json' } },\n );\n };\n\n /**\n * The command that sells this API as an x402 Service on your Agent ID,\n * once it is deployed. Listing is a separate, explicit step: the endpoint\n * is live-probed (it must answer 402 with a Sui challenge that pays YOUR\n * wallet) and then recorded on-chain, sponsored and gasless.\n *\n * This used to emit curls against the hosted mpp.t2000.ai catalog. That\n * proxy mall was purged 2026-08-01 (SPEC_T2_CLEANUP_USDC_ONLY) — there is\n * no central catalog to submit to. Your Agent ID IS the listing, and\n * buyers find it with `t2 services`.\n */\n catalogSubmitCommand(deployedUrl?: string): string {\n const base = (deployedUrl ?? this.baseUrl ?? 'https://<your-deployed-app>').replace(/\\/$/, '');\n const paidPaths = [...this.routes.values()].filter((r) => r.meta.priceUsdc);\n const example = paidPaths[0]?.meta.path ?? '<route>';\n return [\n '# Sell it as an x402 Service on your Agent ID (live-probed, gasless):',\n `npx @t2000/cli agent sell ${base}/${example}`,\n '# Buyers then find it with `t2 services` and pay per call with `t2 pay`.',\n ].join('\\n');\n }\n}\n\nexport function createServe(config: ServeConfig): Serve {\n return new Serve(config);\n}\n\n/**\n * Build a Serve from environment variables — the template-app path where\n * config lives in the host's env UI, not code.\n *\n * T2000_PAY_TO required — the seller's Sui address\n * T2000_NETWORK optional — 'mainnet' (default) | 'testnet'\n * T2000_BASE_URL optional — public URL of the deployed app\n * T2000_NAME optional — service name for discovery docs\n * T2000_DESCRIPTION optional — one-liner for discovery docs\n * T2000_ACTIVITY_REPORT_URL\n * optional — where settled payments are reported\n * (fire-and-forget x402.paid after each successful settle;\n * chain-verified server-side, never affects buyer\n * responses). DEFAULT-ON for FromEnv: unset →\n * https://t2000.ai/api/activity/x402 so new sellers appear\n * on the t2000.ai activity tape. Opt out with\n * `false` | `0` | `off` | `none` (case-insensitive), or\n * set a custom URL. (`new Serve({...})` without\n * activityReportUrl stays silent — only FromEnv defaults.)\n * KV_REST_API_URL / KV_REST_API_TOKEN\n * optional — enables the durable Upstash replay store\n * (REQUIRED in serverless production; without it replay\n * state is per-instance memory)\n *\n * Empty strings are treated as unset (the Vercel empty-env bug class).\n */\nexport function createServeFromEnv(env: Record<string, string | undefined> = process.env): Serve {\n const read = (key: string): string | undefined => {\n const v = env[key]?.trim();\n return v && v.length > 0 ? v : undefined;\n };\n\n const payTo = read('T2000_PAY_TO');\n if (!payTo) {\n throw new Error(\n '[serve] T2000_PAY_TO is not set (or is empty). Set it to the Sui address your payments should settle to — `t2 address` prints yours.',\n );\n }\n\n const network = read('T2000_NETWORK');\n if (network && network !== 'mainnet' && network !== 'testnet') {\n throw new Error(`[serve] T2000_NETWORK must be 'mainnet' or 'testnet', got \"${network}\"`);\n }\n\n const kvUrl = read('KV_REST_API_URL');\n const kvToken = read('KV_REST_API_TOKEN');\n const store =\n kvUrl && kvToken ? new UpstashDigestStore({ url: kvUrl, token: kvToken }) : undefined;\n\n if (!store) {\n console.warn(\n '[serve] No KV_REST_API_URL/KV_REST_API_TOKEN — using the in-memory replay store. ' +\n 'Fine for a single long-lived process; on serverless hosts set both so replay protection is durable.',\n );\n }\n\n return new Serve({\n payTo,\n network: (network as ServeNetwork | undefined) ?? 'mainnet',\n baseUrl: read('T2000_BASE_URL'),\n name: read('T2000_NAME'),\n description: read('T2000_DESCRIPTION'),\n activityReportUrl: resolveReportUrlFromEnv(read('T2000_ACTIVITY_REPORT_URL')),\n store,\n });\n}\n\n/** FromEnv activity-report resolution (B2 default-on): unset/empty →\n * the t2000.ai default; an explicit opt-out token → undefined (silent);\n * anything else is the seller's custom report URL. */\nfunction resolveReportUrlFromEnv(raw: string | undefined): string | undefined {\n if (raw === undefined) return DEFAULT_ACTIVITY_REPORT_URL;\n if (REPORT_OPT_OUT.has(raw.toLowerCase())) return undefined;\n return raw;\n}\n","import type { BuiltRoute } from './types.js';\n\n/**\n * Export a built route the way Next.js App Router needs it.\n *\n * Next dispatches ONLY the methods a route.ts exports — serve's own CORS\n * handling (OPTIONS → 204 with the ACAO headers) never runs if the file\n * exports just `POST`: the browser preflight gets Next's bare 204 with no\n * CORS headers, and every browser buyer (Passport, the store's Try it)\n * fails while CLI/server buyers — who never preflight — work fine. Fetch\n * runtimes mounted via a single handler (`serve.fetch`-style) don't have\n * this hole; it is a Next export contract, not a serve one.\n *\n * export const { POST, OPTIONS } = asNextRoute(\n * serve.route({ path: 'haiku' }).paid('0.01').handler(fn),\n * );\n */\nexport function asNextRoute(route: BuiltRoute): {\n POST: BuiltRoute;\n OPTIONS: BuiltRoute;\n} {\n return { POST: route, OPTIONS: route };\n}\n"]}
package/dist/index.d.cts CHANGED
@@ -25,6 +25,17 @@ interface ServeConfig {
25
25
  name?: string;
26
26
  /** One-line description (discovery docs, slice 2). */
27
27
  description?: string;
28
+ /**
29
+ * Opt-in attributed activity reporting (SPEC_T2_ACTIVITY_X402 B2). After a
30
+ * SUCCESSFUL settle, serve fire-and-forgets the settlement digest to this
31
+ * URL (`https://t2000.ai/api/activity/x402` — the endpoint chain-verifies
32
+ * before anything is recorded). Strictly best-effort: a dead report can
33
+ * never change the buyer's response. Unset = no report.
34
+ *
35
+ * (The old `report` option — removed 2026-08-01 — posted to the retired
36
+ * mpp gateway; this posts to the receipt-backed t2000.ai ledger instead.)
37
+ */
38
+ activityReportUrl?: string;
28
39
  /** Override the Sui fullnode gRPC URL (default: mainnet/testnet fullnode). */
29
40
  rpcUrl?: string;
30
41
  }
@@ -113,6 +124,8 @@ interface RouteRuntime {
113
124
  store: DigestStore;
114
125
  baseUrl?: string;
115
126
  rpcUrl?: string;
127
+ /** B2 attributed reporting — unset = no report (see ServeConfig). */
128
+ activityReportUrl?: string;
116
129
  }
117
130
  interface RouteOptions {
118
131
  path: string;
@@ -154,6 +167,9 @@ declare class RouteBuilder<TBody = undefined> {
154
167
  handler(fn: (ctx: HandlerContext<TBody>) => HandlerResult | Promise<HandlerResult>): BuiltRoute;
155
168
  }
156
169
 
170
+ /** The t2000.ai attributed-activity report endpoint — ONE canonical string
171
+ * (matches the sdk's DEFAULT_ACTIVITY_REPORT_URL; tests assert equality). */
172
+ declare const DEFAULT_ACTIVITY_REPORT_URL = "https://t2000.ai/api/activity/x402";
157
173
  declare class Serve {
158
174
  private readonly runtime;
159
175
  /** Every route built through this instance, keyed by path (discovery). */
@@ -163,6 +179,8 @@ declare class Serve {
163
179
  readonly name?: string;
164
180
  readonly description?: string;
165
181
  readonly baseUrl?: string;
182
+ /** Where settled payments are reported (B2) — undefined = no report. */
183
+ readonly activityReportUrl?: string;
166
184
  constructor(config: ServeConfig);
167
185
  /** Start building a route. Chain `.paid()` / `.body()` / `.handler()`. */
168
186
  route(options: RouteOptions): RouteBuilder;
@@ -214,6 +232,16 @@ declare function createServe(config: ServeConfig): Serve;
214
232
  * T2000_BASE_URL optional — public URL of the deployed app
215
233
  * T2000_NAME optional — service name for discovery docs
216
234
  * T2000_DESCRIPTION optional — one-liner for discovery docs
235
+ * T2000_ACTIVITY_REPORT_URL
236
+ * optional — where settled payments are reported
237
+ * (fire-and-forget x402.paid after each successful settle;
238
+ * chain-verified server-side, never affects buyer
239
+ * responses). DEFAULT-ON for FromEnv: unset →
240
+ * https://t2000.ai/api/activity/x402 so new sellers appear
241
+ * on the t2000.ai activity tape. Opt out with
242
+ * `false` | `0` | `off` | `none` (case-insensitive), or
243
+ * set a custom URL. (`new Serve({...})` without
244
+ * activityReportUrl stays silent — only FromEnv defaults.)
217
245
  * KV_REST_API_URL / KV_REST_API_TOKEN
218
246
  * optional — enables the durable Upstash replay store
219
247
  * (REQUIRED in serverless production; without it replay
@@ -267,4 +295,4 @@ declare function __resetChainCaches(): void;
267
295
  /** Test seam — pre-seed chain info so tests never hit the network. */
268
296
  declare function __seedChainInfo(network: ServeNetwork, chain: string, epoch: string): void;
269
297
 
270
- export { type BuiltRoute, type HandlerContext, type HandlerResult, RouteBuilder, type RouteMeta, Serve, type ServeConfig, type ServeNetwork, type ServeSchema, UpstashDigestStore, type UpstashDigestStoreOptions, __resetChainCaches, __seedChainInfo, asNextRoute, buildLlmsTxt, buildOpenApiDocument, createServe, createServeFromEnv };
298
+ export { type BuiltRoute, DEFAULT_ACTIVITY_REPORT_URL, type HandlerContext, type HandlerResult, RouteBuilder, type RouteMeta, Serve, type ServeConfig, type ServeNetwork, type ServeSchema, UpstashDigestStore, type UpstashDigestStoreOptions, __resetChainCaches, __seedChainInfo, asNextRoute, buildLlmsTxt, buildOpenApiDocument, createServe, createServeFromEnv };
package/dist/index.d.ts CHANGED
@@ -25,6 +25,17 @@ interface ServeConfig {
25
25
  name?: string;
26
26
  /** One-line description (discovery docs, slice 2). */
27
27
  description?: string;
28
+ /**
29
+ * Opt-in attributed activity reporting (SPEC_T2_ACTIVITY_X402 B2). After a
30
+ * SUCCESSFUL settle, serve fire-and-forgets the settlement digest to this
31
+ * URL (`https://t2000.ai/api/activity/x402` — the endpoint chain-verifies
32
+ * before anything is recorded). Strictly best-effort: a dead report can
33
+ * never change the buyer's response. Unset = no report.
34
+ *
35
+ * (The old `report` option — removed 2026-08-01 — posted to the retired
36
+ * mpp gateway; this posts to the receipt-backed t2000.ai ledger instead.)
37
+ */
38
+ activityReportUrl?: string;
28
39
  /** Override the Sui fullnode gRPC URL (default: mainnet/testnet fullnode). */
29
40
  rpcUrl?: string;
30
41
  }
@@ -113,6 +124,8 @@ interface RouteRuntime {
113
124
  store: DigestStore;
114
125
  baseUrl?: string;
115
126
  rpcUrl?: string;
127
+ /** B2 attributed reporting — unset = no report (see ServeConfig). */
128
+ activityReportUrl?: string;
116
129
  }
117
130
  interface RouteOptions {
118
131
  path: string;
@@ -154,6 +167,9 @@ declare class RouteBuilder<TBody = undefined> {
154
167
  handler(fn: (ctx: HandlerContext<TBody>) => HandlerResult | Promise<HandlerResult>): BuiltRoute;
155
168
  }
156
169
 
170
+ /** The t2000.ai attributed-activity report endpoint — ONE canonical string
171
+ * (matches the sdk's DEFAULT_ACTIVITY_REPORT_URL; tests assert equality). */
172
+ declare const DEFAULT_ACTIVITY_REPORT_URL = "https://t2000.ai/api/activity/x402";
157
173
  declare class Serve {
158
174
  private readonly runtime;
159
175
  /** Every route built through this instance, keyed by path (discovery). */
@@ -163,6 +179,8 @@ declare class Serve {
163
179
  readonly name?: string;
164
180
  readonly description?: string;
165
181
  readonly baseUrl?: string;
182
+ /** Where settled payments are reported (B2) — undefined = no report. */
183
+ readonly activityReportUrl?: string;
166
184
  constructor(config: ServeConfig);
167
185
  /** Start building a route. Chain `.paid()` / `.body()` / `.handler()`. */
168
186
  route(options: RouteOptions): RouteBuilder;
@@ -214,6 +232,16 @@ declare function createServe(config: ServeConfig): Serve;
214
232
  * T2000_BASE_URL optional — public URL of the deployed app
215
233
  * T2000_NAME optional — service name for discovery docs
216
234
  * T2000_DESCRIPTION optional — one-liner for discovery docs
235
+ * T2000_ACTIVITY_REPORT_URL
236
+ * optional — where settled payments are reported
237
+ * (fire-and-forget x402.paid after each successful settle;
238
+ * chain-verified server-side, never affects buyer
239
+ * responses). DEFAULT-ON for FromEnv: unset →
240
+ * https://t2000.ai/api/activity/x402 so new sellers appear
241
+ * on the t2000.ai activity tape. Opt out with
242
+ * `false` | `0` | `off` | `none` (case-insensitive), or
243
+ * set a custom URL. (`new Serve({...})` without
244
+ * activityReportUrl stays silent — only FromEnv defaults.)
217
245
  * KV_REST_API_URL / KV_REST_API_TOKEN
218
246
  * optional — enables the durable Upstash replay store
219
247
  * (REQUIRED in serverless production; without it replay
@@ -267,4 +295,4 @@ declare function __resetChainCaches(): void;
267
295
  /** Test seam — pre-seed chain info so tests never hit the network. */
268
296
  declare function __seedChainInfo(network: ServeNetwork, chain: string, epoch: string): void;
269
297
 
270
- export { type BuiltRoute, type HandlerContext, type HandlerResult, RouteBuilder, type RouteMeta, Serve, type ServeConfig, type ServeNetwork, type ServeSchema, UpstashDigestStore, type UpstashDigestStoreOptions, __resetChainCaches, __seedChainInfo, asNextRoute, buildLlmsTxt, buildOpenApiDocument, createServe, createServeFromEnv };
298
+ export { type BuiltRoute, DEFAULT_ACTIVITY_REPORT_URL, type HandlerContext, type HandlerResult, RouteBuilder, type RouteMeta, Serve, type ServeConfig, type ServeNetwork, type ServeSchema, UpstashDigestStore, type UpstashDigestStoreOptions, __resetChainCaches, __seedChainInfo, asNextRoute, buildLlmsTxt, buildOpenApiDocument, createServe, createServeFromEnv };
package/dist/index.js CHANGED
@@ -368,6 +368,12 @@ var RouteBuilder = class {
368
368
  await runtime.store.set(challengeKey);
369
369
  } catch {
370
370
  }
371
+ reportActivity(runtime, {
372
+ digest: settle.transaction,
373
+ payer: settle.payer,
374
+ priceUsdc,
375
+ resource
376
+ });
371
377
  const headers = new Headers(served.headers);
372
378
  headers.set(X402_PAYMENT_RESPONSE_HEADER, encodeX402Response(settle));
373
379
  return new Response(served.body, { status: served.status, headers });
@@ -384,6 +390,27 @@ var RouteBuilder = class {
384
390
  return route;
385
391
  }
386
392
  };
393
+ function reportActivity(runtime, args) {
394
+ const url = runtime.activityReportUrl;
395
+ if (!url) return;
396
+ try {
397
+ void fetch(url, {
398
+ method: "POST",
399
+ headers: { "content-type": "application/json" },
400
+ body: JSON.stringify({
401
+ digest: args.digest,
402
+ payTo: runtime.payTo,
403
+ payer: args.payer,
404
+ amountMicroUsdc: Math.round(Number(args.priceUsdc) * 1e6),
405
+ network: `sui:${runtime.network}`,
406
+ route: args.resource,
407
+ source: "serve"
408
+ }),
409
+ signal: AbortSignal.timeout(1500)
410
+ }).catch(() => void 0);
411
+ } catch {
412
+ }
413
+ }
387
414
  async function respond402(runtime, args) {
388
415
  try {
389
416
  const { chain, epoch } = await getChainInfo(runtime.network, runtime.rpcUrl);
@@ -461,6 +488,8 @@ var UpstashDigestStore = class {
461
488
  };
462
489
 
463
490
  // src/serve.ts
491
+ var DEFAULT_ACTIVITY_REPORT_URL = "https://t2000.ai/api/activity/x402";
492
+ var REPORT_OPT_OUT = /* @__PURE__ */ new Set(["false", "0", "off", "none"]);
464
493
  var Serve = class {
465
494
  runtime;
466
495
  /** Every route built through this instance, keyed by path (discovery). */
@@ -470,6 +499,8 @@ var Serve = class {
470
499
  name;
471
500
  description;
472
501
  baseUrl;
502
+ /** Where settled payments are reported (B2) — undefined = no report. */
503
+ activityReportUrl;
473
504
  constructor(config) {
474
505
  if (!config.payTo || !isValidSuiAddress(config.payTo)) {
475
506
  throw new Error(
@@ -481,6 +512,7 @@ var Serve = class {
481
512
  this.name = config.name;
482
513
  this.description = config.description;
483
514
  this.baseUrl = config.baseUrl?.replace(/\/$/, "");
515
+ this.activityReportUrl = config.activityReportUrl;
484
516
  const currency = this.network === "testnet" ? USDC_TESTNET : USDC;
485
517
  this.runtime = {
486
518
  payTo: this.payTo,
@@ -488,7 +520,8 @@ var Serve = class {
488
520
  currency,
489
521
  store: config.store ?? new InMemoryDigestStore(),
490
522
  baseUrl: this.baseUrl,
491
- rpcUrl: config.rpcUrl
523
+ rpcUrl: config.rpcUrl,
524
+ activityReportUrl: this.activityReportUrl
492
525
  };
493
526
  }
494
527
  /** Start building a route. Chain `.paid()` / `.body()` / `.handler()`. */
@@ -596,15 +629,21 @@ function createServeFromEnv(env = process.env) {
596
629
  baseUrl: read("T2000_BASE_URL"),
597
630
  name: read("T2000_NAME"),
598
631
  description: read("T2000_DESCRIPTION"),
632
+ activityReportUrl: resolveReportUrlFromEnv(read("T2000_ACTIVITY_REPORT_URL")),
599
633
  store
600
634
  });
601
635
  }
636
+ function resolveReportUrlFromEnv(raw) {
637
+ if (raw === void 0) return DEFAULT_ACTIVITY_REPORT_URL;
638
+ if (REPORT_OPT_OUT.has(raw.toLowerCase())) return void 0;
639
+ return raw;
640
+ }
602
641
 
603
642
  // src/next.ts
604
643
  function asNextRoute(route) {
605
644
  return { POST: route, OPTIONS: route };
606
645
  }
607
646
 
608
- export { RouteBuilder, Serve, UpstashDigestStore, __resetChainCaches, __seedChainInfo, asNextRoute, buildLlmsTxt, buildOpenApiDocument, createServe, createServeFromEnv };
647
+ export { DEFAULT_ACTIVITY_REPORT_URL, RouteBuilder, Serve, UpstashDigestStore, __resetChainCaches, __seedChainInfo, asNextRoute, buildLlmsTxt, buildOpenApiDocument, createServe, createServeFromEnv };
609
648
  //# sourceMappingURL=index.js.map
610
649
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/discovery.ts","../src/chain.ts","../src/route.ts","../src/store.ts","../src/serve.ts","../src/next.ts"],"names":["result","USDC_TESTNET","USDC","InMemoryDigestStore"],"mappings":"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","file":"index.js","sourcesContent":["import { USDC, USDC_TESTNET } from '@t2000/sui-x402';\nimport type { Serve } from './serve.js';\n\n// ---------------------------------------------------------------------------\n// Discovery docs — /openapi.json + /llms.txt.\n//\n// The shapes here are what the on-chain listing probe grades (the check\n// behind `t2 agent sell`) (was: apps/gateway/lib/\n// catalog-ingest.ts `gradeListing`): a warning-free listing needs info.title,\n// a one-paragraph info.description, a flat string `x-payment-info.price` per\n// paid operation, and an application/json requestBody schema with typed\n// properties. Everything serve can derive is emitted automatically; the JSON\n// request schema comes from the route's `inputSchema` (zod v4 users:\n// `z.toJSONSchema(schema)`).\n// ---------------------------------------------------------------------------\n\nexport function buildOpenApiDocument(serve: Serve, origin?: string): Record<string, unknown> {\n const base = serve.baseUrl ?? origin;\n const paths: Record<string, unknown> = {};\n\n for (const route of serve.routes.values()) {\n const { path, priceUsdc, description, inputSchema, outputSchema } = route.meta;\n const operation: Record<string, unknown> = {\n operationId: path.replace(/[^a-zA-Z0-9]+/g, '_'),\n summary: description ?? path,\n responses: {\n '200': outputSchema\n ? {\n description: 'Success',\n content: { 'application/json': { schema: outputSchema } },\n }\n : { description: 'Success' },\n ...(priceUsdc\n ? {\n '402': {\n description:\n 'Payment required — the body carries an x402 accepts[] envelope (scheme \"exact\", network sui). Sign it and retry with the X-PAYMENT header.',\n },\n }\n : {}),\n '422': { description: 'Invalid request body — never charged' },\n },\n };\n if (priceUsdc) {\n // Same shape the gateway's own /openapi.json emits: 'mpp' is the\n // protocol family, 'x402' the dialect; the x402 block mirrors the\n // static half of the live accepts[] entry (dynamic fields ride the 402).\n operation['x-payment-info'] = {\n pricingMode: 'fixed',\n price: priceUsdc,\n currency: 'USDC',\n protocols: ['mpp', 'x402'],\n x402: {\n scheme: 'exact',\n network: `sui:${serve.network}`,\n asset: (serve.network === 'testnet' ? USDC_TESTNET : USDC).type,\n payTo: serve.payTo,\n },\n };\n }\n if (inputSchema) {\n operation.requestBody = {\n required: true,\n content: { 'application/json': { schema: inputSchema } },\n };\n }\n paths[`/${path}`] = { post: operation };\n }\n\n return {\n openapi: '3.1.0',\n info: {\n title: serve.name ?? 'Paid API',\n version: '1.0.0',\n description:\n serve.description ??\n 'Agent-payable API. Every paid endpoint answers 402 with an x402 accepts[] envelope; payment settles in USDC on Sui.',\n },\n ...(base ? { servers: [{ url: base }] } : {}),\n paths,\n };\n}\n\nexport function buildLlmsTxt(serve: Serve, origin?: string): string {\n const base = serve.baseUrl ?? origin ?? '';\n const lines: string[] = [];\n lines.push(`# ${serve.name ?? 'Paid API'}`);\n lines.push('');\n if (serve.description) {\n lines.push(serve.description);\n lines.push('');\n }\n lines.push('## How to pay');\n lines.push('');\n lines.push(\n 'Endpoints below are paid per call in USDC on Sui (x402). An unpaid request returns',\n 'HTTP 402 with an `accepts[]` envelope; sign it and retry with the `X-PAYMENT` header.',\n 'Invalid input returns 422 before any payment is taken. A failed call is never charged.',\n '',\n 'Easiest client: `npm i -g @t2000/cli` then `t2 pay <url> --data \\'{...}\\'`,',\n 'or the t2000 MCP server (`t2000_pay`), or `@t2000/sdk` `pay()`.',\n '',\n );\n lines.push('## Endpoints');\n lines.push('');\n for (const route of serve.routes.values()) {\n const { path, priceUsdc, description, inputSchema, outputSchema } = route.meta;\n const price = priceUsdc ? `${priceUsdc} USDC per call` : 'free';\n lines.push(`### POST ${base}/${path} — ${price}`);\n if (description) lines.push(description);\n if (inputSchema) {\n lines.push('Request body (JSON Schema):');\n lines.push('```json');\n lines.push(JSON.stringify(inputSchema, null, 2));\n lines.push('```');\n }\n if (outputSchema) {\n lines.push('Response (JSON Schema — contentMediaType/format annotations name the deliverable types):');\n lines.push('```json');\n lines.push(JSON.stringify(outputSchema, null, 2));\n lines.push('```');\n }\n lines.push('');\n }\n lines.push(`Discovery: ${base}/openapi.json`);\n return lines.join('\\n');\n}\n","import { SuiGrpcClient } from '@mysten/sui/grpc';\nimport type { ServeNetwork } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Chain plumbing — same shape as the gateway's x402-dialect.ts (the reference\n// composition). All reads are gRPC; this package never touches JSON-RPC.\n//\n// Cache policy: the chain identifier (genesis digest) is immutable per\n// network — cached forever. The epoch advances ~daily and x402 requirements\n// are valid for [epoch, epoch+1], so a 10-minute TTL is conservatively fresh.\n// ---------------------------------------------------------------------------\n\nconst FULLNODE_URLS: Record<ServeNetwork, string> = {\n mainnet: 'https://fullnode.mainnet.sui.io:443',\n testnet: 'https://fullnode.testnet.sui.io:443',\n};\n\nconst EPOCH_TTL_MS = 10 * 60 * 1000;\n\nexport interface ChainInfo {\n chain: string;\n epoch: string;\n}\n\ninterface ChainState {\n client?: SuiGrpcClient;\n chainId?: string;\n epoch?: { value: string; fetchedAt: number };\n}\n\nconst state: Partial<Record<ServeNetwork, ChainState>> = {};\n\nexport function getGrpcClient(network: ServeNetwork, rpcUrl?: string): SuiGrpcClient {\n const s = (state[network] ??= {});\n if (!s.client) {\n s.client = new SuiGrpcClient({\n baseUrl: rpcUrl ?? FULLNODE_URLS[network],\n network,\n });\n }\n return s.client;\n}\n\nexport async function getChainInfo(network: ServeNetwork, rpcUrl?: string): Promise<ChainInfo> {\n const client = getGrpcClient(network, rpcUrl);\n const s = (state[network] ??= {});\n if (!s.chainId) {\n const res = await client.core.getChainIdentifier();\n s.chainId = res.chainIdentifier;\n }\n if (!s.epoch || Date.now() - s.epoch.fetchedAt > EPOCH_TTL_MS) {\n const res = await client.core.getCurrentSystemState();\n s.epoch = { value: String(res.systemState.epoch), fetchedAt: Date.now() };\n }\n return { chain: s.chainId, epoch: s.epoch.value };\n}\n\n/** Test seam — reset module caches between cases. */\nexport function __resetChainCaches(): void {\n delete state.mainnet;\n delete state.testnet;\n}\n\n/** Test seam — pre-seed chain info so tests never hit the network. */\nexport function __seedChainInfo(network: ServeNetwork, chain: string, epoch: string): void {\n const s = (state[network] ??= {});\n s.chainId = chain;\n s.epoch = { value: epoch, fetchedAt: Date.now() };\n}\n","import type { Currency, DigestStore } from '@t2000/sui-x402';\nimport {\n createX402Requirements,\n encodeX402Response,\n isX402EscrowHeader,\n parseX402Header,\n settleX402Payment,\n verifyX402Payment,\n X402_PAYMENT_HEADER,\n X402_PAYMENT_RESPONSE_HEADER,\n X402_VERSION,\n type X402SettleResponse,\n} from '@t2000/sui-x402';\nimport { getChainInfo, getGrpcClient } from './chain.js';\nimport type {\n BuiltRoute,\n HandlerContext,\n HandlerResult,\n ServeNetwork,\n ServeSchema,\n StandardSchemaLike,\n} from './types.js';\n\n// ---------------------------------------------------------------------------\n// The paid-request lifecycle (SPEC_T2000_SERVE §3 — sign-then-settle,\n// handler-then-settle):\n//\n// no X-PAYMENT → 402 with the accepts[] envelope (never a charge;\n// the catalog probe and every discovery tool read\n// this, so it fires BEFORE body validation)\n// X-PAYMENT present:\n// 1. parse + STRUCTURAL verify (right amount/recipient/nonce — no RPC)\n// 2. challenge-once check (a signed payload is single-use)\n// 3. validate the body — invalid → 422, payment NEVER submitted\n// (the JMPR paid-422 class is impossible: the buyer keeps their money)\n// 4. run the handler — throws → 500, payment NEVER submitted\n// 5. settle (submit the buyer-signed gasless bytes; digest-once inside)\n// 6. consume the challenge, attach the X-PAYMENT-RESPONSE receipt\n//\n// Money only moves at step 5, after the seller has already produced the\n// result. A forged payload can waste seller compute (signature authority is\n// the chain at settle time), never buyer money.\n// ---------------------------------------------------------------------------\n\nexport interface RouteRuntime {\n payTo: string;\n network: ServeNetwork;\n currency: Currency;\n store: DigestStore;\n baseUrl?: string;\n rpcUrl?: string;\n}\n\nexport interface RouteOptions {\n path: string;\n description?: string;\n}\n\n/** Sanity cap on a per-call price — above this, the work is job-shaped\n * (escrow) rather than a per-call x402 Service. */\nconst CATALOG_PRICE_CAP_USDC = 5;\n\nconst CORS_HEADERS: Record<string, string> = {\n 'access-control-allow-origin': '*',\n 'access-control-allow-methods': 'GET, POST, PUT, DELETE, OPTIONS',\n 'access-control-allow-headers': `content-type, ${X402_PAYMENT_HEADER}`,\n 'access-control-expose-headers': `${X402_PAYMENT_RESPONSE_HEADER}, WWW-Authenticate`,\n};\n\nfunction withCors(response: Response): Response {\n const headers = new Headers(response.headers);\n for (const [k, v] of Object.entries(CORS_HEADERS)) headers.set(k, v);\n return new Response(response.body, { status: response.status, headers });\n}\n\nfunction json(status: number, body: unknown, headers?: Record<string, string>): Response {\n return withCors(\n new Response(JSON.stringify(body), {\n status,\n headers: { 'content-type': 'application/json', ...headers },\n }),\n );\n}\n\nfunction isStandardSchema(schema: ServeSchema): schema is StandardSchemaLike {\n return typeof schema === 'object' && schema !== null && '~standard' in schema;\n}\n\nasync function validateBody(\n schema: ServeSchema,\n value: unknown,\n): Promise<{ ok: true; data: unknown } | { ok: false; message: string }> {\n if (isStandardSchema(schema)) {\n const result = await schema['~standard'].validate(value);\n if (result.issues) {\n // Name the failing field — bare \"Invalid input\" ×N gives a paying\n // buyer's agent nothing to self-correct with.\n const message = result.issues\n .map((i) => {\n const path = (i.path ?? [])\n .map((seg) => (typeof seg === 'object' ? String(seg.key) : String(seg)))\n .join('.');\n return path ? `${path}: ${i.message}` : i.message;\n })\n .join('; ');\n return { ok: false, message };\n }\n return { ok: true, data: result.value };\n }\n const result = schema.safeParse(value);\n if (!result.success) {\n return { ok: false, message: result.error.message ?? 'invalid body' };\n }\n return { ok: true, data: result.data };\n}\n\n/** Positive decimal USDC string, max 6dp (atomic precision). */\nfunction assertValidPrice(price: string, path: string): void {\n if (!/^\\d+(\\.\\d{1,6})?$/.test(price) || Number(price) <= 0) {\n throw new Error(\n `[serve] Route \"${path}\": price must be a positive decimal USDC string with up to 6 decimals, got \"${price}\"`,\n );\n }\n if (Number(price) > CATALOG_PRICE_CAP_USDC) {\n console.warn(\n `[serve] Route \"${path}\": price ${price} USDC is above the ${CATALOG_PRICE_CAP_USDC} USDC listing cap — ` +\n 'the route works, but per-call x402 is the wrong shape for it. Job-class work belongs in `t2 service create` (escrow).',\n );\n }\n}\n\nexport class RouteBuilder<TBody = undefined> {\n private priceUsdc?: string;\n private bodySchema?: ServeSchema;\n private inputSchema?: Record<string, unknown>;\n private outputSchema?: Record<string, unknown>;\n private isFree = false;\n\n constructor(\n private readonly runtime: RouteRuntime,\n private readonly options: RouteOptions,\n private readonly register: (route: BuiltRoute) => void,\n ) {}\n\n /** Charge this many USDC per call (human units, e.g. \"0.01\"). */\n paid(priceUsdc: string): this {\n assertValidPrice(priceUsdc, this.options.path);\n this.priceUsdc = priceUsdc;\n this.isFree = false;\n return this;\n }\n\n /** Serve without payment (health checks, previews, docs). */\n unprotected(): this {\n this.isFree = true;\n this.priceUsdc = undefined;\n return this;\n }\n\n /**\n * Validate the JSON request body. zod v4 / valibot / arktype / anything\n * Standard-Schema, or anything with a zod-style safeParse.\n *\n * Pass the JSON Schema as the second argument to publish it in\n * /openapi.json + /llms.txt (zod v4: `z.toJSONSchema(schema)`) — buyers'\n * agents build request bodies from it, and the catalog grades listings\n * without one.\n */\n body<T>(schema: ServeSchema<T>, jsonSchema?: Record<string, unknown>): RouteBuilder<T> {\n this.bodySchema = schema;\n this.inputSchema = jsonSchema;\n return this as unknown as RouteBuilder<T>;\n }\n\n /**\n * Declare the 200 response's JSON Schema (zod v4: `z.toJSONSchema(schema)`).\n * Published in /openapi.json + /llms.txt so buyer agents know what they're\n * buying and buyer UIs can render the deliverable by TYPE instead of\n * sniffing it — annotate with `contentMediaType` (e.g. \"image/svg+xml\",\n * \"text/markdown\") and `format: \"color\"` where they apply. Declaration\n * only; responses are never validated at runtime.\n */\n response(jsonSchema: Record<string, unknown>): this {\n this.outputSchema = jsonSchema;\n return this;\n }\n\n handler(fn: (ctx: HandlerContext<TBody>) => HandlerResult | Promise<HandlerResult>): BuiltRoute {\n if (!this.isFree && !this.priceUsdc) {\n throw new Error(\n `[serve] Route \"${this.options.path}\": call .paid('<usdc>') or .unprotected() before .handler()`,\n );\n }\n const runtime = this.runtime;\n const { path, description } = this.options;\n const priceUsdc = this.priceUsdc;\n const bodySchema = this.bodySchema;\n\n const route = (async (req: Request): Promise<Response> => {\n if (req.method === 'OPTIONS') {\n return withCors(new Response(null, { status: 204 }));\n }\n\n // Read + parse the body once, up front. A missing/empty body on a\n // schema-less route is fine; JSON parse failures only matter when a\n // paid request must be validated (the unpaid 402 fires regardless).\n let parsedBody: unknown;\n let bodyParseError: string | undefined;\n if (req.method !== 'GET' && req.method !== 'HEAD') {\n const text = await req.text();\n if (text.trim().length > 0) {\n try {\n parsedBody = JSON.parse(text);\n } catch {\n bodyParseError = 'request body is not valid JSON';\n }\n }\n }\n\n const resource = (runtime.baseUrl ?? new URL(req.url).origin).replace(/\\/$/, '') + `/${path}`;\n\n const runHandler = async (payer?: string): Promise<Response> => {\n let validated: unknown = parsedBody;\n if (bodySchema) {\n // `paid: false` is machine-readable charge honesty — a 422 fires\n // BEFORE settlement, so the buyer always keeps their money.\n if (bodyParseError) {\n return json(422, { error: bodyParseError, paid: false });\n }\n const result = await validateBody(bodySchema, parsedBody ?? {});\n if (!result.ok) {\n return json(422, { error: result.message, paid: false });\n }\n validated = result.data;\n }\n const out = await fn({ body: validated as TBody, req, payer });\n if (out instanceof Response) return withCors(out);\n return json(200, out);\n };\n\n // Free route — no payment machinery at all.\n if (!priceUsdc) {\n try {\n return await runHandler();\n } catch (err) {\n console.error(`[serve] Route \"${path}\" handler failed:`, err);\n return json(500, { error: 'internal error' });\n }\n }\n\n const paymentHeader = req.headers.get(X402_PAYMENT_HEADER);\n\n // Unpaid → 402 with the accepts[] envelope. This fires before body\n // validation on purpose: the catalog probe (and every discovery tool)\n // POSTs `{}` and must see the challenge, and an unpaid request can\n // never be charged, so there is nothing to protect yet.\n if (!paymentHeader) {\n return await respond402(runtime, { resource, priceUsdc });\n }\n\n if (isX402EscrowHeader(paymentHeader)) {\n return await respond402(runtime, {\n resource,\n priceUsdc,\n error:\n 'this endpoint sells instant per-call work (settle-then-serve), not escrow jobs — retry with a signed x402 payment',\n });\n }\n\n // 1. Parse + structural verify — right terms, right recipient, right\n // nonce. No RPC, no state. Wrong-terms payloads never reach the\n // handler.\n let payment: ReturnType<typeof parseX402Header>;\n try {\n payment = parseX402Header(paymentHeader);\n verifyX402Payment({\n payment,\n expected: {\n challengeId: payment.payload.challengeId,\n amount: priceUsdc,\n currency: runtime.currency,\n recipient: runtime.payTo,\n network: runtime.network,\n },\n });\n } catch (err) {\n return await respond402(runtime, {\n resource,\n priceUsdc,\n error: `invalid payment: ${err instanceof Error ? err.message : String(err)}`,\n });\n }\n\n // 2. Challenge-once — a signed payload is single-use even before it\n // settles (the settled digest is separately consumed inside\n // settleX402Payment, digest-once).\n const challengeKey = `challenge:${payment.payload.challengeId}`;\n if (await runtime.store.has(challengeKey)) {\n return await respond402(runtime, {\n resource,\n priceUsdc,\n error: 'payment challenge already used — sign a fresh payment',\n });\n }\n\n // 3 + 4. Validate, then compute the result. Any failure here returns\n // WITHOUT settling — the buyer-signed bytes are never submitted.\n let served: Response;\n try {\n served = await runHandler(payment.payload.senderAddress);\n } catch (err) {\n console.error(`[serve] Route \"${path}\" handler failed (payment NOT settled):`, err);\n return json(500, { error: 'internal error — you were not charged' });\n }\n if (served.status >= 400) return served; // 422 etc. — not charged\n\n // 5. Settle — submit the buyer-signed gasless bytes, confirm the\n // on-chain balance change, record the digest (digest-once).\n let settle: X402SettleResponse;\n try {\n settle = await settleX402Payment({\n payment,\n client: getGrpcClient(runtime.network, runtime.rpcUrl),\n store: runtime.store,\n expected: {\n challengeId: payment.payload.challengeId,\n amount: priceUsdc,\n currency: runtime.currency,\n recipient: runtime.payTo,\n network: runtime.network,\n },\n });\n } catch (err) {\n return await respond402(runtime, {\n resource,\n priceUsdc,\n error: `settlement failed: ${err instanceof Error ? err.message : String(err)}`,\n });\n }\n\n // 6. Consume the challenge + attach the receipt.\n try {\n await runtime.store.set(challengeKey);\n } catch {\n // Digest-once already holds; challenge-once is defense in depth.\n }\n\n const headers = new Headers(served.headers);\n headers.set(X402_PAYMENT_RESPONSE_HEADER, encodeX402Response(settle));\n return new Response(served.body, { status: served.status, headers });\n }) as BuiltRoute;\n\n route.meta = {\n path,\n priceUsdc,\n description,\n bodySchema,\n inputSchema: this.inputSchema,\n outputSchema: this.outputSchema,\n };\n this.register(route);\n return route;\n }\n}\n\nasync function respond402(\n runtime: RouteRuntime,\n args: { resource: string; priceUsdc: string; error?: string },\n): Promise<Response> {\n try {\n const { chain, epoch } = await getChainInfo(runtime.network, runtime.rpcUrl);\n const requirements = createX402Requirements({\n challengeId: crypto.randomUUID(),\n amount: args.priceUsdc,\n currency: runtime.currency,\n recipient: runtime.payTo,\n resource: args.resource,\n network: runtime.network,\n chain,\n currentEpoch: epoch,\n });\n // Belt-and-suspenders for pre-0.2.2 discovery clients and dual-dialect\n // consumers: mirror the challenge into the MPP WWW-Authenticate shape.\n // The accepts[] body stays the authoritative envelope — the header carries\n // the same recipient/currency and the DECIMAL amount that dialect uses.\n const host = (() => {\n try {\n return new URL(args.resource).hostname;\n } catch {\n return undefined;\n }\n })();\n const wwwAuth = `Payment realm=\"${host ?? 'x402'}\", recipient=\"${runtime.payTo}\", currency=\"${runtime.currency}\", amount=\"${args.priceUsdc}\"`;\n return json(\n 402,\n {\n x402Version: X402_VERSION,\n error: args.error ?? 'Payment required',\n accepts: [requirements],\n },\n { 'WWW-Authenticate': wwwAuth },\n );\n } catch (err) {\n // Chain info unreachable — a 402 without the envelope is unpayable, so\n // be honest about the outage instead of serving a dead challenge.\n console.error('[serve] failed to build 402 challenge:', err);\n return json(503, { error: 'payment challenge temporarily unavailable' });\n }\n}\n\n","import type { DigestStore } from '@t2000/sui-x402';\n\nexport { InMemoryDigestStore } from '@t2000/sui-x402';\nexport type { DigestStore } from '@t2000/sui-x402';\n\n// ---------------------------------------------------------------------------\n// Upstash-REST digest store — the production replay store for serverless\n// hosts. Mirrors the gateway's upstash-digest-store.ts but speaks the\n// Upstash REST API over plain fetch (no @upstash/redis dependency).\n//\n// TTL: 72h. x402 payments are chain-valid for the whole ValidDuring window\n// ([minEpoch, minEpoch+1] ≈ up to ~48h on mainnet). Sui resubmission of an\n// executed tx is idempotent, so if the digest/challenge keys expired BEFORE\n// the window closed, a replayed X-PAYMENT would re-settle \"successfully\"\n// and serve again on a single payment. 72h > max window + drift.\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_TTL_SECONDS = 72 * 60 * 60;\nconst PREFIX = 'serve:digest:';\n\nexport interface UpstashDigestStoreOptions {\n url: string;\n token: string;\n /** Key TTL in seconds. Default 72h — do not lower below ~50h (see above). */\n ttlSeconds?: number;\n}\n\nexport class UpstashDigestStore implements DigestStore {\n private readonly url: string;\n private readonly token: string;\n private readonly ttlSeconds: number;\n\n constructor(options: UpstashDigestStoreOptions) {\n this.url = options.url.replace(/\\/$/, '');\n this.token = options.token;\n this.ttlSeconds = options.ttlSeconds ?? DEFAULT_TTL_SECONDS;\n }\n\n private async command(segments: string[]): Promise<unknown> {\n const res = await fetch(`${this.url}/${segments.map(encodeURIComponent).join('/')}`, {\n headers: { authorization: `Bearer ${this.token}` },\n });\n if (!res.ok) {\n throw new Error(`Upstash command failed: ${res.status} ${await res.text()}`);\n }\n const body = (await res.json()) as { result?: unknown; error?: string };\n if (body.error) throw new Error(`Upstash error: ${body.error}`);\n return body.result;\n }\n\n async has(digest: string): Promise<boolean> {\n const result = await this.command(['GET', PREFIX + digest]);\n return result !== null && result !== undefined;\n }\n\n async set(digest: string): Promise<void> {\n // SET key 1 EX <ttl> NX — atomic set-if-absent. A null result means the\n // key already existed: the digest (or challenge) was already consumed.\n const result = await this.command([\n 'SET',\n PREFIX + digest,\n '1',\n 'EX',\n String(this.ttlSeconds),\n 'NX',\n ]);\n if (result === null || result === undefined) {\n throw new Error(`Digest already used: ${digest}`);\n }\n }\n}\n","import { isValidSuiAddress, normalizeSuiAddress } from '@mysten/sui/utils';\nimport { InMemoryDigestStore, USDC, USDC_TESTNET, type Currency } from '@t2000/sui-x402';\nimport { buildLlmsTxt, buildOpenApiDocument } from './discovery.js';\nimport { RouteBuilder, type RouteOptions, type RouteRuntime } from './route.js';\nimport { UpstashDigestStore } from './store.js';\nimport type { BuiltRoute, ServeConfig, ServeNetwork } from './types.js';\n\nexport class Serve {\n private readonly runtime: RouteRuntime;\n /** Every route built through this instance, keyed by path (discovery). */\n readonly routes = new Map<string, BuiltRoute>();\n\n readonly payTo: string;\n readonly network: ServeNetwork;\n readonly name?: string;\n readonly description?: string;\n readonly baseUrl?: string;\n\n constructor(config: ServeConfig) {\n if (!config.payTo || !isValidSuiAddress(config.payTo)) {\n throw new Error(\n `[serve] payTo must be a valid Sui address (the wallet your payments settle to), got \"${config.payTo}\"`,\n );\n }\n this.payTo = normalizeSuiAddress(config.payTo);\n this.network = config.network ?? 'mainnet';\n this.name = config.name;\n this.description = config.description;\n this.baseUrl = config.baseUrl?.replace(/\\/$/, '');\n\n const currency: Currency = this.network === 'testnet' ? USDC_TESTNET : USDC;\n this.runtime = {\n payTo: this.payTo,\n network: this.network,\n currency,\n store: config.store ?? new InMemoryDigestStore(),\n baseUrl: this.baseUrl,\n rpcUrl: config.rpcUrl,\n };\n }\n\n /** Start building a route. Chain `.paid()` / `.body()` / `.handler()`. */\n route(options: RouteOptions): RouteBuilder {\n const path = options.path.replace(/^\\/+/, '').replace(/\\/+$/, '');\n if (!path) throw new Error('[serve] route path must be non-empty');\n return new RouteBuilder({ ...this.runtime }, { ...options, path }, (route) => {\n this.routes.set(path, route);\n });\n }\n\n /**\n * Discovery: GET handler for /openapi.json. OpenAPI 3.1 with the\n * `x-payment-info` pricing extension on every paid operation — the shape\n * x402 tooling (and any catalog built on it) indexes.\n *\n * export const GET = serve.openapi(); // app/openapi.json/route.ts\n */\n openapi(): (req: Request) => Response {\n return (req: Request) =>\n new Response(JSON.stringify(buildOpenApiDocument(this, new URL(req.url).origin), null, 2), {\n headers: { 'content-type': 'application/json', 'access-control-allow-origin': '*' },\n });\n }\n\n /**\n * Discovery: GET handler for /llms.txt — plain-text guidance agents read\n * to understand what the API sells, what it costs, and how to pay.\n *\n * export const GET = serve.llms(); // app/llms.txt/route.ts\n */\n llms(): (req: Request) => Response {\n return (req: Request) =>\n new Response(buildLlmsTxt(this, new URL(req.url).origin), {\n headers: { 'content-type': 'text/plain; charset=utf-8', 'access-control-allow-origin': '*' },\n });\n }\n\n /**\n * One fetch handler for the whole app — routes + discovery docs. For\n * fetch-native runtimes (Bun.serve, Deno.serve, Hono, Cloudflare Workers):\n *\n * Bun.serve({ fetch: serve.fetch });\n * app.all('*', (c) => serve.fetch(c.req.raw)); // Hono\n *\n * Next.js apps can skip this and export route handlers directly.\n */\n readonly fetch = async (req: Request): Promise<Response> => {\n const pathname = new URL(req.url).pathname.replace(/^\\/+/, '').replace(/\\/+$/, '');\n if (pathname === 'openapi.json') return this.openapi()(req);\n if (pathname === 'llms.txt') return this.llms()(req);\n const route = this.routes.get(pathname);\n if (route) return route(req);\n return new Response(\n JSON.stringify({ error: 'not found', discovery: ['/openapi.json', '/llms.txt'] }),\n { status: 404, headers: { 'content-type': 'application/json' } },\n );\n };\n\n /**\n * The command that sells this API as an x402 Service on your Agent ID,\n * once it is deployed. Listing is a separate, explicit step: the endpoint\n * is live-probed (it must answer 402 with a Sui challenge that pays YOUR\n * wallet) and then recorded on-chain, sponsored and gasless.\n *\n * This used to emit curls against the hosted mpp.t2000.ai catalog. That\n * proxy mall was purged 2026-08-01 (SPEC_T2_CLEANUP_USDC_ONLY) — there is\n * no central catalog to submit to. Your Agent ID IS the listing, and\n * buyers find it with `t2 services`.\n */\n catalogSubmitCommand(deployedUrl?: string): string {\n const base = (deployedUrl ?? this.baseUrl ?? 'https://<your-deployed-app>').replace(/\\/$/, '');\n const paidPaths = [...this.routes.values()].filter((r) => r.meta.priceUsdc);\n const example = paidPaths[0]?.meta.path ?? '<route>';\n return [\n '# Sell it as an x402 Service on your Agent ID (live-probed, gasless):',\n `npx @t2000/cli agent sell ${base}/${example}`,\n '# Buyers then find it with `t2 services` and pay per call with `t2 pay`.',\n ].join('\\n');\n }\n}\n\nexport function createServe(config: ServeConfig): Serve {\n return new Serve(config);\n}\n\n/**\n * Build a Serve from environment variables — the template-app path where\n * config lives in the host's env UI, not code.\n *\n * T2000_PAY_TO required — the seller's Sui address\n * T2000_NETWORK optional — 'mainnet' (default) | 'testnet'\n * T2000_BASE_URL optional — public URL of the deployed app\n * T2000_NAME optional — service name for discovery docs\n * T2000_DESCRIPTION optional — one-liner for discovery docs\n * KV_REST_API_URL / KV_REST_API_TOKEN\n * optional — enables the durable Upstash replay store\n * (REQUIRED in serverless production; without it replay\n * state is per-instance memory)\n *\n * Empty strings are treated as unset (the Vercel empty-env bug class).\n */\nexport function createServeFromEnv(env: Record<string, string | undefined> = process.env): Serve {\n const read = (key: string): string | undefined => {\n const v = env[key]?.trim();\n return v && v.length > 0 ? v : undefined;\n };\n\n const payTo = read('T2000_PAY_TO');\n if (!payTo) {\n throw new Error(\n '[serve] T2000_PAY_TO is not set (or is empty). Set it to the Sui address your payments should settle to — `t2 address` prints yours.',\n );\n }\n\n const network = read('T2000_NETWORK');\n if (network && network !== 'mainnet' && network !== 'testnet') {\n throw new Error(`[serve] T2000_NETWORK must be 'mainnet' or 'testnet', got \"${network}\"`);\n }\n\n const kvUrl = read('KV_REST_API_URL');\n const kvToken = read('KV_REST_API_TOKEN');\n const store =\n kvUrl && kvToken ? new UpstashDigestStore({ url: kvUrl, token: kvToken }) : undefined;\n\n if (!store) {\n console.warn(\n '[serve] No KV_REST_API_URL/KV_REST_API_TOKEN — using the in-memory replay store. ' +\n 'Fine for a single long-lived process; on serverless hosts set both so replay protection is durable.',\n );\n }\n\n return new Serve({\n payTo,\n network: (network as ServeNetwork | undefined) ?? 'mainnet',\n baseUrl: read('T2000_BASE_URL'),\n name: read('T2000_NAME'),\n description: read('T2000_DESCRIPTION'),\n store,\n });\n}\n","import type { BuiltRoute } from './types.js';\n\n/**\n * Export a built route the way Next.js App Router needs it.\n *\n * Next dispatches ONLY the methods a route.ts exports — serve's own CORS\n * handling (OPTIONS → 204 with the ACAO headers) never runs if the file\n * exports just `POST`: the browser preflight gets Next's bare 204 with no\n * CORS headers, and every browser buyer (Passport, the store's Try it)\n * fails while CLI/server buyers — who never preflight — work fine. Fetch\n * runtimes mounted via a single handler (`serve.fetch`-style) don't have\n * this hole; it is a Next export contract, not a serve one.\n *\n * export const { POST, OPTIONS } = asNextRoute(\n * serve.route({ path: 'haiku' }).paid('0.01').handler(fn),\n * );\n */\nexport function asNextRoute(route: BuiltRoute): {\n POST: BuiltRoute;\n OPTIONS: BuiltRoute;\n} {\n return { POST: route, OPTIONS: route };\n}\n"]}
1
+ {"version":3,"sources":["../src/discovery.ts","../src/chain.ts","../src/route.ts","../src/store.ts","../src/serve.ts","../src/next.ts"],"names":["result","USDC_TESTNET","USDC","InMemoryDigestStore"],"mappings":"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","file":"index.js","sourcesContent":["import { USDC, USDC_TESTNET } from '@t2000/sui-x402';\nimport type { Serve } from './serve.js';\n\n// ---------------------------------------------------------------------------\n// Discovery docs — /openapi.json + /llms.txt.\n//\n// The shapes here are what the on-chain listing probe grades (the check\n// behind `t2 agent sell`) (was: apps/gateway/lib/\n// catalog-ingest.ts `gradeListing`): a warning-free listing needs info.title,\n// a one-paragraph info.description, a flat string `x-payment-info.price` per\n// paid operation, and an application/json requestBody schema with typed\n// properties. Everything serve can derive is emitted automatically; the JSON\n// request schema comes from the route's `inputSchema` (zod v4 users:\n// `z.toJSONSchema(schema)`).\n// ---------------------------------------------------------------------------\n\nexport function buildOpenApiDocument(serve: Serve, origin?: string): Record<string, unknown> {\n const base = serve.baseUrl ?? origin;\n const paths: Record<string, unknown> = {};\n\n for (const route of serve.routes.values()) {\n const { path, priceUsdc, description, inputSchema, outputSchema } = route.meta;\n const operation: Record<string, unknown> = {\n operationId: path.replace(/[^a-zA-Z0-9]+/g, '_'),\n summary: description ?? path,\n responses: {\n '200': outputSchema\n ? {\n description: 'Success',\n content: { 'application/json': { schema: outputSchema } },\n }\n : { description: 'Success' },\n ...(priceUsdc\n ? {\n '402': {\n description:\n 'Payment required — the body carries an x402 accepts[] envelope (scheme \"exact\", network sui). Sign it and retry with the X-PAYMENT header.',\n },\n }\n : {}),\n '422': { description: 'Invalid request body — never charged' },\n },\n };\n if (priceUsdc) {\n // Same shape the gateway's own /openapi.json emits: 'mpp' is the\n // protocol family, 'x402' the dialect; the x402 block mirrors the\n // static half of the live accepts[] entry (dynamic fields ride the 402).\n operation['x-payment-info'] = {\n pricingMode: 'fixed',\n price: priceUsdc,\n currency: 'USDC',\n protocols: ['mpp', 'x402'],\n x402: {\n scheme: 'exact',\n network: `sui:${serve.network}`,\n asset: (serve.network === 'testnet' ? USDC_TESTNET : USDC).type,\n payTo: serve.payTo,\n },\n };\n }\n if (inputSchema) {\n operation.requestBody = {\n required: true,\n content: { 'application/json': { schema: inputSchema } },\n };\n }\n paths[`/${path}`] = { post: operation };\n }\n\n return {\n openapi: '3.1.0',\n info: {\n title: serve.name ?? 'Paid API',\n version: '1.0.0',\n description:\n serve.description ??\n 'Agent-payable API. Every paid endpoint answers 402 with an x402 accepts[] envelope; payment settles in USDC on Sui.',\n },\n ...(base ? { servers: [{ url: base }] } : {}),\n paths,\n };\n}\n\nexport function buildLlmsTxt(serve: Serve, origin?: string): string {\n const base = serve.baseUrl ?? origin ?? '';\n const lines: string[] = [];\n lines.push(`# ${serve.name ?? 'Paid API'}`);\n lines.push('');\n if (serve.description) {\n lines.push(serve.description);\n lines.push('');\n }\n lines.push('## How to pay');\n lines.push('');\n lines.push(\n 'Endpoints below are paid per call in USDC on Sui (x402). An unpaid request returns',\n 'HTTP 402 with an `accepts[]` envelope; sign it and retry with the `X-PAYMENT` header.',\n 'Invalid input returns 422 before any payment is taken. A failed call is never charged.',\n '',\n 'Easiest client: `npm i -g @t2000/cli` then `t2 pay <url> --data \\'{...}\\'`,',\n 'or the t2000 MCP server (`t2000_pay`), or `@t2000/sdk` `pay()`.',\n '',\n );\n lines.push('## Endpoints');\n lines.push('');\n for (const route of serve.routes.values()) {\n const { path, priceUsdc, description, inputSchema, outputSchema } = route.meta;\n const price = priceUsdc ? `${priceUsdc} USDC per call` : 'free';\n lines.push(`### POST ${base}/${path} — ${price}`);\n if (description) lines.push(description);\n if (inputSchema) {\n lines.push('Request body (JSON Schema):');\n lines.push('```json');\n lines.push(JSON.stringify(inputSchema, null, 2));\n lines.push('```');\n }\n if (outputSchema) {\n lines.push('Response (JSON Schema — contentMediaType/format annotations name the deliverable types):');\n lines.push('```json');\n lines.push(JSON.stringify(outputSchema, null, 2));\n lines.push('```');\n }\n lines.push('');\n }\n lines.push(`Discovery: ${base}/openapi.json`);\n return lines.join('\\n');\n}\n","import { SuiGrpcClient } from '@mysten/sui/grpc';\nimport type { ServeNetwork } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Chain plumbing — same shape as the gateway's x402-dialect.ts (the reference\n// composition). All reads are gRPC; this package never touches JSON-RPC.\n//\n// Cache policy: the chain identifier (genesis digest) is immutable per\n// network — cached forever. The epoch advances ~daily and x402 requirements\n// are valid for [epoch, epoch+1], so a 10-minute TTL is conservatively fresh.\n// ---------------------------------------------------------------------------\n\nconst FULLNODE_URLS: Record<ServeNetwork, string> = {\n mainnet: 'https://fullnode.mainnet.sui.io:443',\n testnet: 'https://fullnode.testnet.sui.io:443',\n};\n\nconst EPOCH_TTL_MS = 10 * 60 * 1000;\n\nexport interface ChainInfo {\n chain: string;\n epoch: string;\n}\n\ninterface ChainState {\n client?: SuiGrpcClient;\n chainId?: string;\n epoch?: { value: string; fetchedAt: number };\n}\n\nconst state: Partial<Record<ServeNetwork, ChainState>> = {};\n\nexport function getGrpcClient(network: ServeNetwork, rpcUrl?: string): SuiGrpcClient {\n const s = (state[network] ??= {});\n if (!s.client) {\n s.client = new SuiGrpcClient({\n baseUrl: rpcUrl ?? FULLNODE_URLS[network],\n network,\n });\n }\n return s.client;\n}\n\nexport async function getChainInfo(network: ServeNetwork, rpcUrl?: string): Promise<ChainInfo> {\n const client = getGrpcClient(network, rpcUrl);\n const s = (state[network] ??= {});\n if (!s.chainId) {\n const res = await client.core.getChainIdentifier();\n s.chainId = res.chainIdentifier;\n }\n if (!s.epoch || Date.now() - s.epoch.fetchedAt > EPOCH_TTL_MS) {\n const res = await client.core.getCurrentSystemState();\n s.epoch = { value: String(res.systemState.epoch), fetchedAt: Date.now() };\n }\n return { chain: s.chainId, epoch: s.epoch.value };\n}\n\n/** Test seam — reset module caches between cases. */\nexport function __resetChainCaches(): void {\n delete state.mainnet;\n delete state.testnet;\n}\n\n/** Test seam — pre-seed chain info so tests never hit the network. */\nexport function __seedChainInfo(network: ServeNetwork, chain: string, epoch: string): void {\n const s = (state[network] ??= {});\n s.chainId = chain;\n s.epoch = { value: epoch, fetchedAt: Date.now() };\n}\n","import type { Currency, DigestStore } from '@t2000/sui-x402';\nimport {\n createX402Requirements,\n encodeX402Response,\n isX402EscrowHeader,\n parseX402Header,\n settleX402Payment,\n verifyX402Payment,\n X402_PAYMENT_HEADER,\n X402_PAYMENT_RESPONSE_HEADER,\n X402_VERSION,\n type X402SettleResponse,\n} from '@t2000/sui-x402';\nimport { getChainInfo, getGrpcClient } from './chain.js';\nimport type {\n BuiltRoute,\n HandlerContext,\n HandlerResult,\n ServeNetwork,\n ServeSchema,\n StandardSchemaLike,\n} from './types.js';\n\n// ---------------------------------------------------------------------------\n// The paid-request lifecycle (SPEC_T2000_SERVE §3 — sign-then-settle,\n// handler-then-settle):\n//\n// no X-PAYMENT → 402 with the accepts[] envelope (never a charge;\n// the catalog probe and every discovery tool read\n// this, so it fires BEFORE body validation)\n// X-PAYMENT present:\n// 1. parse + STRUCTURAL verify (right amount/recipient/nonce — no RPC)\n// 2. challenge-once check (a signed payload is single-use)\n// 3. validate the body — invalid → 422, payment NEVER submitted\n// (the JMPR paid-422 class is impossible: the buyer keeps their money)\n// 4. run the handler — throws → 500, payment NEVER submitted\n// 5. settle (submit the buyer-signed gasless bytes; digest-once inside)\n// 6. consume the challenge, attach the X-PAYMENT-RESPONSE receipt\n//\n// Money only moves at step 5, after the seller has already produced the\n// result. A forged payload can waste seller compute (signature authority is\n// the chain at settle time), never buyer money.\n// ---------------------------------------------------------------------------\n\nexport interface RouteRuntime {\n payTo: string;\n network: ServeNetwork;\n currency: Currency;\n store: DigestStore;\n baseUrl?: string;\n rpcUrl?: string;\n /** B2 attributed reporting — unset = no report (see ServeConfig). */\n activityReportUrl?: string;\n}\n\nexport interface RouteOptions {\n path: string;\n description?: string;\n}\n\n/** Sanity cap on a per-call price — above this, the work is job-shaped\n * (escrow) rather than a per-call x402 Service. */\nconst CATALOG_PRICE_CAP_USDC = 5;\n\nconst CORS_HEADERS: Record<string, string> = {\n 'access-control-allow-origin': '*',\n 'access-control-allow-methods': 'GET, POST, PUT, DELETE, OPTIONS',\n 'access-control-allow-headers': `content-type, ${X402_PAYMENT_HEADER}`,\n 'access-control-expose-headers': `${X402_PAYMENT_RESPONSE_HEADER}, WWW-Authenticate`,\n};\n\nfunction withCors(response: Response): Response {\n const headers = new Headers(response.headers);\n for (const [k, v] of Object.entries(CORS_HEADERS)) headers.set(k, v);\n return new Response(response.body, { status: response.status, headers });\n}\n\nfunction json(status: number, body: unknown, headers?: Record<string, string>): Response {\n return withCors(\n new Response(JSON.stringify(body), {\n status,\n headers: { 'content-type': 'application/json', ...headers },\n }),\n );\n}\n\nfunction isStandardSchema(schema: ServeSchema): schema is StandardSchemaLike {\n return typeof schema === 'object' && schema !== null && '~standard' in schema;\n}\n\nasync function validateBody(\n schema: ServeSchema,\n value: unknown,\n): Promise<{ ok: true; data: unknown } | { ok: false; message: string }> {\n if (isStandardSchema(schema)) {\n const result = await schema['~standard'].validate(value);\n if (result.issues) {\n // Name the failing field — bare \"Invalid input\" ×N gives a paying\n // buyer's agent nothing to self-correct with.\n const message = result.issues\n .map((i) => {\n const path = (i.path ?? [])\n .map((seg) => (typeof seg === 'object' ? String(seg.key) : String(seg)))\n .join('.');\n return path ? `${path}: ${i.message}` : i.message;\n })\n .join('; ');\n return { ok: false, message };\n }\n return { ok: true, data: result.value };\n }\n const result = schema.safeParse(value);\n if (!result.success) {\n return { ok: false, message: result.error.message ?? 'invalid body' };\n }\n return { ok: true, data: result.data };\n}\n\n/** Positive decimal USDC string, max 6dp (atomic precision). */\nfunction assertValidPrice(price: string, path: string): void {\n if (!/^\\d+(\\.\\d{1,6})?$/.test(price) || Number(price) <= 0) {\n throw new Error(\n `[serve] Route \"${path}\": price must be a positive decimal USDC string with up to 6 decimals, got \"${price}\"`,\n );\n }\n if (Number(price) > CATALOG_PRICE_CAP_USDC) {\n console.warn(\n `[serve] Route \"${path}\": price ${price} USDC is above the ${CATALOG_PRICE_CAP_USDC} USDC listing cap — ` +\n 'the route works, but per-call x402 is the wrong shape for it. Job-class work belongs in `t2 service create` (escrow).',\n );\n }\n}\n\nexport class RouteBuilder<TBody = undefined> {\n private priceUsdc?: string;\n private bodySchema?: ServeSchema;\n private inputSchema?: Record<string, unknown>;\n private outputSchema?: Record<string, unknown>;\n private isFree = false;\n\n constructor(\n private readonly runtime: RouteRuntime,\n private readonly options: RouteOptions,\n private readonly register: (route: BuiltRoute) => void,\n ) {}\n\n /** Charge this many USDC per call (human units, e.g. \"0.01\"). */\n paid(priceUsdc: string): this {\n assertValidPrice(priceUsdc, this.options.path);\n this.priceUsdc = priceUsdc;\n this.isFree = false;\n return this;\n }\n\n /** Serve without payment (health checks, previews, docs). */\n unprotected(): this {\n this.isFree = true;\n this.priceUsdc = undefined;\n return this;\n }\n\n /**\n * Validate the JSON request body. zod v4 / valibot / arktype / anything\n * Standard-Schema, or anything with a zod-style safeParse.\n *\n * Pass the JSON Schema as the second argument to publish it in\n * /openapi.json + /llms.txt (zod v4: `z.toJSONSchema(schema)`) — buyers'\n * agents build request bodies from it, and the catalog grades listings\n * without one.\n */\n body<T>(schema: ServeSchema<T>, jsonSchema?: Record<string, unknown>): RouteBuilder<T> {\n this.bodySchema = schema;\n this.inputSchema = jsonSchema;\n return this as unknown as RouteBuilder<T>;\n }\n\n /**\n * Declare the 200 response's JSON Schema (zod v4: `z.toJSONSchema(schema)`).\n * Published in /openapi.json + /llms.txt so buyer agents know what they're\n * buying and buyer UIs can render the deliverable by TYPE instead of\n * sniffing it — annotate with `contentMediaType` (e.g. \"image/svg+xml\",\n * \"text/markdown\") and `format: \"color\"` where they apply. Declaration\n * only; responses are never validated at runtime.\n */\n response(jsonSchema: Record<string, unknown>): this {\n this.outputSchema = jsonSchema;\n return this;\n }\n\n handler(fn: (ctx: HandlerContext<TBody>) => HandlerResult | Promise<HandlerResult>): BuiltRoute {\n if (!this.isFree && !this.priceUsdc) {\n throw new Error(\n `[serve] Route \"${this.options.path}\": call .paid('<usdc>') or .unprotected() before .handler()`,\n );\n }\n const runtime = this.runtime;\n const { path, description } = this.options;\n const priceUsdc = this.priceUsdc;\n const bodySchema = this.bodySchema;\n\n const route = (async (req: Request): Promise<Response> => {\n if (req.method === 'OPTIONS') {\n return withCors(new Response(null, { status: 204 }));\n }\n\n // Read + parse the body once, up front. A missing/empty body on a\n // schema-less route is fine; JSON parse failures only matter when a\n // paid request must be validated (the unpaid 402 fires regardless).\n let parsedBody: unknown;\n let bodyParseError: string | undefined;\n if (req.method !== 'GET' && req.method !== 'HEAD') {\n const text = await req.text();\n if (text.trim().length > 0) {\n try {\n parsedBody = JSON.parse(text);\n } catch {\n bodyParseError = 'request body is not valid JSON';\n }\n }\n }\n\n const resource = (runtime.baseUrl ?? new URL(req.url).origin).replace(/\\/$/, '') + `/${path}`;\n\n const runHandler = async (payer?: string): Promise<Response> => {\n let validated: unknown = parsedBody;\n if (bodySchema) {\n // `paid: false` is machine-readable charge honesty — a 422 fires\n // BEFORE settlement, so the buyer always keeps their money.\n if (bodyParseError) {\n return json(422, { error: bodyParseError, paid: false });\n }\n const result = await validateBody(bodySchema, parsedBody ?? {});\n if (!result.ok) {\n return json(422, { error: result.message, paid: false });\n }\n validated = result.data;\n }\n const out = await fn({ body: validated as TBody, req, payer });\n if (out instanceof Response) return withCors(out);\n return json(200, out);\n };\n\n // Free route — no payment machinery at all.\n if (!priceUsdc) {\n try {\n return await runHandler();\n } catch (err) {\n console.error(`[serve] Route \"${path}\" handler failed:`, err);\n return json(500, { error: 'internal error' });\n }\n }\n\n const paymentHeader = req.headers.get(X402_PAYMENT_HEADER);\n\n // Unpaid → 402 with the accepts[] envelope. This fires before body\n // validation on purpose: the catalog probe (and every discovery tool)\n // POSTs `{}` and must see the challenge, and an unpaid request can\n // never be charged, so there is nothing to protect yet.\n if (!paymentHeader) {\n return await respond402(runtime, { resource, priceUsdc });\n }\n\n if (isX402EscrowHeader(paymentHeader)) {\n return await respond402(runtime, {\n resource,\n priceUsdc,\n error:\n 'this endpoint sells instant per-call work (settle-then-serve), not escrow jobs — retry with a signed x402 payment',\n });\n }\n\n // 1. Parse + structural verify — right terms, right recipient, right\n // nonce. No RPC, no state. Wrong-terms payloads never reach the\n // handler.\n let payment: ReturnType<typeof parseX402Header>;\n try {\n payment = parseX402Header(paymentHeader);\n verifyX402Payment({\n payment,\n expected: {\n challengeId: payment.payload.challengeId,\n amount: priceUsdc,\n currency: runtime.currency,\n recipient: runtime.payTo,\n network: runtime.network,\n },\n });\n } catch (err) {\n return await respond402(runtime, {\n resource,\n priceUsdc,\n error: `invalid payment: ${err instanceof Error ? err.message : String(err)}`,\n });\n }\n\n // 2. Challenge-once — a signed payload is single-use even before it\n // settles (the settled digest is separately consumed inside\n // settleX402Payment, digest-once).\n const challengeKey = `challenge:${payment.payload.challengeId}`;\n if (await runtime.store.has(challengeKey)) {\n return await respond402(runtime, {\n resource,\n priceUsdc,\n error: 'payment challenge already used — sign a fresh payment',\n });\n }\n\n // 3 + 4. Validate, then compute the result. Any failure here returns\n // WITHOUT settling — the buyer-signed bytes are never submitted.\n let served: Response;\n try {\n served = await runHandler(payment.payload.senderAddress);\n } catch (err) {\n console.error(`[serve] Route \"${path}\" handler failed (payment NOT settled):`, err);\n return json(500, { error: 'internal error — you were not charged' });\n }\n if (served.status >= 400) return served; // 422 etc. — not charged\n\n // 5. Settle — submit the buyer-signed gasless bytes, confirm the\n // on-chain balance change, record the digest (digest-once).\n let settle: X402SettleResponse;\n try {\n settle = await settleX402Payment({\n payment,\n client: getGrpcClient(runtime.network, runtime.rpcUrl),\n store: runtime.store,\n expected: {\n challengeId: payment.payload.challengeId,\n amount: priceUsdc,\n currency: runtime.currency,\n recipient: runtime.payTo,\n network: runtime.network,\n },\n });\n } catch (err) {\n return await respond402(runtime, {\n resource,\n priceUsdc,\n error: `settlement failed: ${err instanceof Error ? err.message : String(err)}`,\n });\n }\n\n // 6. Consume the challenge + attach the receipt.\n try {\n await runtime.store.set(challengeKey);\n } catch {\n // Digest-once already holds; challenge-once is defense in depth.\n }\n\n // B2: attributed activity report — AFTER a successful settle only,\n // strictly fire-and-forget (a dead report can never change the\n // buyer's 200 or the settle; SPEC_T2_ACTIVITY_X402 §7 lock 6).\n reportActivity(runtime, {\n digest: settle.transaction,\n payer: settle.payer,\n priceUsdc,\n resource,\n });\n\n const headers = new Headers(served.headers);\n headers.set(X402_PAYMENT_RESPONSE_HEADER, encodeX402Response(settle));\n return new Response(served.body, { status: served.status, headers });\n }) as BuiltRoute;\n\n route.meta = {\n path,\n priceUsdc,\n description,\n bodySchema,\n inputSchema: this.inputSchema,\n outputSchema: this.outputSchema,\n };\n this.register(route);\n return route;\n }\n}\n\n/** Fire-and-forget x402.paid report (B2). Never awaited into the response\n * path; short timeout; every failure swallowed. The report endpoint\n * chain-verifies the digest, so this carries claims, not trust. */\nfunction reportActivity(\n runtime: RouteRuntime,\n args: { digest: string; payer: string; priceUsdc: string; resource: string },\n): void {\n const url = runtime.activityReportUrl;\n if (!url) return;\n try {\n void fetch(url, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n digest: args.digest,\n payTo: runtime.payTo,\n payer: args.payer,\n amountMicroUsdc: Math.round(Number(args.priceUsdc) * 1_000_000),\n network: `sui:${runtime.network}`,\n route: args.resource,\n source: 'serve',\n }),\n signal: AbortSignal.timeout(1500),\n }).catch(() => undefined);\n } catch {\n // even a sync throw (bad URL) must not touch the buyer's response\n }\n}\n\nasync function respond402(\n runtime: RouteRuntime,\n args: { resource: string; priceUsdc: string; error?: string },\n): Promise<Response> {\n try {\n const { chain, epoch } = await getChainInfo(runtime.network, runtime.rpcUrl);\n const requirements = createX402Requirements({\n challengeId: crypto.randomUUID(),\n amount: args.priceUsdc,\n currency: runtime.currency,\n recipient: runtime.payTo,\n resource: args.resource,\n network: runtime.network,\n chain,\n currentEpoch: epoch,\n });\n // Belt-and-suspenders for pre-0.2.2 discovery clients and dual-dialect\n // consumers: mirror the challenge into the MPP WWW-Authenticate shape.\n // The accepts[] body stays the authoritative envelope — the header carries\n // the same recipient/currency and the DECIMAL amount that dialect uses.\n const host = (() => {\n try {\n return new URL(args.resource).hostname;\n } catch {\n return undefined;\n }\n })();\n const wwwAuth = `Payment realm=\"${host ?? 'x402'}\", recipient=\"${runtime.payTo}\", currency=\"${runtime.currency}\", amount=\"${args.priceUsdc}\"`;\n return json(\n 402,\n {\n x402Version: X402_VERSION,\n error: args.error ?? 'Payment required',\n accepts: [requirements],\n },\n { 'WWW-Authenticate': wwwAuth },\n );\n } catch (err) {\n // Chain info unreachable — a 402 without the envelope is unpayable, so\n // be honest about the outage instead of serving a dead challenge.\n console.error('[serve] failed to build 402 challenge:', err);\n return json(503, { error: 'payment challenge temporarily unavailable' });\n }\n}\n\n","import type { DigestStore } from '@t2000/sui-x402';\n\nexport { InMemoryDigestStore } from '@t2000/sui-x402';\nexport type { DigestStore } from '@t2000/sui-x402';\n\n// ---------------------------------------------------------------------------\n// Upstash-REST digest store — the production replay store for serverless\n// hosts. Mirrors the gateway's upstash-digest-store.ts but speaks the\n// Upstash REST API over plain fetch (no @upstash/redis dependency).\n//\n// TTL: 72h. x402 payments are chain-valid for the whole ValidDuring window\n// ([minEpoch, minEpoch+1] ≈ up to ~48h on mainnet). Sui resubmission of an\n// executed tx is idempotent, so if the digest/challenge keys expired BEFORE\n// the window closed, a replayed X-PAYMENT would re-settle \"successfully\"\n// and serve again on a single payment. 72h > max window + drift.\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_TTL_SECONDS = 72 * 60 * 60;\nconst PREFIX = 'serve:digest:';\n\nexport interface UpstashDigestStoreOptions {\n url: string;\n token: string;\n /** Key TTL in seconds. Default 72h — do not lower below ~50h (see above). */\n ttlSeconds?: number;\n}\n\nexport class UpstashDigestStore implements DigestStore {\n private readonly url: string;\n private readonly token: string;\n private readonly ttlSeconds: number;\n\n constructor(options: UpstashDigestStoreOptions) {\n this.url = options.url.replace(/\\/$/, '');\n this.token = options.token;\n this.ttlSeconds = options.ttlSeconds ?? DEFAULT_TTL_SECONDS;\n }\n\n private async command(segments: string[]): Promise<unknown> {\n const res = await fetch(`${this.url}/${segments.map(encodeURIComponent).join('/')}`, {\n headers: { authorization: `Bearer ${this.token}` },\n });\n if (!res.ok) {\n throw new Error(`Upstash command failed: ${res.status} ${await res.text()}`);\n }\n const body = (await res.json()) as { result?: unknown; error?: string };\n if (body.error) throw new Error(`Upstash error: ${body.error}`);\n return body.result;\n }\n\n async has(digest: string): Promise<boolean> {\n const result = await this.command(['GET', PREFIX + digest]);\n return result !== null && result !== undefined;\n }\n\n async set(digest: string): Promise<void> {\n // SET key 1 EX <ttl> NX — atomic set-if-absent. A null result means the\n // key already existed: the digest (or challenge) was already consumed.\n const result = await this.command([\n 'SET',\n PREFIX + digest,\n '1',\n 'EX',\n String(this.ttlSeconds),\n 'NX',\n ]);\n if (result === null || result === undefined) {\n throw new Error(`Digest already used: ${digest}`);\n }\n }\n}\n","import { isValidSuiAddress, normalizeSuiAddress } from '@mysten/sui/utils';\nimport { InMemoryDigestStore, USDC, USDC_TESTNET, type Currency } from '@t2000/sui-x402';\nimport { buildLlmsTxt, buildOpenApiDocument } from './discovery.js';\nimport { RouteBuilder, type RouteOptions, type RouteRuntime } from './route.js';\nimport { UpstashDigestStore } from './store.js';\nimport type { BuiltRoute, ServeConfig, ServeNetwork } from './types.js';\n\n/** The t2000.ai attributed-activity report endpoint — ONE canonical string\n * (matches the sdk's DEFAULT_ACTIVITY_REPORT_URL; tests assert equality). */\nexport const DEFAULT_ACTIVITY_REPORT_URL = 'https://t2000.ai/api/activity/x402';\n\n/** Explicit opt-out tokens for T2000_ACTIVITY_REPORT_URL (case-insensitive). */\nconst REPORT_OPT_OUT = new Set(['false', '0', 'off', 'none']);\n\nexport class Serve {\n private readonly runtime: RouteRuntime;\n /** Every route built through this instance, keyed by path (discovery). */\n readonly routes = new Map<string, BuiltRoute>();\n\n readonly payTo: string;\n readonly network: ServeNetwork;\n readonly name?: string;\n readonly description?: string;\n readonly baseUrl?: string;\n /** Where settled payments are reported (B2) — undefined = no report. */\n readonly activityReportUrl?: string;\n\n constructor(config: ServeConfig) {\n if (!config.payTo || !isValidSuiAddress(config.payTo)) {\n throw new Error(\n `[serve] payTo must be a valid Sui address (the wallet your payments settle to), got \"${config.payTo}\"`,\n );\n }\n this.payTo = normalizeSuiAddress(config.payTo);\n this.network = config.network ?? 'mainnet';\n this.name = config.name;\n this.description = config.description;\n this.baseUrl = config.baseUrl?.replace(/\\/$/, '');\n this.activityReportUrl = config.activityReportUrl;\n\n const currency: Currency = this.network === 'testnet' ? USDC_TESTNET : USDC;\n this.runtime = {\n payTo: this.payTo,\n network: this.network,\n currency,\n store: config.store ?? new InMemoryDigestStore(),\n baseUrl: this.baseUrl,\n rpcUrl: config.rpcUrl,\n activityReportUrl: this.activityReportUrl,\n };\n }\n\n /** Start building a route. Chain `.paid()` / `.body()` / `.handler()`. */\n route(options: RouteOptions): RouteBuilder {\n const path = options.path.replace(/^\\/+/, '').replace(/\\/+$/, '');\n if (!path) throw new Error('[serve] route path must be non-empty');\n return new RouteBuilder({ ...this.runtime }, { ...options, path }, (route) => {\n this.routes.set(path, route);\n });\n }\n\n /**\n * Discovery: GET handler for /openapi.json. OpenAPI 3.1 with the\n * `x-payment-info` pricing extension on every paid operation — the shape\n * x402 tooling (and any catalog built on it) indexes.\n *\n * export const GET = serve.openapi(); // app/openapi.json/route.ts\n */\n openapi(): (req: Request) => Response {\n return (req: Request) =>\n new Response(JSON.stringify(buildOpenApiDocument(this, new URL(req.url).origin), null, 2), {\n headers: { 'content-type': 'application/json', 'access-control-allow-origin': '*' },\n });\n }\n\n /**\n * Discovery: GET handler for /llms.txt — plain-text guidance agents read\n * to understand what the API sells, what it costs, and how to pay.\n *\n * export const GET = serve.llms(); // app/llms.txt/route.ts\n */\n llms(): (req: Request) => Response {\n return (req: Request) =>\n new Response(buildLlmsTxt(this, new URL(req.url).origin), {\n headers: { 'content-type': 'text/plain; charset=utf-8', 'access-control-allow-origin': '*' },\n });\n }\n\n /**\n * One fetch handler for the whole app — routes + discovery docs. For\n * fetch-native runtimes (Bun.serve, Deno.serve, Hono, Cloudflare Workers):\n *\n * Bun.serve({ fetch: serve.fetch });\n * app.all('*', (c) => serve.fetch(c.req.raw)); // Hono\n *\n * Next.js apps can skip this and export route handlers directly.\n */\n readonly fetch = async (req: Request): Promise<Response> => {\n const pathname = new URL(req.url).pathname.replace(/^\\/+/, '').replace(/\\/+$/, '');\n if (pathname === 'openapi.json') return this.openapi()(req);\n if (pathname === 'llms.txt') return this.llms()(req);\n const route = this.routes.get(pathname);\n if (route) return route(req);\n return new Response(\n JSON.stringify({ error: 'not found', discovery: ['/openapi.json', '/llms.txt'] }),\n { status: 404, headers: { 'content-type': 'application/json' } },\n );\n };\n\n /**\n * The command that sells this API as an x402 Service on your Agent ID,\n * once it is deployed. Listing is a separate, explicit step: the endpoint\n * is live-probed (it must answer 402 with a Sui challenge that pays YOUR\n * wallet) and then recorded on-chain, sponsored and gasless.\n *\n * This used to emit curls against the hosted mpp.t2000.ai catalog. That\n * proxy mall was purged 2026-08-01 (SPEC_T2_CLEANUP_USDC_ONLY) — there is\n * no central catalog to submit to. Your Agent ID IS the listing, and\n * buyers find it with `t2 services`.\n */\n catalogSubmitCommand(deployedUrl?: string): string {\n const base = (deployedUrl ?? this.baseUrl ?? 'https://<your-deployed-app>').replace(/\\/$/, '');\n const paidPaths = [...this.routes.values()].filter((r) => r.meta.priceUsdc);\n const example = paidPaths[0]?.meta.path ?? '<route>';\n return [\n '# Sell it as an x402 Service on your Agent ID (live-probed, gasless):',\n `npx @t2000/cli agent sell ${base}/${example}`,\n '# Buyers then find it with `t2 services` and pay per call with `t2 pay`.',\n ].join('\\n');\n }\n}\n\nexport function createServe(config: ServeConfig): Serve {\n return new Serve(config);\n}\n\n/**\n * Build a Serve from environment variables — the template-app path where\n * config lives in the host's env UI, not code.\n *\n * T2000_PAY_TO required — the seller's Sui address\n * T2000_NETWORK optional — 'mainnet' (default) | 'testnet'\n * T2000_BASE_URL optional — public URL of the deployed app\n * T2000_NAME optional — service name for discovery docs\n * T2000_DESCRIPTION optional — one-liner for discovery docs\n * T2000_ACTIVITY_REPORT_URL\n * optional — where settled payments are reported\n * (fire-and-forget x402.paid after each successful settle;\n * chain-verified server-side, never affects buyer\n * responses). DEFAULT-ON for FromEnv: unset →\n * https://t2000.ai/api/activity/x402 so new sellers appear\n * on the t2000.ai activity tape. Opt out with\n * `false` | `0` | `off` | `none` (case-insensitive), or\n * set a custom URL. (`new Serve({...})` without\n * activityReportUrl stays silent — only FromEnv defaults.)\n * KV_REST_API_URL / KV_REST_API_TOKEN\n * optional — enables the durable Upstash replay store\n * (REQUIRED in serverless production; without it replay\n * state is per-instance memory)\n *\n * Empty strings are treated as unset (the Vercel empty-env bug class).\n */\nexport function createServeFromEnv(env: Record<string, string | undefined> = process.env): Serve {\n const read = (key: string): string | undefined => {\n const v = env[key]?.trim();\n return v && v.length > 0 ? v : undefined;\n };\n\n const payTo = read('T2000_PAY_TO');\n if (!payTo) {\n throw new Error(\n '[serve] T2000_PAY_TO is not set (or is empty). Set it to the Sui address your payments should settle to — `t2 address` prints yours.',\n );\n }\n\n const network = read('T2000_NETWORK');\n if (network && network !== 'mainnet' && network !== 'testnet') {\n throw new Error(`[serve] T2000_NETWORK must be 'mainnet' or 'testnet', got \"${network}\"`);\n }\n\n const kvUrl = read('KV_REST_API_URL');\n const kvToken = read('KV_REST_API_TOKEN');\n const store =\n kvUrl && kvToken ? new UpstashDigestStore({ url: kvUrl, token: kvToken }) : undefined;\n\n if (!store) {\n console.warn(\n '[serve] No KV_REST_API_URL/KV_REST_API_TOKEN — using the in-memory replay store. ' +\n 'Fine for a single long-lived process; on serverless hosts set both so replay protection is durable.',\n );\n }\n\n return new Serve({\n payTo,\n network: (network as ServeNetwork | undefined) ?? 'mainnet',\n baseUrl: read('T2000_BASE_URL'),\n name: read('T2000_NAME'),\n description: read('T2000_DESCRIPTION'),\n activityReportUrl: resolveReportUrlFromEnv(read('T2000_ACTIVITY_REPORT_URL')),\n store,\n });\n}\n\n/** FromEnv activity-report resolution (B2 default-on): unset/empty →\n * the t2000.ai default; an explicit opt-out token → undefined (silent);\n * anything else is the seller's custom report URL. */\nfunction resolveReportUrlFromEnv(raw: string | undefined): string | undefined {\n if (raw === undefined) return DEFAULT_ACTIVITY_REPORT_URL;\n if (REPORT_OPT_OUT.has(raw.toLowerCase())) return undefined;\n return raw;\n}\n","import type { BuiltRoute } from './types.js';\n\n/**\n * Export a built route the way Next.js App Router needs it.\n *\n * Next dispatches ONLY the methods a route.ts exports — serve's own CORS\n * handling (OPTIONS → 204 with the ACAO headers) never runs if the file\n * exports just `POST`: the browser preflight gets Next's bare 204 with no\n * CORS headers, and every browser buyer (Passport, the store's Try it)\n * fails while CLI/server buyers — who never preflight — work fine. Fetch\n * runtimes mounted via a single handler (`serve.fetch`-style) don't have\n * this hole; it is a Next export contract, not a serve one.\n *\n * export const { POST, OPTIONS } = asNextRoute(\n * serve.route({ path: 'haiku' }).paid('0.01').handler(fn),\n * );\n */\nexport function asNextRoute(route: BuiltRoute): {\n POST: BuiltRoute;\n OPTIONS: BuiltRoute;\n} {\n return { POST: route, OPTIONS: route };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@t2000/serve",
3
- "version": "10.21.0",
3
+ "version": "10.21.2",
4
4
  "description": "Merchant-side x402 router for Sui — wrap any API so agents can discover it and pay per call in USDC. One builder: .paid().body().handler(). Sign-then-settle, no seller key, no seller gas.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -36,7 +36,7 @@
36
36
  "homepage": "https://docs.t2000.ai/sell-to-agents/overview",
37
37
  "dependencies": {
38
38
  "@mysten/sui": "^2.17.0",
39
- "@t2000/sui-x402": "10.21.0"
39
+ "@t2000/sui-x402": "10.21.2"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/node": "^20",
@@ -45,7 +45,7 @@
45
45
  "typescript": "^5",
46
46
  "typescript-eslint": "^8.58.0",
47
47
  "vitest": "^3",
48
- "@t2000/discovery": "10.21.0"
48
+ "@t2000/discovery": "10.21.2"
49
49
  },
50
50
  "license": "MIT",
51
51
  "scripts": {