@t2000/serve 10.16.1 → 10.17.1

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
@@ -16,8 +16,8 @@ export const POST = serve
16
16
  ```
17
17
 
18
18
  That route now answers x402 payment challenges, validates inputs, verifies and
19
- settles payments on Sui, and is listable on [mpp.t2000.ai](https://mpp.t2000.ai)
20
- and [agents.t2000.ai](https://agents.t2000.ai) — where every agent running
19
+ settles payments on Sui, and is sellable as a Service on your Agent ID
20
+ and [t2000.ai](https://t2000.ai) — where every agent running
21
21
  `t2 pay` or the t2000 MCP can find and pay it.
22
22
 
23
23
  ## Why Sui / why this package
@@ -56,7 +56,7 @@ serve.route({ path: 'health' }).unprotected().handler(() => ({ ok: true })); //
56
56
  ```
57
57
 
58
58
  - Prices are human-unit USDC strings (`'0.01'`), max 6 decimals.
59
- - Prices above **5 USDC** work but won't list on the mpp.t2000.ai catalog
59
+ - Prices above **5 USDC** work but are the wrong shape for per-call x402
60
60
  deliverable-priced work belongs in escrow (`t2 service create`).
61
61
  - Handlers receive `{ body, req, payer }` — `payer` is the buyer's verified Sui
62
62
  address (wallet-based identity, no accounts).
@@ -75,7 +75,7 @@ app.all('*', (c) => serve.fetch(c.req.raw)); // Hono
75
75
  ```
76
76
 
77
77
  `/openapi.json` is OpenAPI 3.1 with the `x-payment-info` pricing extension on
78
- every paid operation (the shape mpp.t2000.ai indexes); `/llms.txt` is plain-text
78
+ every paid operation (the shape x402 tooling indexes); `/llms.txt` is plain-text
79
79
  guidance for agents. Pass a JSON Schema as `.body(schema, jsonSchema)` (zod v4:
80
80
  `z.toJSONSchema(schema)`) and buyers' agents build request bodies without
81
81
  guessing — a wrong guess against a direct seller is a paid error.
package/dist/index.cjs CHANGED
@@ -144,8 +144,6 @@ function __seedChainInfo(network, chain, epoch) {
144
144
  }
145
145
 
146
146
  // src/route.ts
147
- var MPP_REPORT_URL = "https://mpp.t2000.ai/api/mpp/report";
148
- var REPORT_TIMEOUT_MS = 2e3;
149
147
  var CATALOG_PRICE_CAP_USDC = 5;
150
148
  var CORS_HEADERS = {
151
149
  "access-control-allow-origin": "*",
@@ -195,7 +193,7 @@ function assertValidPrice(price, path) {
195
193
  }
196
194
  if (Number(price) > CATALOG_PRICE_CAP_USDC) {
197
195
  console.warn(
198
- `[serve] Route "${path}": price ${price} USDC is above the ${CATALOG_PRICE_CAP_USDC} USDC listing cap \u2014 the route works, but it will not list on mpp.t2000.ai. Job-class work belongs in \`t2 service create\` (escrow).`
196
+ `[serve] Route "${path}": price ${price} USDC is above the ${CATALOG_PRICE_CAP_USDC} USDC listing cap \u2014 the route works, but per-call x402 is the wrong shape for it. Job-class work belongs in \`t2 service create\` (escrow).`
199
197
  );
200
198
  }
201
199
  }
@@ -372,9 +370,6 @@ var RouteBuilder = class {
372
370
  await runtime.store.set(challengeKey);
373
371
  } catch {
374
372
  }
375
- if (runtime.report) {
376
- reportPayment(settle.transaction, resource);
377
- }
378
373
  const headers = new Headers(served.headers);
379
374
  headers.set(x402.X402_PAYMENT_RESPONSE_HEADER, x402.encodeX402Response(settle));
380
375
  return new Response(served.body, { status: served.status, headers });
@@ -414,15 +409,6 @@ async function respond402(runtime, args) {
414
409
  return json(503, { error: "payment challenge temporarily unavailable" });
415
410
  }
416
411
  }
417
- function reportPayment(digest, url) {
418
- void fetch(MPP_REPORT_URL, {
419
- method: "POST",
420
- headers: { "content-type": "application/json" },
421
- body: JSON.stringify({ digest, url }),
422
- signal: AbortSignal.timeout(REPORT_TIMEOUT_MS)
423
- }).catch(() => {
424
- });
425
- }
426
412
  var DEFAULT_TTL_SECONDS = 72 * 60 * 60;
427
413
  var PREFIX = "serve:digest:";
428
414
  var UpstashDigestStore = class {
@@ -492,8 +478,7 @@ var Serve = class {
492
478
  currency,
493
479
  store: config.store ?? new server.InMemoryDigestStore(),
494
480
  baseUrl: this.baseUrl,
495
- rpcUrl: config.rpcUrl,
496
- report: config.report ?? true
481
+ rpcUrl: config.rpcUrl
497
482
  };
498
483
  }
499
484
  /** Start building a route. Chain `.paid()` / `.body()` / `.handler()`. */
@@ -507,7 +492,7 @@ var Serve = class {
507
492
  /**
508
493
  * Discovery: GET handler for /openapi.json. OpenAPI 3.1 with the
509
494
  * `x-payment-info` pricing extension on every paid operation — the shape
510
- * the mpp.t2000.ai catalog (and x402 tooling generally) indexes.
495
+ * x402 tooling (and any catalog built on it) indexes.
511
496
  *
512
497
  * export const GET = serve.openapi(); // app/openapi.json/route.ts
513
498
  */
@@ -548,20 +533,24 @@ var Serve = class {
548
533
  );
549
534
  };
550
535
  /**
551
- * The curl that lists this API on mpp.t2000.ai / agents.t2000.ai once it
552
- * is deployed. Listing is a separate, explicit step the catalog gates
553
- * (url · probe · dialect · price-cap), not this package, decide outcomes.
554
- * Dry-run first with /api/catalog/preview.
536
+ * The command that sells this API as an x402 Service on your Agent ID,
537
+ * once it is deployed. Listing is a separate, explicit step: the endpoint
538
+ * is live-probed (it must answer 402 with a Sui challenge that pays YOUR
539
+ * wallet) and then recorded on-chain, sponsored and gasless.
540
+ *
541
+ * This used to emit curls against the hosted mpp.t2000.ai catalog. That
542
+ * proxy mall was purged 2026-08-01 (SPEC_T2_CLEANUP_USDC_ONLY) — there is
543
+ * no central catalog to submit to. Your Agent ID IS the listing, and
544
+ * buyers find it with `t2 services`.
555
545
  */
556
546
  catalogSubmitCommand(deployedUrl) {
557
547
  const base = (deployedUrl ?? this.baseUrl ?? "https://<your-deployed-app>").replace(/\/$/, "");
558
548
  const paidPaths = [...this.routes.values()].filter((r) => r.meta.priceUsdc);
559
549
  const example = paidPaths[0]?.meta.path ?? "<route>";
560
550
  return [
561
- "# Dry-run (shows gate results, changes nothing):",
562
- `curl -X POST https://mpp.t2000.ai/api/catalog/preview -H 'content-type: application/json' -d '{"url":"${base}/${example}"}'`,
563
- "# List for real:",
564
- `curl -X POST https://mpp.t2000.ai/api/catalog/submit -H 'content-type: application/json' -d '{"url":"${base}/${example}"}'`
551
+ "# Sell it as an x402 Service on your Agent ID (live-probed, gasless):",
552
+ `npx @t2000/cli agent sell ${base}/${example}`,
553
+ "# Buyers then find it with `t2 services` and pay per call with `t2 pay`."
565
554
  ].join("\n");
566
555
  }
567
556
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/discovery.ts","../src/chain.ts","../src/route.ts","../src/store.ts","../src/serve.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 '@suimpp/mpp/server';\nimport type { Serve } from './serve.js';\n\n// ---------------------------------------------------------------------------\n// Discovery docs — /openapi.json + /llms.txt.\n//\n// The shapes here are graded by the catalog's ingest (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 { DigestStore } from '@suimpp/mpp/server';\nimport type { Currency } from '@suimpp/mpp/server';\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 '@suimpp/mpp/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 report: boolean;\n}\n\nexport interface RouteOptions {\n path: string;\n description?: string;\n}\n\nconst MPP_REPORT_URL = 'https://mpp.t2000.ai/api/mpp/report';\nconst REPORT_TIMEOUT_MS = 2_000;\n\n/** Listing cap on mpp.t2000.ai (catalog-ingest price-cap gate). */\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 it will not list on mpp.t2000.ai. 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 if (runtime.report) {\n reportPayment(settle.transaction, 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\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 return json(402, {\n x402Version: X402_VERSION,\n error: args.error ?? 'Payment required',\n accepts: [requirements],\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/**\n * Best-effort activity-feed report (mpp.t2000.ai). The gateway verifies the\n * digest on-chain before recording anything, so this carries no trusted\n * data — a lost or duplicate report is harmless.\n */\nfunction reportPayment(digest: string, url: string): void {\n void fetch(MPP_REPORT_URL, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ digest, url }),\n signal: AbortSignal.timeout(REPORT_TIMEOUT_MS),\n }).catch(() => {});\n}\n","import type { DigestStore } from '@suimpp/mpp/server';\n\nexport { InMemoryDigestStore } from '@suimpp/mpp/server';\nexport type { DigestStore } from '@suimpp/mpp/server';\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 '@suimpp/mpp/server';\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 report: config.report ?? true,\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 * the mpp.t2000.ai catalog (and x402 tooling generally) 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 curl that lists this API on mpp.t2000.ai / agents.t2000.ai once it\n * is deployed. Listing is a separate, explicit step — the catalog gates\n * (url · probe · dialect · price-cap), not this package, decide outcomes.\n * Dry-run first with /api/catalog/preview.\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 '# Dry-run (shows gate results, changes nothing):',\n `curl -X POST https://mpp.t2000.ai/api/catalog/preview -H 'content-type: application/json' -d '{\"url\":\"${base}/${example}\"}'`,\n '# List for real:',\n `curl -X POST https://mpp.t2000.ai/api/catalog/submit -H 'content-type: application/json' -d '{\"url\":\"${base}/${example}\"}'`,\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"]}
1
+ {"version":3,"sources":["../src/discovery.ts","../src/chain.ts","../src/route.ts","../src/store.ts","../src/serve.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 '@suimpp/mpp/server';\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 { DigestStore } from '@suimpp/mpp/server';\nimport type { Currency } from '@suimpp/mpp/server';\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 '@suimpp/mpp/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 return json(402, {\n x402Version: X402_VERSION,\n error: args.error ?? 'Payment required',\n accepts: [requirements],\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 '@suimpp/mpp/server';\n\nexport { InMemoryDigestStore } from '@suimpp/mpp/server';\nexport type { DigestStore } from '@suimpp/mpp/server';\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 '@suimpp/mpp/server';\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"]}
package/dist/index.d.cts CHANGED
@@ -25,11 +25,6 @@ interface ServeConfig {
25
25
  name?: string;
26
26
  /** One-line description (discovery docs, slice 2). */
27
27
  description?: string;
28
- /**
29
- * Report settled payments to the t2 activity feed (mpp.t2000.ai).
30
- * Fire-and-forget, never blocks or fails a response. Default true.
31
- */
32
- report?: boolean;
33
28
  /** Override the Sui fullnode gRPC URL (default: mainnet/testnet fullnode). */
34
29
  rpcUrl?: string;
35
30
  }
@@ -118,7 +113,6 @@ interface RouteRuntime {
118
113
  store: DigestStore;
119
114
  baseUrl?: string;
120
115
  rpcUrl?: string;
121
- report: boolean;
122
116
  }
123
117
  interface RouteOptions {
124
118
  path: string;
@@ -175,7 +169,7 @@ declare class Serve {
175
169
  /**
176
170
  * Discovery: GET handler for /openapi.json. OpenAPI 3.1 with the
177
171
  * `x-payment-info` pricing extension on every paid operation — the shape
178
- * the mpp.t2000.ai catalog (and x402 tooling generally) indexes.
172
+ * x402 tooling (and any catalog built on it) indexes.
179
173
  *
180
174
  * export const GET = serve.openapi(); // app/openapi.json/route.ts
181
175
  */
@@ -198,10 +192,15 @@ declare class Serve {
198
192
  */
199
193
  readonly fetch: (req: Request) => Promise<Response>;
200
194
  /**
201
- * The curl that lists this API on mpp.t2000.ai / agents.t2000.ai once it
202
- * is deployed. Listing is a separate, explicit step the catalog gates
203
- * (url · probe · dialect · price-cap), not this package, decide outcomes.
204
- * Dry-run first with /api/catalog/preview.
195
+ * The command that sells this API as an x402 Service on your Agent ID,
196
+ * once it is deployed. Listing is a separate, explicit step: the endpoint
197
+ * is live-probed (it must answer 402 with a Sui challenge that pays YOUR
198
+ * wallet) and then recorded on-chain, sponsored and gasless.
199
+ *
200
+ * This used to emit curls against the hosted mpp.t2000.ai catalog. That
201
+ * proxy mall was purged 2026-08-01 (SPEC_T2_CLEANUP_USDC_ONLY) — there is
202
+ * no central catalog to submit to. Your Agent ID IS the listing, and
203
+ * buyers find it with `t2 services`.
205
204
  */
206
205
  catalogSubmitCommand(deployedUrl?: string): string;
207
206
  }
package/dist/index.d.ts CHANGED
@@ -25,11 +25,6 @@ interface ServeConfig {
25
25
  name?: string;
26
26
  /** One-line description (discovery docs, slice 2). */
27
27
  description?: string;
28
- /**
29
- * Report settled payments to the t2 activity feed (mpp.t2000.ai).
30
- * Fire-and-forget, never blocks or fails a response. Default true.
31
- */
32
- report?: boolean;
33
28
  /** Override the Sui fullnode gRPC URL (default: mainnet/testnet fullnode). */
34
29
  rpcUrl?: string;
35
30
  }
@@ -118,7 +113,6 @@ interface RouteRuntime {
118
113
  store: DigestStore;
119
114
  baseUrl?: string;
120
115
  rpcUrl?: string;
121
- report: boolean;
122
116
  }
123
117
  interface RouteOptions {
124
118
  path: string;
@@ -175,7 +169,7 @@ declare class Serve {
175
169
  /**
176
170
  * Discovery: GET handler for /openapi.json. OpenAPI 3.1 with the
177
171
  * `x-payment-info` pricing extension on every paid operation — the shape
178
- * the mpp.t2000.ai catalog (and x402 tooling generally) indexes.
172
+ * x402 tooling (and any catalog built on it) indexes.
179
173
  *
180
174
  * export const GET = serve.openapi(); // app/openapi.json/route.ts
181
175
  */
@@ -198,10 +192,15 @@ declare class Serve {
198
192
  */
199
193
  readonly fetch: (req: Request) => Promise<Response>;
200
194
  /**
201
- * The curl that lists this API on mpp.t2000.ai / agents.t2000.ai once it
202
- * is deployed. Listing is a separate, explicit step the catalog gates
203
- * (url · probe · dialect · price-cap), not this package, decide outcomes.
204
- * Dry-run first with /api/catalog/preview.
195
+ * The command that sells this API as an x402 Service on your Agent ID,
196
+ * once it is deployed. Listing is a separate, explicit step: the endpoint
197
+ * is live-probed (it must answer 402 with a Sui challenge that pays YOUR
198
+ * wallet) and then recorded on-chain, sponsored and gasless.
199
+ *
200
+ * This used to emit curls against the hosted mpp.t2000.ai catalog. That
201
+ * proxy mall was purged 2026-08-01 (SPEC_T2_CLEANUP_USDC_ONLY) — there is
202
+ * no central catalog to submit to. Your Agent ID IS the listing, and
203
+ * buyers find it with `t2 services`.
205
204
  */
206
205
  catalogSubmitCommand(deployedUrl?: string): string;
207
206
  }
package/dist/index.js CHANGED
@@ -143,8 +143,6 @@ function __seedChainInfo(network, chain, epoch) {
143
143
  }
144
144
 
145
145
  // src/route.ts
146
- var MPP_REPORT_URL = "https://mpp.t2000.ai/api/mpp/report";
147
- var REPORT_TIMEOUT_MS = 2e3;
148
146
  var CATALOG_PRICE_CAP_USDC = 5;
149
147
  var CORS_HEADERS = {
150
148
  "access-control-allow-origin": "*",
@@ -194,7 +192,7 @@ function assertValidPrice(price, path) {
194
192
  }
195
193
  if (Number(price) > CATALOG_PRICE_CAP_USDC) {
196
194
  console.warn(
197
- `[serve] Route "${path}": price ${price} USDC is above the ${CATALOG_PRICE_CAP_USDC} USDC listing cap \u2014 the route works, but it will not list on mpp.t2000.ai. Job-class work belongs in \`t2 service create\` (escrow).`
195
+ `[serve] Route "${path}": price ${price} USDC is above the ${CATALOG_PRICE_CAP_USDC} USDC listing cap \u2014 the route works, but per-call x402 is the wrong shape for it. Job-class work belongs in \`t2 service create\` (escrow).`
198
196
  );
199
197
  }
200
198
  }
@@ -371,9 +369,6 @@ var RouteBuilder = class {
371
369
  await runtime.store.set(challengeKey);
372
370
  } catch {
373
371
  }
374
- if (runtime.report) {
375
- reportPayment(settle.transaction, resource);
376
- }
377
372
  const headers = new Headers(served.headers);
378
373
  headers.set(X402_PAYMENT_RESPONSE_HEADER, encodeX402Response(settle));
379
374
  return new Response(served.body, { status: served.status, headers });
@@ -413,15 +408,6 @@ async function respond402(runtime, args) {
413
408
  return json(503, { error: "payment challenge temporarily unavailable" });
414
409
  }
415
410
  }
416
- function reportPayment(digest, url) {
417
- void fetch(MPP_REPORT_URL, {
418
- method: "POST",
419
- headers: { "content-type": "application/json" },
420
- body: JSON.stringify({ digest, url }),
421
- signal: AbortSignal.timeout(REPORT_TIMEOUT_MS)
422
- }).catch(() => {
423
- });
424
- }
425
411
  var DEFAULT_TTL_SECONDS = 72 * 60 * 60;
426
412
  var PREFIX = "serve:digest:";
427
413
  var UpstashDigestStore = class {
@@ -491,8 +477,7 @@ var Serve = class {
491
477
  currency,
492
478
  store: config.store ?? new InMemoryDigestStore(),
493
479
  baseUrl: this.baseUrl,
494
- rpcUrl: config.rpcUrl,
495
- report: config.report ?? true
480
+ rpcUrl: config.rpcUrl
496
481
  };
497
482
  }
498
483
  /** Start building a route. Chain `.paid()` / `.body()` / `.handler()`. */
@@ -506,7 +491,7 @@ var Serve = class {
506
491
  /**
507
492
  * Discovery: GET handler for /openapi.json. OpenAPI 3.1 with the
508
493
  * `x-payment-info` pricing extension on every paid operation — the shape
509
- * the mpp.t2000.ai catalog (and x402 tooling generally) indexes.
494
+ * x402 tooling (and any catalog built on it) indexes.
510
495
  *
511
496
  * export const GET = serve.openapi(); // app/openapi.json/route.ts
512
497
  */
@@ -547,20 +532,24 @@ var Serve = class {
547
532
  );
548
533
  };
549
534
  /**
550
- * The curl that lists this API on mpp.t2000.ai / agents.t2000.ai once it
551
- * is deployed. Listing is a separate, explicit step the catalog gates
552
- * (url · probe · dialect · price-cap), not this package, decide outcomes.
553
- * Dry-run first with /api/catalog/preview.
535
+ * The command that sells this API as an x402 Service on your Agent ID,
536
+ * once it is deployed. Listing is a separate, explicit step: the endpoint
537
+ * is live-probed (it must answer 402 with a Sui challenge that pays YOUR
538
+ * wallet) and then recorded on-chain, sponsored and gasless.
539
+ *
540
+ * This used to emit curls against the hosted mpp.t2000.ai catalog. That
541
+ * proxy mall was purged 2026-08-01 (SPEC_T2_CLEANUP_USDC_ONLY) — there is
542
+ * no central catalog to submit to. Your Agent ID IS the listing, and
543
+ * buyers find it with `t2 services`.
554
544
  */
555
545
  catalogSubmitCommand(deployedUrl) {
556
546
  const base = (deployedUrl ?? this.baseUrl ?? "https://<your-deployed-app>").replace(/\/$/, "");
557
547
  const paidPaths = [...this.routes.values()].filter((r) => r.meta.priceUsdc);
558
548
  const example = paidPaths[0]?.meta.path ?? "<route>";
559
549
  return [
560
- "# Dry-run (shows gate results, changes nothing):",
561
- `curl -X POST https://mpp.t2000.ai/api/catalog/preview -H 'content-type: application/json' -d '{"url":"${base}/${example}"}'`,
562
- "# List for real:",
563
- `curl -X POST https://mpp.t2000.ai/api/catalog/submit -H 'content-type: application/json' -d '{"url":"${base}/${example}"}'`
550
+ "# Sell it as an x402 Service on your Agent ID (live-probed, gasless):",
551
+ `npx @t2000/cli agent sell ${base}/${example}`,
552
+ "# Buyers then find it with `t2 services` and pay per call with `t2 pay`."
564
553
  ].join("\n");
565
554
  }
566
555
  };
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"],"names":["result","USDC_TESTNET","USDC","InMemoryDigestStore"],"mappings":"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","file":"index.js","sourcesContent":["import { USDC, USDC_TESTNET } from '@suimpp/mpp/server';\nimport type { Serve } from './serve.js';\n\n// ---------------------------------------------------------------------------\n// Discovery docs — /openapi.json + /llms.txt.\n//\n// The shapes here are graded by the catalog's ingest (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 { DigestStore } from '@suimpp/mpp/server';\nimport type { Currency } from '@suimpp/mpp/server';\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 '@suimpp/mpp/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 report: boolean;\n}\n\nexport interface RouteOptions {\n path: string;\n description?: string;\n}\n\nconst MPP_REPORT_URL = 'https://mpp.t2000.ai/api/mpp/report';\nconst REPORT_TIMEOUT_MS = 2_000;\n\n/** Listing cap on mpp.t2000.ai (catalog-ingest price-cap gate). */\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 it will not list on mpp.t2000.ai. 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 if (runtime.report) {\n reportPayment(settle.transaction, 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\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 return json(402, {\n x402Version: X402_VERSION,\n error: args.error ?? 'Payment required',\n accepts: [requirements],\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/**\n * Best-effort activity-feed report (mpp.t2000.ai). The gateway verifies the\n * digest on-chain before recording anything, so this carries no trusted\n * data — a lost or duplicate report is harmless.\n */\nfunction reportPayment(digest: string, url: string): void {\n void fetch(MPP_REPORT_URL, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ digest, url }),\n signal: AbortSignal.timeout(REPORT_TIMEOUT_MS),\n }).catch(() => {});\n}\n","import type { DigestStore } from '@suimpp/mpp/server';\n\nexport { InMemoryDigestStore } from '@suimpp/mpp/server';\nexport type { DigestStore } from '@suimpp/mpp/server';\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 '@suimpp/mpp/server';\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 report: config.report ?? true,\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 * the mpp.t2000.ai catalog (and x402 tooling generally) 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 curl that lists this API on mpp.t2000.ai / agents.t2000.ai once it\n * is deployed. Listing is a separate, explicit step — the catalog gates\n * (url · probe · dialect · price-cap), not this package, decide outcomes.\n * Dry-run first with /api/catalog/preview.\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 '# Dry-run (shows gate results, changes nothing):',\n `curl -X POST https://mpp.t2000.ai/api/catalog/preview -H 'content-type: application/json' -d '{\"url\":\"${base}/${example}\"}'`,\n '# List for real:',\n `curl -X POST https://mpp.t2000.ai/api/catalog/submit -H 'content-type: application/json' -d '{\"url\":\"${base}/${example}\"}'`,\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"]}
1
+ {"version":3,"sources":["../src/discovery.ts","../src/chain.ts","../src/route.ts","../src/store.ts","../src/serve.ts"],"names":["result","USDC_TESTNET","USDC","InMemoryDigestStore"],"mappings":"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","file":"index.js","sourcesContent":["import { USDC, USDC_TESTNET } from '@suimpp/mpp/server';\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 { DigestStore } from '@suimpp/mpp/server';\nimport type { Currency } from '@suimpp/mpp/server';\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 '@suimpp/mpp/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 return json(402, {\n x402Version: X402_VERSION,\n error: args.error ?? 'Payment required',\n accepts: [requirements],\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 '@suimpp/mpp/server';\n\nexport { InMemoryDigestStore } from '@suimpp/mpp/server';\nexport type { DigestStore } from '@suimpp/mpp/server';\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 '@suimpp/mpp/server';\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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@t2000/serve",
3
- "version": "10.16.1",
3
+ "version": "10.17.1",
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",