@t2000/serve 10.20.2 → 10.21.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
@@ -51,6 +51,7 @@ npm install @t2000/serve
51
51
  |---|---|---|
52
52
  | `T2000_PAY_TO` | yes | Your Sui address — payments settle here (`t2 address` prints it) |
53
53
  | `T2000_NETWORK` | no | `mainnet` (default) or `testnet` |
54
+ | `T2000_ACTIVITY_REPORT_URL` | no | Fire-and-forget `x402.paid` reports after each successful settle — set `https://t2000.ai/api/activity/x402` to appear on the [t2000.ai](https://t2000.ai/activity) activity tape. Chain-verified server-side; never affects buyer responses. Unset = no report. |
54
55
  | `T2000_BASE_URL` | no | Public URL of the deployed app (used in challenges + discovery) |
55
56
  | `KV_REST_API_URL` / `KV_REST_API_TOKEN` | serverless: yes | Upstash-compatible KV for durable replay protection. Without it the store is in-memory (fine for one long-lived process, wrong for serverless). |
56
57
 
package/dist/index.cjs CHANGED
@@ -369,6 +369,12 @@ var RouteBuilder = class {
369
369
  await runtime.store.set(challengeKey);
370
370
  } catch {
371
371
  }
372
+ reportActivity(runtime, {
373
+ digest: settle.transaction,
374
+ payer: settle.payer,
375
+ priceUsdc,
376
+ resource
377
+ });
372
378
  const headers = new Headers(served.headers);
373
379
  headers.set(suiX402.X402_PAYMENT_RESPONSE_HEADER, suiX402.encodeX402Response(settle));
374
380
  return new Response(served.body, { status: served.status, headers });
@@ -385,6 +391,27 @@ var RouteBuilder = class {
385
391
  return route;
386
392
  }
387
393
  };
394
+ function reportActivity(runtime, args) {
395
+ const url = runtime.activityReportUrl;
396
+ if (!url) return;
397
+ try {
398
+ void fetch(url, {
399
+ method: "POST",
400
+ headers: { "content-type": "application/json" },
401
+ body: JSON.stringify({
402
+ digest: args.digest,
403
+ payTo: runtime.payTo,
404
+ payer: args.payer,
405
+ amountMicroUsdc: Math.round(Number(args.priceUsdc) * 1e6),
406
+ network: `sui:${runtime.network}`,
407
+ route: args.resource,
408
+ source: "serve"
409
+ }),
410
+ signal: AbortSignal.timeout(1500)
411
+ }).catch(() => void 0);
412
+ } catch {
413
+ }
414
+ }
388
415
  async function respond402(runtime, args) {
389
416
  try {
390
417
  const { chain, epoch } = await getChainInfo(runtime.network, runtime.rpcUrl);
@@ -489,7 +516,8 @@ var Serve = class {
489
516
  currency,
490
517
  store: config.store ?? new suiX402.InMemoryDigestStore(),
491
518
  baseUrl: this.baseUrl,
492
- rpcUrl: config.rpcUrl
519
+ rpcUrl: config.rpcUrl,
520
+ activityReportUrl: config.activityReportUrl
493
521
  };
494
522
  }
495
523
  /** Start building a route. Chain `.paid()` / `.body()` / `.handler()`. */
@@ -597,6 +625,7 @@ function createServeFromEnv(env = process.env) {
597
625
  baseUrl: read("T2000_BASE_URL"),
598
626
  name: read("T2000_NAME"),
599
627
  description: read("T2000_DESCRIPTION"),
628
+ activityReportUrl: read("T2000_ACTIVITY_REPORT_URL"),
600
629
  store
601
630
  });
602
631
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/discovery.ts","../src/chain.ts","../src/route.ts","../src/store.ts","../src/serve.ts","../src/next.ts"],"names":["USDC_TESTNET","USDC","SuiGrpcClient","X402_PAYMENT_HEADER","X402_PAYMENT_RESPONSE_HEADER","result","isX402EscrowHeader","parseX402Header","verifyX402Payment","settleX402Payment","encodeX402Response","createX402Requirements","X402_VERSION","isValidSuiAddress","normalizeSuiAddress","InMemoryDigestStore"],"mappings":";;;;;;;AAgBO,SAAS,oBAAA,CAAqB,OAAc,MAAA,EAA0C;AAC3F,EAAA,MAAM,IAAA,GAAO,MAAM,OAAA,IAAW,MAAA;AAC9B,EAAA,MAAM,QAAiC,EAAC;AAExC,EAAA,KAAA,MAAW,KAAA,IAAS,KAAA,CAAM,MAAA,CAAO,MAAA,EAAO,EAAG;AACzC,IAAA,MAAM,EAAE,IAAA,EAAM,SAAA,EAAW,aAAa,WAAA,EAAa,YAAA,KAAiB,KAAA,CAAM,IAAA;AAC1E,IAAA,MAAM,SAAA,GAAqC;AAAA,MACzC,WAAA,EAAa,IAAA,CAAK,OAAA,CAAQ,gBAAA,EAAkB,GAAG,CAAA;AAAA,MAC/C,SAAS,WAAA,IAAe,IAAA;AAAA,MACxB,SAAA,EAAW;AAAA,QACT,OAAO,YAAA,GACH;AAAA,UACE,WAAA,EAAa,SAAA;AAAA,UACb,SAAS,EAAE,kBAAA,EAAoB,EAAE,MAAA,EAAQ,cAAa;AAAE,SAC1D,GACA,EAAE,WAAA,EAAa,SAAA,EAAU;AAAA,QAC7B,GAAI,SAAA,GACA;AAAA,UACE,KAAA,EAAO;AAAA,YACL,WAAA,EACE;AAAA;AACJ,YAEF,EAAC;AAAA,QACL,KAAA,EAAO,EAAE,WAAA,EAAa,2CAAA;AAAuC;AAC/D,KACF;AACA,IAAA,IAAI,SAAA,EAAW;AAIb,MAAA,SAAA,CAAU,gBAAgB,CAAA,GAAI;AAAA,QAC5B,WAAA,EAAa,OAAA;AAAA,QACb,KAAA,EAAO,SAAA;AAAA,QACP,QAAA,EAAU,MAAA;AAAA,QACV,SAAA,EAAW,CAAC,KAAA,EAAO,MAAM,CAAA;AAAA,QACzB,IAAA,EAAM;AAAA,UACJ,MAAA,EAAQ,OAAA;AAAA,UACR,OAAA,EAAS,CAAA,IAAA,EAAO,KAAA,CAAM,OAAO,CAAA,CAAA;AAAA,UAC7B,KAAA,EAAA,CAAQ,KAAA,CAAM,OAAA,KAAY,SAAA,GAAYA,uBAAeC,YAAA,EAAM,IAAA;AAAA,UAC3D,OAAO,KAAA,CAAM;AAAA;AACf,OACF;AAAA,IACF;AACA,IAAA,IAAI,WAAA,EAAa;AACf,MAAA,SAAA,CAAU,WAAA,GAAc;AAAA,QACtB,QAAA,EAAU,IAAA;AAAA,QACV,SAAS,EAAE,kBAAA,EAAoB,EAAE,MAAA,EAAQ,aAAY;AAAE,OACzD;AAAA,IACF;AACA,IAAA,KAAA,CAAM,IAAI,IAAI,CAAA,CAAE,CAAA,GAAI,EAAE,MAAM,SAAA,EAAU;AAAA,EACxC;AAEA,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,OAAA;AAAA,IACT,IAAA,EAAM;AAAA,MACJ,KAAA,EAAO,MAAM,IAAA,IAAQ,UAAA;AAAA,MACrB,OAAA,EAAS,OAAA;AAAA,MACT,WAAA,EACE,MAAM,WAAA,IACN;AAAA,KACJ;AAAA,IACA,GAAI,IAAA,GAAO,EAAE,OAAA,EAAS,CAAC,EAAE,GAAA,EAAK,IAAA,EAAM,CAAA,EAAE,GAAI,EAAC;AAAA,IAC3C;AAAA,GACF;AACF;AAEO,SAAS,YAAA,CAAa,OAAc,MAAA,EAAyB;AAClE,EAAA,MAAM,IAAA,GAAO,KAAA,CAAM,OAAA,IAAW,MAAA,IAAU,EAAA;AACxC,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,EAAA,EAAK,KAAA,CAAM,IAAA,IAAQ,UAAU,CAAA,CAAE,CAAA;AAC1C,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,EAAA,IAAI,MAAM,WAAA,EAAa;AACrB,IAAA,KAAA,CAAM,IAAA,CAAK,MAAM,WAAW,CAAA;AAC5B,IAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAAA,EACf;AACA,EAAA,KAAA,CAAM,KAAK,eAAe,CAAA;AAC1B,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,EAAA,KAAA,CAAM,IAAA;AAAA,IACJ,oFAAA;AAAA,IACA,uFAAA;AAAA,IACA,wFAAA;AAAA,IACA,EAAA;AAAA,IACA,2EAAA;AAAA,IACA,iEAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,KAAA,CAAM,KAAK,cAAc,CAAA;AACzB,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,EAAA,KAAA,MAAW,KAAA,IAAS,KAAA,CAAM,MAAA,CAAO,MAAA,EAAO,EAAG;AACzC,IAAA,MAAM,EAAE,IAAA,EAAM,SAAA,EAAW,aAAa,WAAA,EAAa,YAAA,KAAiB,KAAA,CAAM,IAAA;AAC1E,IAAA,MAAM,KAAA,GAAQ,SAAA,GAAY,CAAA,EAAG,SAAS,CAAA,cAAA,CAAA,GAAmB,MAAA;AACzD,IAAA,KAAA,CAAM,KAAK,CAAA,SAAA,EAAY,IAAI,IAAI,IAAI,CAAA,QAAA,EAAM,KAAK,CAAA,CAAE,CAAA;AAChD,IAAA,IAAI,WAAA,EAAa,KAAA,CAAM,IAAA,CAAK,WAAW,CAAA;AACvC,IAAA,IAAI,WAAA,EAAa;AACf,MAAA,KAAA,CAAM,KAAK,6BAA6B,CAAA;AACxC,MAAA,KAAA,CAAM,KAAK,SAAS,CAAA;AACpB,MAAA,KAAA,CAAM,KAAK,IAAA,CAAK,SAAA,CAAU,WAAA,EAAa,IAAA,EAAM,CAAC,CAAC,CAAA;AAC/C,MAAA,KAAA,CAAM,KAAK,KAAK,CAAA;AAAA,IAClB;AACA,IAAA,IAAI,YAAA,EAAc;AAChB,MAAA,KAAA,CAAM,KAAK,+FAA0F,CAAA;AACrG,MAAA,KAAA,CAAM,KAAK,SAAS,CAAA;AACpB,MAAA,KAAA,CAAM,KAAK,IAAA,CAAK,SAAA,CAAU,YAAA,EAAc,IAAA,EAAM,CAAC,CAAC,CAAA;AAChD,MAAA,KAAA,CAAM,KAAK,KAAK,CAAA;AAAA,IAClB;AACA,IAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAAA,EACf;AACA,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,WAAA,EAAc,IAAI,CAAA,aAAA,CAAe,CAAA;AAC5C,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AACxB;AClHA,IAAM,aAAA,GAA8C;AAAA,EAClD,OAAA,EAAS,qCAAA;AAAA,EACT,OAAA,EAAS;AACX,CAAA;AAEA,IAAM,YAAA,GAAe,KAAK,EAAA,GAAK,GAAA;AAa/B,IAAM,QAAmD,EAAC;AAEnD,SAAS,aAAA,CAAc,SAAuB,MAAA,EAAgC;AACnF,EAAA,MAAM,CAAA,GAAK,KAAA,CAAM,OAAO,CAAA,KAAM,EAAC;AAC/B,EAAA,IAAI,CAAC,EAAE,MAAA,EAAQ;AACb,IAAA,CAAA,CAAE,MAAA,GAAS,IAAIC,kBAAA,CAAc;AAAA,MAC3B,OAAA,EAAS,MAAA,IAAU,aAAA,CAAc,OAAO,CAAA;AAAA,MACxC;AAAA,KACD,CAAA;AAAA,EACH;AACA,EAAA,OAAO,CAAA,CAAE,MAAA;AACX;AAEA,eAAsB,YAAA,CAAa,SAAuB,MAAA,EAAqC;AAC7F,EAAA,MAAM,MAAA,GAAS,aAAA,CAAc,OAAA,EAAS,MAAM,CAAA;AAC5C,EAAA,MAAM,CAAA,GAAK,KAAA,CAAM,OAAO,CAAA,KAAM,EAAC;AAC/B,EAAA,IAAI,CAAC,EAAE,OAAA,EAAS;AACd,IAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,IAAA,CAAK,kBAAA,EAAmB;AACjD,IAAA,CAAA,CAAE,UAAU,GAAA,CAAI,eAAA;AAAA,EAClB;AACA,EAAA,IAAI,CAAC,EAAE,KAAA,IAAS,IAAA,CAAK,KAAI,GAAI,CAAA,CAAE,KAAA,CAAM,SAAA,GAAY,YAAA,EAAc;AAC7D,IAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,IAAA,CAAK,qBAAA,EAAsB;AACpD,IAAA,CAAA,CAAE,KAAA,GAAQ,EAAE,KAAA,EAAO,MAAA,CAAO,GAAA,CAAI,WAAA,CAAY,KAAK,CAAA,EAAG,SAAA,EAAW,IAAA,CAAK,GAAA,EAAI,EAAE;AAAA,EAC1E;AACA,EAAA,OAAO,EAAE,KAAA,EAAO,CAAA,CAAE,SAAS,KAAA,EAAO,CAAA,CAAE,MAAM,KAAA,EAAM;AAClD;AAGO,SAAS,kBAAA,GAA2B;AACzC,EAAA,OAAO,KAAA,CAAM,OAAA;AACb,EAAA,OAAO,KAAA,CAAM,OAAA;AACf;AAGO,SAAS,eAAA,CAAgB,OAAA,EAAuB,KAAA,EAAe,KAAA,EAAqB;AACzF,EAAA,MAAM,CAAA,GAAK,KAAA,CAAM,OAAO,CAAA,KAAM,EAAC;AAC/B,EAAA,CAAA,CAAE,OAAA,GAAU,KAAA;AACZ,EAAA,CAAA,CAAE,QAAQ,EAAE,KAAA,EAAO,OAAO,SAAA,EAAW,IAAA,CAAK,KAAI,EAAE;AAClD;;;ACRA,IAAM,sBAAA,GAAyB,CAAA;AAE/B,IAAM,YAAA,GAAuC;AAAA,EAC3C,6BAAA,EAA+B,GAAA;AAAA,EAC/B,8BAAA,EAAgC,iCAAA;AAAA,EAChC,8BAAA,EAAgC,iBAAiBC,2BAAmB,CAAA,CAAA;AAAA,EACpE,+BAAA,EAAiC,GAAGC,oCAA4B,CAAA,kBAAA;AAClE,CAAA;AAEA,SAAS,SAAS,QAAA,EAA8B;AAC9C,EAAA,MAAM,OAAA,GAAU,IAAI,OAAA,CAAQ,QAAA,CAAS,OAAO,CAAA;AAC5C,EAAA,KAAA,MAAW,CAAC,CAAA,EAAG,CAAC,CAAA,IAAK,MAAA,CAAO,OAAA,CAAQ,YAAY,CAAA,EAAG,OAAA,CAAQ,GAAA,CAAI,CAAA,EAAG,CAAC,CAAA;AACnE,EAAA,OAAO,IAAI,SAAS,QAAA,CAAS,IAAA,EAAM,EAAE,MAAA,EAAQ,QAAA,CAAS,MAAA,EAAQ,OAAA,EAAS,CAAA;AACzE;AAEA,SAAS,IAAA,CAAK,MAAA,EAAgB,IAAA,EAAe,OAAA,EAA4C;AACvF,EAAA,OAAO,QAAA;AAAA,IACL,IAAI,QAAA,CAAS,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA,EAAG;AAAA,MACjC,MAAA;AAAA,MACA,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAoB,GAAG,OAAA;AAAQ,KAC3D;AAAA,GACH;AACF;AAEA,SAAS,iBAAiB,MAAA,EAAmD;AAC3E,EAAA,OAAO,OAAO,MAAA,KAAW,QAAA,IAAY,MAAA,KAAW,QAAQ,WAAA,IAAe,MAAA;AACzE;AAEA,eAAe,YAAA,CACb,QACA,KAAA,EACuE;AACvE,EAAA,IAAI,gBAAA,CAAiB,MAAM,CAAA,EAAG;AAC5B,IAAA,MAAMC,UAAS,MAAM,MAAA,CAAO,WAAW,CAAA,CAAE,SAAS,KAAK,CAAA;AACvD,IAAA,IAAIA,QAAO,MAAA,EAAQ;AAGjB,MAAA,MAAM,OAAA,GAAUA,OAAAA,CAAO,MAAA,CACpB,GAAA,CAAI,CAAC,CAAA,KAAM;AACV,QAAA,MAAM,IAAA,GAAA,CAAQ,EAAE,IAAA,IAAQ,IACrB,GAAA,CAAI,CAAC,QAAS,OAAO,GAAA,KAAQ,WAAW,MAAA,CAAO,GAAA,CAAI,GAAG,CAAA,GAAI,MAAA,CAAO,GAAG,CAAE,CAAA,CACtE,KAAK,GAAG,CAAA;AACX,QAAA,OAAO,OAAO,CAAA,EAAG,IAAI,KAAK,CAAA,CAAE,OAAO,KAAK,CAAA,CAAE,OAAA;AAAA,MAC5C,CAAC,CAAA,CACA,IAAA,CAAK,IAAI,CAAA;AACZ,MAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,OAAA,EAAQ;AAAA,IAC9B;AACA,IAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,IAAA,EAAMA,QAAO,KAAA,EAAM;AAAA,EACxC;AACA,EAAA,MAAM,MAAA,GAAS,MAAA,CAAO,SAAA,CAAU,KAAK,CAAA;AACrC,EAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,IAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,SAAS,MAAA,CAAO,KAAA,CAAM,WAAW,cAAA,EAAe;AAAA,EACtE;AACA,EAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,IAAA,EAAM,OAAO,IAAA,EAAK;AACvC;AAGA,SAAS,gBAAA,CAAiB,OAAe,IAAA,EAAoB;AAC3D,EAAA,IAAI,CAAC,oBAAoB,IAAA,CAAK,KAAK,KAAK,MAAA,CAAO,KAAK,KAAK,CAAA,EAAG;AAC1D,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,eAAA,EAAkB,IAAI,CAAA,4EAAA,EAA+E,KAAK,CAAA,CAAA;AAAA,KAC5G;AAAA,EACF;AACA,EAAA,IAAI,MAAA,CAAO,KAAK,CAAA,GAAI,sBAAA,EAAwB;AAC1C,IAAA,OAAA,CAAQ,IAAA;AAAA,MACN,CAAA,eAAA,EAAkB,IAAI,CAAA,SAAA,EAAY,KAAK,sBAAsB,sBAAsB,CAAA,gJAAA;AAAA,KAErF;AAAA,EACF;AACF;AAEO,IAAM,eAAN,MAAsC;AAAA,EAO3C,WAAA,CACmB,OAAA,EACA,OAAA,EACA,QAAA,EACjB;AAHiB,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AACA,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AACA,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AAAA,EAChB;AAAA,EAVK,SAAA;AAAA,EACA,UAAA;AAAA,EACA,WAAA;AAAA,EACA,YAAA;AAAA,EACA,MAAA,GAAS,KAAA;AAAA;AAAA,EASjB,KAAK,SAAA,EAAyB;AAC5B,IAAA,gBAAA,CAAiB,SAAA,EAAW,IAAA,CAAK,OAAA,CAAQ,IAAI,CAAA;AAC7C,IAAA,IAAA,CAAK,SAAA,GAAY,SAAA;AACjB,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AACd,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA,EAGA,WAAA,GAAoB;AAClB,IAAA,IAAA,CAAK,MAAA,GAAS,IAAA;AACd,IAAA,IAAA,CAAK,SAAA,GAAY,MAAA;AACjB,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,IAAA,CAAQ,QAAwB,UAAA,EAAuD;AACrF,IAAA,IAAA,CAAK,UAAA,GAAa,MAAA;AAClB,IAAA,IAAA,CAAK,WAAA,GAAc,UAAA;AACnB,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,SAAS,UAAA,EAA2C;AAClD,IAAA,IAAA,CAAK,YAAA,GAAe,UAAA;AACpB,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,QAAQ,EAAA,EAAwF;AAC9F,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,IAAU,CAAC,KAAK,SAAA,EAAW;AACnC,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,eAAA,EAAkB,IAAA,CAAK,OAAA,CAAQ,IAAI,CAAA,2DAAA;AAAA,OACrC;AAAA,IACF;AACA,IAAA,MAAM,UAAU,IAAA,CAAK,OAAA;AACrB,IAAA,MAAM,EAAE,IAAA,EAAM,WAAA,EAAY,GAAI,IAAA,CAAK,OAAA;AACnC,IAAA,MAAM,YAAY,IAAA,CAAK,SAAA;AACvB,IAAA,MAAM,aAAa,IAAA,CAAK,UAAA;AAExB,IAAA,MAAM,KAAA,IAAS,OAAO,GAAA,KAAoC;AACxD,MAAA,IAAI,GAAA,CAAI,WAAW,SAAA,EAAW;AAC5B,QAAA,OAAO,QAAA,CAAS,IAAI,QAAA,CAAS,IAAA,EAAM,EAAE,MAAA,EAAQ,GAAA,EAAK,CAAC,CAAA;AAAA,MACrD;AAKA,MAAA,IAAI,UAAA;AACJ,MAAA,IAAI,cAAA;AACJ,MAAA,IAAI,GAAA,CAAI,MAAA,KAAW,KAAA,IAAS,GAAA,CAAI,WAAW,MAAA,EAAQ;AACjD,QAAA,MAAM,IAAA,GAAO,MAAM,GAAA,CAAI,IAAA,EAAK;AAC5B,QAAA,IAAI,IAAA,CAAK,IAAA,EAAK,CAAE,MAAA,GAAS,CAAA,EAAG;AAC1B,UAAA,IAAI;AACF,YAAA,UAAA,GAAa,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,UAC9B,CAAA,CAAA,MAAQ;AACN,YAAA,cAAA,GAAiB,gCAAA;AAAA,UACnB;AAAA,QACF;AAAA,MACF;AAEA,MAAA,MAAM,QAAA,GAAA,CAAY,OAAA,CAAQ,OAAA,IAAW,IAAI,IAAI,GAAA,CAAI,GAAG,CAAA,CAAE,MAAA,EAAQ,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA,GAAI,IAAI,IAAI,CAAA,CAAA;AAE3F,MAAA,MAAM,UAAA,GAAa,OAAO,KAAA,KAAsC;AAC9D,QAAA,IAAI,SAAA,GAAqB,UAAA;AACzB,QAAA,IAAI,UAAA,EAAY;AAGd,UAAA,IAAI,cAAA,EAAgB;AAClB,YAAA,OAAO,KAAK,GAAA,EAAK,EAAE,OAAO,cAAA,EAAgB,IAAA,EAAM,OAAO,CAAA;AAAA,UACzD;AACA,UAAA,MAAM,SAAS,MAAM,YAAA,CAAa,UAAA,EAAY,UAAA,IAAc,EAAE,CAAA;AAC9D,UAAA,IAAI,CAAC,OAAO,EAAA,EAAI;AACd,YAAA,OAAO,IAAA,CAAK,KAAK,EAAE,KAAA,EAAO,OAAO,OAAA,EAAS,IAAA,EAAM,OAAO,CAAA;AAAA,UACzD;AACA,UAAA,SAAA,GAAY,MAAA,CAAO,IAAA;AAAA,QACrB;AACA,QAAA,MAAM,GAAA,GAAM,MAAM,EAAA,CAAG,EAAE,MAAM,SAAA,EAAoB,GAAA,EAAK,OAAO,CAAA;AAC7D,QAAA,IAAI,GAAA,YAAe,QAAA,EAAU,OAAO,QAAA,CAAS,GAAG,CAAA;AAChD,QAAA,OAAO,IAAA,CAAK,KAAK,GAAG,CAAA;AAAA,MACtB,CAAA;AAGA,MAAA,IAAI,CAAC,SAAA,EAAW;AACd,QAAA,IAAI;AACF,UAAA,OAAO,MAAM,UAAA,EAAW;AAAA,QAC1B,SAAS,GAAA,EAAK;AACZ,UAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,eAAA,EAAkB,IAAI,CAAA,iBAAA,CAAA,EAAqB,GAAG,CAAA;AAC5D,UAAA,OAAO,IAAA,CAAK,GAAA,EAAK,EAAE,KAAA,EAAO,kBAAkB,CAAA;AAAA,QAC9C;AAAA,MACF;AAEA,MAAA,MAAM,aAAA,GAAgB,GAAA,CAAI,OAAA,CAAQ,GAAA,CAAIF,2BAAmB,CAAA;AAMzD,MAAA,IAAI,CAAC,aAAA,EAAe;AAClB,QAAA,OAAO,MAAM,UAAA,CAAW,OAAA,EAAS,EAAE,QAAA,EAAU,WAAW,CAAA;AAAA,MAC1D;AAEA,MAAA,IAAIG,0BAAA,CAAmB,aAAa,CAAA,EAAG;AACrC,QAAA,OAAO,MAAM,WAAW,OAAA,EAAS;AAAA,UAC/B,QAAA;AAAA,UACA,SAAA;AAAA,UACA,KAAA,EACE;AAAA,SACH,CAAA;AAAA,MACH;AAKA,MAAA,IAAI,OAAA;AACJ,MAAA,IAAI;AACF,QAAA,OAAA,GAAUC,wBAAgB,aAAa,CAAA;AACvC,QAAAC,yBAAA,CAAkB;AAAA,UAChB,OAAA;AAAA,UACA,QAAA,EAAU;AAAA,YACR,WAAA,EAAa,QAAQ,OAAA,CAAQ,WAAA;AAAA,YAC7B,MAAA,EAAQ,SAAA;AAAA,YACR,UAAU,OAAA,CAAQ,QAAA;AAAA,YAClB,WAAW,OAAA,CAAQ,KAAA;AAAA,YACnB,SAAS,OAAA,CAAQ;AAAA;AACnB,SACD,CAAA;AAAA,MACH,SAAS,GAAA,EAAK;AACZ,QAAA,OAAO,MAAM,WAAW,OAAA,EAAS;AAAA,UAC/B,QAAA;AAAA,UACA,SAAA;AAAA,UACA,KAAA,EAAO,oBAAoB,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,SAC5E,CAAA;AAAA,MACH;AAKA,MAAA,MAAM,YAAA,GAAe,CAAA,UAAA,EAAa,OAAA,CAAQ,OAAA,CAAQ,WAAW,CAAA,CAAA;AAC7D,MAAA,IAAI,MAAM,OAAA,CAAQ,KAAA,CAAM,GAAA,CAAI,YAAY,CAAA,EAAG;AACzC,QAAA,OAAO,MAAM,WAAW,OAAA,EAAS;AAAA,UAC/B,QAAA;AAAA,UACA,SAAA;AAAA,UACA,KAAA,EAAO;AAAA,SACR,CAAA;AAAA,MACH;AAIA,MAAA,IAAI,MAAA;AACJ,MAAA,IAAI;AACF,QAAA,MAAA,GAAS,MAAM,UAAA,CAAW,OAAA,CAAQ,OAAA,CAAQ,aAAa,CAAA;AAAA,MACzD,SAAS,GAAA,EAAK;AACZ,QAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,eAAA,EAAkB,IAAI,CAAA,uCAAA,CAAA,EAA2C,GAAG,CAAA;AAClF,QAAA,OAAO,IAAA,CAAK,GAAA,EAAK,EAAE,KAAA,EAAO,8CAAyC,CAAA;AAAA,MACrE;AACA,MAAA,IAAI,MAAA,CAAO,MAAA,IAAU,GAAA,EAAK,OAAO,MAAA;AAIjC,MAAA,IAAI,MAAA;AACJ,MAAA,IAAI;AACF,QAAA,MAAA,GAAS,MAAMC,yBAAA,CAAkB;AAAA,UAC/B,OAAA;AAAA,UACA,MAAA,EAAQ,aAAA,CAAc,OAAA,CAAQ,OAAA,EAAS,QAAQ,MAAM,CAAA;AAAA,UACrD,OAAO,OAAA,CAAQ,KAAA;AAAA,UACf,QAAA,EAAU;AAAA,YACR,WAAA,EAAa,QAAQ,OAAA,CAAQ,WAAA;AAAA,YAC7B,MAAA,EAAQ,SAAA;AAAA,YACR,UAAU,OAAA,CAAQ,QAAA;AAAA,YAClB,WAAW,OAAA,CAAQ,KAAA;AAAA,YACnB,SAAS,OAAA,CAAQ;AAAA;AACnB,SACD,CAAA;AAAA,MACH,SAAS,GAAA,EAAK;AACZ,QAAA,OAAO,MAAM,WAAW,OAAA,EAAS;AAAA,UAC/B,QAAA;AAAA,UACA,SAAA;AAAA,UACA,KAAA,EAAO,sBAAsB,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,SAC9E,CAAA;AAAA,MACH;AAGA,MAAA,IAAI;AACF,QAAA,MAAM,OAAA,CAAQ,KAAA,CAAM,GAAA,CAAI,YAAY,CAAA;AAAA,MACtC,CAAA,CAAA,MAAQ;AAAA,MAER;AAEA,MAAA,MAAM,OAAA,GAAU,IAAI,OAAA,CAAQ,MAAA,CAAO,OAAO,CAAA;AAC1C,MAAA,OAAA,CAAQ,GAAA,CAAIL,oCAAA,EAA8BM,0BAAA,CAAmB,MAAM,CAAC,CAAA;AACpE,MAAA,OAAO,IAAI,SAAS,MAAA,CAAO,IAAA,EAAM,EAAE,MAAA,EAAQ,MAAA,CAAO,MAAA,EAAQ,OAAA,EAAS,CAAA;AAAA,IACrE,CAAA,CAAA;AAEA,IAAA,KAAA,CAAM,IAAA,GAAO;AAAA,MACX,IAAA;AAAA,MACA,SAAA;AAAA,MACA,WAAA;AAAA,MACA,UAAA;AAAA,MACA,aAAa,IAAA,CAAK,WAAA;AAAA,MAClB,cAAc,IAAA,CAAK;AAAA,KACrB;AACA,IAAA,IAAA,CAAK,SAAS,KAAK,CAAA;AACnB,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEA,eAAe,UAAA,CACb,SACA,IAAA,EACmB;AACnB,EAAA,IAAI;AACF,IAAA,MAAM,EAAE,OAAO,KAAA,EAAM,GAAI,MAAM,YAAA,CAAa,OAAA,CAAQ,OAAA,EAAS,OAAA,CAAQ,MAAM,CAAA;AAC3E,IAAA,MAAM,eAAeC,8BAAA,CAAuB;AAAA,MAC1C,WAAA,EAAa,OAAO,UAAA,EAAW;AAAA,MAC/B,QAAQ,IAAA,CAAK,SAAA;AAAA,MACb,UAAU,OAAA,CAAQ,QAAA;AAAA,MAClB,WAAW,OAAA,CAAQ,KAAA;AAAA,MACnB,UAAU,IAAA,CAAK,QAAA;AAAA,MACf,SAAS,OAAA,CAAQ,OAAA;AAAA,MACjB,KAAA;AAAA,MACA,YAAA,EAAc;AAAA,KACf,CAAA;AAKD,IAAA,MAAM,QAAQ,MAAM;AAClB,MAAA,IAAI;AACF,QAAA,OAAO,IAAI,GAAA,CAAI,IAAA,CAAK,QAAQ,CAAA,CAAE,QAAA;AAAA,MAChC,CAAA,CAAA,MAAQ;AACN,QAAA,OAAO,KAAA,CAAA;AAAA,MACT;AAAA,IACF,CAAA,GAAG;AACH,IAAA,MAAM,OAAA,GAAU,CAAA,eAAA,EAAkB,IAAA,IAAQ,MAAM,CAAA,cAAA,EAAiB,OAAA,CAAQ,KAAK,CAAA,aAAA,EAAgB,OAAA,CAAQ,QAAQ,CAAA,WAAA,EAAc,IAAA,CAAK,SAAS,CAAA,CAAA,CAAA;AAC1I,IAAA,OAAO,IAAA;AAAA,MACL,GAAA;AAAA,MACA;AAAA,QACE,WAAA,EAAaC,oBAAA;AAAA,QACb,KAAA,EAAO,KAAK,KAAA,IAAS,kBAAA;AAAA,QACrB,OAAA,EAAS,CAAC,YAAY;AAAA,OACxB;AAAA,MACA,EAAE,oBAAoB,OAAA;AAAQ,KAChC;AAAA,EACF,SAAS,GAAA,EAAK;AAGZ,IAAA,OAAA,CAAQ,KAAA,CAAM,0CAA0C,GAAG,CAAA;AAC3D,IAAA,OAAO,IAAA,CAAK,GAAA,EAAK,EAAE,KAAA,EAAO,6CAA6C,CAAA;AAAA,EACzE;AACF;ACvYA,IAAM,mBAAA,GAAsB,KAAK,EAAA,GAAK,EAAA;AACtC,IAAM,MAAA,GAAS,eAAA;AASR,IAAM,qBAAN,MAAgD;AAAA,EACpC,GAAA;AAAA,EACA,KAAA;AAAA,EACA,UAAA;AAAA,EAEjB,YAAY,OAAA,EAAoC;AAC9C,IAAA,IAAA,CAAK,GAAA,GAAM,OAAA,CAAQ,GAAA,CAAI,OAAA,CAAQ,OAAO,EAAE,CAAA;AACxC,IAAA,IAAA,CAAK,QAAQ,OAAA,CAAQ,KAAA;AACrB,IAAA,IAAA,CAAK,UAAA,GAAa,QAAQ,UAAA,IAAc,mBAAA;AAAA,EAC1C;AAAA,EAEA,MAAc,QAAQ,QAAA,EAAsC;AAC1D,IAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,CAAA,EAAG,KAAK,GAAG,CAAA,CAAA,EAAI,QAAA,CAAS,GAAA,CAAI,kBAAkB,CAAA,CAAE,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA,EAAI;AAAA,MACnF,SAAS,EAAE,aAAA,EAAe,CAAA,OAAA,EAAU,IAAA,CAAK,KAAK,CAAA,CAAA;AAAG,KAClD,CAAA;AACD,IAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,wBAAA,EAA2B,GAAA,CAAI,MAAM,IAAI,MAAM,GAAA,CAAI,IAAA,EAAM,CAAA,CAAE,CAAA;AAAA,IAC7E;AACA,IAAA,MAAM,IAAA,GAAQ,MAAM,GAAA,CAAI,IAAA,EAAK;AAC7B,IAAA,IAAI,IAAA,CAAK,OAAO,MAAM,IAAI,MAAM,CAAA,eAAA,EAAkB,IAAA,CAAK,KAAK,CAAA,CAAE,CAAA;AAC9D,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACd;AAAA,EAEA,MAAM,IAAI,MAAA,EAAkC;AAC1C,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,OAAA,CAAQ,CAAC,KAAA,EAAO,MAAA,GAAS,MAAM,CAAC,CAAA;AAC1D,IAAA,OAAO,MAAA,KAAW,QAAQ,MAAA,KAAW,MAAA;AAAA,EACvC;AAAA,EAEA,MAAM,IAAI,MAAA,EAA+B;AAGvC,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,OAAA,CAAQ;AAAA,MAChC,KAAA;AAAA,MACA,MAAA,GAAS,MAAA;AAAA,MACT,GAAA;AAAA,MACA,IAAA;AAAA,MACA,MAAA,CAAO,KAAK,UAAU,CAAA;AAAA,MACtB;AAAA,KACD,CAAA;AACD,IAAA,IAAI,MAAA,KAAW,IAAA,IAAQ,MAAA,KAAW,MAAA,EAAW;AAC3C,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,qBAAA,EAAwB,MAAM,CAAA,CAAE,CAAA;AAAA,IAClD;AAAA,EACF;AACF;;;AC/DO,IAAM,QAAN,MAAY;AAAA,EACA,OAAA;AAAA;AAAA,EAER,MAAA,uBAAa,GAAA,EAAwB;AAAA,EAErC,KAAA;AAAA,EACA,OAAA;AAAA,EACA,IAAA;AAAA,EACA,WAAA;AAAA,EACA,OAAA;AAAA,EAET,YAAY,MAAA,EAAqB;AAC/B,IAAA,IAAI,CAAC,MAAA,CAAO,KAAA,IAAS,CAACC,uBAAA,CAAkB,MAAA,CAAO,KAAK,CAAA,EAAG;AACrD,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,qFAAA,EAAwF,OAAO,KAAK,CAAA,CAAA;AAAA,OACtG;AAAA,IACF;AACA,IAAA,IAAA,CAAK,KAAA,GAAQC,yBAAA,CAAoB,MAAA,CAAO,KAAK,CAAA;AAC7C,IAAA,IAAA,CAAK,OAAA,GAAU,OAAO,OAAA,IAAW,SAAA;AACjC,IAAA,IAAA,CAAK,OAAO,MAAA,CAAO,IAAA;AACnB,IAAA,IAAA,CAAK,cAAc,MAAA,CAAO,WAAA;AAC1B,IAAA,IAAA,CAAK,OAAA,GAAU,MAAA,CAAO,OAAA,EAAS,OAAA,CAAQ,OAAO,EAAE,CAAA;AAEhD,IAAA,MAAM,QAAA,GAAqB,IAAA,CAAK,OAAA,KAAY,SAAA,GAAYd,oBAAAA,GAAeC,YAAAA;AACvE,IAAA,IAAA,CAAK,OAAA,GAAU;AAAA,MACb,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,QAAA;AAAA,MACA,KAAA,EAAO,MAAA,CAAO,KAAA,IAAS,IAAIc,2BAAAA,EAAoB;AAAA,MAC/C,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,QAAQ,MAAA,CAAO;AAAA,KACjB;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,OAAA,EAAqC;AACzC,IAAA,MAAM,IAAA,GAAO,QAAQ,IAAA,CAAK,OAAA,CAAQ,QAAQ,EAAE,CAAA,CAAE,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAA;AAChE,IAAA,IAAI,CAAC,IAAA,EAAM,MAAM,IAAI,MAAM,sCAAsC,CAAA;AACjE,IAAA,OAAO,IAAI,YAAA,CAAa,EAAE,GAAG,IAAA,CAAK,OAAA,EAAQ,EAAG,EAAE,GAAG,OAAA,EAAS,IAAA,EAAK,EAAG,CAAC,KAAA,KAAU;AAC5E,MAAA,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,IAAA,EAAM,KAAK,CAAA;AAAA,IAC7B,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAA,GAAsC;AACpC,IAAA,OAAO,CAAC,GAAA,KACN,IAAI,QAAA,CAAS,IAAA,CAAK,UAAU,oBAAA,CAAqB,IAAA,EAAM,IAAI,GAAA,CAAI,IAAI,GAAG,CAAA,CAAE,MAAM,CAAA,EAAG,IAAA,EAAM,CAAC,CAAA,EAAG;AAAA,MACzF,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAoB,+BAA+B,GAAA;AAAI,KACnF,CAAA;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAA,GAAmC;AACjC,IAAA,OAAO,CAAC,GAAA,KACN,IAAI,QAAA,CAAS,YAAA,CAAa,IAAA,EAAM,IAAI,GAAA,CAAI,GAAA,CAAI,GAAG,CAAA,CAAE,MAAM,CAAA,EAAG;AAAA,MACxD,OAAA,EAAS,EAAE,cAAA,EAAgB,2BAAA,EAA6B,+BAA+B,GAAA;AAAI,KAC5F,CAAA;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWS,KAAA,GAAQ,OAAO,GAAA,KAAoC;AAC1D,IAAA,MAAM,QAAA,GAAW,IAAI,GAAA,CAAI,GAAA,CAAI,GAAG,CAAA,CAAE,QAAA,CAAS,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAA,CAAE,OAAA,CAAQ,QAAQ,EAAE,CAAA;AACjF,IAAA,IAAI,aAAa,cAAA,EAAgB,OAAO,IAAA,CAAK,OAAA,GAAU,GAAG,CAAA;AAC1D,IAAA,IAAI,aAAa,UAAA,EAAY,OAAO,IAAA,CAAK,IAAA,GAAO,GAAG,CAAA;AACnD,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,QAAQ,CAAA;AACtC,IAAA,IAAI,KAAA,EAAO,OAAO,KAAA,CAAM,GAAG,CAAA;AAC3B,IAAA,OAAO,IAAI,QAAA;AAAA,MACT,IAAA,CAAK,SAAA,CAAU,EAAE,KAAA,EAAO,WAAA,EAAa,WAAW,CAAC,eAAA,EAAiB,WAAW,CAAA,EAAG,CAAA;AAAA,MAChF,EAAE,MAAA,EAAQ,GAAA,EAAK,SAAS,EAAE,cAAA,EAAgB,oBAAmB;AAAE,KACjE;AAAA,EACF,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,qBAAqB,WAAA,EAA8B;AACjD,IAAA,MAAM,QAAQ,WAAA,IAAe,IAAA,CAAK,WAAW,6BAAA,EAA+B,OAAA,CAAQ,OAAO,EAAE,CAAA;AAC7F,IAAA,MAAM,SAAA,GAAY,CAAC,GAAG,IAAA,CAAK,MAAA,CAAO,MAAA,EAAQ,CAAA,CAAE,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,KAAK,SAAS,CAAA;AAC1E,IAAA,MAAM,OAAA,GAAU,SAAA,CAAU,CAAC,CAAA,EAAG,KAAK,IAAA,IAAQ,SAAA;AAC3C,IAAA,OAAO;AAAA,MACL,uEAAA;AAAA,MACA,CAAA,0BAAA,EAA6B,IAAI,CAAA,CAAA,EAAI,OAAO,CAAA,CAAA;AAAA,MAC5C;AAAA,KACF,CAAE,KAAK,IAAI,CAAA;AAAA,EACb;AACF;AAEO,SAAS,YAAY,MAAA,EAA4B;AACtD,EAAA,OAAO,IAAI,MAAM,MAAM,CAAA;AACzB;AAkBO,SAAS,kBAAA,CAAmB,GAAA,GAA0C,OAAA,CAAQ,GAAA,EAAY;AAC/F,EAAA,MAAM,IAAA,GAAO,CAAC,GAAA,KAAoC;AAChD,IAAA,MAAM,CAAA,GAAI,GAAA,CAAI,GAAG,CAAA,EAAG,IAAA,EAAK;AACzB,IAAA,OAAO,CAAA,IAAK,CAAA,CAAE,MAAA,GAAS,CAAA,GAAI,CAAA,GAAI,MAAA;AAAA,EACjC,CAAA;AAEA,EAAA,MAAM,KAAA,GAAQ,KAAK,cAAc,CAAA;AACjC,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AAEA,EAAA,MAAM,OAAA,GAAU,KAAK,eAAe,CAAA;AACpC,EAAA,IAAI,OAAA,IAAW,OAAA,KAAY,SAAA,IAAa,OAAA,KAAY,SAAA,EAAW;AAC7D,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,2DAAA,EAA8D,OAAO,CAAA,CAAA,CAAG,CAAA;AAAA,EAC1F;AAEA,EAAA,MAAM,KAAA,GAAQ,KAAK,iBAAiB,CAAA;AACpC,EAAA,MAAM,OAAA,GAAU,KAAK,mBAAmB,CAAA;AACxC,EAAA,MAAM,KAAA,GACJ,KAAA,IAAS,OAAA,GAAU,IAAI,kBAAA,CAAmB,EAAE,GAAA,EAAK,KAAA,EAAO,KAAA,EAAO,OAAA,EAAS,CAAA,GAAI,MAAA;AAE9E,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,OAAA,CAAQ,IAAA;AAAA,MACN;AAAA,KAEF;AAAA,EACF;AAEA,EAAA,OAAO,IAAI,KAAA,CAAM;AAAA,IACf,KAAA;AAAA,IACA,SAAU,OAAA,IAAwC,SAAA;AAAA,IAClD,OAAA,EAAS,KAAK,gBAAgB,CAAA;AAAA,IAC9B,IAAA,EAAM,KAAK,YAAY,CAAA;AAAA,IACvB,WAAA,EAAa,KAAK,mBAAmB,CAAA;AAAA,IACrC;AAAA,GACD,CAAA;AACH;;;AClKO,SAAS,YAAY,KAAA,EAG1B;AACA,EAAA,OAAO,EAAE,IAAA,EAAM,KAAA,EAAO,OAAA,EAAS,KAAA,EAAM;AACvC","file":"index.cjs","sourcesContent":["import { USDC, USDC_TESTNET } from '@t2000/sui-x402';\nimport type { Serve } from './serve.js';\n\n// ---------------------------------------------------------------------------\n// Discovery docs — /openapi.json + /llms.txt.\n//\n// The shapes here are what the on-chain listing probe grades (the check\n// behind `t2 agent sell`) (was: apps/gateway/lib/\n// catalog-ingest.ts `gradeListing`): a warning-free listing needs info.title,\n// a one-paragraph info.description, a flat string `x-payment-info.price` per\n// paid operation, and an application/json requestBody schema with typed\n// properties. Everything serve can derive is emitted automatically; the JSON\n// request schema comes from the route's `inputSchema` (zod v4 users:\n// `z.toJSONSchema(schema)`).\n// ---------------------------------------------------------------------------\n\nexport function buildOpenApiDocument(serve: Serve, origin?: string): Record<string, unknown> {\n const base = serve.baseUrl ?? origin;\n const paths: Record<string, unknown> = {};\n\n for (const route of serve.routes.values()) {\n const { path, priceUsdc, description, inputSchema, outputSchema } = route.meta;\n const operation: Record<string, unknown> = {\n operationId: path.replace(/[^a-zA-Z0-9]+/g, '_'),\n summary: description ?? path,\n responses: {\n '200': outputSchema\n ? {\n description: 'Success',\n content: { 'application/json': { schema: outputSchema } },\n }\n : { description: 'Success' },\n ...(priceUsdc\n ? {\n '402': {\n description:\n 'Payment required — the body carries an x402 accepts[] envelope (scheme \"exact\", network sui). Sign it and retry with the X-PAYMENT header.',\n },\n }\n : {}),\n '422': { description: 'Invalid request body — never charged' },\n },\n };\n if (priceUsdc) {\n // Same shape the gateway's own /openapi.json emits: 'mpp' is the\n // protocol family, 'x402' the dialect; the x402 block mirrors the\n // static half of the live accepts[] entry (dynamic fields ride the 402).\n operation['x-payment-info'] = {\n pricingMode: 'fixed',\n price: priceUsdc,\n currency: 'USDC',\n protocols: ['mpp', 'x402'],\n x402: {\n scheme: 'exact',\n network: `sui:${serve.network}`,\n asset: (serve.network === 'testnet' ? USDC_TESTNET : USDC).type,\n payTo: serve.payTo,\n },\n };\n }\n if (inputSchema) {\n operation.requestBody = {\n required: true,\n content: { 'application/json': { schema: inputSchema } },\n };\n }\n paths[`/${path}`] = { post: operation };\n }\n\n return {\n openapi: '3.1.0',\n info: {\n title: serve.name ?? 'Paid API',\n version: '1.0.0',\n description:\n serve.description ??\n 'Agent-payable API. Every paid endpoint answers 402 with an x402 accepts[] envelope; payment settles in USDC on Sui.',\n },\n ...(base ? { servers: [{ url: base }] } : {}),\n paths,\n };\n}\n\nexport function buildLlmsTxt(serve: Serve, origin?: string): string {\n const base = serve.baseUrl ?? origin ?? '';\n const lines: string[] = [];\n lines.push(`# ${serve.name ?? 'Paid API'}`);\n lines.push('');\n if (serve.description) {\n lines.push(serve.description);\n lines.push('');\n }\n lines.push('## How to pay');\n lines.push('');\n lines.push(\n 'Endpoints below are paid per call in USDC on Sui (x402). An unpaid request returns',\n 'HTTP 402 with an `accepts[]` envelope; sign it and retry with the `X-PAYMENT` header.',\n 'Invalid input returns 422 before any payment is taken. A failed call is never charged.',\n '',\n 'Easiest client: `npm i -g @t2000/cli` then `t2 pay <url> --data \\'{...}\\'`,',\n 'or the t2000 MCP server (`t2000_pay`), or `@t2000/sdk` `pay()`.',\n '',\n );\n lines.push('## Endpoints');\n lines.push('');\n for (const route of serve.routes.values()) {\n const { path, priceUsdc, description, inputSchema, outputSchema } = route.meta;\n const price = priceUsdc ? `${priceUsdc} USDC per call` : 'free';\n lines.push(`### POST ${base}/${path} — ${price}`);\n if (description) lines.push(description);\n if (inputSchema) {\n lines.push('Request body (JSON Schema):');\n lines.push('```json');\n lines.push(JSON.stringify(inputSchema, null, 2));\n lines.push('```');\n }\n if (outputSchema) {\n lines.push('Response (JSON Schema — contentMediaType/format annotations name the deliverable types):');\n lines.push('```json');\n lines.push(JSON.stringify(outputSchema, null, 2));\n lines.push('```');\n }\n lines.push('');\n }\n lines.push(`Discovery: ${base}/openapi.json`);\n return lines.join('\\n');\n}\n","import { SuiGrpcClient } from '@mysten/sui/grpc';\nimport type { ServeNetwork } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Chain plumbing — same shape as the gateway's x402-dialect.ts (the reference\n// composition). All reads are gRPC; this package never touches JSON-RPC.\n//\n// Cache policy: the chain identifier (genesis digest) is immutable per\n// network — cached forever. The epoch advances ~daily and x402 requirements\n// are valid for [epoch, epoch+1], so a 10-minute TTL is conservatively fresh.\n// ---------------------------------------------------------------------------\n\nconst FULLNODE_URLS: Record<ServeNetwork, string> = {\n mainnet: 'https://fullnode.mainnet.sui.io:443',\n testnet: 'https://fullnode.testnet.sui.io:443',\n};\n\nconst EPOCH_TTL_MS = 10 * 60 * 1000;\n\nexport interface ChainInfo {\n chain: string;\n epoch: string;\n}\n\ninterface ChainState {\n client?: SuiGrpcClient;\n chainId?: string;\n epoch?: { value: string; fetchedAt: number };\n}\n\nconst state: Partial<Record<ServeNetwork, ChainState>> = {};\n\nexport function getGrpcClient(network: ServeNetwork, rpcUrl?: string): SuiGrpcClient {\n const s = (state[network] ??= {});\n if (!s.client) {\n s.client = new SuiGrpcClient({\n baseUrl: rpcUrl ?? FULLNODE_URLS[network],\n network,\n });\n }\n return s.client;\n}\n\nexport async function getChainInfo(network: ServeNetwork, rpcUrl?: string): Promise<ChainInfo> {\n const client = getGrpcClient(network, rpcUrl);\n const s = (state[network] ??= {});\n if (!s.chainId) {\n const res = await client.core.getChainIdentifier();\n s.chainId = res.chainIdentifier;\n }\n if (!s.epoch || Date.now() - s.epoch.fetchedAt > EPOCH_TTL_MS) {\n const res = await client.core.getCurrentSystemState();\n s.epoch = { value: String(res.systemState.epoch), fetchedAt: Date.now() };\n }\n return { chain: s.chainId, epoch: s.epoch.value };\n}\n\n/** Test seam — reset module caches between cases. */\nexport function __resetChainCaches(): void {\n delete state.mainnet;\n delete state.testnet;\n}\n\n/** Test seam — pre-seed chain info so tests never hit the network. */\nexport function __seedChainInfo(network: ServeNetwork, chain: string, epoch: string): void {\n const s = (state[network] ??= {});\n s.chainId = chain;\n s.epoch = { value: epoch, fetchedAt: Date.now() };\n}\n","import type { Currency, DigestStore } from '@t2000/sui-x402';\nimport {\n createX402Requirements,\n encodeX402Response,\n isX402EscrowHeader,\n parseX402Header,\n settleX402Payment,\n verifyX402Payment,\n X402_PAYMENT_HEADER,\n X402_PAYMENT_RESPONSE_HEADER,\n X402_VERSION,\n type X402SettleResponse,\n} from '@t2000/sui-x402';\nimport { getChainInfo, getGrpcClient } from './chain.js';\nimport type {\n BuiltRoute,\n HandlerContext,\n HandlerResult,\n ServeNetwork,\n ServeSchema,\n StandardSchemaLike,\n} from './types.js';\n\n// ---------------------------------------------------------------------------\n// The paid-request lifecycle (SPEC_T2000_SERVE §3 — sign-then-settle,\n// handler-then-settle):\n//\n// no X-PAYMENT → 402 with the accepts[] envelope (never a charge;\n// the catalog probe and every discovery tool read\n// this, so it fires BEFORE body validation)\n// X-PAYMENT present:\n// 1. parse + STRUCTURAL verify (right amount/recipient/nonce — no RPC)\n// 2. challenge-once check (a signed payload is single-use)\n// 3. validate the body — invalid → 422, payment NEVER submitted\n// (the JMPR paid-422 class is impossible: the buyer keeps their money)\n// 4. run the handler — throws → 500, payment NEVER submitted\n// 5. settle (submit the buyer-signed gasless bytes; digest-once inside)\n// 6. consume the challenge, attach the X-PAYMENT-RESPONSE receipt\n//\n// Money only moves at step 5, after the seller has already produced the\n// result. A forged payload can waste seller compute (signature authority is\n// the chain at settle time), never buyer money.\n// ---------------------------------------------------------------------------\n\nexport interface RouteRuntime {\n payTo: string;\n network: ServeNetwork;\n currency: Currency;\n store: DigestStore;\n baseUrl?: string;\n rpcUrl?: string;\n}\n\nexport interface RouteOptions {\n path: string;\n description?: string;\n}\n\n/** Sanity cap on a per-call price — above this, the work is job-shaped\n * (escrow) rather than a per-call x402 Service. */\nconst CATALOG_PRICE_CAP_USDC = 5;\n\nconst CORS_HEADERS: Record<string, string> = {\n 'access-control-allow-origin': '*',\n 'access-control-allow-methods': 'GET, POST, PUT, DELETE, OPTIONS',\n 'access-control-allow-headers': `content-type, ${X402_PAYMENT_HEADER}`,\n 'access-control-expose-headers': `${X402_PAYMENT_RESPONSE_HEADER}, WWW-Authenticate`,\n};\n\nfunction withCors(response: Response): Response {\n const headers = new Headers(response.headers);\n for (const [k, v] of Object.entries(CORS_HEADERS)) headers.set(k, v);\n return new Response(response.body, { status: response.status, headers });\n}\n\nfunction json(status: number, body: unknown, headers?: Record<string, string>): Response {\n return withCors(\n new Response(JSON.stringify(body), {\n status,\n headers: { 'content-type': 'application/json', ...headers },\n }),\n );\n}\n\nfunction isStandardSchema(schema: ServeSchema): schema is StandardSchemaLike {\n return typeof schema === 'object' && schema !== null && '~standard' in schema;\n}\n\nasync function validateBody(\n schema: ServeSchema,\n value: unknown,\n): Promise<{ ok: true; data: unknown } | { ok: false; message: string }> {\n if (isStandardSchema(schema)) {\n const result = await schema['~standard'].validate(value);\n if (result.issues) {\n // Name the failing field — bare \"Invalid input\" ×N gives a paying\n // buyer's agent nothing to self-correct with.\n const message = result.issues\n .map((i) => {\n const path = (i.path ?? [])\n .map((seg) => (typeof seg === 'object' ? String(seg.key) : String(seg)))\n .join('.');\n return path ? `${path}: ${i.message}` : i.message;\n })\n .join('; ');\n return { ok: false, message };\n }\n return { ok: true, data: result.value };\n }\n const result = schema.safeParse(value);\n if (!result.success) {\n return { ok: false, message: result.error.message ?? 'invalid body' };\n }\n return { ok: true, data: result.data };\n}\n\n/** Positive decimal USDC string, max 6dp (atomic precision). */\nfunction assertValidPrice(price: string, path: string): void {\n if (!/^\\d+(\\.\\d{1,6})?$/.test(price) || Number(price) <= 0) {\n throw new Error(\n `[serve] Route \"${path}\": price must be a positive decimal USDC string with up to 6 decimals, got \"${price}\"`,\n );\n }\n if (Number(price) > CATALOG_PRICE_CAP_USDC) {\n console.warn(\n `[serve] Route \"${path}\": price ${price} USDC is above the ${CATALOG_PRICE_CAP_USDC} USDC listing cap — ` +\n 'the route works, but per-call x402 is the wrong shape for it. Job-class work belongs in `t2 service create` (escrow).',\n );\n }\n}\n\nexport class RouteBuilder<TBody = undefined> {\n private priceUsdc?: string;\n private bodySchema?: ServeSchema;\n private inputSchema?: Record<string, unknown>;\n private outputSchema?: Record<string, unknown>;\n private isFree = false;\n\n constructor(\n private readonly runtime: RouteRuntime,\n private readonly options: RouteOptions,\n private readonly register: (route: BuiltRoute) => void,\n ) {}\n\n /** Charge this many USDC per call (human units, e.g. \"0.01\"). */\n paid(priceUsdc: string): this {\n assertValidPrice(priceUsdc, this.options.path);\n this.priceUsdc = priceUsdc;\n this.isFree = false;\n return this;\n }\n\n /** Serve without payment (health checks, previews, docs). */\n unprotected(): this {\n this.isFree = true;\n this.priceUsdc = undefined;\n return this;\n }\n\n /**\n * Validate the JSON request body. zod v4 / valibot / arktype / anything\n * Standard-Schema, or anything with a zod-style safeParse.\n *\n * Pass the JSON Schema as the second argument to publish it in\n * /openapi.json + /llms.txt (zod v4: `z.toJSONSchema(schema)`) — buyers'\n * agents build request bodies from it, and the catalog grades listings\n * without one.\n */\n body<T>(schema: ServeSchema<T>, jsonSchema?: Record<string, unknown>): RouteBuilder<T> {\n this.bodySchema = schema;\n this.inputSchema = jsonSchema;\n return this as unknown as RouteBuilder<T>;\n }\n\n /**\n * Declare the 200 response's JSON Schema (zod v4: `z.toJSONSchema(schema)`).\n * Published in /openapi.json + /llms.txt so buyer agents know what they're\n * buying and buyer UIs can render the deliverable by TYPE instead of\n * sniffing it — annotate with `contentMediaType` (e.g. \"image/svg+xml\",\n * \"text/markdown\") and `format: \"color\"` where they apply. Declaration\n * only; responses are never validated at runtime.\n */\n response(jsonSchema: Record<string, unknown>): this {\n this.outputSchema = jsonSchema;\n return this;\n }\n\n handler(fn: (ctx: HandlerContext<TBody>) => HandlerResult | Promise<HandlerResult>): BuiltRoute {\n if (!this.isFree && !this.priceUsdc) {\n throw new Error(\n `[serve] Route \"${this.options.path}\": call .paid('<usdc>') or .unprotected() before .handler()`,\n );\n }\n const runtime = this.runtime;\n const { path, description } = this.options;\n const priceUsdc = this.priceUsdc;\n const bodySchema = this.bodySchema;\n\n const route = (async (req: Request): Promise<Response> => {\n if (req.method === 'OPTIONS') {\n return withCors(new Response(null, { status: 204 }));\n }\n\n // Read + parse the body once, up front. A missing/empty body on a\n // schema-less route is fine; JSON parse failures only matter when a\n // paid request must be validated (the unpaid 402 fires regardless).\n let parsedBody: unknown;\n let bodyParseError: string | undefined;\n if (req.method !== 'GET' && req.method !== 'HEAD') {\n const text = await req.text();\n if (text.trim().length > 0) {\n try {\n parsedBody = JSON.parse(text);\n } catch {\n bodyParseError = 'request body is not valid JSON';\n }\n }\n }\n\n const resource = (runtime.baseUrl ?? new URL(req.url).origin).replace(/\\/$/, '') + `/${path}`;\n\n const runHandler = async (payer?: string): Promise<Response> => {\n let validated: unknown = parsedBody;\n if (bodySchema) {\n // `paid: false` is machine-readable charge honesty — a 422 fires\n // BEFORE settlement, so the buyer always keeps their money.\n if (bodyParseError) {\n return json(422, { error: bodyParseError, paid: false });\n }\n const result = await validateBody(bodySchema, parsedBody ?? {});\n if (!result.ok) {\n return json(422, { error: result.message, paid: false });\n }\n validated = result.data;\n }\n const out = await fn({ body: validated as TBody, req, payer });\n if (out instanceof Response) return withCors(out);\n return json(200, out);\n };\n\n // Free route — no payment machinery at all.\n if (!priceUsdc) {\n try {\n return await runHandler();\n } catch (err) {\n console.error(`[serve] Route \"${path}\" handler failed:`, err);\n return json(500, { error: 'internal error' });\n }\n }\n\n const paymentHeader = req.headers.get(X402_PAYMENT_HEADER);\n\n // Unpaid → 402 with the accepts[] envelope. This fires before body\n // validation on purpose: the catalog probe (and every discovery tool)\n // POSTs `{}` and must see the challenge, and an unpaid request can\n // never be charged, so there is nothing to protect yet.\n if (!paymentHeader) {\n return await respond402(runtime, { resource, priceUsdc });\n }\n\n if (isX402EscrowHeader(paymentHeader)) {\n return await respond402(runtime, {\n resource,\n priceUsdc,\n error:\n 'this endpoint sells instant per-call work (settle-then-serve), not escrow jobs — retry with a signed x402 payment',\n });\n }\n\n // 1. Parse + structural verify — right terms, right recipient, right\n // nonce. No RPC, no state. Wrong-terms payloads never reach the\n // handler.\n let payment: ReturnType<typeof parseX402Header>;\n try {\n payment = parseX402Header(paymentHeader);\n verifyX402Payment({\n payment,\n expected: {\n challengeId: payment.payload.challengeId,\n amount: priceUsdc,\n currency: runtime.currency,\n recipient: runtime.payTo,\n network: runtime.network,\n },\n });\n } catch (err) {\n return await respond402(runtime, {\n resource,\n priceUsdc,\n error: `invalid payment: ${err instanceof Error ? err.message : String(err)}`,\n });\n }\n\n // 2. Challenge-once — a signed payload is single-use even before it\n // settles (the settled digest is separately consumed inside\n // settleX402Payment, digest-once).\n const challengeKey = `challenge:${payment.payload.challengeId}`;\n if (await runtime.store.has(challengeKey)) {\n return await respond402(runtime, {\n resource,\n priceUsdc,\n error: 'payment challenge already used — sign a fresh payment',\n });\n }\n\n // 3 + 4. Validate, then compute the result. Any failure here returns\n // WITHOUT settling — the buyer-signed bytes are never submitted.\n let served: Response;\n try {\n served = await runHandler(payment.payload.senderAddress);\n } catch (err) {\n console.error(`[serve] Route \"${path}\" handler failed (payment NOT settled):`, err);\n return json(500, { error: 'internal error — you were not charged' });\n }\n if (served.status >= 400) return served; // 422 etc. — not charged\n\n // 5. Settle — submit the buyer-signed gasless bytes, confirm the\n // on-chain balance change, record the digest (digest-once).\n let settle: X402SettleResponse;\n try {\n settle = await settleX402Payment({\n payment,\n client: getGrpcClient(runtime.network, runtime.rpcUrl),\n store: runtime.store,\n expected: {\n challengeId: payment.payload.challengeId,\n amount: priceUsdc,\n currency: runtime.currency,\n recipient: runtime.payTo,\n network: runtime.network,\n },\n });\n } catch (err) {\n return await respond402(runtime, {\n resource,\n priceUsdc,\n error: `settlement failed: ${err instanceof Error ? err.message : String(err)}`,\n });\n }\n\n // 6. Consume the challenge + attach the receipt.\n try {\n await runtime.store.set(challengeKey);\n } catch {\n // Digest-once already holds; challenge-once is defense in depth.\n }\n\n const headers = new Headers(served.headers);\n headers.set(X402_PAYMENT_RESPONSE_HEADER, encodeX402Response(settle));\n return new Response(served.body, { status: served.status, headers });\n }) as BuiltRoute;\n\n route.meta = {\n path,\n priceUsdc,\n description,\n bodySchema,\n inputSchema: this.inputSchema,\n outputSchema: this.outputSchema,\n };\n this.register(route);\n return route;\n }\n}\n\nasync function respond402(\n runtime: RouteRuntime,\n args: { resource: string; priceUsdc: string; error?: string },\n): Promise<Response> {\n try {\n const { chain, epoch } = await getChainInfo(runtime.network, runtime.rpcUrl);\n const requirements = createX402Requirements({\n challengeId: crypto.randomUUID(),\n amount: args.priceUsdc,\n currency: runtime.currency,\n recipient: runtime.payTo,\n resource: args.resource,\n network: runtime.network,\n chain,\n currentEpoch: epoch,\n });\n // Belt-and-suspenders for pre-0.2.2 discovery clients and dual-dialect\n // consumers: mirror the challenge into the MPP WWW-Authenticate shape.\n // The accepts[] body stays the authoritative envelope — the header carries\n // the same recipient/currency and the DECIMAL amount that dialect uses.\n const host = (() => {\n try {\n return new URL(args.resource).hostname;\n } catch {\n return undefined;\n }\n })();\n const wwwAuth = `Payment realm=\"${host ?? 'x402'}\", recipient=\"${runtime.payTo}\", currency=\"${runtime.currency}\", amount=\"${args.priceUsdc}\"`;\n return json(\n 402,\n {\n x402Version: X402_VERSION,\n error: args.error ?? 'Payment required',\n accepts: [requirements],\n },\n { 'WWW-Authenticate': wwwAuth },\n );\n } catch (err) {\n // Chain info unreachable — a 402 without the envelope is unpayable, so\n // be honest about the outage instead of serving a dead challenge.\n console.error('[serve] failed to build 402 challenge:', err);\n return json(503, { error: 'payment challenge temporarily unavailable' });\n }\n}\n\n","import type { DigestStore } from '@t2000/sui-x402';\n\nexport { InMemoryDigestStore } from '@t2000/sui-x402';\nexport type { DigestStore } from '@t2000/sui-x402';\n\n// ---------------------------------------------------------------------------\n// Upstash-REST digest store — the production replay store for serverless\n// hosts. Mirrors the gateway's upstash-digest-store.ts but speaks the\n// Upstash REST API over plain fetch (no @upstash/redis dependency).\n//\n// TTL: 72h. x402 payments are chain-valid for the whole ValidDuring window\n// ([minEpoch, minEpoch+1] ≈ up to ~48h on mainnet). Sui resubmission of an\n// executed tx is idempotent, so if the digest/challenge keys expired BEFORE\n// the window closed, a replayed X-PAYMENT would re-settle \"successfully\"\n// and serve again on a single payment. 72h > max window + drift.\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_TTL_SECONDS = 72 * 60 * 60;\nconst PREFIX = 'serve:digest:';\n\nexport interface UpstashDigestStoreOptions {\n url: string;\n token: string;\n /** Key TTL in seconds. Default 72h — do not lower below ~50h (see above). */\n ttlSeconds?: number;\n}\n\nexport class UpstashDigestStore implements DigestStore {\n private readonly url: string;\n private readonly token: string;\n private readonly ttlSeconds: number;\n\n constructor(options: UpstashDigestStoreOptions) {\n this.url = options.url.replace(/\\/$/, '');\n this.token = options.token;\n this.ttlSeconds = options.ttlSeconds ?? DEFAULT_TTL_SECONDS;\n }\n\n private async command(segments: string[]): Promise<unknown> {\n const res = await fetch(`${this.url}/${segments.map(encodeURIComponent).join('/')}`, {\n headers: { authorization: `Bearer ${this.token}` },\n });\n if (!res.ok) {\n throw new Error(`Upstash command failed: ${res.status} ${await res.text()}`);\n }\n const body = (await res.json()) as { result?: unknown; error?: string };\n if (body.error) throw new Error(`Upstash error: ${body.error}`);\n return body.result;\n }\n\n async has(digest: string): Promise<boolean> {\n const result = await this.command(['GET', PREFIX + digest]);\n return result !== null && result !== undefined;\n }\n\n async set(digest: string): Promise<void> {\n // SET key 1 EX <ttl> NX — atomic set-if-absent. A null result means the\n // key already existed: the digest (or challenge) was already consumed.\n const result = await this.command([\n 'SET',\n PREFIX + digest,\n '1',\n 'EX',\n String(this.ttlSeconds),\n 'NX',\n ]);\n if (result === null || result === undefined) {\n throw new Error(`Digest already used: ${digest}`);\n }\n }\n}\n","import { isValidSuiAddress, normalizeSuiAddress } from '@mysten/sui/utils';\nimport { InMemoryDigestStore, USDC, USDC_TESTNET, type Currency } from '@t2000/sui-x402';\nimport { buildLlmsTxt, buildOpenApiDocument } from './discovery.js';\nimport { RouteBuilder, type RouteOptions, type RouteRuntime } from './route.js';\nimport { UpstashDigestStore } from './store.js';\nimport type { BuiltRoute, ServeConfig, ServeNetwork } from './types.js';\n\nexport class Serve {\n private readonly runtime: RouteRuntime;\n /** Every route built through this instance, keyed by path (discovery). */\n readonly routes = new Map<string, BuiltRoute>();\n\n readonly payTo: string;\n readonly network: ServeNetwork;\n readonly name?: string;\n readonly description?: string;\n readonly baseUrl?: string;\n\n constructor(config: ServeConfig) {\n if (!config.payTo || !isValidSuiAddress(config.payTo)) {\n throw new Error(\n `[serve] payTo must be a valid Sui address (the wallet your payments settle to), got \"${config.payTo}\"`,\n );\n }\n this.payTo = normalizeSuiAddress(config.payTo);\n this.network = config.network ?? 'mainnet';\n this.name = config.name;\n this.description = config.description;\n this.baseUrl = config.baseUrl?.replace(/\\/$/, '');\n\n const currency: Currency = this.network === 'testnet' ? USDC_TESTNET : USDC;\n this.runtime = {\n payTo: this.payTo,\n network: this.network,\n currency,\n store: config.store ?? new InMemoryDigestStore(),\n baseUrl: this.baseUrl,\n rpcUrl: config.rpcUrl,\n };\n }\n\n /** Start building a route. Chain `.paid()` / `.body()` / `.handler()`. */\n route(options: RouteOptions): RouteBuilder {\n const path = options.path.replace(/^\\/+/, '').replace(/\\/+$/, '');\n if (!path) throw new Error('[serve] route path must be non-empty');\n return new RouteBuilder({ ...this.runtime }, { ...options, path }, (route) => {\n this.routes.set(path, route);\n });\n }\n\n /**\n * Discovery: GET handler for /openapi.json. OpenAPI 3.1 with the\n * `x-payment-info` pricing extension on every paid operation — the shape\n * x402 tooling (and any catalog built on it) indexes.\n *\n * export const GET = serve.openapi(); // app/openapi.json/route.ts\n */\n openapi(): (req: Request) => Response {\n return (req: Request) =>\n new Response(JSON.stringify(buildOpenApiDocument(this, new URL(req.url).origin), null, 2), {\n headers: { 'content-type': 'application/json', 'access-control-allow-origin': '*' },\n });\n }\n\n /**\n * Discovery: GET handler for /llms.txt — plain-text guidance agents read\n * to understand what the API sells, what it costs, and how to pay.\n *\n * export const GET = serve.llms(); // app/llms.txt/route.ts\n */\n llms(): (req: Request) => Response {\n return (req: Request) =>\n new Response(buildLlmsTxt(this, new URL(req.url).origin), {\n headers: { 'content-type': 'text/plain; charset=utf-8', 'access-control-allow-origin': '*' },\n });\n }\n\n /**\n * One fetch handler for the whole app — routes + discovery docs. For\n * fetch-native runtimes (Bun.serve, Deno.serve, Hono, Cloudflare Workers):\n *\n * Bun.serve({ fetch: serve.fetch });\n * app.all('*', (c) => serve.fetch(c.req.raw)); // Hono\n *\n * Next.js apps can skip this and export route handlers directly.\n */\n readonly fetch = async (req: Request): Promise<Response> => {\n const pathname = new URL(req.url).pathname.replace(/^\\/+/, '').replace(/\\/+$/, '');\n if (pathname === 'openapi.json') return this.openapi()(req);\n if (pathname === 'llms.txt') return this.llms()(req);\n const route = this.routes.get(pathname);\n if (route) return route(req);\n return new Response(\n JSON.stringify({ error: 'not found', discovery: ['/openapi.json', '/llms.txt'] }),\n { status: 404, headers: { 'content-type': 'application/json' } },\n );\n };\n\n /**\n * The command that sells this API as an x402 Service on your Agent ID,\n * once it is deployed. Listing is a separate, explicit step: the endpoint\n * is live-probed (it must answer 402 with a Sui challenge that pays YOUR\n * wallet) and then recorded on-chain, sponsored and gasless.\n *\n * This used to emit curls against the hosted mpp.t2000.ai catalog. That\n * proxy mall was purged 2026-08-01 (SPEC_T2_CLEANUP_USDC_ONLY) — there is\n * no central catalog to submit to. Your Agent ID IS the listing, and\n * buyers find it with `t2 services`.\n */\n catalogSubmitCommand(deployedUrl?: string): string {\n const base = (deployedUrl ?? this.baseUrl ?? 'https://<your-deployed-app>').replace(/\\/$/, '');\n const paidPaths = [...this.routes.values()].filter((r) => r.meta.priceUsdc);\n const example = paidPaths[0]?.meta.path ?? '<route>';\n return [\n '# Sell it as an x402 Service on your Agent ID (live-probed, gasless):',\n `npx @t2000/cli agent sell ${base}/${example}`,\n '# Buyers then find it with `t2 services` and pay per call with `t2 pay`.',\n ].join('\\n');\n }\n}\n\nexport function createServe(config: ServeConfig): Serve {\n return new Serve(config);\n}\n\n/**\n * Build a Serve from environment variables — the template-app path where\n * config lives in the host's env UI, not code.\n *\n * T2000_PAY_TO required — the seller's Sui address\n * T2000_NETWORK optional — 'mainnet' (default) | 'testnet'\n * T2000_BASE_URL optional — public URL of the deployed app\n * T2000_NAME optional — service name for discovery docs\n * T2000_DESCRIPTION optional — one-liner for discovery docs\n * KV_REST_API_URL / KV_REST_API_TOKEN\n * optional — enables the durable Upstash replay store\n * (REQUIRED in serverless production; without it replay\n * state is per-instance memory)\n *\n * Empty strings are treated as unset (the Vercel empty-env bug class).\n */\nexport function createServeFromEnv(env: Record<string, string | undefined> = process.env): Serve {\n const read = (key: string): string | undefined => {\n const v = env[key]?.trim();\n return v && v.length > 0 ? v : undefined;\n };\n\n const payTo = read('T2000_PAY_TO');\n if (!payTo) {\n throw new Error(\n '[serve] T2000_PAY_TO is not set (or is empty). Set it to the Sui address your payments should settle to — `t2 address` prints yours.',\n );\n }\n\n const network = read('T2000_NETWORK');\n if (network && network !== 'mainnet' && network !== 'testnet') {\n throw new Error(`[serve] T2000_NETWORK must be 'mainnet' or 'testnet', got \"${network}\"`);\n }\n\n const kvUrl = read('KV_REST_API_URL');\n const kvToken = read('KV_REST_API_TOKEN');\n const store =\n kvUrl && kvToken ? new UpstashDigestStore({ url: kvUrl, token: kvToken }) : undefined;\n\n if (!store) {\n console.warn(\n '[serve] No KV_REST_API_URL/KV_REST_API_TOKEN — using the in-memory replay store. ' +\n 'Fine for a single long-lived process; on serverless hosts set both so replay protection is durable.',\n );\n }\n\n return new Serve({\n payTo,\n network: (network as ServeNetwork | undefined) ?? 'mainnet',\n baseUrl: read('T2000_BASE_URL'),\n name: read('T2000_NAME'),\n description: read('T2000_DESCRIPTION'),\n store,\n });\n}\n","import type { BuiltRoute } from './types.js';\n\n/**\n * Export a built route the way Next.js App Router needs it.\n *\n * Next dispatches ONLY the methods a route.ts exports — serve's own CORS\n * handling (OPTIONS → 204 with the ACAO headers) never runs if the file\n * exports just `POST`: the browser preflight gets Next's bare 204 with no\n * CORS headers, and every browser buyer (Passport, the store's Try it)\n * fails while CLI/server buyers — who never preflight — work fine. Fetch\n * runtimes mounted via a single handler (`serve.fetch`-style) don't have\n * this hole; it is a Next export contract, not a serve one.\n *\n * export const { POST, OPTIONS } = asNextRoute(\n * serve.route({ path: 'haiku' }).paid('0.01').handler(fn),\n * );\n */\nexport function asNextRoute(route: BuiltRoute): {\n POST: BuiltRoute;\n OPTIONS: BuiltRoute;\n} {\n return { POST: route, OPTIONS: route };\n}\n"]}
1
+ {"version":3,"sources":["../src/discovery.ts","../src/chain.ts","../src/route.ts","../src/store.ts","../src/serve.ts","../src/next.ts"],"names":["USDC_TESTNET","USDC","SuiGrpcClient","X402_PAYMENT_HEADER","X402_PAYMENT_RESPONSE_HEADER","result","isX402EscrowHeader","parseX402Header","verifyX402Payment","settleX402Payment","encodeX402Response","createX402Requirements","X402_VERSION","isValidSuiAddress","normalizeSuiAddress","InMemoryDigestStore"],"mappings":";;;;;;;AAgBO,SAAS,oBAAA,CAAqB,OAAc,MAAA,EAA0C;AAC3F,EAAA,MAAM,IAAA,GAAO,MAAM,OAAA,IAAW,MAAA;AAC9B,EAAA,MAAM,QAAiC,EAAC;AAExC,EAAA,KAAA,MAAW,KAAA,IAAS,KAAA,CAAM,MAAA,CAAO,MAAA,EAAO,EAAG;AACzC,IAAA,MAAM,EAAE,IAAA,EAAM,SAAA,EAAW,aAAa,WAAA,EAAa,YAAA,KAAiB,KAAA,CAAM,IAAA;AAC1E,IAAA,MAAM,SAAA,GAAqC;AAAA,MACzC,WAAA,EAAa,IAAA,CAAK,OAAA,CAAQ,gBAAA,EAAkB,GAAG,CAAA;AAAA,MAC/C,SAAS,WAAA,IAAe,IAAA;AAAA,MACxB,SAAA,EAAW;AAAA,QACT,OAAO,YAAA,GACH;AAAA,UACE,WAAA,EAAa,SAAA;AAAA,UACb,SAAS,EAAE,kBAAA,EAAoB,EAAE,MAAA,EAAQ,cAAa;AAAE,SAC1D,GACA,EAAE,WAAA,EAAa,SAAA,EAAU;AAAA,QAC7B,GAAI,SAAA,GACA;AAAA,UACE,KAAA,EAAO;AAAA,YACL,WAAA,EACE;AAAA;AACJ,YAEF,EAAC;AAAA,QACL,KAAA,EAAO,EAAE,WAAA,EAAa,2CAAA;AAAuC;AAC/D,KACF;AACA,IAAA,IAAI,SAAA,EAAW;AAIb,MAAA,SAAA,CAAU,gBAAgB,CAAA,GAAI;AAAA,QAC5B,WAAA,EAAa,OAAA;AAAA,QACb,KAAA,EAAO,SAAA;AAAA,QACP,QAAA,EAAU,MAAA;AAAA,QACV,SAAA,EAAW,CAAC,KAAA,EAAO,MAAM,CAAA;AAAA,QACzB,IAAA,EAAM;AAAA,UACJ,MAAA,EAAQ,OAAA;AAAA,UACR,OAAA,EAAS,CAAA,IAAA,EAAO,KAAA,CAAM,OAAO,CAAA,CAAA;AAAA,UAC7B,KAAA,EAAA,CAAQ,KAAA,CAAM,OAAA,KAAY,SAAA,GAAYA,uBAAeC,YAAA,EAAM,IAAA;AAAA,UAC3D,OAAO,KAAA,CAAM;AAAA;AACf,OACF;AAAA,IACF;AACA,IAAA,IAAI,WAAA,EAAa;AACf,MAAA,SAAA,CAAU,WAAA,GAAc;AAAA,QACtB,QAAA,EAAU,IAAA;AAAA,QACV,SAAS,EAAE,kBAAA,EAAoB,EAAE,MAAA,EAAQ,aAAY;AAAE,OACzD;AAAA,IACF;AACA,IAAA,KAAA,CAAM,IAAI,IAAI,CAAA,CAAE,CAAA,GAAI,EAAE,MAAM,SAAA,EAAU;AAAA,EACxC;AAEA,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,OAAA;AAAA,IACT,IAAA,EAAM;AAAA,MACJ,KAAA,EAAO,MAAM,IAAA,IAAQ,UAAA;AAAA,MACrB,OAAA,EAAS,OAAA;AAAA,MACT,WAAA,EACE,MAAM,WAAA,IACN;AAAA,KACJ;AAAA,IACA,GAAI,IAAA,GAAO,EAAE,OAAA,EAAS,CAAC,EAAE,GAAA,EAAK,IAAA,EAAM,CAAA,EAAE,GAAI,EAAC;AAAA,IAC3C;AAAA,GACF;AACF;AAEO,SAAS,YAAA,CAAa,OAAc,MAAA,EAAyB;AAClE,EAAA,MAAM,IAAA,GAAO,KAAA,CAAM,OAAA,IAAW,MAAA,IAAU,EAAA;AACxC,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,EAAA,EAAK,KAAA,CAAM,IAAA,IAAQ,UAAU,CAAA,CAAE,CAAA;AAC1C,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,EAAA,IAAI,MAAM,WAAA,EAAa;AACrB,IAAA,KAAA,CAAM,IAAA,CAAK,MAAM,WAAW,CAAA;AAC5B,IAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAAA,EACf;AACA,EAAA,KAAA,CAAM,KAAK,eAAe,CAAA;AAC1B,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,EAAA,KAAA,CAAM,IAAA;AAAA,IACJ,oFAAA;AAAA,IACA,uFAAA;AAAA,IACA,wFAAA;AAAA,IACA,EAAA;AAAA,IACA,2EAAA;AAAA,IACA,iEAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,KAAA,CAAM,KAAK,cAAc,CAAA;AACzB,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,EAAA,KAAA,MAAW,KAAA,IAAS,KAAA,CAAM,MAAA,CAAO,MAAA,EAAO,EAAG;AACzC,IAAA,MAAM,EAAE,IAAA,EAAM,SAAA,EAAW,aAAa,WAAA,EAAa,YAAA,KAAiB,KAAA,CAAM,IAAA;AAC1E,IAAA,MAAM,KAAA,GAAQ,SAAA,GAAY,CAAA,EAAG,SAAS,CAAA,cAAA,CAAA,GAAmB,MAAA;AACzD,IAAA,KAAA,CAAM,KAAK,CAAA,SAAA,EAAY,IAAI,IAAI,IAAI,CAAA,QAAA,EAAM,KAAK,CAAA,CAAE,CAAA;AAChD,IAAA,IAAI,WAAA,EAAa,KAAA,CAAM,IAAA,CAAK,WAAW,CAAA;AACvC,IAAA,IAAI,WAAA,EAAa;AACf,MAAA,KAAA,CAAM,KAAK,6BAA6B,CAAA;AACxC,MAAA,KAAA,CAAM,KAAK,SAAS,CAAA;AACpB,MAAA,KAAA,CAAM,KAAK,IAAA,CAAK,SAAA,CAAU,WAAA,EAAa,IAAA,EAAM,CAAC,CAAC,CAAA;AAC/C,MAAA,KAAA,CAAM,KAAK,KAAK,CAAA;AAAA,IAClB;AACA,IAAA,IAAI,YAAA,EAAc;AAChB,MAAA,KAAA,CAAM,KAAK,+FAA0F,CAAA;AACrG,MAAA,KAAA,CAAM,KAAK,SAAS,CAAA;AACpB,MAAA,KAAA,CAAM,KAAK,IAAA,CAAK,SAAA,CAAU,YAAA,EAAc,IAAA,EAAM,CAAC,CAAC,CAAA;AAChD,MAAA,KAAA,CAAM,KAAK,KAAK,CAAA;AAAA,IAClB;AACA,IAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAAA,EACf;AACA,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,WAAA,EAAc,IAAI,CAAA,aAAA,CAAe,CAAA;AAC5C,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AACxB;AClHA,IAAM,aAAA,GAA8C;AAAA,EAClD,OAAA,EAAS,qCAAA;AAAA,EACT,OAAA,EAAS;AACX,CAAA;AAEA,IAAM,YAAA,GAAe,KAAK,EAAA,GAAK,GAAA;AAa/B,IAAM,QAAmD,EAAC;AAEnD,SAAS,aAAA,CAAc,SAAuB,MAAA,EAAgC;AACnF,EAAA,MAAM,CAAA,GAAK,KAAA,CAAM,OAAO,CAAA,KAAM,EAAC;AAC/B,EAAA,IAAI,CAAC,EAAE,MAAA,EAAQ;AACb,IAAA,CAAA,CAAE,MAAA,GAAS,IAAIC,kBAAA,CAAc;AAAA,MAC3B,OAAA,EAAS,MAAA,IAAU,aAAA,CAAc,OAAO,CAAA;AAAA,MACxC;AAAA,KACD,CAAA;AAAA,EACH;AACA,EAAA,OAAO,CAAA,CAAE,MAAA;AACX;AAEA,eAAsB,YAAA,CAAa,SAAuB,MAAA,EAAqC;AAC7F,EAAA,MAAM,MAAA,GAAS,aAAA,CAAc,OAAA,EAAS,MAAM,CAAA;AAC5C,EAAA,MAAM,CAAA,GAAK,KAAA,CAAM,OAAO,CAAA,KAAM,EAAC;AAC/B,EAAA,IAAI,CAAC,EAAE,OAAA,EAAS;AACd,IAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,IAAA,CAAK,kBAAA,EAAmB;AACjD,IAAA,CAAA,CAAE,UAAU,GAAA,CAAI,eAAA;AAAA,EAClB;AACA,EAAA,IAAI,CAAC,EAAE,KAAA,IAAS,IAAA,CAAK,KAAI,GAAI,CAAA,CAAE,KAAA,CAAM,SAAA,GAAY,YAAA,EAAc;AAC7D,IAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,IAAA,CAAK,qBAAA,EAAsB;AACpD,IAAA,CAAA,CAAE,KAAA,GAAQ,EAAE,KAAA,EAAO,MAAA,CAAO,GAAA,CAAI,WAAA,CAAY,KAAK,CAAA,EAAG,SAAA,EAAW,IAAA,CAAK,GAAA,EAAI,EAAE;AAAA,EAC1E;AACA,EAAA,OAAO,EAAE,KAAA,EAAO,CAAA,CAAE,SAAS,KAAA,EAAO,CAAA,CAAE,MAAM,KAAA,EAAM;AAClD;AAGO,SAAS,kBAAA,GAA2B;AACzC,EAAA,OAAO,KAAA,CAAM,OAAA;AACb,EAAA,OAAO,KAAA,CAAM,OAAA;AACf;AAGO,SAAS,eAAA,CAAgB,OAAA,EAAuB,KAAA,EAAe,KAAA,EAAqB;AACzF,EAAA,MAAM,CAAA,GAAK,KAAA,CAAM,OAAO,CAAA,KAAM,EAAC;AAC/B,EAAA,CAAA,CAAE,OAAA,GAAU,KAAA;AACZ,EAAA,CAAA,CAAE,QAAQ,EAAE,KAAA,EAAO,OAAO,SAAA,EAAW,IAAA,CAAK,KAAI,EAAE;AAClD;;;ACNA,IAAM,sBAAA,GAAyB,CAAA;AAE/B,IAAM,YAAA,GAAuC;AAAA,EAC3C,6BAAA,EAA+B,GAAA;AAAA,EAC/B,8BAAA,EAAgC,iCAAA;AAAA,EAChC,8BAAA,EAAgC,iBAAiBC,2BAAmB,CAAA,CAAA;AAAA,EACpE,+BAAA,EAAiC,GAAGC,oCAA4B,CAAA,kBAAA;AAClE,CAAA;AAEA,SAAS,SAAS,QAAA,EAA8B;AAC9C,EAAA,MAAM,OAAA,GAAU,IAAI,OAAA,CAAQ,QAAA,CAAS,OAAO,CAAA;AAC5C,EAAA,KAAA,MAAW,CAAC,CAAA,EAAG,CAAC,CAAA,IAAK,MAAA,CAAO,OAAA,CAAQ,YAAY,CAAA,EAAG,OAAA,CAAQ,GAAA,CAAI,CAAA,EAAG,CAAC,CAAA;AACnE,EAAA,OAAO,IAAI,SAAS,QAAA,CAAS,IAAA,EAAM,EAAE,MAAA,EAAQ,QAAA,CAAS,MAAA,EAAQ,OAAA,EAAS,CAAA;AACzE;AAEA,SAAS,IAAA,CAAK,MAAA,EAAgB,IAAA,EAAe,OAAA,EAA4C;AACvF,EAAA,OAAO,QAAA;AAAA,IACL,IAAI,QAAA,CAAS,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA,EAAG;AAAA,MACjC,MAAA;AAAA,MACA,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAoB,GAAG,OAAA;AAAQ,KAC3D;AAAA,GACH;AACF;AAEA,SAAS,iBAAiB,MAAA,EAAmD;AAC3E,EAAA,OAAO,OAAO,MAAA,KAAW,QAAA,IAAY,MAAA,KAAW,QAAQ,WAAA,IAAe,MAAA;AACzE;AAEA,eAAe,YAAA,CACb,QACA,KAAA,EACuE;AACvE,EAAA,IAAI,gBAAA,CAAiB,MAAM,CAAA,EAAG;AAC5B,IAAA,MAAMC,UAAS,MAAM,MAAA,CAAO,WAAW,CAAA,CAAE,SAAS,KAAK,CAAA;AACvD,IAAA,IAAIA,QAAO,MAAA,EAAQ;AAGjB,MAAA,MAAM,OAAA,GAAUA,OAAAA,CAAO,MAAA,CACpB,GAAA,CAAI,CAAC,CAAA,KAAM;AACV,QAAA,MAAM,IAAA,GAAA,CAAQ,EAAE,IAAA,IAAQ,IACrB,GAAA,CAAI,CAAC,QAAS,OAAO,GAAA,KAAQ,WAAW,MAAA,CAAO,GAAA,CAAI,GAAG,CAAA,GAAI,MAAA,CAAO,GAAG,CAAE,CAAA,CACtE,KAAK,GAAG,CAAA;AACX,QAAA,OAAO,OAAO,CAAA,EAAG,IAAI,KAAK,CAAA,CAAE,OAAO,KAAK,CAAA,CAAE,OAAA;AAAA,MAC5C,CAAC,CAAA,CACA,IAAA,CAAK,IAAI,CAAA;AACZ,MAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,OAAA,EAAQ;AAAA,IAC9B;AACA,IAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,IAAA,EAAMA,QAAO,KAAA,EAAM;AAAA,EACxC;AACA,EAAA,MAAM,MAAA,GAAS,MAAA,CAAO,SAAA,CAAU,KAAK,CAAA;AACrC,EAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,IAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,SAAS,MAAA,CAAO,KAAA,CAAM,WAAW,cAAA,EAAe;AAAA,EACtE;AACA,EAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,IAAA,EAAM,OAAO,IAAA,EAAK;AACvC;AAGA,SAAS,gBAAA,CAAiB,OAAe,IAAA,EAAoB;AAC3D,EAAA,IAAI,CAAC,oBAAoB,IAAA,CAAK,KAAK,KAAK,MAAA,CAAO,KAAK,KAAK,CAAA,EAAG;AAC1D,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,eAAA,EAAkB,IAAI,CAAA,4EAAA,EAA+E,KAAK,CAAA,CAAA;AAAA,KAC5G;AAAA,EACF;AACA,EAAA,IAAI,MAAA,CAAO,KAAK,CAAA,GAAI,sBAAA,EAAwB;AAC1C,IAAA,OAAA,CAAQ,IAAA;AAAA,MACN,CAAA,eAAA,EAAkB,IAAI,CAAA,SAAA,EAAY,KAAK,sBAAsB,sBAAsB,CAAA,gJAAA;AAAA,KAErF;AAAA,EACF;AACF;AAEO,IAAM,eAAN,MAAsC;AAAA,EAO3C,WAAA,CACmB,OAAA,EACA,OAAA,EACA,QAAA,EACjB;AAHiB,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AACA,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AACA,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AAAA,EAChB;AAAA,EAVK,SAAA;AAAA,EACA,UAAA;AAAA,EACA,WAAA;AAAA,EACA,YAAA;AAAA,EACA,MAAA,GAAS,KAAA;AAAA;AAAA,EASjB,KAAK,SAAA,EAAyB;AAC5B,IAAA,gBAAA,CAAiB,SAAA,EAAW,IAAA,CAAK,OAAA,CAAQ,IAAI,CAAA;AAC7C,IAAA,IAAA,CAAK,SAAA,GAAY,SAAA;AACjB,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AACd,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA,EAGA,WAAA,GAAoB;AAClB,IAAA,IAAA,CAAK,MAAA,GAAS,IAAA;AACd,IAAA,IAAA,CAAK,SAAA,GAAY,MAAA;AACjB,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,IAAA,CAAQ,QAAwB,UAAA,EAAuD;AACrF,IAAA,IAAA,CAAK,UAAA,GAAa,MAAA;AAClB,IAAA,IAAA,CAAK,WAAA,GAAc,UAAA;AACnB,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,SAAS,UAAA,EAA2C;AAClD,IAAA,IAAA,CAAK,YAAA,GAAe,UAAA;AACpB,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,QAAQ,EAAA,EAAwF;AAC9F,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,IAAU,CAAC,KAAK,SAAA,EAAW;AACnC,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,eAAA,EAAkB,IAAA,CAAK,OAAA,CAAQ,IAAI,CAAA,2DAAA;AAAA,OACrC;AAAA,IACF;AACA,IAAA,MAAM,UAAU,IAAA,CAAK,OAAA;AACrB,IAAA,MAAM,EAAE,IAAA,EAAM,WAAA,EAAY,GAAI,IAAA,CAAK,OAAA;AACnC,IAAA,MAAM,YAAY,IAAA,CAAK,SAAA;AACvB,IAAA,MAAM,aAAa,IAAA,CAAK,UAAA;AAExB,IAAA,MAAM,KAAA,IAAS,OAAO,GAAA,KAAoC;AACxD,MAAA,IAAI,GAAA,CAAI,WAAW,SAAA,EAAW;AAC5B,QAAA,OAAO,QAAA,CAAS,IAAI,QAAA,CAAS,IAAA,EAAM,EAAE,MAAA,EAAQ,GAAA,EAAK,CAAC,CAAA;AAAA,MACrD;AAKA,MAAA,IAAI,UAAA;AACJ,MAAA,IAAI,cAAA;AACJ,MAAA,IAAI,GAAA,CAAI,MAAA,KAAW,KAAA,IAAS,GAAA,CAAI,WAAW,MAAA,EAAQ;AACjD,QAAA,MAAM,IAAA,GAAO,MAAM,GAAA,CAAI,IAAA,EAAK;AAC5B,QAAA,IAAI,IAAA,CAAK,IAAA,EAAK,CAAE,MAAA,GAAS,CAAA,EAAG;AAC1B,UAAA,IAAI;AACF,YAAA,UAAA,GAAa,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,UAC9B,CAAA,CAAA,MAAQ;AACN,YAAA,cAAA,GAAiB,gCAAA;AAAA,UACnB;AAAA,QACF;AAAA,MACF;AAEA,MAAA,MAAM,QAAA,GAAA,CAAY,OAAA,CAAQ,OAAA,IAAW,IAAI,IAAI,GAAA,CAAI,GAAG,CAAA,CAAE,MAAA,EAAQ,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA,GAAI,IAAI,IAAI,CAAA,CAAA;AAE3F,MAAA,MAAM,UAAA,GAAa,OAAO,KAAA,KAAsC;AAC9D,QAAA,IAAI,SAAA,GAAqB,UAAA;AACzB,QAAA,IAAI,UAAA,EAAY;AAGd,UAAA,IAAI,cAAA,EAAgB;AAClB,YAAA,OAAO,KAAK,GAAA,EAAK,EAAE,OAAO,cAAA,EAAgB,IAAA,EAAM,OAAO,CAAA;AAAA,UACzD;AACA,UAAA,MAAM,SAAS,MAAM,YAAA,CAAa,UAAA,EAAY,UAAA,IAAc,EAAE,CAAA;AAC9D,UAAA,IAAI,CAAC,OAAO,EAAA,EAAI;AACd,YAAA,OAAO,IAAA,CAAK,KAAK,EAAE,KAAA,EAAO,OAAO,OAAA,EAAS,IAAA,EAAM,OAAO,CAAA;AAAA,UACzD;AACA,UAAA,SAAA,GAAY,MAAA,CAAO,IAAA;AAAA,QACrB;AACA,QAAA,MAAM,GAAA,GAAM,MAAM,EAAA,CAAG,EAAE,MAAM,SAAA,EAAoB,GAAA,EAAK,OAAO,CAAA;AAC7D,QAAA,IAAI,GAAA,YAAe,QAAA,EAAU,OAAO,QAAA,CAAS,GAAG,CAAA;AAChD,QAAA,OAAO,IAAA,CAAK,KAAK,GAAG,CAAA;AAAA,MACtB,CAAA;AAGA,MAAA,IAAI,CAAC,SAAA,EAAW;AACd,QAAA,IAAI;AACF,UAAA,OAAO,MAAM,UAAA,EAAW;AAAA,QAC1B,SAAS,GAAA,EAAK;AACZ,UAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,eAAA,EAAkB,IAAI,CAAA,iBAAA,CAAA,EAAqB,GAAG,CAAA;AAC5D,UAAA,OAAO,IAAA,CAAK,GAAA,EAAK,EAAE,KAAA,EAAO,kBAAkB,CAAA;AAAA,QAC9C;AAAA,MACF;AAEA,MAAA,MAAM,aAAA,GAAgB,GAAA,CAAI,OAAA,CAAQ,GAAA,CAAIF,2BAAmB,CAAA;AAMzD,MAAA,IAAI,CAAC,aAAA,EAAe;AAClB,QAAA,OAAO,MAAM,UAAA,CAAW,OAAA,EAAS,EAAE,QAAA,EAAU,WAAW,CAAA;AAAA,MAC1D;AAEA,MAAA,IAAIG,0BAAA,CAAmB,aAAa,CAAA,EAAG;AACrC,QAAA,OAAO,MAAM,WAAW,OAAA,EAAS;AAAA,UAC/B,QAAA;AAAA,UACA,SAAA;AAAA,UACA,KAAA,EACE;AAAA,SACH,CAAA;AAAA,MACH;AAKA,MAAA,IAAI,OAAA;AACJ,MAAA,IAAI;AACF,QAAA,OAAA,GAAUC,wBAAgB,aAAa,CAAA;AACvC,QAAAC,yBAAA,CAAkB;AAAA,UAChB,OAAA;AAAA,UACA,QAAA,EAAU;AAAA,YACR,WAAA,EAAa,QAAQ,OAAA,CAAQ,WAAA;AAAA,YAC7B,MAAA,EAAQ,SAAA;AAAA,YACR,UAAU,OAAA,CAAQ,QAAA;AAAA,YAClB,WAAW,OAAA,CAAQ,KAAA;AAAA,YACnB,SAAS,OAAA,CAAQ;AAAA;AACnB,SACD,CAAA;AAAA,MACH,SAAS,GAAA,EAAK;AACZ,QAAA,OAAO,MAAM,WAAW,OAAA,EAAS;AAAA,UAC/B,QAAA;AAAA,UACA,SAAA;AAAA,UACA,KAAA,EAAO,oBAAoB,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,SAC5E,CAAA;AAAA,MACH;AAKA,MAAA,MAAM,YAAA,GAAe,CAAA,UAAA,EAAa,OAAA,CAAQ,OAAA,CAAQ,WAAW,CAAA,CAAA;AAC7D,MAAA,IAAI,MAAM,OAAA,CAAQ,KAAA,CAAM,GAAA,CAAI,YAAY,CAAA,EAAG;AACzC,QAAA,OAAO,MAAM,WAAW,OAAA,EAAS;AAAA,UAC/B,QAAA;AAAA,UACA,SAAA;AAAA,UACA,KAAA,EAAO;AAAA,SACR,CAAA;AAAA,MACH;AAIA,MAAA,IAAI,MAAA;AACJ,MAAA,IAAI;AACF,QAAA,MAAA,GAAS,MAAM,UAAA,CAAW,OAAA,CAAQ,OAAA,CAAQ,aAAa,CAAA;AAAA,MACzD,SAAS,GAAA,EAAK;AACZ,QAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,eAAA,EAAkB,IAAI,CAAA,uCAAA,CAAA,EAA2C,GAAG,CAAA;AAClF,QAAA,OAAO,IAAA,CAAK,GAAA,EAAK,EAAE,KAAA,EAAO,8CAAyC,CAAA;AAAA,MACrE;AACA,MAAA,IAAI,MAAA,CAAO,MAAA,IAAU,GAAA,EAAK,OAAO,MAAA;AAIjC,MAAA,IAAI,MAAA;AACJ,MAAA,IAAI;AACF,QAAA,MAAA,GAAS,MAAMC,yBAAA,CAAkB;AAAA,UAC/B,OAAA;AAAA,UACA,MAAA,EAAQ,aAAA,CAAc,OAAA,CAAQ,OAAA,EAAS,QAAQ,MAAM,CAAA;AAAA,UACrD,OAAO,OAAA,CAAQ,KAAA;AAAA,UACf,QAAA,EAAU;AAAA,YACR,WAAA,EAAa,QAAQ,OAAA,CAAQ,WAAA;AAAA,YAC7B,MAAA,EAAQ,SAAA;AAAA,YACR,UAAU,OAAA,CAAQ,QAAA;AAAA,YAClB,WAAW,OAAA,CAAQ,KAAA;AAAA,YACnB,SAAS,OAAA,CAAQ;AAAA;AACnB,SACD,CAAA;AAAA,MACH,SAAS,GAAA,EAAK;AACZ,QAAA,OAAO,MAAM,WAAW,OAAA,EAAS;AAAA,UAC/B,QAAA;AAAA,UACA,SAAA;AAAA,UACA,KAAA,EAAO,sBAAsB,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,SAC9E,CAAA;AAAA,MACH;AAGA,MAAA,IAAI;AACF,QAAA,MAAM,OAAA,CAAQ,KAAA,CAAM,GAAA,CAAI,YAAY,CAAA;AAAA,MACtC,CAAA,CAAA,MAAQ;AAAA,MAER;AAKA,MAAA,cAAA,CAAe,OAAA,EAAS;AAAA,QACtB,QAAQ,MAAA,CAAO,WAAA;AAAA,QACf,OAAO,MAAA,CAAO,KAAA;AAAA,QACd,SAAA;AAAA,QACA;AAAA,OACD,CAAA;AAED,MAAA,MAAM,OAAA,GAAU,IAAI,OAAA,CAAQ,MAAA,CAAO,OAAO,CAAA;AAC1C,MAAA,OAAA,CAAQ,GAAA,CAAIL,oCAAA,EAA8BM,0BAAA,CAAmB,MAAM,CAAC,CAAA;AACpE,MAAA,OAAO,IAAI,SAAS,MAAA,CAAO,IAAA,EAAM,EAAE,MAAA,EAAQ,MAAA,CAAO,MAAA,EAAQ,OAAA,EAAS,CAAA;AAAA,IACrE,CAAA,CAAA;AAEA,IAAA,KAAA,CAAM,IAAA,GAAO;AAAA,MACX,IAAA;AAAA,MACA,SAAA;AAAA,MACA,WAAA;AAAA,MACA,UAAA;AAAA,MACA,aAAa,IAAA,CAAK,WAAA;AAAA,MAClB,cAAc,IAAA,CAAK;AAAA,KACrB;AACA,IAAA,IAAA,CAAK,SAAS,KAAK,CAAA;AACnB,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAKA,SAAS,cAAA,CACP,SACA,IAAA,EACM;AACN,EAAA,MAAM,MAAM,OAAA,CAAQ,iBAAA;AACpB,EAAA,IAAI,CAAC,GAAA,EAAK;AACV,EAAA,IAAI;AACF,IAAA,KAAK,MAAM,GAAA,EAAK;AAAA,MACd,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAmB;AAAA,MAC9C,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,QACnB,QAAQ,IAAA,CAAK,MAAA;AAAA,QACb,OAAO,OAAA,CAAQ,KAAA;AAAA,QACf,OAAO,IAAA,CAAK,KAAA;AAAA,QACZ,iBAAiB,IAAA,CAAK,KAAA,CAAM,OAAO,IAAA,CAAK,SAAS,IAAI,GAAS,CAAA;AAAA,QAC9D,OAAA,EAAS,CAAA,IAAA,EAAO,OAAA,CAAQ,OAAO,CAAA,CAAA;AAAA,QAC/B,OAAO,IAAA,CAAK,QAAA;AAAA,QACZ,MAAA,EAAQ;AAAA,OACT,CAAA;AAAA,MACD,MAAA,EAAQ,WAAA,CAAY,OAAA,CAAQ,IAAI;AAAA,KACjC,CAAA,CAAE,KAAA,CAAM,MAAM,KAAA,CAAS,CAAA;AAAA,EAC1B,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;AAEA,eAAe,UAAA,CACb,SACA,IAAA,EACmB;AACnB,EAAA,IAAI;AACF,IAAA,MAAM,EAAE,OAAO,KAAA,EAAM,GAAI,MAAM,YAAA,CAAa,OAAA,CAAQ,OAAA,EAAS,OAAA,CAAQ,MAAM,CAAA;AAC3E,IAAA,MAAM,eAAeC,8BAAA,CAAuB;AAAA,MAC1C,WAAA,EAAa,OAAO,UAAA,EAAW;AAAA,MAC/B,QAAQ,IAAA,CAAK,SAAA;AAAA,MACb,UAAU,OAAA,CAAQ,QAAA;AAAA,MAClB,WAAW,OAAA,CAAQ,KAAA;AAAA,MACnB,UAAU,IAAA,CAAK,QAAA;AAAA,MACf,SAAS,OAAA,CAAQ,OAAA;AAAA,MACjB,KAAA;AAAA,MACA,YAAA,EAAc;AAAA,KACf,CAAA;AAKD,IAAA,MAAM,QAAQ,MAAM;AAClB,MAAA,IAAI;AACF,QAAA,OAAO,IAAI,GAAA,CAAI,IAAA,CAAK,QAAQ,CAAA,CAAE,QAAA;AAAA,MAChC,CAAA,CAAA,MAAQ;AACN,QAAA,OAAO,KAAA,CAAA;AAAA,MACT;AAAA,IACF,CAAA,GAAG;AACH,IAAA,MAAM,OAAA,GAAU,CAAA,eAAA,EAAkB,IAAA,IAAQ,MAAM,CAAA,cAAA,EAAiB,OAAA,CAAQ,KAAK,CAAA,aAAA,EAAgB,OAAA,CAAQ,QAAQ,CAAA,WAAA,EAAc,IAAA,CAAK,SAAS,CAAA,CAAA,CAAA;AAC1I,IAAA,OAAO,IAAA;AAAA,MACL,GAAA;AAAA,MACA;AAAA,QACE,WAAA,EAAaC,oBAAA;AAAA,QACb,KAAA,EAAO,KAAK,KAAA,IAAS,kBAAA;AAAA,QACrB,OAAA,EAAS,CAAC,YAAY;AAAA,OACxB;AAAA,MACA,EAAE,oBAAoB,OAAA;AAAQ,KAChC;AAAA,EACF,SAAS,GAAA,EAAK;AAGZ,IAAA,OAAA,CAAQ,KAAA,CAAM,0CAA0C,GAAG,CAAA;AAC3D,IAAA,OAAO,IAAA,CAAK,GAAA,EAAK,EAAE,KAAA,EAAO,6CAA6C,CAAA;AAAA,EACzE;AACF;AChbA,IAAM,mBAAA,GAAsB,KAAK,EAAA,GAAK,EAAA;AACtC,IAAM,MAAA,GAAS,eAAA;AASR,IAAM,qBAAN,MAAgD;AAAA,EACpC,GAAA;AAAA,EACA,KAAA;AAAA,EACA,UAAA;AAAA,EAEjB,YAAY,OAAA,EAAoC;AAC9C,IAAA,IAAA,CAAK,GAAA,GAAM,OAAA,CAAQ,GAAA,CAAI,OAAA,CAAQ,OAAO,EAAE,CAAA;AACxC,IAAA,IAAA,CAAK,QAAQ,OAAA,CAAQ,KAAA;AACrB,IAAA,IAAA,CAAK,UAAA,GAAa,QAAQ,UAAA,IAAc,mBAAA;AAAA,EAC1C;AAAA,EAEA,MAAc,QAAQ,QAAA,EAAsC;AAC1D,IAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,CAAA,EAAG,KAAK,GAAG,CAAA,CAAA,EAAI,QAAA,CAAS,GAAA,CAAI,kBAAkB,CAAA,CAAE,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA,EAAI;AAAA,MACnF,SAAS,EAAE,aAAA,EAAe,CAAA,OAAA,EAAU,IAAA,CAAK,KAAK,CAAA,CAAA;AAAG,KAClD,CAAA;AACD,IAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,wBAAA,EAA2B,GAAA,CAAI,MAAM,IAAI,MAAM,GAAA,CAAI,IAAA,EAAM,CAAA,CAAE,CAAA;AAAA,IAC7E;AACA,IAAA,MAAM,IAAA,GAAQ,MAAM,GAAA,CAAI,IAAA,EAAK;AAC7B,IAAA,IAAI,IAAA,CAAK,OAAO,MAAM,IAAI,MAAM,CAAA,eAAA,EAAkB,IAAA,CAAK,KAAK,CAAA,CAAE,CAAA;AAC9D,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACd;AAAA,EAEA,MAAM,IAAI,MAAA,EAAkC;AAC1C,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,OAAA,CAAQ,CAAC,KAAA,EAAO,MAAA,GAAS,MAAM,CAAC,CAAA;AAC1D,IAAA,OAAO,MAAA,KAAW,QAAQ,MAAA,KAAW,MAAA;AAAA,EACvC;AAAA,EAEA,MAAM,IAAI,MAAA,EAA+B;AAGvC,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,OAAA,CAAQ;AAAA,MAChC,KAAA;AAAA,MACA,MAAA,GAAS,MAAA;AAAA,MACT,GAAA;AAAA,MACA,IAAA;AAAA,MACA,MAAA,CAAO,KAAK,UAAU,CAAA;AAAA,MACtB;AAAA,KACD,CAAA;AACD,IAAA,IAAI,MAAA,KAAW,IAAA,IAAQ,MAAA,KAAW,MAAA,EAAW;AAC3C,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,qBAAA,EAAwB,MAAM,CAAA,CAAE,CAAA;AAAA,IAClD;AAAA,EACF;AACF;;;AC/DO,IAAM,QAAN,MAAY;AAAA,EACA,OAAA;AAAA;AAAA,EAER,MAAA,uBAAa,GAAA,EAAwB;AAAA,EAErC,KAAA;AAAA,EACA,OAAA;AAAA,EACA,IAAA;AAAA,EACA,WAAA;AAAA,EACA,OAAA;AAAA,EAET,YAAY,MAAA,EAAqB;AAC/B,IAAA,IAAI,CAAC,MAAA,CAAO,KAAA,IAAS,CAACC,uBAAA,CAAkB,MAAA,CAAO,KAAK,CAAA,EAAG;AACrD,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,qFAAA,EAAwF,OAAO,KAAK,CAAA,CAAA;AAAA,OACtG;AAAA,IACF;AACA,IAAA,IAAA,CAAK,KAAA,GAAQC,yBAAA,CAAoB,MAAA,CAAO,KAAK,CAAA;AAC7C,IAAA,IAAA,CAAK,OAAA,GAAU,OAAO,OAAA,IAAW,SAAA;AACjC,IAAA,IAAA,CAAK,OAAO,MAAA,CAAO,IAAA;AACnB,IAAA,IAAA,CAAK,cAAc,MAAA,CAAO,WAAA;AAC1B,IAAA,IAAA,CAAK,OAAA,GAAU,MAAA,CAAO,OAAA,EAAS,OAAA,CAAQ,OAAO,EAAE,CAAA;AAEhD,IAAA,MAAM,QAAA,GAAqB,IAAA,CAAK,OAAA,KAAY,SAAA,GAAYd,oBAAAA,GAAeC,YAAAA;AACvE,IAAA,IAAA,CAAK,OAAA,GAAU;AAAA,MACb,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,QAAA;AAAA,MACA,KAAA,EAAO,MAAA,CAAO,KAAA,IAAS,IAAIc,2BAAAA,EAAoB;AAAA,MAC/C,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,QAAQ,MAAA,CAAO,MAAA;AAAA,MACf,mBAAmB,MAAA,CAAO;AAAA,KAC5B;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,OAAA,EAAqC;AACzC,IAAA,MAAM,IAAA,GAAO,QAAQ,IAAA,CAAK,OAAA,CAAQ,QAAQ,EAAE,CAAA,CAAE,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAA;AAChE,IAAA,IAAI,CAAC,IAAA,EAAM,MAAM,IAAI,MAAM,sCAAsC,CAAA;AACjE,IAAA,OAAO,IAAI,YAAA,CAAa,EAAE,GAAG,IAAA,CAAK,OAAA,EAAQ,EAAG,EAAE,GAAG,OAAA,EAAS,IAAA,EAAK,EAAG,CAAC,KAAA,KAAU;AAC5E,MAAA,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,IAAA,EAAM,KAAK,CAAA;AAAA,IAC7B,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAA,GAAsC;AACpC,IAAA,OAAO,CAAC,GAAA,KACN,IAAI,QAAA,CAAS,IAAA,CAAK,UAAU,oBAAA,CAAqB,IAAA,EAAM,IAAI,GAAA,CAAI,IAAI,GAAG,CAAA,CAAE,MAAM,CAAA,EAAG,IAAA,EAAM,CAAC,CAAA,EAAG;AAAA,MACzF,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAoB,+BAA+B,GAAA;AAAI,KACnF,CAAA;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAA,GAAmC;AACjC,IAAA,OAAO,CAAC,GAAA,KACN,IAAI,QAAA,CAAS,YAAA,CAAa,IAAA,EAAM,IAAI,GAAA,CAAI,GAAA,CAAI,GAAG,CAAA,CAAE,MAAM,CAAA,EAAG;AAAA,MACxD,OAAA,EAAS,EAAE,cAAA,EAAgB,2BAAA,EAA6B,+BAA+B,GAAA;AAAI,KAC5F,CAAA;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWS,KAAA,GAAQ,OAAO,GAAA,KAAoC;AAC1D,IAAA,MAAM,QAAA,GAAW,IAAI,GAAA,CAAI,GAAA,CAAI,GAAG,CAAA,CAAE,QAAA,CAAS,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAA,CAAE,OAAA,CAAQ,QAAQ,EAAE,CAAA;AACjF,IAAA,IAAI,aAAa,cAAA,EAAgB,OAAO,IAAA,CAAK,OAAA,GAAU,GAAG,CAAA;AAC1D,IAAA,IAAI,aAAa,UAAA,EAAY,OAAO,IAAA,CAAK,IAAA,GAAO,GAAG,CAAA;AACnD,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,QAAQ,CAAA;AACtC,IAAA,IAAI,KAAA,EAAO,OAAO,KAAA,CAAM,GAAG,CAAA;AAC3B,IAAA,OAAO,IAAI,QAAA;AAAA,MACT,IAAA,CAAK,SAAA,CAAU,EAAE,KAAA,EAAO,WAAA,EAAa,WAAW,CAAC,eAAA,EAAiB,WAAW,CAAA,EAAG,CAAA;AAAA,MAChF,EAAE,MAAA,EAAQ,GAAA,EAAK,SAAS,EAAE,cAAA,EAAgB,oBAAmB;AAAE,KACjE;AAAA,EACF,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,qBAAqB,WAAA,EAA8B;AACjD,IAAA,MAAM,QAAQ,WAAA,IAAe,IAAA,CAAK,WAAW,6BAAA,EAA+B,OAAA,CAAQ,OAAO,EAAE,CAAA;AAC7F,IAAA,MAAM,SAAA,GAAY,CAAC,GAAG,IAAA,CAAK,MAAA,CAAO,MAAA,EAAQ,CAAA,CAAE,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,KAAK,SAAS,CAAA;AAC1E,IAAA,MAAM,OAAA,GAAU,SAAA,CAAU,CAAC,CAAA,EAAG,KAAK,IAAA,IAAQ,SAAA;AAC3C,IAAA,OAAO;AAAA,MACL,uEAAA;AAAA,MACA,CAAA,0BAAA,EAA6B,IAAI,CAAA,CAAA,EAAI,OAAO,CAAA,CAAA;AAAA,MAC5C;AAAA,KACF,CAAE,KAAK,IAAI,CAAA;AAAA,EACb;AACF;AAEO,SAAS,YAAY,MAAA,EAA4B;AACtD,EAAA,OAAO,IAAI,MAAM,MAAM,CAAA;AACzB;AAuBO,SAAS,kBAAA,CAAmB,GAAA,GAA0C,OAAA,CAAQ,GAAA,EAAY;AAC/F,EAAA,MAAM,IAAA,GAAO,CAAC,GAAA,KAAoC;AAChD,IAAA,MAAM,CAAA,GAAI,GAAA,CAAI,GAAG,CAAA,EAAG,IAAA,EAAK;AACzB,IAAA,OAAO,CAAA,IAAK,CAAA,CAAE,MAAA,GAAS,CAAA,GAAI,CAAA,GAAI,MAAA;AAAA,EACjC,CAAA;AAEA,EAAA,MAAM,KAAA,GAAQ,KAAK,cAAc,CAAA;AACjC,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AAEA,EAAA,MAAM,OAAA,GAAU,KAAK,eAAe,CAAA;AACpC,EAAA,IAAI,OAAA,IAAW,OAAA,KAAY,SAAA,IAAa,OAAA,KAAY,SAAA,EAAW;AAC7D,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,2DAAA,EAA8D,OAAO,CAAA,CAAA,CAAG,CAAA;AAAA,EAC1F;AAEA,EAAA,MAAM,KAAA,GAAQ,KAAK,iBAAiB,CAAA;AACpC,EAAA,MAAM,OAAA,GAAU,KAAK,mBAAmB,CAAA;AACxC,EAAA,MAAM,KAAA,GACJ,KAAA,IAAS,OAAA,GAAU,IAAI,kBAAA,CAAmB,EAAE,GAAA,EAAK,KAAA,EAAO,KAAA,EAAO,OAAA,EAAS,CAAA,GAAI,MAAA;AAE9E,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,OAAA,CAAQ,IAAA;AAAA,MACN;AAAA,KAEF;AAAA,EACF;AAEA,EAAA,OAAO,IAAI,KAAA,CAAM;AAAA,IACf,KAAA;AAAA,IACA,SAAU,OAAA,IAAwC,SAAA;AAAA,IAClD,OAAA,EAAS,KAAK,gBAAgB,CAAA;AAAA,IAC9B,IAAA,EAAM,KAAK,YAAY,CAAA;AAAA,IACvB,WAAA,EAAa,KAAK,mBAAmB,CAAA;AAAA,IACrC,iBAAA,EAAmB,KAAK,2BAA2B,CAAA;AAAA,IACnD;AAAA,GACD,CAAA;AACH;;;ACzKO,SAAS,YAAY,KAAA,EAG1B;AACA,EAAA,OAAO,EAAE,IAAA,EAAM,KAAA,EAAO,OAAA,EAAS,KAAA,EAAM;AACvC","file":"index.cjs","sourcesContent":["import { USDC, USDC_TESTNET } from '@t2000/sui-x402';\nimport type { Serve } from './serve.js';\n\n// ---------------------------------------------------------------------------\n// Discovery docs — /openapi.json + /llms.txt.\n//\n// The shapes here are what the on-chain listing probe grades (the check\n// behind `t2 agent sell`) (was: apps/gateway/lib/\n// catalog-ingest.ts `gradeListing`): a warning-free listing needs info.title,\n// a one-paragraph info.description, a flat string `x-payment-info.price` per\n// paid operation, and an application/json requestBody schema with typed\n// properties. Everything serve can derive is emitted automatically; the JSON\n// request schema comes from the route's `inputSchema` (zod v4 users:\n// `z.toJSONSchema(schema)`).\n// ---------------------------------------------------------------------------\n\nexport function buildOpenApiDocument(serve: Serve, origin?: string): Record<string, unknown> {\n const base = serve.baseUrl ?? origin;\n const paths: Record<string, unknown> = {};\n\n for (const route of serve.routes.values()) {\n const { path, priceUsdc, description, inputSchema, outputSchema } = route.meta;\n const operation: Record<string, unknown> = {\n operationId: path.replace(/[^a-zA-Z0-9]+/g, '_'),\n summary: description ?? path,\n responses: {\n '200': outputSchema\n ? {\n description: 'Success',\n content: { 'application/json': { schema: outputSchema } },\n }\n : { description: 'Success' },\n ...(priceUsdc\n ? {\n '402': {\n description:\n 'Payment required — the body carries an x402 accepts[] envelope (scheme \"exact\", network sui). Sign it and retry with the X-PAYMENT header.',\n },\n }\n : {}),\n '422': { description: 'Invalid request body — never charged' },\n },\n };\n if (priceUsdc) {\n // Same shape the gateway's own /openapi.json emits: 'mpp' is the\n // protocol family, 'x402' the dialect; the x402 block mirrors the\n // static half of the live accepts[] entry (dynamic fields ride the 402).\n operation['x-payment-info'] = {\n pricingMode: 'fixed',\n price: priceUsdc,\n currency: 'USDC',\n protocols: ['mpp', 'x402'],\n x402: {\n scheme: 'exact',\n network: `sui:${serve.network}`,\n asset: (serve.network === 'testnet' ? USDC_TESTNET : USDC).type,\n payTo: serve.payTo,\n },\n };\n }\n if (inputSchema) {\n operation.requestBody = {\n required: true,\n content: { 'application/json': { schema: inputSchema } },\n };\n }\n paths[`/${path}`] = { post: operation };\n }\n\n return {\n openapi: '3.1.0',\n info: {\n title: serve.name ?? 'Paid API',\n version: '1.0.0',\n description:\n serve.description ??\n 'Agent-payable API. Every paid endpoint answers 402 with an x402 accepts[] envelope; payment settles in USDC on Sui.',\n },\n ...(base ? { servers: [{ url: base }] } : {}),\n paths,\n };\n}\n\nexport function buildLlmsTxt(serve: Serve, origin?: string): string {\n const base = serve.baseUrl ?? origin ?? '';\n const lines: string[] = [];\n lines.push(`# ${serve.name ?? 'Paid API'}`);\n lines.push('');\n if (serve.description) {\n lines.push(serve.description);\n lines.push('');\n }\n lines.push('## How to pay');\n lines.push('');\n lines.push(\n 'Endpoints below are paid per call in USDC on Sui (x402). An unpaid request returns',\n 'HTTP 402 with an `accepts[]` envelope; sign it and retry with the `X-PAYMENT` header.',\n 'Invalid input returns 422 before any payment is taken. A failed call is never charged.',\n '',\n 'Easiest client: `npm i -g @t2000/cli` then `t2 pay <url> --data \\'{...}\\'`,',\n 'or the t2000 MCP server (`t2000_pay`), or `@t2000/sdk` `pay()`.',\n '',\n );\n lines.push('## Endpoints');\n lines.push('');\n for (const route of serve.routes.values()) {\n const { path, priceUsdc, description, inputSchema, outputSchema } = route.meta;\n const price = priceUsdc ? `${priceUsdc} USDC per call` : 'free';\n lines.push(`### POST ${base}/${path} — ${price}`);\n if (description) lines.push(description);\n if (inputSchema) {\n lines.push('Request body (JSON Schema):');\n lines.push('```json');\n lines.push(JSON.stringify(inputSchema, null, 2));\n lines.push('```');\n }\n if (outputSchema) {\n lines.push('Response (JSON Schema — contentMediaType/format annotations name the deliverable types):');\n lines.push('```json');\n lines.push(JSON.stringify(outputSchema, null, 2));\n lines.push('```');\n }\n lines.push('');\n }\n lines.push(`Discovery: ${base}/openapi.json`);\n return lines.join('\\n');\n}\n","import { SuiGrpcClient } from '@mysten/sui/grpc';\nimport type { ServeNetwork } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Chain plumbing — same shape as the gateway's x402-dialect.ts (the reference\n// composition). All reads are gRPC; this package never touches JSON-RPC.\n//\n// Cache policy: the chain identifier (genesis digest) is immutable per\n// network — cached forever. The epoch advances ~daily and x402 requirements\n// are valid for [epoch, epoch+1], so a 10-minute TTL is conservatively fresh.\n// ---------------------------------------------------------------------------\n\nconst FULLNODE_URLS: Record<ServeNetwork, string> = {\n mainnet: 'https://fullnode.mainnet.sui.io:443',\n testnet: 'https://fullnode.testnet.sui.io:443',\n};\n\nconst EPOCH_TTL_MS = 10 * 60 * 1000;\n\nexport interface ChainInfo {\n chain: string;\n epoch: string;\n}\n\ninterface ChainState {\n client?: SuiGrpcClient;\n chainId?: string;\n epoch?: { value: string; fetchedAt: number };\n}\n\nconst state: Partial<Record<ServeNetwork, ChainState>> = {};\n\nexport function getGrpcClient(network: ServeNetwork, rpcUrl?: string): SuiGrpcClient {\n const s = (state[network] ??= {});\n if (!s.client) {\n s.client = new SuiGrpcClient({\n baseUrl: rpcUrl ?? FULLNODE_URLS[network],\n network,\n });\n }\n return s.client;\n}\n\nexport async function getChainInfo(network: ServeNetwork, rpcUrl?: string): Promise<ChainInfo> {\n const client = getGrpcClient(network, rpcUrl);\n const s = (state[network] ??= {});\n if (!s.chainId) {\n const res = await client.core.getChainIdentifier();\n s.chainId = res.chainIdentifier;\n }\n if (!s.epoch || Date.now() - s.epoch.fetchedAt > EPOCH_TTL_MS) {\n const res = await client.core.getCurrentSystemState();\n s.epoch = { value: String(res.systemState.epoch), fetchedAt: Date.now() };\n }\n return { chain: s.chainId, epoch: s.epoch.value };\n}\n\n/** Test seam — reset module caches between cases. */\nexport function __resetChainCaches(): void {\n delete state.mainnet;\n delete state.testnet;\n}\n\n/** Test seam — pre-seed chain info so tests never hit the network. */\nexport function __seedChainInfo(network: ServeNetwork, chain: string, epoch: string): void {\n const s = (state[network] ??= {});\n s.chainId = chain;\n s.epoch = { value: epoch, fetchedAt: Date.now() };\n}\n","import type { Currency, DigestStore } from '@t2000/sui-x402';\nimport {\n createX402Requirements,\n encodeX402Response,\n isX402EscrowHeader,\n parseX402Header,\n settleX402Payment,\n verifyX402Payment,\n X402_PAYMENT_HEADER,\n X402_PAYMENT_RESPONSE_HEADER,\n X402_VERSION,\n type X402SettleResponse,\n} from '@t2000/sui-x402';\nimport { getChainInfo, getGrpcClient } from './chain.js';\nimport type {\n BuiltRoute,\n HandlerContext,\n HandlerResult,\n ServeNetwork,\n ServeSchema,\n StandardSchemaLike,\n} from './types.js';\n\n// ---------------------------------------------------------------------------\n// The paid-request lifecycle (SPEC_T2000_SERVE §3 — sign-then-settle,\n// handler-then-settle):\n//\n// no X-PAYMENT → 402 with the accepts[] envelope (never a charge;\n// the catalog probe and every discovery tool read\n// this, so it fires BEFORE body validation)\n// X-PAYMENT present:\n// 1. parse + STRUCTURAL verify (right amount/recipient/nonce — no RPC)\n// 2. challenge-once check (a signed payload is single-use)\n// 3. validate the body — invalid → 422, payment NEVER submitted\n// (the JMPR paid-422 class is impossible: the buyer keeps their money)\n// 4. run the handler — throws → 500, payment NEVER submitted\n// 5. settle (submit the buyer-signed gasless bytes; digest-once inside)\n// 6. consume the challenge, attach the X-PAYMENT-RESPONSE receipt\n//\n// Money only moves at step 5, after the seller has already produced the\n// result. A forged payload can waste seller compute (signature authority is\n// the chain at settle time), never buyer money.\n// ---------------------------------------------------------------------------\n\nexport interface RouteRuntime {\n payTo: string;\n network: ServeNetwork;\n currency: Currency;\n store: DigestStore;\n baseUrl?: string;\n rpcUrl?: string;\n /** B2 attributed reporting — unset = no report (see ServeConfig). */\n activityReportUrl?: string;\n}\n\nexport interface RouteOptions {\n path: string;\n description?: string;\n}\n\n/** Sanity cap on a per-call price — above this, the work is job-shaped\n * (escrow) rather than a per-call x402 Service. */\nconst CATALOG_PRICE_CAP_USDC = 5;\n\nconst CORS_HEADERS: Record<string, string> = {\n 'access-control-allow-origin': '*',\n 'access-control-allow-methods': 'GET, POST, PUT, DELETE, OPTIONS',\n 'access-control-allow-headers': `content-type, ${X402_PAYMENT_HEADER}`,\n 'access-control-expose-headers': `${X402_PAYMENT_RESPONSE_HEADER}, WWW-Authenticate`,\n};\n\nfunction withCors(response: Response): Response {\n const headers = new Headers(response.headers);\n for (const [k, v] of Object.entries(CORS_HEADERS)) headers.set(k, v);\n return new Response(response.body, { status: response.status, headers });\n}\n\nfunction json(status: number, body: unknown, headers?: Record<string, string>): Response {\n return withCors(\n new Response(JSON.stringify(body), {\n status,\n headers: { 'content-type': 'application/json', ...headers },\n }),\n );\n}\n\nfunction isStandardSchema(schema: ServeSchema): schema is StandardSchemaLike {\n return typeof schema === 'object' && schema !== null && '~standard' in schema;\n}\n\nasync function validateBody(\n schema: ServeSchema,\n value: unknown,\n): Promise<{ ok: true; data: unknown } | { ok: false; message: string }> {\n if (isStandardSchema(schema)) {\n const result = await schema['~standard'].validate(value);\n if (result.issues) {\n // Name the failing field — bare \"Invalid input\" ×N gives a paying\n // buyer's agent nothing to self-correct with.\n const message = result.issues\n .map((i) => {\n const path = (i.path ?? [])\n .map((seg) => (typeof seg === 'object' ? String(seg.key) : String(seg)))\n .join('.');\n return path ? `${path}: ${i.message}` : i.message;\n })\n .join('; ');\n return { ok: false, message };\n }\n return { ok: true, data: result.value };\n }\n const result = schema.safeParse(value);\n if (!result.success) {\n return { ok: false, message: result.error.message ?? 'invalid body' };\n }\n return { ok: true, data: result.data };\n}\n\n/** Positive decimal USDC string, max 6dp (atomic precision). */\nfunction assertValidPrice(price: string, path: string): void {\n if (!/^\\d+(\\.\\d{1,6})?$/.test(price) || Number(price) <= 0) {\n throw new Error(\n `[serve] Route \"${path}\": price must be a positive decimal USDC string with up to 6 decimals, got \"${price}\"`,\n );\n }\n if (Number(price) > CATALOG_PRICE_CAP_USDC) {\n console.warn(\n `[serve] Route \"${path}\": price ${price} USDC is above the ${CATALOG_PRICE_CAP_USDC} USDC listing cap — ` +\n 'the route works, but per-call x402 is the wrong shape for it. Job-class work belongs in `t2 service create` (escrow).',\n );\n }\n}\n\nexport class RouteBuilder<TBody = undefined> {\n private priceUsdc?: string;\n private bodySchema?: ServeSchema;\n private inputSchema?: Record<string, unknown>;\n private outputSchema?: Record<string, unknown>;\n private isFree = false;\n\n constructor(\n private readonly runtime: RouteRuntime,\n private readonly options: RouteOptions,\n private readonly register: (route: BuiltRoute) => void,\n ) {}\n\n /** Charge this many USDC per call (human units, e.g. \"0.01\"). */\n paid(priceUsdc: string): this {\n assertValidPrice(priceUsdc, this.options.path);\n this.priceUsdc = priceUsdc;\n this.isFree = false;\n return this;\n }\n\n /** Serve without payment (health checks, previews, docs). */\n unprotected(): this {\n this.isFree = true;\n this.priceUsdc = undefined;\n return this;\n }\n\n /**\n * Validate the JSON request body. zod v4 / valibot / arktype / anything\n * Standard-Schema, or anything with a zod-style safeParse.\n *\n * Pass the JSON Schema as the second argument to publish it in\n * /openapi.json + /llms.txt (zod v4: `z.toJSONSchema(schema)`) — buyers'\n * agents build request bodies from it, and the catalog grades listings\n * without one.\n */\n body<T>(schema: ServeSchema<T>, jsonSchema?: Record<string, unknown>): RouteBuilder<T> {\n this.bodySchema = schema;\n this.inputSchema = jsonSchema;\n return this as unknown as RouteBuilder<T>;\n }\n\n /**\n * Declare the 200 response's JSON Schema (zod v4: `z.toJSONSchema(schema)`).\n * Published in /openapi.json + /llms.txt so buyer agents know what they're\n * buying and buyer UIs can render the deliverable by TYPE instead of\n * sniffing it — annotate with `contentMediaType` (e.g. \"image/svg+xml\",\n * \"text/markdown\") and `format: \"color\"` where they apply. Declaration\n * only; responses are never validated at runtime.\n */\n response(jsonSchema: Record<string, unknown>): this {\n this.outputSchema = jsonSchema;\n return this;\n }\n\n handler(fn: (ctx: HandlerContext<TBody>) => HandlerResult | Promise<HandlerResult>): BuiltRoute {\n if (!this.isFree && !this.priceUsdc) {\n throw new Error(\n `[serve] Route \"${this.options.path}\": call .paid('<usdc>') or .unprotected() before .handler()`,\n );\n }\n const runtime = this.runtime;\n const { path, description } = this.options;\n const priceUsdc = this.priceUsdc;\n const bodySchema = this.bodySchema;\n\n const route = (async (req: Request): Promise<Response> => {\n if (req.method === 'OPTIONS') {\n return withCors(new Response(null, { status: 204 }));\n }\n\n // Read + parse the body once, up front. A missing/empty body on a\n // schema-less route is fine; JSON parse failures only matter when a\n // paid request must be validated (the unpaid 402 fires regardless).\n let parsedBody: unknown;\n let bodyParseError: string | undefined;\n if (req.method !== 'GET' && req.method !== 'HEAD') {\n const text = await req.text();\n if (text.trim().length > 0) {\n try {\n parsedBody = JSON.parse(text);\n } catch {\n bodyParseError = 'request body is not valid JSON';\n }\n }\n }\n\n const resource = (runtime.baseUrl ?? new URL(req.url).origin).replace(/\\/$/, '') + `/${path}`;\n\n const runHandler = async (payer?: string): Promise<Response> => {\n let validated: unknown = parsedBody;\n if (bodySchema) {\n // `paid: false` is machine-readable charge honesty — a 422 fires\n // BEFORE settlement, so the buyer always keeps their money.\n if (bodyParseError) {\n return json(422, { error: bodyParseError, paid: false });\n }\n const result = await validateBody(bodySchema, parsedBody ?? {});\n if (!result.ok) {\n return json(422, { error: result.message, paid: false });\n }\n validated = result.data;\n }\n const out = await fn({ body: validated as TBody, req, payer });\n if (out instanceof Response) return withCors(out);\n return json(200, out);\n };\n\n // Free route — no payment machinery at all.\n if (!priceUsdc) {\n try {\n return await runHandler();\n } catch (err) {\n console.error(`[serve] Route \"${path}\" handler failed:`, err);\n return json(500, { error: 'internal error' });\n }\n }\n\n const paymentHeader = req.headers.get(X402_PAYMENT_HEADER);\n\n // Unpaid → 402 with the accepts[] envelope. This fires before body\n // validation on purpose: the catalog probe (and every discovery tool)\n // POSTs `{}` and must see the challenge, and an unpaid request can\n // never be charged, so there is nothing to protect yet.\n if (!paymentHeader) {\n return await respond402(runtime, { resource, priceUsdc });\n }\n\n if (isX402EscrowHeader(paymentHeader)) {\n return await respond402(runtime, {\n resource,\n priceUsdc,\n error:\n 'this endpoint sells instant per-call work (settle-then-serve), not escrow jobs — retry with a signed x402 payment',\n });\n }\n\n // 1. Parse + structural verify — right terms, right recipient, right\n // nonce. No RPC, no state. Wrong-terms payloads never reach the\n // handler.\n let payment: ReturnType<typeof parseX402Header>;\n try {\n payment = parseX402Header(paymentHeader);\n verifyX402Payment({\n payment,\n expected: {\n challengeId: payment.payload.challengeId,\n amount: priceUsdc,\n currency: runtime.currency,\n recipient: runtime.payTo,\n network: runtime.network,\n },\n });\n } catch (err) {\n return await respond402(runtime, {\n resource,\n priceUsdc,\n error: `invalid payment: ${err instanceof Error ? err.message : String(err)}`,\n });\n }\n\n // 2. Challenge-once — a signed payload is single-use even before it\n // settles (the settled digest is separately consumed inside\n // settleX402Payment, digest-once).\n const challengeKey = `challenge:${payment.payload.challengeId}`;\n if (await runtime.store.has(challengeKey)) {\n return await respond402(runtime, {\n resource,\n priceUsdc,\n error: 'payment challenge already used — sign a fresh payment',\n });\n }\n\n // 3 + 4. Validate, then compute the result. Any failure here returns\n // WITHOUT settling — the buyer-signed bytes are never submitted.\n let served: Response;\n try {\n served = await runHandler(payment.payload.senderAddress);\n } catch (err) {\n console.error(`[serve] Route \"${path}\" handler failed (payment NOT settled):`, err);\n return json(500, { error: 'internal error — you were not charged' });\n }\n if (served.status >= 400) return served; // 422 etc. — not charged\n\n // 5. Settle — submit the buyer-signed gasless bytes, confirm the\n // on-chain balance change, record the digest (digest-once).\n let settle: X402SettleResponse;\n try {\n settle = await settleX402Payment({\n payment,\n client: getGrpcClient(runtime.network, runtime.rpcUrl),\n store: runtime.store,\n expected: {\n challengeId: payment.payload.challengeId,\n amount: priceUsdc,\n currency: runtime.currency,\n recipient: runtime.payTo,\n network: runtime.network,\n },\n });\n } catch (err) {\n return await respond402(runtime, {\n resource,\n priceUsdc,\n error: `settlement failed: ${err instanceof Error ? err.message : String(err)}`,\n });\n }\n\n // 6. Consume the challenge + attach the receipt.\n try {\n await runtime.store.set(challengeKey);\n } catch {\n // Digest-once already holds; challenge-once is defense in depth.\n }\n\n // B2: attributed activity report — AFTER a successful settle only,\n // strictly fire-and-forget (a dead report can never change the\n // buyer's 200 or the settle; SPEC_T2_ACTIVITY_X402 §7 lock 6).\n reportActivity(runtime, {\n digest: settle.transaction,\n payer: settle.payer,\n priceUsdc,\n resource,\n });\n\n const headers = new Headers(served.headers);\n headers.set(X402_PAYMENT_RESPONSE_HEADER, encodeX402Response(settle));\n return new Response(served.body, { status: served.status, headers });\n }) as BuiltRoute;\n\n route.meta = {\n path,\n priceUsdc,\n description,\n bodySchema,\n inputSchema: this.inputSchema,\n outputSchema: this.outputSchema,\n };\n this.register(route);\n return route;\n }\n}\n\n/** Fire-and-forget x402.paid report (B2). Never awaited into the response\n * path; short timeout; every failure swallowed. The report endpoint\n * chain-verifies the digest, so this carries claims, not trust. */\nfunction reportActivity(\n runtime: RouteRuntime,\n args: { digest: string; payer: string; priceUsdc: string; resource: string },\n): void {\n const url = runtime.activityReportUrl;\n if (!url) return;\n try {\n void fetch(url, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n digest: args.digest,\n payTo: runtime.payTo,\n payer: args.payer,\n amountMicroUsdc: Math.round(Number(args.priceUsdc) * 1_000_000),\n network: `sui:${runtime.network}`,\n route: args.resource,\n source: 'serve',\n }),\n signal: AbortSignal.timeout(1500),\n }).catch(() => undefined);\n } catch {\n // even a sync throw (bad URL) must not touch the buyer's response\n }\n}\n\nasync function respond402(\n runtime: RouteRuntime,\n args: { resource: string; priceUsdc: string; error?: string },\n): Promise<Response> {\n try {\n const { chain, epoch } = await getChainInfo(runtime.network, runtime.rpcUrl);\n const requirements = createX402Requirements({\n challengeId: crypto.randomUUID(),\n amount: args.priceUsdc,\n currency: runtime.currency,\n recipient: runtime.payTo,\n resource: args.resource,\n network: runtime.network,\n chain,\n currentEpoch: epoch,\n });\n // Belt-and-suspenders for pre-0.2.2 discovery clients and dual-dialect\n // consumers: mirror the challenge into the MPP WWW-Authenticate shape.\n // The accepts[] body stays the authoritative envelope — the header carries\n // the same recipient/currency and the DECIMAL amount that dialect uses.\n const host = (() => {\n try {\n return new URL(args.resource).hostname;\n } catch {\n return undefined;\n }\n })();\n const wwwAuth = `Payment realm=\"${host ?? 'x402'}\", recipient=\"${runtime.payTo}\", currency=\"${runtime.currency}\", amount=\"${args.priceUsdc}\"`;\n return json(\n 402,\n {\n x402Version: X402_VERSION,\n error: args.error ?? 'Payment required',\n accepts: [requirements],\n },\n { 'WWW-Authenticate': wwwAuth },\n );\n } catch (err) {\n // Chain info unreachable — a 402 without the envelope is unpayable, so\n // be honest about the outage instead of serving a dead challenge.\n console.error('[serve] failed to build 402 challenge:', err);\n return json(503, { error: 'payment challenge temporarily unavailable' });\n }\n}\n\n","import type { DigestStore } from '@t2000/sui-x402';\n\nexport { InMemoryDigestStore } from '@t2000/sui-x402';\nexport type { DigestStore } from '@t2000/sui-x402';\n\n// ---------------------------------------------------------------------------\n// Upstash-REST digest store — the production replay store for serverless\n// hosts. Mirrors the gateway's upstash-digest-store.ts but speaks the\n// Upstash REST API over plain fetch (no @upstash/redis dependency).\n//\n// TTL: 72h. x402 payments are chain-valid for the whole ValidDuring window\n// ([minEpoch, minEpoch+1] ≈ up to ~48h on mainnet). Sui resubmission of an\n// executed tx is idempotent, so if the digest/challenge keys expired BEFORE\n// the window closed, a replayed X-PAYMENT would re-settle \"successfully\"\n// and serve again on a single payment. 72h > max window + drift.\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_TTL_SECONDS = 72 * 60 * 60;\nconst PREFIX = 'serve:digest:';\n\nexport interface UpstashDigestStoreOptions {\n url: string;\n token: string;\n /** Key TTL in seconds. Default 72h — do not lower below ~50h (see above). */\n ttlSeconds?: number;\n}\n\nexport class UpstashDigestStore implements DigestStore {\n private readonly url: string;\n private readonly token: string;\n private readonly ttlSeconds: number;\n\n constructor(options: UpstashDigestStoreOptions) {\n this.url = options.url.replace(/\\/$/, '');\n this.token = options.token;\n this.ttlSeconds = options.ttlSeconds ?? DEFAULT_TTL_SECONDS;\n }\n\n private async command(segments: string[]): Promise<unknown> {\n const res = await fetch(`${this.url}/${segments.map(encodeURIComponent).join('/')}`, {\n headers: { authorization: `Bearer ${this.token}` },\n });\n if (!res.ok) {\n throw new Error(`Upstash command failed: ${res.status} ${await res.text()}`);\n }\n const body = (await res.json()) as { result?: unknown; error?: string };\n if (body.error) throw new Error(`Upstash error: ${body.error}`);\n return body.result;\n }\n\n async has(digest: string): Promise<boolean> {\n const result = await this.command(['GET', PREFIX + digest]);\n return result !== null && result !== undefined;\n }\n\n async set(digest: string): Promise<void> {\n // SET key 1 EX <ttl> NX — atomic set-if-absent. A null result means the\n // key already existed: the digest (or challenge) was already consumed.\n const result = await this.command([\n 'SET',\n PREFIX + digest,\n '1',\n 'EX',\n String(this.ttlSeconds),\n 'NX',\n ]);\n if (result === null || result === undefined) {\n throw new Error(`Digest already used: ${digest}`);\n }\n }\n}\n","import { isValidSuiAddress, normalizeSuiAddress } from '@mysten/sui/utils';\nimport { InMemoryDigestStore, USDC, USDC_TESTNET, type Currency } from '@t2000/sui-x402';\nimport { buildLlmsTxt, buildOpenApiDocument } from './discovery.js';\nimport { RouteBuilder, type RouteOptions, type RouteRuntime } from './route.js';\nimport { UpstashDigestStore } from './store.js';\nimport type { BuiltRoute, ServeConfig, ServeNetwork } from './types.js';\n\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 activityReportUrl: config.activityReportUrl,\n };\n }\n\n /** Start building a route. Chain `.paid()` / `.body()` / `.handler()`. */\n route(options: RouteOptions): RouteBuilder {\n const path = options.path.replace(/^\\/+/, '').replace(/\\/+$/, '');\n if (!path) throw new Error('[serve] route path must be non-empty');\n return new RouteBuilder({ ...this.runtime }, { ...options, path }, (route) => {\n this.routes.set(path, route);\n });\n }\n\n /**\n * Discovery: GET handler for /openapi.json. OpenAPI 3.1 with the\n * `x-payment-info` pricing extension on every paid operation — the shape\n * x402 tooling (and any catalog built on it) indexes.\n *\n * export const GET = serve.openapi(); // app/openapi.json/route.ts\n */\n openapi(): (req: Request) => Response {\n return (req: Request) =>\n new Response(JSON.stringify(buildOpenApiDocument(this, new URL(req.url).origin), null, 2), {\n headers: { 'content-type': 'application/json', 'access-control-allow-origin': '*' },\n });\n }\n\n /**\n * Discovery: GET handler for /llms.txt — plain-text guidance agents read\n * to understand what the API sells, what it costs, and how to pay.\n *\n * export const GET = serve.llms(); // app/llms.txt/route.ts\n */\n llms(): (req: Request) => Response {\n return (req: Request) =>\n new Response(buildLlmsTxt(this, new URL(req.url).origin), {\n headers: { 'content-type': 'text/plain; charset=utf-8', 'access-control-allow-origin': '*' },\n });\n }\n\n /**\n * One fetch handler for the whole app — routes + discovery docs. For\n * fetch-native runtimes (Bun.serve, Deno.serve, Hono, Cloudflare Workers):\n *\n * Bun.serve({ fetch: serve.fetch });\n * app.all('*', (c) => serve.fetch(c.req.raw)); // Hono\n *\n * Next.js apps can skip this and export route handlers directly.\n */\n readonly fetch = async (req: Request): Promise<Response> => {\n const pathname = new URL(req.url).pathname.replace(/^\\/+/, '').replace(/\\/+$/, '');\n if (pathname === 'openapi.json') return this.openapi()(req);\n if (pathname === 'llms.txt') return this.llms()(req);\n const route = this.routes.get(pathname);\n if (route) return route(req);\n return new Response(\n JSON.stringify({ error: 'not found', discovery: ['/openapi.json', '/llms.txt'] }),\n { status: 404, headers: { 'content-type': 'application/json' } },\n );\n };\n\n /**\n * The command that sells this API as an x402 Service on your Agent ID,\n * once it is deployed. Listing is a separate, explicit step: the endpoint\n * is live-probed (it must answer 402 with a Sui challenge that pays YOUR\n * wallet) and then recorded on-chain, sponsored and gasless.\n *\n * This used to emit curls against the hosted mpp.t2000.ai catalog. That\n * proxy mall was purged 2026-08-01 (SPEC_T2_CLEANUP_USDC_ONLY) — there is\n * no central catalog to submit to. Your Agent ID IS the listing, and\n * buyers find it with `t2 services`.\n */\n catalogSubmitCommand(deployedUrl?: string): string {\n const base = (deployedUrl ?? this.baseUrl ?? 'https://<your-deployed-app>').replace(/\\/$/, '');\n const paidPaths = [...this.routes.values()].filter((r) => r.meta.priceUsdc);\n const example = paidPaths[0]?.meta.path ?? '<route>';\n return [\n '# Sell it as an x402 Service on your Agent ID (live-probed, gasless):',\n `npx @t2000/cli agent sell ${base}/${example}`,\n '# Buyers then find it with `t2 services` and pay per call with `t2 pay`.',\n ].join('\\n');\n }\n}\n\nexport function createServe(config: ServeConfig): Serve {\n return new Serve(config);\n}\n\n/**\n * Build a Serve from environment variables — the template-app path where\n * config lives in the host's env UI, not code.\n *\n * T2000_PAY_TO required — the seller's Sui address\n * T2000_NETWORK optional — 'mainnet' (default) | 'testnet'\n * T2000_BASE_URL optional — public URL of the deployed app\n * T2000_NAME optional — service name for discovery docs\n * T2000_DESCRIPTION optional — one-liner for discovery docs\n * T2000_ACTIVITY_REPORT_URL\n * optional — fire-and-forget x402.paid reports after each\n * successful settle; set https://t2000.ai/api/activity/x402\n * to appear on the t2000.ai activity tape (chain-verified\n * server-side, never affects buyer responses)\n * KV_REST_API_URL / KV_REST_API_TOKEN\n * optional — enables the durable Upstash replay store\n * (REQUIRED in serverless production; without it replay\n * state is per-instance memory)\n *\n * Empty strings are treated as unset (the Vercel empty-env bug class).\n */\nexport function createServeFromEnv(env: Record<string, string | undefined> = process.env): Serve {\n const read = (key: string): string | undefined => {\n const v = env[key]?.trim();\n return v && v.length > 0 ? v : undefined;\n };\n\n const payTo = read('T2000_PAY_TO');\n if (!payTo) {\n throw new Error(\n '[serve] T2000_PAY_TO is not set (or is empty). Set it to the Sui address your payments should settle to — `t2 address` prints yours.',\n );\n }\n\n const network = read('T2000_NETWORK');\n if (network && network !== 'mainnet' && network !== 'testnet') {\n throw new Error(`[serve] T2000_NETWORK must be 'mainnet' or 'testnet', got \"${network}\"`);\n }\n\n const kvUrl = read('KV_REST_API_URL');\n const kvToken = read('KV_REST_API_TOKEN');\n const store =\n kvUrl && kvToken ? new UpstashDigestStore({ url: kvUrl, token: kvToken }) : undefined;\n\n if (!store) {\n console.warn(\n '[serve] No KV_REST_API_URL/KV_REST_API_TOKEN — using the in-memory replay store. ' +\n 'Fine for a single long-lived process; on serverless hosts set both so replay protection is durable.',\n );\n }\n\n return new Serve({\n payTo,\n network: (network as ServeNetwork | undefined) ?? 'mainnet',\n baseUrl: read('T2000_BASE_URL'),\n name: read('T2000_NAME'),\n description: read('T2000_DESCRIPTION'),\n activityReportUrl: read('T2000_ACTIVITY_REPORT_URL'),\n store,\n });\n}\n","import type { BuiltRoute } from './types.js';\n\n/**\n * Export a built route the way Next.js App Router needs it.\n *\n * Next dispatches ONLY the methods a route.ts exports — serve's own CORS\n * handling (OPTIONS → 204 with the ACAO headers) never runs if the file\n * exports just `POST`: the browser preflight gets Next's bare 204 with no\n * CORS headers, and every browser buyer (Passport, the store's Try it)\n * fails while CLI/server buyers — who never preflight — work fine. Fetch\n * runtimes mounted via a single handler (`serve.fetch`-style) don't have\n * this hole; it is a Next export contract, not a serve one.\n *\n * export const { POST, OPTIONS } = asNextRoute(\n * serve.route({ path: 'haiku' }).paid('0.01').handler(fn),\n * );\n */\nexport function asNextRoute(route: BuiltRoute): {\n POST: BuiltRoute;\n OPTIONS: BuiltRoute;\n} {\n return { POST: route, OPTIONS: route };\n}\n"]}
package/dist/index.d.cts CHANGED
@@ -25,6 +25,17 @@ interface ServeConfig {
25
25
  name?: string;
26
26
  /** One-line description (discovery docs, slice 2). */
27
27
  description?: string;
28
+ /**
29
+ * Opt-in attributed activity reporting (SPEC_T2_ACTIVITY_X402 B2). After a
30
+ * SUCCESSFUL settle, serve fire-and-forgets the settlement digest to this
31
+ * URL (`https://t2000.ai/api/activity/x402` — the endpoint chain-verifies
32
+ * before anything is recorded). Strictly best-effort: a dead report can
33
+ * never change the buyer's response. Unset = no report.
34
+ *
35
+ * (The old `report` option — removed 2026-08-01 — posted to the retired
36
+ * mpp gateway; this posts to the receipt-backed t2000.ai ledger instead.)
37
+ */
38
+ activityReportUrl?: string;
28
39
  /** Override the Sui fullnode gRPC URL (default: mainnet/testnet fullnode). */
29
40
  rpcUrl?: string;
30
41
  }
@@ -113,6 +124,8 @@ interface RouteRuntime {
113
124
  store: DigestStore;
114
125
  baseUrl?: string;
115
126
  rpcUrl?: string;
127
+ /** B2 attributed reporting — unset = no report (see ServeConfig). */
128
+ activityReportUrl?: string;
116
129
  }
117
130
  interface RouteOptions {
118
131
  path: string;
@@ -214,6 +227,11 @@ declare function createServe(config: ServeConfig): Serve;
214
227
  * T2000_BASE_URL optional — public URL of the deployed app
215
228
  * T2000_NAME optional — service name for discovery docs
216
229
  * T2000_DESCRIPTION optional — one-liner for discovery docs
230
+ * T2000_ACTIVITY_REPORT_URL
231
+ * optional — fire-and-forget x402.paid reports after each
232
+ * successful settle; set https://t2000.ai/api/activity/x402
233
+ * to appear on the t2000.ai activity tape (chain-verified
234
+ * server-side, never affects buyer responses)
217
235
  * KV_REST_API_URL / KV_REST_API_TOKEN
218
236
  * optional — enables the durable Upstash replay store
219
237
  * (REQUIRED in serverless production; without it replay
package/dist/index.d.ts CHANGED
@@ -25,6 +25,17 @@ interface ServeConfig {
25
25
  name?: string;
26
26
  /** One-line description (discovery docs, slice 2). */
27
27
  description?: string;
28
+ /**
29
+ * Opt-in attributed activity reporting (SPEC_T2_ACTIVITY_X402 B2). After a
30
+ * SUCCESSFUL settle, serve fire-and-forgets the settlement digest to this
31
+ * URL (`https://t2000.ai/api/activity/x402` — the endpoint chain-verifies
32
+ * before anything is recorded). Strictly best-effort: a dead report can
33
+ * never change the buyer's response. Unset = no report.
34
+ *
35
+ * (The old `report` option — removed 2026-08-01 — posted to the retired
36
+ * mpp gateway; this posts to the receipt-backed t2000.ai ledger instead.)
37
+ */
38
+ activityReportUrl?: string;
28
39
  /** Override the Sui fullnode gRPC URL (default: mainnet/testnet fullnode). */
29
40
  rpcUrl?: string;
30
41
  }
@@ -113,6 +124,8 @@ interface RouteRuntime {
113
124
  store: DigestStore;
114
125
  baseUrl?: string;
115
126
  rpcUrl?: string;
127
+ /** B2 attributed reporting — unset = no report (see ServeConfig). */
128
+ activityReportUrl?: string;
116
129
  }
117
130
  interface RouteOptions {
118
131
  path: string;
@@ -214,6 +227,11 @@ declare function createServe(config: ServeConfig): Serve;
214
227
  * T2000_BASE_URL optional — public URL of the deployed app
215
228
  * T2000_NAME optional — service name for discovery docs
216
229
  * T2000_DESCRIPTION optional — one-liner for discovery docs
230
+ * T2000_ACTIVITY_REPORT_URL
231
+ * optional — fire-and-forget x402.paid reports after each
232
+ * successful settle; set https://t2000.ai/api/activity/x402
233
+ * to appear on the t2000.ai activity tape (chain-verified
234
+ * server-side, never affects buyer responses)
217
235
  * KV_REST_API_URL / KV_REST_API_TOKEN
218
236
  * optional — enables the durable Upstash replay store
219
237
  * (REQUIRED in serverless production; without it replay
package/dist/index.js CHANGED
@@ -368,6 +368,12 @@ var RouteBuilder = class {
368
368
  await runtime.store.set(challengeKey);
369
369
  } catch {
370
370
  }
371
+ reportActivity(runtime, {
372
+ digest: settle.transaction,
373
+ payer: settle.payer,
374
+ priceUsdc,
375
+ resource
376
+ });
371
377
  const headers = new Headers(served.headers);
372
378
  headers.set(X402_PAYMENT_RESPONSE_HEADER, encodeX402Response(settle));
373
379
  return new Response(served.body, { status: served.status, headers });
@@ -384,6 +390,27 @@ var RouteBuilder = class {
384
390
  return route;
385
391
  }
386
392
  };
393
+ function reportActivity(runtime, args) {
394
+ const url = runtime.activityReportUrl;
395
+ if (!url) return;
396
+ try {
397
+ void fetch(url, {
398
+ method: "POST",
399
+ headers: { "content-type": "application/json" },
400
+ body: JSON.stringify({
401
+ digest: args.digest,
402
+ payTo: runtime.payTo,
403
+ payer: args.payer,
404
+ amountMicroUsdc: Math.round(Number(args.priceUsdc) * 1e6),
405
+ network: `sui:${runtime.network}`,
406
+ route: args.resource,
407
+ source: "serve"
408
+ }),
409
+ signal: AbortSignal.timeout(1500)
410
+ }).catch(() => void 0);
411
+ } catch {
412
+ }
413
+ }
387
414
  async function respond402(runtime, args) {
388
415
  try {
389
416
  const { chain, epoch } = await getChainInfo(runtime.network, runtime.rpcUrl);
@@ -488,7 +515,8 @@ var Serve = class {
488
515
  currency,
489
516
  store: config.store ?? new InMemoryDigestStore(),
490
517
  baseUrl: this.baseUrl,
491
- rpcUrl: config.rpcUrl
518
+ rpcUrl: config.rpcUrl,
519
+ activityReportUrl: config.activityReportUrl
492
520
  };
493
521
  }
494
522
  /** Start building a route. Chain `.paid()` / `.body()` / `.handler()`. */
@@ -596,6 +624,7 @@ function createServeFromEnv(env = process.env) {
596
624
  baseUrl: read("T2000_BASE_URL"),
597
625
  name: read("T2000_NAME"),
598
626
  description: read("T2000_DESCRIPTION"),
627
+ activityReportUrl: read("T2000_ACTIVITY_REPORT_URL"),
599
628
  store
600
629
  });
601
630
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/discovery.ts","../src/chain.ts","../src/route.ts","../src/store.ts","../src/serve.ts","../src/next.ts"],"names":["result","USDC_TESTNET","USDC","InMemoryDigestStore"],"mappings":"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","file":"index.js","sourcesContent":["import { USDC, USDC_TESTNET } from '@t2000/sui-x402';\nimport type { Serve } from './serve.js';\n\n// ---------------------------------------------------------------------------\n// Discovery docs — /openapi.json + /llms.txt.\n//\n// The shapes here are what the on-chain listing probe grades (the check\n// behind `t2 agent sell`) (was: apps/gateway/lib/\n// catalog-ingest.ts `gradeListing`): a warning-free listing needs info.title,\n// a one-paragraph info.description, a flat string `x-payment-info.price` per\n// paid operation, and an application/json requestBody schema with typed\n// properties. Everything serve can derive is emitted automatically; the JSON\n// request schema comes from the route's `inputSchema` (zod v4 users:\n// `z.toJSONSchema(schema)`).\n// ---------------------------------------------------------------------------\n\nexport function buildOpenApiDocument(serve: Serve, origin?: string): Record<string, unknown> {\n const base = serve.baseUrl ?? origin;\n const paths: Record<string, unknown> = {};\n\n for (const route of serve.routes.values()) {\n const { path, priceUsdc, description, inputSchema, outputSchema } = route.meta;\n const operation: Record<string, unknown> = {\n operationId: path.replace(/[^a-zA-Z0-9]+/g, '_'),\n summary: description ?? path,\n responses: {\n '200': outputSchema\n ? {\n description: 'Success',\n content: { 'application/json': { schema: outputSchema } },\n }\n : { description: 'Success' },\n ...(priceUsdc\n ? {\n '402': {\n description:\n 'Payment required — the body carries an x402 accepts[] envelope (scheme \"exact\", network sui). Sign it and retry with the X-PAYMENT header.',\n },\n }\n : {}),\n '422': { description: 'Invalid request body — never charged' },\n },\n };\n if (priceUsdc) {\n // Same shape the gateway's own /openapi.json emits: 'mpp' is the\n // protocol family, 'x402' the dialect; the x402 block mirrors the\n // static half of the live accepts[] entry (dynamic fields ride the 402).\n operation['x-payment-info'] = {\n pricingMode: 'fixed',\n price: priceUsdc,\n currency: 'USDC',\n protocols: ['mpp', 'x402'],\n x402: {\n scheme: 'exact',\n network: `sui:${serve.network}`,\n asset: (serve.network === 'testnet' ? USDC_TESTNET : USDC).type,\n payTo: serve.payTo,\n },\n };\n }\n if (inputSchema) {\n operation.requestBody = {\n required: true,\n content: { 'application/json': { schema: inputSchema } },\n };\n }\n paths[`/${path}`] = { post: operation };\n }\n\n return {\n openapi: '3.1.0',\n info: {\n title: serve.name ?? 'Paid API',\n version: '1.0.0',\n description:\n serve.description ??\n 'Agent-payable API. Every paid endpoint answers 402 with an x402 accepts[] envelope; payment settles in USDC on Sui.',\n },\n ...(base ? { servers: [{ url: base }] } : {}),\n paths,\n };\n}\n\nexport function buildLlmsTxt(serve: Serve, origin?: string): string {\n const base = serve.baseUrl ?? origin ?? '';\n const lines: string[] = [];\n lines.push(`# ${serve.name ?? 'Paid API'}`);\n lines.push('');\n if (serve.description) {\n lines.push(serve.description);\n lines.push('');\n }\n lines.push('## How to pay');\n lines.push('');\n lines.push(\n 'Endpoints below are paid per call in USDC on Sui (x402). An unpaid request returns',\n 'HTTP 402 with an `accepts[]` envelope; sign it and retry with the `X-PAYMENT` header.',\n 'Invalid input returns 422 before any payment is taken. A failed call is never charged.',\n '',\n 'Easiest client: `npm i -g @t2000/cli` then `t2 pay <url> --data \\'{...}\\'`,',\n 'or the t2000 MCP server (`t2000_pay`), or `@t2000/sdk` `pay()`.',\n '',\n );\n lines.push('## Endpoints');\n lines.push('');\n for (const route of serve.routes.values()) {\n const { path, priceUsdc, description, inputSchema, outputSchema } = route.meta;\n const price = priceUsdc ? `${priceUsdc} USDC per call` : 'free';\n lines.push(`### POST ${base}/${path} — ${price}`);\n if (description) lines.push(description);\n if (inputSchema) {\n lines.push('Request body (JSON Schema):');\n lines.push('```json');\n lines.push(JSON.stringify(inputSchema, null, 2));\n lines.push('```');\n }\n if (outputSchema) {\n lines.push('Response (JSON Schema — contentMediaType/format annotations name the deliverable types):');\n lines.push('```json');\n lines.push(JSON.stringify(outputSchema, null, 2));\n lines.push('```');\n }\n lines.push('');\n }\n lines.push(`Discovery: ${base}/openapi.json`);\n return lines.join('\\n');\n}\n","import { SuiGrpcClient } from '@mysten/sui/grpc';\nimport type { ServeNetwork } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Chain plumbing — same shape as the gateway's x402-dialect.ts (the reference\n// composition). All reads are gRPC; this package never touches JSON-RPC.\n//\n// Cache policy: the chain identifier (genesis digest) is immutable per\n// network — cached forever. The epoch advances ~daily and x402 requirements\n// are valid for [epoch, epoch+1], so a 10-minute TTL is conservatively fresh.\n// ---------------------------------------------------------------------------\n\nconst FULLNODE_URLS: Record<ServeNetwork, string> = {\n mainnet: 'https://fullnode.mainnet.sui.io:443',\n testnet: 'https://fullnode.testnet.sui.io:443',\n};\n\nconst EPOCH_TTL_MS = 10 * 60 * 1000;\n\nexport interface ChainInfo {\n chain: string;\n epoch: string;\n}\n\ninterface ChainState {\n client?: SuiGrpcClient;\n chainId?: string;\n epoch?: { value: string; fetchedAt: number };\n}\n\nconst state: Partial<Record<ServeNetwork, ChainState>> = {};\n\nexport function getGrpcClient(network: ServeNetwork, rpcUrl?: string): SuiGrpcClient {\n const s = (state[network] ??= {});\n if (!s.client) {\n s.client = new SuiGrpcClient({\n baseUrl: rpcUrl ?? FULLNODE_URLS[network],\n network,\n });\n }\n return s.client;\n}\n\nexport async function getChainInfo(network: ServeNetwork, rpcUrl?: string): Promise<ChainInfo> {\n const client = getGrpcClient(network, rpcUrl);\n const s = (state[network] ??= {});\n if (!s.chainId) {\n const res = await client.core.getChainIdentifier();\n s.chainId = res.chainIdentifier;\n }\n if (!s.epoch || Date.now() - s.epoch.fetchedAt > EPOCH_TTL_MS) {\n const res = await client.core.getCurrentSystemState();\n s.epoch = { value: String(res.systemState.epoch), fetchedAt: Date.now() };\n }\n return { chain: s.chainId, epoch: s.epoch.value };\n}\n\n/** Test seam — reset module caches between cases. */\nexport function __resetChainCaches(): void {\n delete state.mainnet;\n delete state.testnet;\n}\n\n/** Test seam — pre-seed chain info so tests never hit the network. */\nexport function __seedChainInfo(network: ServeNetwork, chain: string, epoch: string): void {\n const s = (state[network] ??= {});\n s.chainId = chain;\n s.epoch = { value: epoch, fetchedAt: Date.now() };\n}\n","import type { Currency, DigestStore } from '@t2000/sui-x402';\nimport {\n createX402Requirements,\n encodeX402Response,\n isX402EscrowHeader,\n parseX402Header,\n settleX402Payment,\n verifyX402Payment,\n X402_PAYMENT_HEADER,\n X402_PAYMENT_RESPONSE_HEADER,\n X402_VERSION,\n type X402SettleResponse,\n} from '@t2000/sui-x402';\nimport { getChainInfo, getGrpcClient } from './chain.js';\nimport type {\n BuiltRoute,\n HandlerContext,\n HandlerResult,\n ServeNetwork,\n ServeSchema,\n StandardSchemaLike,\n} from './types.js';\n\n// ---------------------------------------------------------------------------\n// The paid-request lifecycle (SPEC_T2000_SERVE §3 — sign-then-settle,\n// handler-then-settle):\n//\n// no X-PAYMENT → 402 with the accepts[] envelope (never a charge;\n// the catalog probe and every discovery tool read\n// this, so it fires BEFORE body validation)\n// X-PAYMENT present:\n// 1. parse + STRUCTURAL verify (right amount/recipient/nonce — no RPC)\n// 2. challenge-once check (a signed payload is single-use)\n// 3. validate the body — invalid → 422, payment NEVER submitted\n// (the JMPR paid-422 class is impossible: the buyer keeps their money)\n// 4. run the handler — throws → 500, payment NEVER submitted\n// 5. settle (submit the buyer-signed gasless bytes; digest-once inside)\n// 6. consume the challenge, attach the X-PAYMENT-RESPONSE receipt\n//\n// Money only moves at step 5, after the seller has already produced the\n// result. A forged payload can waste seller compute (signature authority is\n// the chain at settle time), never buyer money.\n// ---------------------------------------------------------------------------\n\nexport interface RouteRuntime {\n payTo: string;\n network: ServeNetwork;\n currency: Currency;\n store: DigestStore;\n baseUrl?: string;\n rpcUrl?: string;\n}\n\nexport interface RouteOptions {\n path: string;\n description?: string;\n}\n\n/** Sanity cap on a per-call price — above this, the work is job-shaped\n * (escrow) rather than a per-call x402 Service. */\nconst CATALOG_PRICE_CAP_USDC = 5;\n\nconst CORS_HEADERS: Record<string, string> = {\n 'access-control-allow-origin': '*',\n 'access-control-allow-methods': 'GET, POST, PUT, DELETE, OPTIONS',\n 'access-control-allow-headers': `content-type, ${X402_PAYMENT_HEADER}`,\n 'access-control-expose-headers': `${X402_PAYMENT_RESPONSE_HEADER}, WWW-Authenticate`,\n};\n\nfunction withCors(response: Response): Response {\n const headers = new Headers(response.headers);\n for (const [k, v] of Object.entries(CORS_HEADERS)) headers.set(k, v);\n return new Response(response.body, { status: response.status, headers });\n}\n\nfunction json(status: number, body: unknown, headers?: Record<string, string>): Response {\n return withCors(\n new Response(JSON.stringify(body), {\n status,\n headers: { 'content-type': 'application/json', ...headers },\n }),\n );\n}\n\nfunction isStandardSchema(schema: ServeSchema): schema is StandardSchemaLike {\n return typeof schema === 'object' && schema !== null && '~standard' in schema;\n}\n\nasync function validateBody(\n schema: ServeSchema,\n value: unknown,\n): Promise<{ ok: true; data: unknown } | { ok: false; message: string }> {\n if (isStandardSchema(schema)) {\n const result = await schema['~standard'].validate(value);\n if (result.issues) {\n // Name the failing field — bare \"Invalid input\" ×N gives a paying\n // buyer's agent nothing to self-correct with.\n const message = result.issues\n .map((i) => {\n const path = (i.path ?? [])\n .map((seg) => (typeof seg === 'object' ? String(seg.key) : String(seg)))\n .join('.');\n return path ? `${path}: ${i.message}` : i.message;\n })\n .join('; ');\n return { ok: false, message };\n }\n return { ok: true, data: result.value };\n }\n const result = schema.safeParse(value);\n if (!result.success) {\n return { ok: false, message: result.error.message ?? 'invalid body' };\n }\n return { ok: true, data: result.data };\n}\n\n/** Positive decimal USDC string, max 6dp (atomic precision). */\nfunction assertValidPrice(price: string, path: string): void {\n if (!/^\\d+(\\.\\d{1,6})?$/.test(price) || Number(price) <= 0) {\n throw new Error(\n `[serve] Route \"${path}\": price must be a positive decimal USDC string with up to 6 decimals, got \"${price}\"`,\n );\n }\n if (Number(price) > CATALOG_PRICE_CAP_USDC) {\n console.warn(\n `[serve] Route \"${path}\": price ${price} USDC is above the ${CATALOG_PRICE_CAP_USDC} USDC listing cap — ` +\n 'the route works, but per-call x402 is the wrong shape for it. Job-class work belongs in `t2 service create` (escrow).',\n );\n }\n}\n\nexport class RouteBuilder<TBody = undefined> {\n private priceUsdc?: string;\n private bodySchema?: ServeSchema;\n private inputSchema?: Record<string, unknown>;\n private outputSchema?: Record<string, unknown>;\n private isFree = false;\n\n constructor(\n private readonly runtime: RouteRuntime,\n private readonly options: RouteOptions,\n private readonly register: (route: BuiltRoute) => void,\n ) {}\n\n /** Charge this many USDC per call (human units, e.g. \"0.01\"). */\n paid(priceUsdc: string): this {\n assertValidPrice(priceUsdc, this.options.path);\n this.priceUsdc = priceUsdc;\n this.isFree = false;\n return this;\n }\n\n /** Serve without payment (health checks, previews, docs). */\n unprotected(): this {\n this.isFree = true;\n this.priceUsdc = undefined;\n return this;\n }\n\n /**\n * Validate the JSON request body. zod v4 / valibot / arktype / anything\n * Standard-Schema, or anything with a zod-style safeParse.\n *\n * Pass the JSON Schema as the second argument to publish it in\n * /openapi.json + /llms.txt (zod v4: `z.toJSONSchema(schema)`) — buyers'\n * agents build request bodies from it, and the catalog grades listings\n * without one.\n */\n body<T>(schema: ServeSchema<T>, jsonSchema?: Record<string, unknown>): RouteBuilder<T> {\n this.bodySchema = schema;\n this.inputSchema = jsonSchema;\n return this as unknown as RouteBuilder<T>;\n }\n\n /**\n * Declare the 200 response's JSON Schema (zod v4: `z.toJSONSchema(schema)`).\n * Published in /openapi.json + /llms.txt so buyer agents know what they're\n * buying and buyer UIs can render the deliverable by TYPE instead of\n * sniffing it — annotate with `contentMediaType` (e.g. \"image/svg+xml\",\n * \"text/markdown\") and `format: \"color\"` where they apply. Declaration\n * only; responses are never validated at runtime.\n */\n response(jsonSchema: Record<string, unknown>): this {\n this.outputSchema = jsonSchema;\n return this;\n }\n\n handler(fn: (ctx: HandlerContext<TBody>) => HandlerResult | Promise<HandlerResult>): BuiltRoute {\n if (!this.isFree && !this.priceUsdc) {\n throw new Error(\n `[serve] Route \"${this.options.path}\": call .paid('<usdc>') or .unprotected() before .handler()`,\n );\n }\n const runtime = this.runtime;\n const { path, description } = this.options;\n const priceUsdc = this.priceUsdc;\n const bodySchema = this.bodySchema;\n\n const route = (async (req: Request): Promise<Response> => {\n if (req.method === 'OPTIONS') {\n return withCors(new Response(null, { status: 204 }));\n }\n\n // Read + parse the body once, up front. A missing/empty body on a\n // schema-less route is fine; JSON parse failures only matter when a\n // paid request must be validated (the unpaid 402 fires regardless).\n let parsedBody: unknown;\n let bodyParseError: string | undefined;\n if (req.method !== 'GET' && req.method !== 'HEAD') {\n const text = await req.text();\n if (text.trim().length > 0) {\n try {\n parsedBody = JSON.parse(text);\n } catch {\n bodyParseError = 'request body is not valid JSON';\n }\n }\n }\n\n const resource = (runtime.baseUrl ?? new URL(req.url).origin).replace(/\\/$/, '') + `/${path}`;\n\n const runHandler = async (payer?: string): Promise<Response> => {\n let validated: unknown = parsedBody;\n if (bodySchema) {\n // `paid: false` is machine-readable charge honesty — a 422 fires\n // BEFORE settlement, so the buyer always keeps their money.\n if (bodyParseError) {\n return json(422, { error: bodyParseError, paid: false });\n }\n const result = await validateBody(bodySchema, parsedBody ?? {});\n if (!result.ok) {\n return json(422, { error: result.message, paid: false });\n }\n validated = result.data;\n }\n const out = await fn({ body: validated as TBody, req, payer });\n if (out instanceof Response) return withCors(out);\n return json(200, out);\n };\n\n // Free route — no payment machinery at all.\n if (!priceUsdc) {\n try {\n return await runHandler();\n } catch (err) {\n console.error(`[serve] Route \"${path}\" handler failed:`, err);\n return json(500, { error: 'internal error' });\n }\n }\n\n const paymentHeader = req.headers.get(X402_PAYMENT_HEADER);\n\n // Unpaid → 402 with the accepts[] envelope. This fires before body\n // validation on purpose: the catalog probe (and every discovery tool)\n // POSTs `{}` and must see the challenge, and an unpaid request can\n // never be charged, so there is nothing to protect yet.\n if (!paymentHeader) {\n return await respond402(runtime, { resource, priceUsdc });\n }\n\n if (isX402EscrowHeader(paymentHeader)) {\n return await respond402(runtime, {\n resource,\n priceUsdc,\n error:\n 'this endpoint sells instant per-call work (settle-then-serve), not escrow jobs — retry with a signed x402 payment',\n });\n }\n\n // 1. Parse + structural verify — right terms, right recipient, right\n // nonce. No RPC, no state. Wrong-terms payloads never reach the\n // handler.\n let payment: ReturnType<typeof parseX402Header>;\n try {\n payment = parseX402Header(paymentHeader);\n verifyX402Payment({\n payment,\n expected: {\n challengeId: payment.payload.challengeId,\n amount: priceUsdc,\n currency: runtime.currency,\n recipient: runtime.payTo,\n network: runtime.network,\n },\n });\n } catch (err) {\n return await respond402(runtime, {\n resource,\n priceUsdc,\n error: `invalid payment: ${err instanceof Error ? err.message : String(err)}`,\n });\n }\n\n // 2. Challenge-once — a signed payload is single-use even before it\n // settles (the settled digest is separately consumed inside\n // settleX402Payment, digest-once).\n const challengeKey = `challenge:${payment.payload.challengeId}`;\n if (await runtime.store.has(challengeKey)) {\n return await respond402(runtime, {\n resource,\n priceUsdc,\n error: 'payment challenge already used — sign a fresh payment',\n });\n }\n\n // 3 + 4. Validate, then compute the result. Any failure here returns\n // WITHOUT settling — the buyer-signed bytes are never submitted.\n let served: Response;\n try {\n served = await runHandler(payment.payload.senderAddress);\n } catch (err) {\n console.error(`[serve] Route \"${path}\" handler failed (payment NOT settled):`, err);\n return json(500, { error: 'internal error — you were not charged' });\n }\n if (served.status >= 400) return served; // 422 etc. — not charged\n\n // 5. Settle — submit the buyer-signed gasless bytes, confirm the\n // on-chain balance change, record the digest (digest-once).\n let settle: X402SettleResponse;\n try {\n settle = await settleX402Payment({\n payment,\n client: getGrpcClient(runtime.network, runtime.rpcUrl),\n store: runtime.store,\n expected: {\n challengeId: payment.payload.challengeId,\n amount: priceUsdc,\n currency: runtime.currency,\n recipient: runtime.payTo,\n network: runtime.network,\n },\n });\n } catch (err) {\n return await respond402(runtime, {\n resource,\n priceUsdc,\n error: `settlement failed: ${err instanceof Error ? err.message : String(err)}`,\n });\n }\n\n // 6. Consume the challenge + attach the receipt.\n try {\n await runtime.store.set(challengeKey);\n } catch {\n // Digest-once already holds; challenge-once is defense in depth.\n }\n\n const headers = new Headers(served.headers);\n headers.set(X402_PAYMENT_RESPONSE_HEADER, encodeX402Response(settle));\n return new Response(served.body, { status: served.status, headers });\n }) as BuiltRoute;\n\n route.meta = {\n path,\n priceUsdc,\n description,\n bodySchema,\n inputSchema: this.inputSchema,\n outputSchema: this.outputSchema,\n };\n this.register(route);\n return route;\n }\n}\n\nasync function respond402(\n runtime: RouteRuntime,\n args: { resource: string; priceUsdc: string; error?: string },\n): Promise<Response> {\n try {\n const { chain, epoch } = await getChainInfo(runtime.network, runtime.rpcUrl);\n const requirements = createX402Requirements({\n challengeId: crypto.randomUUID(),\n amount: args.priceUsdc,\n currency: runtime.currency,\n recipient: runtime.payTo,\n resource: args.resource,\n network: runtime.network,\n chain,\n currentEpoch: epoch,\n });\n // Belt-and-suspenders for pre-0.2.2 discovery clients and dual-dialect\n // consumers: mirror the challenge into the MPP WWW-Authenticate shape.\n // The accepts[] body stays the authoritative envelope — the header carries\n // the same recipient/currency and the DECIMAL amount that dialect uses.\n const host = (() => {\n try {\n return new URL(args.resource).hostname;\n } catch {\n return undefined;\n }\n })();\n const wwwAuth = `Payment realm=\"${host ?? 'x402'}\", recipient=\"${runtime.payTo}\", currency=\"${runtime.currency}\", amount=\"${args.priceUsdc}\"`;\n return json(\n 402,\n {\n x402Version: X402_VERSION,\n error: args.error ?? 'Payment required',\n accepts: [requirements],\n },\n { 'WWW-Authenticate': wwwAuth },\n );\n } catch (err) {\n // Chain info unreachable — a 402 without the envelope is unpayable, so\n // be honest about the outage instead of serving a dead challenge.\n console.error('[serve] failed to build 402 challenge:', err);\n return json(503, { error: 'payment challenge temporarily unavailable' });\n }\n}\n\n","import type { DigestStore } from '@t2000/sui-x402';\n\nexport { InMemoryDigestStore } from '@t2000/sui-x402';\nexport type { DigestStore } from '@t2000/sui-x402';\n\n// ---------------------------------------------------------------------------\n// Upstash-REST digest store — the production replay store for serverless\n// hosts. Mirrors the gateway's upstash-digest-store.ts but speaks the\n// Upstash REST API over plain fetch (no @upstash/redis dependency).\n//\n// TTL: 72h. x402 payments are chain-valid for the whole ValidDuring window\n// ([minEpoch, minEpoch+1] ≈ up to ~48h on mainnet). Sui resubmission of an\n// executed tx is idempotent, so if the digest/challenge keys expired BEFORE\n// the window closed, a replayed X-PAYMENT would re-settle \"successfully\"\n// and serve again on a single payment. 72h > max window + drift.\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_TTL_SECONDS = 72 * 60 * 60;\nconst PREFIX = 'serve:digest:';\n\nexport interface UpstashDigestStoreOptions {\n url: string;\n token: string;\n /** Key TTL in seconds. Default 72h — do not lower below ~50h (see above). */\n ttlSeconds?: number;\n}\n\nexport class UpstashDigestStore implements DigestStore {\n private readonly url: string;\n private readonly token: string;\n private readonly ttlSeconds: number;\n\n constructor(options: UpstashDigestStoreOptions) {\n this.url = options.url.replace(/\\/$/, '');\n this.token = options.token;\n this.ttlSeconds = options.ttlSeconds ?? DEFAULT_TTL_SECONDS;\n }\n\n private async command(segments: string[]): Promise<unknown> {\n const res = await fetch(`${this.url}/${segments.map(encodeURIComponent).join('/')}`, {\n headers: { authorization: `Bearer ${this.token}` },\n });\n if (!res.ok) {\n throw new Error(`Upstash command failed: ${res.status} ${await res.text()}`);\n }\n const body = (await res.json()) as { result?: unknown; error?: string };\n if (body.error) throw new Error(`Upstash error: ${body.error}`);\n return body.result;\n }\n\n async has(digest: string): Promise<boolean> {\n const result = await this.command(['GET', PREFIX + digest]);\n return result !== null && result !== undefined;\n }\n\n async set(digest: string): Promise<void> {\n // SET key 1 EX <ttl> NX — atomic set-if-absent. A null result means the\n // key already existed: the digest (or challenge) was already consumed.\n const result = await this.command([\n 'SET',\n PREFIX + digest,\n '1',\n 'EX',\n String(this.ttlSeconds),\n 'NX',\n ]);\n if (result === null || result === undefined) {\n throw new Error(`Digest already used: ${digest}`);\n }\n }\n}\n","import { isValidSuiAddress, normalizeSuiAddress } from '@mysten/sui/utils';\nimport { InMemoryDigestStore, USDC, USDC_TESTNET, type Currency } from '@t2000/sui-x402';\nimport { buildLlmsTxt, buildOpenApiDocument } from './discovery.js';\nimport { RouteBuilder, type RouteOptions, type RouteRuntime } from './route.js';\nimport { UpstashDigestStore } from './store.js';\nimport type { BuiltRoute, ServeConfig, ServeNetwork } from './types.js';\n\nexport class Serve {\n private readonly runtime: RouteRuntime;\n /** Every route built through this instance, keyed by path (discovery). */\n readonly routes = new Map<string, BuiltRoute>();\n\n readonly payTo: string;\n readonly network: ServeNetwork;\n readonly name?: string;\n readonly description?: string;\n readonly baseUrl?: string;\n\n constructor(config: ServeConfig) {\n if (!config.payTo || !isValidSuiAddress(config.payTo)) {\n throw new Error(\n `[serve] payTo must be a valid Sui address (the wallet your payments settle to), got \"${config.payTo}\"`,\n );\n }\n this.payTo = normalizeSuiAddress(config.payTo);\n this.network = config.network ?? 'mainnet';\n this.name = config.name;\n this.description = config.description;\n this.baseUrl = config.baseUrl?.replace(/\\/$/, '');\n\n const currency: Currency = this.network === 'testnet' ? USDC_TESTNET : USDC;\n this.runtime = {\n payTo: this.payTo,\n network: this.network,\n currency,\n store: config.store ?? new InMemoryDigestStore(),\n baseUrl: this.baseUrl,\n rpcUrl: config.rpcUrl,\n };\n }\n\n /** Start building a route. Chain `.paid()` / `.body()` / `.handler()`. */\n route(options: RouteOptions): RouteBuilder {\n const path = options.path.replace(/^\\/+/, '').replace(/\\/+$/, '');\n if (!path) throw new Error('[serve] route path must be non-empty');\n return new RouteBuilder({ ...this.runtime }, { ...options, path }, (route) => {\n this.routes.set(path, route);\n });\n }\n\n /**\n * Discovery: GET handler for /openapi.json. OpenAPI 3.1 with the\n * `x-payment-info` pricing extension on every paid operation — the shape\n * x402 tooling (and any catalog built on it) indexes.\n *\n * export const GET = serve.openapi(); // app/openapi.json/route.ts\n */\n openapi(): (req: Request) => Response {\n return (req: Request) =>\n new Response(JSON.stringify(buildOpenApiDocument(this, new URL(req.url).origin), null, 2), {\n headers: { 'content-type': 'application/json', 'access-control-allow-origin': '*' },\n });\n }\n\n /**\n * Discovery: GET handler for /llms.txt — plain-text guidance agents read\n * to understand what the API sells, what it costs, and how to pay.\n *\n * export const GET = serve.llms(); // app/llms.txt/route.ts\n */\n llms(): (req: Request) => Response {\n return (req: Request) =>\n new Response(buildLlmsTxt(this, new URL(req.url).origin), {\n headers: { 'content-type': 'text/plain; charset=utf-8', 'access-control-allow-origin': '*' },\n });\n }\n\n /**\n * One fetch handler for the whole app — routes + discovery docs. For\n * fetch-native runtimes (Bun.serve, Deno.serve, Hono, Cloudflare Workers):\n *\n * Bun.serve({ fetch: serve.fetch });\n * app.all('*', (c) => serve.fetch(c.req.raw)); // Hono\n *\n * Next.js apps can skip this and export route handlers directly.\n */\n readonly fetch = async (req: Request): Promise<Response> => {\n const pathname = new URL(req.url).pathname.replace(/^\\/+/, '').replace(/\\/+$/, '');\n if (pathname === 'openapi.json') return this.openapi()(req);\n if (pathname === 'llms.txt') return this.llms()(req);\n const route = this.routes.get(pathname);\n if (route) return route(req);\n return new Response(\n JSON.stringify({ error: 'not found', discovery: ['/openapi.json', '/llms.txt'] }),\n { status: 404, headers: { 'content-type': 'application/json' } },\n );\n };\n\n /**\n * The command that sells this API as an x402 Service on your Agent ID,\n * once it is deployed. Listing is a separate, explicit step: the endpoint\n * is live-probed (it must answer 402 with a Sui challenge that pays YOUR\n * wallet) and then recorded on-chain, sponsored and gasless.\n *\n * This used to emit curls against the hosted mpp.t2000.ai catalog. That\n * proxy mall was purged 2026-08-01 (SPEC_T2_CLEANUP_USDC_ONLY) — there is\n * no central catalog to submit to. Your Agent ID IS the listing, and\n * buyers find it with `t2 services`.\n */\n catalogSubmitCommand(deployedUrl?: string): string {\n const base = (deployedUrl ?? this.baseUrl ?? 'https://<your-deployed-app>').replace(/\\/$/, '');\n const paidPaths = [...this.routes.values()].filter((r) => r.meta.priceUsdc);\n const example = paidPaths[0]?.meta.path ?? '<route>';\n return [\n '# Sell it as an x402 Service on your Agent ID (live-probed, gasless):',\n `npx @t2000/cli agent sell ${base}/${example}`,\n '# Buyers then find it with `t2 services` and pay per call with `t2 pay`.',\n ].join('\\n');\n }\n}\n\nexport function createServe(config: ServeConfig): Serve {\n return new Serve(config);\n}\n\n/**\n * Build a Serve from environment variables — the template-app path where\n * config lives in the host's env UI, not code.\n *\n * T2000_PAY_TO required — the seller's Sui address\n * T2000_NETWORK optional — 'mainnet' (default) | 'testnet'\n * T2000_BASE_URL optional — public URL of the deployed app\n * T2000_NAME optional — service name for discovery docs\n * T2000_DESCRIPTION optional — one-liner for discovery docs\n * KV_REST_API_URL / KV_REST_API_TOKEN\n * optional — enables the durable Upstash replay store\n * (REQUIRED in serverless production; without it replay\n * state is per-instance memory)\n *\n * Empty strings are treated as unset (the Vercel empty-env bug class).\n */\nexport function createServeFromEnv(env: Record<string, string | undefined> = process.env): Serve {\n const read = (key: string): string | undefined => {\n const v = env[key]?.trim();\n return v && v.length > 0 ? v : undefined;\n };\n\n const payTo = read('T2000_PAY_TO');\n if (!payTo) {\n throw new Error(\n '[serve] T2000_PAY_TO is not set (or is empty). Set it to the Sui address your payments should settle to — `t2 address` prints yours.',\n );\n }\n\n const network = read('T2000_NETWORK');\n if (network && network !== 'mainnet' && network !== 'testnet') {\n throw new Error(`[serve] T2000_NETWORK must be 'mainnet' or 'testnet', got \"${network}\"`);\n }\n\n const kvUrl = read('KV_REST_API_URL');\n const kvToken = read('KV_REST_API_TOKEN');\n const store =\n kvUrl && kvToken ? new UpstashDigestStore({ url: kvUrl, token: kvToken }) : undefined;\n\n if (!store) {\n console.warn(\n '[serve] No KV_REST_API_URL/KV_REST_API_TOKEN — using the in-memory replay store. ' +\n 'Fine for a single long-lived process; on serverless hosts set both so replay protection is durable.',\n );\n }\n\n return new Serve({\n payTo,\n network: (network as ServeNetwork | undefined) ?? 'mainnet',\n baseUrl: read('T2000_BASE_URL'),\n name: read('T2000_NAME'),\n description: read('T2000_DESCRIPTION'),\n store,\n });\n}\n","import type { BuiltRoute } from './types.js';\n\n/**\n * Export a built route the way Next.js App Router needs it.\n *\n * Next dispatches ONLY the methods a route.ts exports — serve's own CORS\n * handling (OPTIONS → 204 with the ACAO headers) never runs if the file\n * exports just `POST`: the browser preflight gets Next's bare 204 with no\n * CORS headers, and every browser buyer (Passport, the store's Try it)\n * fails while CLI/server buyers — who never preflight — work fine. Fetch\n * runtimes mounted via a single handler (`serve.fetch`-style) don't have\n * this hole; it is a Next export contract, not a serve one.\n *\n * export const { POST, OPTIONS } = asNextRoute(\n * serve.route({ path: 'haiku' }).paid('0.01').handler(fn),\n * );\n */\nexport function asNextRoute(route: BuiltRoute): {\n POST: BuiltRoute;\n OPTIONS: BuiltRoute;\n} {\n return { POST: route, OPTIONS: route };\n}\n"]}
1
+ {"version":3,"sources":["../src/discovery.ts","../src/chain.ts","../src/route.ts","../src/store.ts","../src/serve.ts","../src/next.ts"],"names":["result","USDC_TESTNET","USDC","InMemoryDigestStore"],"mappings":";;;;;;AAgBO,SAAS,oBAAA,CAAqB,OAAc,MAAA,EAA0C;AAC3F,EAAA,MAAM,IAAA,GAAO,MAAM,OAAA,IAAW,MAAA;AAC9B,EAAA,MAAM,QAAiC,EAAC;AAExC,EAAA,KAAA,MAAW,KAAA,IAAS,KAAA,CAAM,MAAA,CAAO,MAAA,EAAO,EAAG;AACzC,IAAA,MAAM,EAAE,IAAA,EAAM,SAAA,EAAW,aAAa,WAAA,EAAa,YAAA,KAAiB,KAAA,CAAM,IAAA;AAC1E,IAAA,MAAM,SAAA,GAAqC;AAAA,MACzC,WAAA,EAAa,IAAA,CAAK,OAAA,CAAQ,gBAAA,EAAkB,GAAG,CAAA;AAAA,MAC/C,SAAS,WAAA,IAAe,IAAA;AAAA,MACxB,SAAA,EAAW;AAAA,QACT,OAAO,YAAA,GACH;AAAA,UACE,WAAA,EAAa,SAAA;AAAA,UACb,SAAS,EAAE,kBAAA,EAAoB,EAAE,MAAA,EAAQ,cAAa;AAAE,SAC1D,GACA,EAAE,WAAA,EAAa,SAAA,EAAU;AAAA,QAC7B,GAAI,SAAA,GACA;AAAA,UACE,KAAA,EAAO;AAAA,YACL,WAAA,EACE;AAAA;AACJ,YAEF,EAAC;AAAA,QACL,KAAA,EAAO,EAAE,WAAA,EAAa,2CAAA;AAAuC;AAC/D,KACF;AACA,IAAA,IAAI,SAAA,EAAW;AAIb,MAAA,SAAA,CAAU,gBAAgB,CAAA,GAAI;AAAA,QAC5B,WAAA,EAAa,OAAA;AAAA,QACb,KAAA,EAAO,SAAA;AAAA,QACP,QAAA,EAAU,MAAA;AAAA,QACV,SAAA,EAAW,CAAC,KAAA,EAAO,MAAM,CAAA;AAAA,QACzB,IAAA,EAAM;AAAA,UACJ,MAAA,EAAQ,OAAA;AAAA,UACR,OAAA,EAAS,CAAA,IAAA,EAAO,KAAA,CAAM,OAAO,CAAA,CAAA;AAAA,UAC7B,KAAA,EAAA,CAAQ,KAAA,CAAM,OAAA,KAAY,SAAA,GAAY,eAAe,IAAA,EAAM,IAAA;AAAA,UAC3D,OAAO,KAAA,CAAM;AAAA;AACf,OACF;AAAA,IACF;AACA,IAAA,IAAI,WAAA,EAAa;AACf,MAAA,SAAA,CAAU,WAAA,GAAc;AAAA,QACtB,QAAA,EAAU,IAAA;AAAA,QACV,SAAS,EAAE,kBAAA,EAAoB,EAAE,MAAA,EAAQ,aAAY;AAAE,OACzD;AAAA,IACF;AACA,IAAA,KAAA,CAAM,IAAI,IAAI,CAAA,CAAE,CAAA,GAAI,EAAE,MAAM,SAAA,EAAU;AAAA,EACxC;AAEA,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,OAAA;AAAA,IACT,IAAA,EAAM;AAAA,MACJ,KAAA,EAAO,MAAM,IAAA,IAAQ,UAAA;AAAA,MACrB,OAAA,EAAS,OAAA;AAAA,MACT,WAAA,EACE,MAAM,WAAA,IACN;AAAA,KACJ;AAAA,IACA,GAAI,IAAA,GAAO,EAAE,OAAA,EAAS,CAAC,EAAE,GAAA,EAAK,IAAA,EAAM,CAAA,EAAE,GAAI,EAAC;AAAA,IAC3C;AAAA,GACF;AACF;AAEO,SAAS,YAAA,CAAa,OAAc,MAAA,EAAyB;AAClE,EAAA,MAAM,IAAA,GAAO,KAAA,CAAM,OAAA,IAAW,MAAA,IAAU,EAAA;AACxC,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,EAAA,EAAK,KAAA,CAAM,IAAA,IAAQ,UAAU,CAAA,CAAE,CAAA;AAC1C,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,EAAA,IAAI,MAAM,WAAA,EAAa;AACrB,IAAA,KAAA,CAAM,IAAA,CAAK,MAAM,WAAW,CAAA;AAC5B,IAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAAA,EACf;AACA,EAAA,KAAA,CAAM,KAAK,eAAe,CAAA;AAC1B,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,EAAA,KAAA,CAAM,IAAA;AAAA,IACJ,oFAAA;AAAA,IACA,uFAAA;AAAA,IACA,wFAAA;AAAA,IACA,EAAA;AAAA,IACA,2EAAA;AAAA,IACA,iEAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,KAAA,CAAM,KAAK,cAAc,CAAA;AACzB,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,EAAA,KAAA,MAAW,KAAA,IAAS,KAAA,CAAM,MAAA,CAAO,MAAA,EAAO,EAAG;AACzC,IAAA,MAAM,EAAE,IAAA,EAAM,SAAA,EAAW,aAAa,WAAA,EAAa,YAAA,KAAiB,KAAA,CAAM,IAAA;AAC1E,IAAA,MAAM,KAAA,GAAQ,SAAA,GAAY,CAAA,EAAG,SAAS,CAAA,cAAA,CAAA,GAAmB,MAAA;AACzD,IAAA,KAAA,CAAM,KAAK,CAAA,SAAA,EAAY,IAAI,IAAI,IAAI,CAAA,QAAA,EAAM,KAAK,CAAA,CAAE,CAAA;AAChD,IAAA,IAAI,WAAA,EAAa,KAAA,CAAM,IAAA,CAAK,WAAW,CAAA;AACvC,IAAA,IAAI,WAAA,EAAa;AACf,MAAA,KAAA,CAAM,KAAK,6BAA6B,CAAA;AACxC,MAAA,KAAA,CAAM,KAAK,SAAS,CAAA;AACpB,MAAA,KAAA,CAAM,KAAK,IAAA,CAAK,SAAA,CAAU,WAAA,EAAa,IAAA,EAAM,CAAC,CAAC,CAAA;AAC/C,MAAA,KAAA,CAAM,KAAK,KAAK,CAAA;AAAA,IAClB;AACA,IAAA,IAAI,YAAA,EAAc;AAChB,MAAA,KAAA,CAAM,KAAK,+FAA0F,CAAA;AACrG,MAAA,KAAA,CAAM,KAAK,SAAS,CAAA;AACpB,MAAA,KAAA,CAAM,KAAK,IAAA,CAAK,SAAA,CAAU,YAAA,EAAc,IAAA,EAAM,CAAC,CAAC,CAAA;AAChD,MAAA,KAAA,CAAM,KAAK,KAAK,CAAA;AAAA,IAClB;AACA,IAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAAA,EACf;AACA,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,WAAA,EAAc,IAAI,CAAA,aAAA,CAAe,CAAA;AAC5C,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AACxB;AClHA,IAAM,aAAA,GAA8C;AAAA,EAClD,OAAA,EAAS,qCAAA;AAAA,EACT,OAAA,EAAS;AACX,CAAA;AAEA,IAAM,YAAA,GAAe,KAAK,EAAA,GAAK,GAAA;AAa/B,IAAM,QAAmD,EAAC;AAEnD,SAAS,aAAA,CAAc,SAAuB,MAAA,EAAgC;AACnF,EAAA,MAAM,CAAA,GAAK,KAAA,CAAM,OAAO,CAAA,KAAM,EAAC;AAC/B,EAAA,IAAI,CAAC,EAAE,MAAA,EAAQ;AACb,IAAA,CAAA,CAAE,MAAA,GAAS,IAAI,aAAA,CAAc;AAAA,MAC3B,OAAA,EAAS,MAAA,IAAU,aAAA,CAAc,OAAO,CAAA;AAAA,MACxC;AAAA,KACD,CAAA;AAAA,EACH;AACA,EAAA,OAAO,CAAA,CAAE,MAAA;AACX;AAEA,eAAsB,YAAA,CAAa,SAAuB,MAAA,EAAqC;AAC7F,EAAA,MAAM,MAAA,GAAS,aAAA,CAAc,OAAA,EAAS,MAAM,CAAA;AAC5C,EAAA,MAAM,CAAA,GAAK,KAAA,CAAM,OAAO,CAAA,KAAM,EAAC;AAC/B,EAAA,IAAI,CAAC,EAAE,OAAA,EAAS;AACd,IAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,IAAA,CAAK,kBAAA,EAAmB;AACjD,IAAA,CAAA,CAAE,UAAU,GAAA,CAAI,eAAA;AAAA,EAClB;AACA,EAAA,IAAI,CAAC,EAAE,KAAA,IAAS,IAAA,CAAK,KAAI,GAAI,CAAA,CAAE,KAAA,CAAM,SAAA,GAAY,YAAA,EAAc;AAC7D,IAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,IAAA,CAAK,qBAAA,EAAsB;AACpD,IAAA,CAAA,CAAE,KAAA,GAAQ,EAAE,KAAA,EAAO,MAAA,CAAO,GAAA,CAAI,WAAA,CAAY,KAAK,CAAA,EAAG,SAAA,EAAW,IAAA,CAAK,GAAA,EAAI,EAAE;AAAA,EAC1E;AACA,EAAA,OAAO,EAAE,KAAA,EAAO,CAAA,CAAE,SAAS,KAAA,EAAO,CAAA,CAAE,MAAM,KAAA,EAAM;AAClD;AAGO,SAAS,kBAAA,GAA2B;AACzC,EAAA,OAAO,KAAA,CAAM,OAAA;AACb,EAAA,OAAO,KAAA,CAAM,OAAA;AACf;AAGO,SAAS,eAAA,CAAgB,OAAA,EAAuB,KAAA,EAAe,KAAA,EAAqB;AACzF,EAAA,MAAM,CAAA,GAAK,KAAA,CAAM,OAAO,CAAA,KAAM,EAAC;AAC/B,EAAA,CAAA,CAAE,OAAA,GAAU,KAAA;AACZ,EAAA,CAAA,CAAE,QAAQ,EAAE,KAAA,EAAO,OAAO,SAAA,EAAW,IAAA,CAAK,KAAI,EAAE;AAClD;;;ACNA,IAAM,sBAAA,GAAyB,CAAA;AAE/B,IAAM,YAAA,GAAuC;AAAA,EAC3C,6BAAA,EAA+B,GAAA;AAAA,EAC/B,8BAAA,EAAgC,iCAAA;AAAA,EAChC,8BAAA,EAAgC,iBAAiB,mBAAmB,CAAA,CAAA;AAAA,EACpE,+BAAA,EAAiC,GAAG,4BAA4B,CAAA,kBAAA;AAClE,CAAA;AAEA,SAAS,SAAS,QAAA,EAA8B;AAC9C,EAAA,MAAM,OAAA,GAAU,IAAI,OAAA,CAAQ,QAAA,CAAS,OAAO,CAAA;AAC5C,EAAA,KAAA,MAAW,CAAC,CAAA,EAAG,CAAC,CAAA,IAAK,MAAA,CAAO,OAAA,CAAQ,YAAY,CAAA,EAAG,OAAA,CAAQ,GAAA,CAAI,CAAA,EAAG,CAAC,CAAA;AACnE,EAAA,OAAO,IAAI,SAAS,QAAA,CAAS,IAAA,EAAM,EAAE,MAAA,EAAQ,QAAA,CAAS,MAAA,EAAQ,OAAA,EAAS,CAAA;AACzE;AAEA,SAAS,IAAA,CAAK,MAAA,EAAgB,IAAA,EAAe,OAAA,EAA4C;AACvF,EAAA,OAAO,QAAA;AAAA,IACL,IAAI,QAAA,CAAS,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA,EAAG;AAAA,MACjC,MAAA;AAAA,MACA,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAoB,GAAG,OAAA;AAAQ,KAC3D;AAAA,GACH;AACF;AAEA,SAAS,iBAAiB,MAAA,EAAmD;AAC3E,EAAA,OAAO,OAAO,MAAA,KAAW,QAAA,IAAY,MAAA,KAAW,QAAQ,WAAA,IAAe,MAAA;AACzE;AAEA,eAAe,YAAA,CACb,QACA,KAAA,EACuE;AACvE,EAAA,IAAI,gBAAA,CAAiB,MAAM,CAAA,EAAG;AAC5B,IAAA,MAAMA,UAAS,MAAM,MAAA,CAAO,WAAW,CAAA,CAAE,SAAS,KAAK,CAAA;AACvD,IAAA,IAAIA,QAAO,MAAA,EAAQ;AAGjB,MAAA,MAAM,OAAA,GAAUA,OAAAA,CAAO,MAAA,CACpB,GAAA,CAAI,CAAC,CAAA,KAAM;AACV,QAAA,MAAM,IAAA,GAAA,CAAQ,EAAE,IAAA,IAAQ,IACrB,GAAA,CAAI,CAAC,QAAS,OAAO,GAAA,KAAQ,WAAW,MAAA,CAAO,GAAA,CAAI,GAAG,CAAA,GAAI,MAAA,CAAO,GAAG,CAAE,CAAA,CACtE,KAAK,GAAG,CAAA;AACX,QAAA,OAAO,OAAO,CAAA,EAAG,IAAI,KAAK,CAAA,CAAE,OAAO,KAAK,CAAA,CAAE,OAAA;AAAA,MAC5C,CAAC,CAAA,CACA,IAAA,CAAK,IAAI,CAAA;AACZ,MAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,OAAA,EAAQ;AAAA,IAC9B;AACA,IAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,IAAA,EAAMA,QAAO,KAAA,EAAM;AAAA,EACxC;AACA,EAAA,MAAM,MAAA,GAAS,MAAA,CAAO,SAAA,CAAU,KAAK,CAAA;AACrC,EAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,IAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,SAAS,MAAA,CAAO,KAAA,CAAM,WAAW,cAAA,EAAe;AAAA,EACtE;AACA,EAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,IAAA,EAAM,OAAO,IAAA,EAAK;AACvC;AAGA,SAAS,gBAAA,CAAiB,OAAe,IAAA,EAAoB;AAC3D,EAAA,IAAI,CAAC,oBAAoB,IAAA,CAAK,KAAK,KAAK,MAAA,CAAO,KAAK,KAAK,CAAA,EAAG;AAC1D,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,eAAA,EAAkB,IAAI,CAAA,4EAAA,EAA+E,KAAK,CAAA,CAAA;AAAA,KAC5G;AAAA,EACF;AACA,EAAA,IAAI,MAAA,CAAO,KAAK,CAAA,GAAI,sBAAA,EAAwB;AAC1C,IAAA,OAAA,CAAQ,IAAA;AAAA,MACN,CAAA,eAAA,EAAkB,IAAI,CAAA,SAAA,EAAY,KAAK,sBAAsB,sBAAsB,CAAA,gJAAA;AAAA,KAErF;AAAA,EACF;AACF;AAEO,IAAM,eAAN,MAAsC;AAAA,EAO3C,WAAA,CACmB,OAAA,EACA,OAAA,EACA,QAAA,EACjB;AAHiB,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AACA,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AACA,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AAAA,EAChB;AAAA,EAVK,SAAA;AAAA,EACA,UAAA;AAAA,EACA,WAAA;AAAA,EACA,YAAA;AAAA,EACA,MAAA,GAAS,KAAA;AAAA;AAAA,EASjB,KAAK,SAAA,EAAyB;AAC5B,IAAA,gBAAA,CAAiB,SAAA,EAAW,IAAA,CAAK,OAAA,CAAQ,IAAI,CAAA;AAC7C,IAAA,IAAA,CAAK,SAAA,GAAY,SAAA;AACjB,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AACd,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA,EAGA,WAAA,GAAoB;AAClB,IAAA,IAAA,CAAK,MAAA,GAAS,IAAA;AACd,IAAA,IAAA,CAAK,SAAA,GAAY,MAAA;AACjB,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,IAAA,CAAQ,QAAwB,UAAA,EAAuD;AACrF,IAAA,IAAA,CAAK,UAAA,GAAa,MAAA;AAClB,IAAA,IAAA,CAAK,WAAA,GAAc,UAAA;AACnB,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,SAAS,UAAA,EAA2C;AAClD,IAAA,IAAA,CAAK,YAAA,GAAe,UAAA;AACpB,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,QAAQ,EAAA,EAAwF;AAC9F,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,IAAU,CAAC,KAAK,SAAA,EAAW;AACnC,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,eAAA,EAAkB,IAAA,CAAK,OAAA,CAAQ,IAAI,CAAA,2DAAA;AAAA,OACrC;AAAA,IACF;AACA,IAAA,MAAM,UAAU,IAAA,CAAK,OAAA;AACrB,IAAA,MAAM,EAAE,IAAA,EAAM,WAAA,EAAY,GAAI,IAAA,CAAK,OAAA;AACnC,IAAA,MAAM,YAAY,IAAA,CAAK,SAAA;AACvB,IAAA,MAAM,aAAa,IAAA,CAAK,UAAA;AAExB,IAAA,MAAM,KAAA,IAAS,OAAO,GAAA,KAAoC;AACxD,MAAA,IAAI,GAAA,CAAI,WAAW,SAAA,EAAW;AAC5B,QAAA,OAAO,QAAA,CAAS,IAAI,QAAA,CAAS,IAAA,EAAM,EAAE,MAAA,EAAQ,GAAA,EAAK,CAAC,CAAA;AAAA,MACrD;AAKA,MAAA,IAAI,UAAA;AACJ,MAAA,IAAI,cAAA;AACJ,MAAA,IAAI,GAAA,CAAI,MAAA,KAAW,KAAA,IAAS,GAAA,CAAI,WAAW,MAAA,EAAQ;AACjD,QAAA,MAAM,IAAA,GAAO,MAAM,GAAA,CAAI,IAAA,EAAK;AAC5B,QAAA,IAAI,IAAA,CAAK,IAAA,EAAK,CAAE,MAAA,GAAS,CAAA,EAAG;AAC1B,UAAA,IAAI;AACF,YAAA,UAAA,GAAa,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,UAC9B,CAAA,CAAA,MAAQ;AACN,YAAA,cAAA,GAAiB,gCAAA;AAAA,UACnB;AAAA,QACF;AAAA,MACF;AAEA,MAAA,MAAM,QAAA,GAAA,CAAY,OAAA,CAAQ,OAAA,IAAW,IAAI,IAAI,GAAA,CAAI,GAAG,CAAA,CAAE,MAAA,EAAQ,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA,GAAI,IAAI,IAAI,CAAA,CAAA;AAE3F,MAAA,MAAM,UAAA,GAAa,OAAO,KAAA,KAAsC;AAC9D,QAAA,IAAI,SAAA,GAAqB,UAAA;AACzB,QAAA,IAAI,UAAA,EAAY;AAGd,UAAA,IAAI,cAAA,EAAgB;AAClB,YAAA,OAAO,KAAK,GAAA,EAAK,EAAE,OAAO,cAAA,EAAgB,IAAA,EAAM,OAAO,CAAA;AAAA,UACzD;AACA,UAAA,MAAM,SAAS,MAAM,YAAA,CAAa,UAAA,EAAY,UAAA,IAAc,EAAE,CAAA;AAC9D,UAAA,IAAI,CAAC,OAAO,EAAA,EAAI;AACd,YAAA,OAAO,IAAA,CAAK,KAAK,EAAE,KAAA,EAAO,OAAO,OAAA,EAAS,IAAA,EAAM,OAAO,CAAA;AAAA,UACzD;AACA,UAAA,SAAA,GAAY,MAAA,CAAO,IAAA;AAAA,QACrB;AACA,QAAA,MAAM,GAAA,GAAM,MAAM,EAAA,CAAG,EAAE,MAAM,SAAA,EAAoB,GAAA,EAAK,OAAO,CAAA;AAC7D,QAAA,IAAI,GAAA,YAAe,QAAA,EAAU,OAAO,QAAA,CAAS,GAAG,CAAA;AAChD,QAAA,OAAO,IAAA,CAAK,KAAK,GAAG,CAAA;AAAA,MACtB,CAAA;AAGA,MAAA,IAAI,CAAC,SAAA,EAAW;AACd,QAAA,IAAI;AACF,UAAA,OAAO,MAAM,UAAA,EAAW;AAAA,QAC1B,SAAS,GAAA,EAAK;AACZ,UAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,eAAA,EAAkB,IAAI,CAAA,iBAAA,CAAA,EAAqB,GAAG,CAAA;AAC5D,UAAA,OAAO,IAAA,CAAK,GAAA,EAAK,EAAE,KAAA,EAAO,kBAAkB,CAAA;AAAA,QAC9C;AAAA,MACF;AAEA,MAAA,MAAM,aAAA,GAAgB,GAAA,CAAI,OAAA,CAAQ,GAAA,CAAI,mBAAmB,CAAA;AAMzD,MAAA,IAAI,CAAC,aAAA,EAAe;AAClB,QAAA,OAAO,MAAM,UAAA,CAAW,OAAA,EAAS,EAAE,QAAA,EAAU,WAAW,CAAA;AAAA,MAC1D;AAEA,MAAA,IAAI,kBAAA,CAAmB,aAAa,CAAA,EAAG;AACrC,QAAA,OAAO,MAAM,WAAW,OAAA,EAAS;AAAA,UAC/B,QAAA;AAAA,UACA,SAAA;AAAA,UACA,KAAA,EACE;AAAA,SACH,CAAA;AAAA,MACH;AAKA,MAAA,IAAI,OAAA;AACJ,MAAA,IAAI;AACF,QAAA,OAAA,GAAU,gBAAgB,aAAa,CAAA;AACvC,QAAA,iBAAA,CAAkB;AAAA,UAChB,OAAA;AAAA,UACA,QAAA,EAAU;AAAA,YACR,WAAA,EAAa,QAAQ,OAAA,CAAQ,WAAA;AAAA,YAC7B,MAAA,EAAQ,SAAA;AAAA,YACR,UAAU,OAAA,CAAQ,QAAA;AAAA,YAClB,WAAW,OAAA,CAAQ,KAAA;AAAA,YACnB,SAAS,OAAA,CAAQ;AAAA;AACnB,SACD,CAAA;AAAA,MACH,SAAS,GAAA,EAAK;AACZ,QAAA,OAAO,MAAM,WAAW,OAAA,EAAS;AAAA,UAC/B,QAAA;AAAA,UACA,SAAA;AAAA,UACA,KAAA,EAAO,oBAAoB,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,SAC5E,CAAA;AAAA,MACH;AAKA,MAAA,MAAM,YAAA,GAAe,CAAA,UAAA,EAAa,OAAA,CAAQ,OAAA,CAAQ,WAAW,CAAA,CAAA;AAC7D,MAAA,IAAI,MAAM,OAAA,CAAQ,KAAA,CAAM,GAAA,CAAI,YAAY,CAAA,EAAG;AACzC,QAAA,OAAO,MAAM,WAAW,OAAA,EAAS;AAAA,UAC/B,QAAA;AAAA,UACA,SAAA;AAAA,UACA,KAAA,EAAO;AAAA,SACR,CAAA;AAAA,MACH;AAIA,MAAA,IAAI,MAAA;AACJ,MAAA,IAAI;AACF,QAAA,MAAA,GAAS,MAAM,UAAA,CAAW,OAAA,CAAQ,OAAA,CAAQ,aAAa,CAAA;AAAA,MACzD,SAAS,GAAA,EAAK;AACZ,QAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,eAAA,EAAkB,IAAI,CAAA,uCAAA,CAAA,EAA2C,GAAG,CAAA;AAClF,QAAA,OAAO,IAAA,CAAK,GAAA,EAAK,EAAE,KAAA,EAAO,8CAAyC,CAAA;AAAA,MACrE;AACA,MAAA,IAAI,MAAA,CAAO,MAAA,IAAU,GAAA,EAAK,OAAO,MAAA;AAIjC,MAAA,IAAI,MAAA;AACJ,MAAA,IAAI;AACF,QAAA,MAAA,GAAS,MAAM,iBAAA,CAAkB;AAAA,UAC/B,OAAA;AAAA,UACA,MAAA,EAAQ,aAAA,CAAc,OAAA,CAAQ,OAAA,EAAS,QAAQ,MAAM,CAAA;AAAA,UACrD,OAAO,OAAA,CAAQ,KAAA;AAAA,UACf,QAAA,EAAU;AAAA,YACR,WAAA,EAAa,QAAQ,OAAA,CAAQ,WAAA;AAAA,YAC7B,MAAA,EAAQ,SAAA;AAAA,YACR,UAAU,OAAA,CAAQ,QAAA;AAAA,YAClB,WAAW,OAAA,CAAQ,KAAA;AAAA,YACnB,SAAS,OAAA,CAAQ;AAAA;AACnB,SACD,CAAA;AAAA,MACH,SAAS,GAAA,EAAK;AACZ,QAAA,OAAO,MAAM,WAAW,OAAA,EAAS;AAAA,UAC/B,QAAA;AAAA,UACA,SAAA;AAAA,UACA,KAAA,EAAO,sBAAsB,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,SAC9E,CAAA;AAAA,MACH;AAGA,MAAA,IAAI;AACF,QAAA,MAAM,OAAA,CAAQ,KAAA,CAAM,GAAA,CAAI,YAAY,CAAA;AAAA,MACtC,CAAA,CAAA,MAAQ;AAAA,MAER;AAKA,MAAA,cAAA,CAAe,OAAA,EAAS;AAAA,QACtB,QAAQ,MAAA,CAAO,WAAA;AAAA,QACf,OAAO,MAAA,CAAO,KAAA;AAAA,QACd,SAAA;AAAA,QACA;AAAA,OACD,CAAA;AAED,MAAA,MAAM,OAAA,GAAU,IAAI,OAAA,CAAQ,MAAA,CAAO,OAAO,CAAA;AAC1C,MAAA,OAAA,CAAQ,GAAA,CAAI,4BAAA,EAA8B,kBAAA,CAAmB,MAAM,CAAC,CAAA;AACpE,MAAA,OAAO,IAAI,SAAS,MAAA,CAAO,IAAA,EAAM,EAAE,MAAA,EAAQ,MAAA,CAAO,MAAA,EAAQ,OAAA,EAAS,CAAA;AAAA,IACrE,CAAA,CAAA;AAEA,IAAA,KAAA,CAAM,IAAA,GAAO;AAAA,MACX,IAAA;AAAA,MACA,SAAA;AAAA,MACA,WAAA;AAAA,MACA,UAAA;AAAA,MACA,aAAa,IAAA,CAAK,WAAA;AAAA,MAClB,cAAc,IAAA,CAAK;AAAA,KACrB;AACA,IAAA,IAAA,CAAK,SAAS,KAAK,CAAA;AACnB,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAKA,SAAS,cAAA,CACP,SACA,IAAA,EACM;AACN,EAAA,MAAM,MAAM,OAAA,CAAQ,iBAAA;AACpB,EAAA,IAAI,CAAC,GAAA,EAAK;AACV,EAAA,IAAI;AACF,IAAA,KAAK,MAAM,GAAA,EAAK;AAAA,MACd,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAmB;AAAA,MAC9C,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,QACnB,QAAQ,IAAA,CAAK,MAAA;AAAA,QACb,OAAO,OAAA,CAAQ,KAAA;AAAA,QACf,OAAO,IAAA,CAAK,KAAA;AAAA,QACZ,iBAAiB,IAAA,CAAK,KAAA,CAAM,OAAO,IAAA,CAAK,SAAS,IAAI,GAAS,CAAA;AAAA,QAC9D,OAAA,EAAS,CAAA,IAAA,EAAO,OAAA,CAAQ,OAAO,CAAA,CAAA;AAAA,QAC/B,OAAO,IAAA,CAAK,QAAA;AAAA,QACZ,MAAA,EAAQ;AAAA,OACT,CAAA;AAAA,MACD,MAAA,EAAQ,WAAA,CAAY,OAAA,CAAQ,IAAI;AAAA,KACjC,CAAA,CAAE,KAAA,CAAM,MAAM,KAAA,CAAS,CAAA;AAAA,EAC1B,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;AAEA,eAAe,UAAA,CACb,SACA,IAAA,EACmB;AACnB,EAAA,IAAI;AACF,IAAA,MAAM,EAAE,OAAO,KAAA,EAAM,GAAI,MAAM,YAAA,CAAa,OAAA,CAAQ,OAAA,EAAS,OAAA,CAAQ,MAAM,CAAA;AAC3E,IAAA,MAAM,eAAe,sBAAA,CAAuB;AAAA,MAC1C,WAAA,EAAa,OAAO,UAAA,EAAW;AAAA,MAC/B,QAAQ,IAAA,CAAK,SAAA;AAAA,MACb,UAAU,OAAA,CAAQ,QAAA;AAAA,MAClB,WAAW,OAAA,CAAQ,KAAA;AAAA,MACnB,UAAU,IAAA,CAAK,QAAA;AAAA,MACf,SAAS,OAAA,CAAQ,OAAA;AAAA,MACjB,KAAA;AAAA,MACA,YAAA,EAAc;AAAA,KACf,CAAA;AAKD,IAAA,MAAM,QAAQ,MAAM;AAClB,MAAA,IAAI;AACF,QAAA,OAAO,IAAI,GAAA,CAAI,IAAA,CAAK,QAAQ,CAAA,CAAE,QAAA;AAAA,MAChC,CAAA,CAAA,MAAQ;AACN,QAAA,OAAO,KAAA,CAAA;AAAA,MACT;AAAA,IACF,CAAA,GAAG;AACH,IAAA,MAAM,OAAA,GAAU,CAAA,eAAA,EAAkB,IAAA,IAAQ,MAAM,CAAA,cAAA,EAAiB,OAAA,CAAQ,KAAK,CAAA,aAAA,EAAgB,OAAA,CAAQ,QAAQ,CAAA,WAAA,EAAc,IAAA,CAAK,SAAS,CAAA,CAAA,CAAA;AAC1I,IAAA,OAAO,IAAA;AAAA,MACL,GAAA;AAAA,MACA;AAAA,QACE,WAAA,EAAa,YAAA;AAAA,QACb,KAAA,EAAO,KAAK,KAAA,IAAS,kBAAA;AAAA,QACrB,OAAA,EAAS,CAAC,YAAY;AAAA,OACxB;AAAA,MACA,EAAE,oBAAoB,OAAA;AAAQ,KAChC;AAAA,EACF,SAAS,GAAA,EAAK;AAGZ,IAAA,OAAA,CAAQ,KAAA,CAAM,0CAA0C,GAAG,CAAA;AAC3D,IAAA,OAAO,IAAA,CAAK,GAAA,EAAK,EAAE,KAAA,EAAO,6CAA6C,CAAA;AAAA,EACzE;AACF;AChbA,IAAM,mBAAA,GAAsB,KAAK,EAAA,GAAK,EAAA;AACtC,IAAM,MAAA,GAAS,eAAA;AASR,IAAM,qBAAN,MAAgD;AAAA,EACpC,GAAA;AAAA,EACA,KAAA;AAAA,EACA,UAAA;AAAA,EAEjB,YAAY,OAAA,EAAoC;AAC9C,IAAA,IAAA,CAAK,GAAA,GAAM,OAAA,CAAQ,GAAA,CAAI,OAAA,CAAQ,OAAO,EAAE,CAAA;AACxC,IAAA,IAAA,CAAK,QAAQ,OAAA,CAAQ,KAAA;AACrB,IAAA,IAAA,CAAK,UAAA,GAAa,QAAQ,UAAA,IAAc,mBAAA;AAAA,EAC1C;AAAA,EAEA,MAAc,QAAQ,QAAA,EAAsC;AAC1D,IAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,CAAA,EAAG,KAAK,GAAG,CAAA,CAAA,EAAI,QAAA,CAAS,GAAA,CAAI,kBAAkB,CAAA,CAAE,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA,EAAI;AAAA,MACnF,SAAS,EAAE,aAAA,EAAe,CAAA,OAAA,EAAU,IAAA,CAAK,KAAK,CAAA,CAAA;AAAG,KAClD,CAAA;AACD,IAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,wBAAA,EAA2B,GAAA,CAAI,MAAM,IAAI,MAAM,GAAA,CAAI,IAAA,EAAM,CAAA,CAAE,CAAA;AAAA,IAC7E;AACA,IAAA,MAAM,IAAA,GAAQ,MAAM,GAAA,CAAI,IAAA,EAAK;AAC7B,IAAA,IAAI,IAAA,CAAK,OAAO,MAAM,IAAI,MAAM,CAAA,eAAA,EAAkB,IAAA,CAAK,KAAK,CAAA,CAAE,CAAA;AAC9D,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACd;AAAA,EAEA,MAAM,IAAI,MAAA,EAAkC;AAC1C,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,OAAA,CAAQ,CAAC,KAAA,EAAO,MAAA,GAAS,MAAM,CAAC,CAAA;AAC1D,IAAA,OAAO,MAAA,KAAW,QAAQ,MAAA,KAAW,MAAA;AAAA,EACvC;AAAA,EAEA,MAAM,IAAI,MAAA,EAA+B;AAGvC,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,OAAA,CAAQ;AAAA,MAChC,KAAA;AAAA,MACA,MAAA,GAAS,MAAA;AAAA,MACT,GAAA;AAAA,MACA,IAAA;AAAA,MACA,MAAA,CAAO,KAAK,UAAU,CAAA;AAAA,MACtB;AAAA,KACD,CAAA;AACD,IAAA,IAAI,MAAA,KAAW,IAAA,IAAQ,MAAA,KAAW,MAAA,EAAW;AAC3C,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,qBAAA,EAAwB,MAAM,CAAA,CAAE,CAAA;AAAA,IAClD;AAAA,EACF;AACF;;;AC/DO,IAAM,QAAN,MAAY;AAAA,EACA,OAAA;AAAA;AAAA,EAER,MAAA,uBAAa,GAAA,EAAwB;AAAA,EAErC,KAAA;AAAA,EACA,OAAA;AAAA,EACA,IAAA;AAAA,EACA,WAAA;AAAA,EACA,OAAA;AAAA,EAET,YAAY,MAAA,EAAqB;AAC/B,IAAA,IAAI,CAAC,MAAA,CAAO,KAAA,IAAS,CAAC,iBAAA,CAAkB,MAAA,CAAO,KAAK,CAAA,EAAG;AACrD,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,qFAAA,EAAwF,OAAO,KAAK,CAAA,CAAA;AAAA,OACtG;AAAA,IACF;AACA,IAAA,IAAA,CAAK,KAAA,GAAQ,mBAAA,CAAoB,MAAA,CAAO,KAAK,CAAA;AAC7C,IAAA,IAAA,CAAK,OAAA,GAAU,OAAO,OAAA,IAAW,SAAA;AACjC,IAAA,IAAA,CAAK,OAAO,MAAA,CAAO,IAAA;AACnB,IAAA,IAAA,CAAK,cAAc,MAAA,CAAO,WAAA;AAC1B,IAAA,IAAA,CAAK,OAAA,GAAU,MAAA,CAAO,OAAA,EAAS,OAAA,CAAQ,OAAO,EAAE,CAAA;AAEhD,IAAA,MAAM,QAAA,GAAqB,IAAA,CAAK,OAAA,KAAY,SAAA,GAAYC,YAAAA,GAAeC,IAAAA;AACvE,IAAA,IAAA,CAAK,OAAA,GAAU;AAAA,MACb,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,QAAA;AAAA,MACA,KAAA,EAAO,MAAA,CAAO,KAAA,IAAS,IAAIC,mBAAAA,EAAoB;AAAA,MAC/C,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,QAAQ,MAAA,CAAO,MAAA;AAAA,MACf,mBAAmB,MAAA,CAAO;AAAA,KAC5B;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,OAAA,EAAqC;AACzC,IAAA,MAAM,IAAA,GAAO,QAAQ,IAAA,CAAK,OAAA,CAAQ,QAAQ,EAAE,CAAA,CAAE,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAA;AAChE,IAAA,IAAI,CAAC,IAAA,EAAM,MAAM,IAAI,MAAM,sCAAsC,CAAA;AACjE,IAAA,OAAO,IAAI,YAAA,CAAa,EAAE,GAAG,IAAA,CAAK,OAAA,EAAQ,EAAG,EAAE,GAAG,OAAA,EAAS,IAAA,EAAK,EAAG,CAAC,KAAA,KAAU;AAC5E,MAAA,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,IAAA,EAAM,KAAK,CAAA;AAAA,IAC7B,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAA,GAAsC;AACpC,IAAA,OAAO,CAAC,GAAA,KACN,IAAI,QAAA,CAAS,IAAA,CAAK,UAAU,oBAAA,CAAqB,IAAA,EAAM,IAAI,GAAA,CAAI,IAAI,GAAG,CAAA,CAAE,MAAM,CAAA,EAAG,IAAA,EAAM,CAAC,CAAA,EAAG;AAAA,MACzF,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAoB,+BAA+B,GAAA;AAAI,KACnF,CAAA;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAA,GAAmC;AACjC,IAAA,OAAO,CAAC,GAAA,KACN,IAAI,QAAA,CAAS,YAAA,CAAa,IAAA,EAAM,IAAI,GAAA,CAAI,GAAA,CAAI,GAAG,CAAA,CAAE,MAAM,CAAA,EAAG;AAAA,MACxD,OAAA,EAAS,EAAE,cAAA,EAAgB,2BAAA,EAA6B,+BAA+B,GAAA;AAAI,KAC5F,CAAA;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWS,KAAA,GAAQ,OAAO,GAAA,KAAoC;AAC1D,IAAA,MAAM,QAAA,GAAW,IAAI,GAAA,CAAI,GAAA,CAAI,GAAG,CAAA,CAAE,QAAA,CAAS,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAA,CAAE,OAAA,CAAQ,QAAQ,EAAE,CAAA;AACjF,IAAA,IAAI,aAAa,cAAA,EAAgB,OAAO,IAAA,CAAK,OAAA,GAAU,GAAG,CAAA;AAC1D,IAAA,IAAI,aAAa,UAAA,EAAY,OAAO,IAAA,CAAK,IAAA,GAAO,GAAG,CAAA;AACnD,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,QAAQ,CAAA;AACtC,IAAA,IAAI,KAAA,EAAO,OAAO,KAAA,CAAM,GAAG,CAAA;AAC3B,IAAA,OAAO,IAAI,QAAA;AAAA,MACT,IAAA,CAAK,SAAA,CAAU,EAAE,KAAA,EAAO,WAAA,EAAa,WAAW,CAAC,eAAA,EAAiB,WAAW,CAAA,EAAG,CAAA;AAAA,MAChF,EAAE,MAAA,EAAQ,GAAA,EAAK,SAAS,EAAE,cAAA,EAAgB,oBAAmB;AAAE,KACjE;AAAA,EACF,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,qBAAqB,WAAA,EAA8B;AACjD,IAAA,MAAM,QAAQ,WAAA,IAAe,IAAA,CAAK,WAAW,6BAAA,EAA+B,OAAA,CAAQ,OAAO,EAAE,CAAA;AAC7F,IAAA,MAAM,SAAA,GAAY,CAAC,GAAG,IAAA,CAAK,MAAA,CAAO,MAAA,EAAQ,CAAA,CAAE,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,KAAK,SAAS,CAAA;AAC1E,IAAA,MAAM,OAAA,GAAU,SAAA,CAAU,CAAC,CAAA,EAAG,KAAK,IAAA,IAAQ,SAAA;AAC3C,IAAA,OAAO;AAAA,MACL,uEAAA;AAAA,MACA,CAAA,0BAAA,EAA6B,IAAI,CAAA,CAAA,EAAI,OAAO,CAAA,CAAA;AAAA,MAC5C;AAAA,KACF,CAAE,KAAK,IAAI,CAAA;AAAA,EACb;AACF;AAEO,SAAS,YAAY,MAAA,EAA4B;AACtD,EAAA,OAAO,IAAI,MAAM,MAAM,CAAA;AACzB;AAuBO,SAAS,kBAAA,CAAmB,GAAA,GAA0C,OAAA,CAAQ,GAAA,EAAY;AAC/F,EAAA,MAAM,IAAA,GAAO,CAAC,GAAA,KAAoC;AAChD,IAAA,MAAM,CAAA,GAAI,GAAA,CAAI,GAAG,CAAA,EAAG,IAAA,EAAK;AACzB,IAAA,OAAO,CAAA,IAAK,CAAA,CAAE,MAAA,GAAS,CAAA,GAAI,CAAA,GAAI,MAAA;AAAA,EACjC,CAAA;AAEA,EAAA,MAAM,KAAA,GAAQ,KAAK,cAAc,CAAA;AACjC,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AAEA,EAAA,MAAM,OAAA,GAAU,KAAK,eAAe,CAAA;AACpC,EAAA,IAAI,OAAA,IAAW,OAAA,KAAY,SAAA,IAAa,OAAA,KAAY,SAAA,EAAW;AAC7D,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,2DAAA,EAA8D,OAAO,CAAA,CAAA,CAAG,CAAA;AAAA,EAC1F;AAEA,EAAA,MAAM,KAAA,GAAQ,KAAK,iBAAiB,CAAA;AACpC,EAAA,MAAM,OAAA,GAAU,KAAK,mBAAmB,CAAA;AACxC,EAAA,MAAM,KAAA,GACJ,KAAA,IAAS,OAAA,GAAU,IAAI,kBAAA,CAAmB,EAAE,GAAA,EAAK,KAAA,EAAO,KAAA,EAAO,OAAA,EAAS,CAAA,GAAI,MAAA;AAE9E,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,OAAA,CAAQ,IAAA;AAAA,MACN;AAAA,KAEF;AAAA,EACF;AAEA,EAAA,OAAO,IAAI,KAAA,CAAM;AAAA,IACf,KAAA;AAAA,IACA,SAAU,OAAA,IAAwC,SAAA;AAAA,IAClD,OAAA,EAAS,KAAK,gBAAgB,CAAA;AAAA,IAC9B,IAAA,EAAM,KAAK,YAAY,CAAA;AAAA,IACvB,WAAA,EAAa,KAAK,mBAAmB,CAAA;AAAA,IACrC,iBAAA,EAAmB,KAAK,2BAA2B,CAAA;AAAA,IACnD;AAAA,GACD,CAAA;AACH;;;ACzKO,SAAS,YAAY,KAAA,EAG1B;AACA,EAAA,OAAO,EAAE,IAAA,EAAM,KAAA,EAAO,OAAA,EAAS,KAAA,EAAM;AACvC","file":"index.js","sourcesContent":["import { USDC, USDC_TESTNET } from '@t2000/sui-x402';\nimport type { Serve } from './serve.js';\n\n// ---------------------------------------------------------------------------\n// Discovery docs — /openapi.json + /llms.txt.\n//\n// The shapes here are what the on-chain listing probe grades (the check\n// behind `t2 agent sell`) (was: apps/gateway/lib/\n// catalog-ingest.ts `gradeListing`): a warning-free listing needs info.title,\n// a one-paragraph info.description, a flat string `x-payment-info.price` per\n// paid operation, and an application/json requestBody schema with typed\n// properties. Everything serve can derive is emitted automatically; the JSON\n// request schema comes from the route's `inputSchema` (zod v4 users:\n// `z.toJSONSchema(schema)`).\n// ---------------------------------------------------------------------------\n\nexport function buildOpenApiDocument(serve: Serve, origin?: string): Record<string, unknown> {\n const base = serve.baseUrl ?? origin;\n const paths: Record<string, unknown> = {};\n\n for (const route of serve.routes.values()) {\n const { path, priceUsdc, description, inputSchema, outputSchema } = route.meta;\n const operation: Record<string, unknown> = {\n operationId: path.replace(/[^a-zA-Z0-9]+/g, '_'),\n summary: description ?? path,\n responses: {\n '200': outputSchema\n ? {\n description: 'Success',\n content: { 'application/json': { schema: outputSchema } },\n }\n : { description: 'Success' },\n ...(priceUsdc\n ? {\n '402': {\n description:\n 'Payment required — the body carries an x402 accepts[] envelope (scheme \"exact\", network sui). Sign it and retry with the X-PAYMENT header.',\n },\n }\n : {}),\n '422': { description: 'Invalid request body — never charged' },\n },\n };\n if (priceUsdc) {\n // Same shape the gateway's own /openapi.json emits: 'mpp' is the\n // protocol family, 'x402' the dialect; the x402 block mirrors the\n // static half of the live accepts[] entry (dynamic fields ride the 402).\n operation['x-payment-info'] = {\n pricingMode: 'fixed',\n price: priceUsdc,\n currency: 'USDC',\n protocols: ['mpp', 'x402'],\n x402: {\n scheme: 'exact',\n network: `sui:${serve.network}`,\n asset: (serve.network === 'testnet' ? USDC_TESTNET : USDC).type,\n payTo: serve.payTo,\n },\n };\n }\n if (inputSchema) {\n operation.requestBody = {\n required: true,\n content: { 'application/json': { schema: inputSchema } },\n };\n }\n paths[`/${path}`] = { post: operation };\n }\n\n return {\n openapi: '3.1.0',\n info: {\n title: serve.name ?? 'Paid API',\n version: '1.0.0',\n description:\n serve.description ??\n 'Agent-payable API. Every paid endpoint answers 402 with an x402 accepts[] envelope; payment settles in USDC on Sui.',\n },\n ...(base ? { servers: [{ url: base }] } : {}),\n paths,\n };\n}\n\nexport function buildLlmsTxt(serve: Serve, origin?: string): string {\n const base = serve.baseUrl ?? origin ?? '';\n const lines: string[] = [];\n lines.push(`# ${serve.name ?? 'Paid API'}`);\n lines.push('');\n if (serve.description) {\n lines.push(serve.description);\n lines.push('');\n }\n lines.push('## How to pay');\n lines.push('');\n lines.push(\n 'Endpoints below are paid per call in USDC on Sui (x402). An unpaid request returns',\n 'HTTP 402 with an `accepts[]` envelope; sign it and retry with the `X-PAYMENT` header.',\n 'Invalid input returns 422 before any payment is taken. A failed call is never charged.',\n '',\n 'Easiest client: `npm i -g @t2000/cli` then `t2 pay <url> --data \\'{...}\\'`,',\n 'or the t2000 MCP server (`t2000_pay`), or `@t2000/sdk` `pay()`.',\n '',\n );\n lines.push('## Endpoints');\n lines.push('');\n for (const route of serve.routes.values()) {\n const { path, priceUsdc, description, inputSchema, outputSchema } = route.meta;\n const price = priceUsdc ? `${priceUsdc} USDC per call` : 'free';\n lines.push(`### POST ${base}/${path} — ${price}`);\n if (description) lines.push(description);\n if (inputSchema) {\n lines.push('Request body (JSON Schema):');\n lines.push('```json');\n lines.push(JSON.stringify(inputSchema, null, 2));\n lines.push('```');\n }\n if (outputSchema) {\n lines.push('Response (JSON Schema — contentMediaType/format annotations name the deliverable types):');\n lines.push('```json');\n lines.push(JSON.stringify(outputSchema, null, 2));\n lines.push('```');\n }\n lines.push('');\n }\n lines.push(`Discovery: ${base}/openapi.json`);\n return lines.join('\\n');\n}\n","import { SuiGrpcClient } from '@mysten/sui/grpc';\nimport type { ServeNetwork } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Chain plumbing — same shape as the gateway's x402-dialect.ts (the reference\n// composition). All reads are gRPC; this package never touches JSON-RPC.\n//\n// Cache policy: the chain identifier (genesis digest) is immutable per\n// network — cached forever. The epoch advances ~daily and x402 requirements\n// are valid for [epoch, epoch+1], so a 10-minute TTL is conservatively fresh.\n// ---------------------------------------------------------------------------\n\nconst FULLNODE_URLS: Record<ServeNetwork, string> = {\n mainnet: 'https://fullnode.mainnet.sui.io:443',\n testnet: 'https://fullnode.testnet.sui.io:443',\n};\n\nconst EPOCH_TTL_MS = 10 * 60 * 1000;\n\nexport interface ChainInfo {\n chain: string;\n epoch: string;\n}\n\ninterface ChainState {\n client?: SuiGrpcClient;\n chainId?: string;\n epoch?: { value: string; fetchedAt: number };\n}\n\nconst state: Partial<Record<ServeNetwork, ChainState>> = {};\n\nexport function getGrpcClient(network: ServeNetwork, rpcUrl?: string): SuiGrpcClient {\n const s = (state[network] ??= {});\n if (!s.client) {\n s.client = new SuiGrpcClient({\n baseUrl: rpcUrl ?? FULLNODE_URLS[network],\n network,\n });\n }\n return s.client;\n}\n\nexport async function getChainInfo(network: ServeNetwork, rpcUrl?: string): Promise<ChainInfo> {\n const client = getGrpcClient(network, rpcUrl);\n const s = (state[network] ??= {});\n if (!s.chainId) {\n const res = await client.core.getChainIdentifier();\n s.chainId = res.chainIdentifier;\n }\n if (!s.epoch || Date.now() - s.epoch.fetchedAt > EPOCH_TTL_MS) {\n const res = await client.core.getCurrentSystemState();\n s.epoch = { value: String(res.systemState.epoch), fetchedAt: Date.now() };\n }\n return { chain: s.chainId, epoch: s.epoch.value };\n}\n\n/** Test seam — reset module caches between cases. */\nexport function __resetChainCaches(): void {\n delete state.mainnet;\n delete state.testnet;\n}\n\n/** Test seam — pre-seed chain info so tests never hit the network. */\nexport function __seedChainInfo(network: ServeNetwork, chain: string, epoch: string): void {\n const s = (state[network] ??= {});\n s.chainId = chain;\n s.epoch = { value: epoch, fetchedAt: Date.now() };\n}\n","import type { Currency, DigestStore } from '@t2000/sui-x402';\nimport {\n createX402Requirements,\n encodeX402Response,\n isX402EscrowHeader,\n parseX402Header,\n settleX402Payment,\n verifyX402Payment,\n X402_PAYMENT_HEADER,\n X402_PAYMENT_RESPONSE_HEADER,\n X402_VERSION,\n type X402SettleResponse,\n} from '@t2000/sui-x402';\nimport { getChainInfo, getGrpcClient } from './chain.js';\nimport type {\n BuiltRoute,\n HandlerContext,\n HandlerResult,\n ServeNetwork,\n ServeSchema,\n StandardSchemaLike,\n} from './types.js';\n\n// ---------------------------------------------------------------------------\n// The paid-request lifecycle (SPEC_T2000_SERVE §3 — sign-then-settle,\n// handler-then-settle):\n//\n// no X-PAYMENT → 402 with the accepts[] envelope (never a charge;\n// the catalog probe and every discovery tool read\n// this, so it fires BEFORE body validation)\n// X-PAYMENT present:\n// 1. parse + STRUCTURAL verify (right amount/recipient/nonce — no RPC)\n// 2. challenge-once check (a signed payload is single-use)\n// 3. validate the body — invalid → 422, payment NEVER submitted\n// (the JMPR paid-422 class is impossible: the buyer keeps their money)\n// 4. run the handler — throws → 500, payment NEVER submitted\n// 5. settle (submit the buyer-signed gasless bytes; digest-once inside)\n// 6. consume the challenge, attach the X-PAYMENT-RESPONSE receipt\n//\n// Money only moves at step 5, after the seller has already produced the\n// result. A forged payload can waste seller compute (signature authority is\n// the chain at settle time), never buyer money.\n// ---------------------------------------------------------------------------\n\nexport interface RouteRuntime {\n payTo: string;\n network: ServeNetwork;\n currency: Currency;\n store: DigestStore;\n baseUrl?: string;\n rpcUrl?: string;\n /** B2 attributed reporting — unset = no report (see ServeConfig). */\n activityReportUrl?: string;\n}\n\nexport interface RouteOptions {\n path: string;\n description?: string;\n}\n\n/** Sanity cap on a per-call price — above this, the work is job-shaped\n * (escrow) rather than a per-call x402 Service. */\nconst CATALOG_PRICE_CAP_USDC = 5;\n\nconst CORS_HEADERS: Record<string, string> = {\n 'access-control-allow-origin': '*',\n 'access-control-allow-methods': 'GET, POST, PUT, DELETE, OPTIONS',\n 'access-control-allow-headers': `content-type, ${X402_PAYMENT_HEADER}`,\n 'access-control-expose-headers': `${X402_PAYMENT_RESPONSE_HEADER}, WWW-Authenticate`,\n};\n\nfunction withCors(response: Response): Response {\n const headers = new Headers(response.headers);\n for (const [k, v] of Object.entries(CORS_HEADERS)) headers.set(k, v);\n return new Response(response.body, { status: response.status, headers });\n}\n\nfunction json(status: number, body: unknown, headers?: Record<string, string>): Response {\n return withCors(\n new Response(JSON.stringify(body), {\n status,\n headers: { 'content-type': 'application/json', ...headers },\n }),\n );\n}\n\nfunction isStandardSchema(schema: ServeSchema): schema is StandardSchemaLike {\n return typeof schema === 'object' && schema !== null && '~standard' in schema;\n}\n\nasync function validateBody(\n schema: ServeSchema,\n value: unknown,\n): Promise<{ ok: true; data: unknown } | { ok: false; message: string }> {\n if (isStandardSchema(schema)) {\n const result = await schema['~standard'].validate(value);\n if (result.issues) {\n // Name the failing field — bare \"Invalid input\" ×N gives a paying\n // buyer's agent nothing to self-correct with.\n const message = result.issues\n .map((i) => {\n const path = (i.path ?? [])\n .map((seg) => (typeof seg === 'object' ? String(seg.key) : String(seg)))\n .join('.');\n return path ? `${path}: ${i.message}` : i.message;\n })\n .join('; ');\n return { ok: false, message };\n }\n return { ok: true, data: result.value };\n }\n const result = schema.safeParse(value);\n if (!result.success) {\n return { ok: false, message: result.error.message ?? 'invalid body' };\n }\n return { ok: true, data: result.data };\n}\n\n/** Positive decimal USDC string, max 6dp (atomic precision). */\nfunction assertValidPrice(price: string, path: string): void {\n if (!/^\\d+(\\.\\d{1,6})?$/.test(price) || Number(price) <= 0) {\n throw new Error(\n `[serve] Route \"${path}\": price must be a positive decimal USDC string with up to 6 decimals, got \"${price}\"`,\n );\n }\n if (Number(price) > CATALOG_PRICE_CAP_USDC) {\n console.warn(\n `[serve] Route \"${path}\": price ${price} USDC is above the ${CATALOG_PRICE_CAP_USDC} USDC listing cap — ` +\n 'the route works, but per-call x402 is the wrong shape for it. Job-class work belongs in `t2 service create` (escrow).',\n );\n }\n}\n\nexport class RouteBuilder<TBody = undefined> {\n private priceUsdc?: string;\n private bodySchema?: ServeSchema;\n private inputSchema?: Record<string, unknown>;\n private outputSchema?: Record<string, unknown>;\n private isFree = false;\n\n constructor(\n private readonly runtime: RouteRuntime,\n private readonly options: RouteOptions,\n private readonly register: (route: BuiltRoute) => void,\n ) {}\n\n /** Charge this many USDC per call (human units, e.g. \"0.01\"). */\n paid(priceUsdc: string): this {\n assertValidPrice(priceUsdc, this.options.path);\n this.priceUsdc = priceUsdc;\n this.isFree = false;\n return this;\n }\n\n /** Serve without payment (health checks, previews, docs). */\n unprotected(): this {\n this.isFree = true;\n this.priceUsdc = undefined;\n return this;\n }\n\n /**\n * Validate the JSON request body. zod v4 / valibot / arktype / anything\n * Standard-Schema, or anything with a zod-style safeParse.\n *\n * Pass the JSON Schema as the second argument to publish it in\n * /openapi.json + /llms.txt (zod v4: `z.toJSONSchema(schema)`) — buyers'\n * agents build request bodies from it, and the catalog grades listings\n * without one.\n */\n body<T>(schema: ServeSchema<T>, jsonSchema?: Record<string, unknown>): RouteBuilder<T> {\n this.bodySchema = schema;\n this.inputSchema = jsonSchema;\n return this as unknown as RouteBuilder<T>;\n }\n\n /**\n * Declare the 200 response's JSON Schema (zod v4: `z.toJSONSchema(schema)`).\n * Published in /openapi.json + /llms.txt so buyer agents know what they're\n * buying and buyer UIs can render the deliverable by TYPE instead of\n * sniffing it — annotate with `contentMediaType` (e.g. \"image/svg+xml\",\n * \"text/markdown\") and `format: \"color\"` where they apply. Declaration\n * only; responses are never validated at runtime.\n */\n response(jsonSchema: Record<string, unknown>): this {\n this.outputSchema = jsonSchema;\n return this;\n }\n\n handler(fn: (ctx: HandlerContext<TBody>) => HandlerResult | Promise<HandlerResult>): BuiltRoute {\n if (!this.isFree && !this.priceUsdc) {\n throw new Error(\n `[serve] Route \"${this.options.path}\": call .paid('<usdc>') or .unprotected() before .handler()`,\n );\n }\n const runtime = this.runtime;\n const { path, description } = this.options;\n const priceUsdc = this.priceUsdc;\n const bodySchema = this.bodySchema;\n\n const route = (async (req: Request): Promise<Response> => {\n if (req.method === 'OPTIONS') {\n return withCors(new Response(null, { status: 204 }));\n }\n\n // Read + parse the body once, up front. A missing/empty body on a\n // schema-less route is fine; JSON parse failures only matter when a\n // paid request must be validated (the unpaid 402 fires regardless).\n let parsedBody: unknown;\n let bodyParseError: string | undefined;\n if (req.method !== 'GET' && req.method !== 'HEAD') {\n const text = await req.text();\n if (text.trim().length > 0) {\n try {\n parsedBody = JSON.parse(text);\n } catch {\n bodyParseError = 'request body is not valid JSON';\n }\n }\n }\n\n const resource = (runtime.baseUrl ?? new URL(req.url).origin).replace(/\\/$/, '') + `/${path}`;\n\n const runHandler = async (payer?: string): Promise<Response> => {\n let validated: unknown = parsedBody;\n if (bodySchema) {\n // `paid: false` is machine-readable charge honesty — a 422 fires\n // BEFORE settlement, so the buyer always keeps their money.\n if (bodyParseError) {\n return json(422, { error: bodyParseError, paid: false });\n }\n const result = await validateBody(bodySchema, parsedBody ?? {});\n if (!result.ok) {\n return json(422, { error: result.message, paid: false });\n }\n validated = result.data;\n }\n const out = await fn({ body: validated as TBody, req, payer });\n if (out instanceof Response) return withCors(out);\n return json(200, out);\n };\n\n // Free route — no payment machinery at all.\n if (!priceUsdc) {\n try {\n return await runHandler();\n } catch (err) {\n console.error(`[serve] Route \"${path}\" handler failed:`, err);\n return json(500, { error: 'internal error' });\n }\n }\n\n const paymentHeader = req.headers.get(X402_PAYMENT_HEADER);\n\n // Unpaid → 402 with the accepts[] envelope. This fires before body\n // validation on purpose: the catalog probe (and every discovery tool)\n // POSTs `{}` and must see the challenge, and an unpaid request can\n // never be charged, so there is nothing to protect yet.\n if (!paymentHeader) {\n return await respond402(runtime, { resource, priceUsdc });\n }\n\n if (isX402EscrowHeader(paymentHeader)) {\n return await respond402(runtime, {\n resource,\n priceUsdc,\n error:\n 'this endpoint sells instant per-call work (settle-then-serve), not escrow jobs — retry with a signed x402 payment',\n });\n }\n\n // 1. Parse + structural verify — right terms, right recipient, right\n // nonce. No RPC, no state. Wrong-terms payloads never reach the\n // handler.\n let payment: ReturnType<typeof parseX402Header>;\n try {\n payment = parseX402Header(paymentHeader);\n verifyX402Payment({\n payment,\n expected: {\n challengeId: payment.payload.challengeId,\n amount: priceUsdc,\n currency: runtime.currency,\n recipient: runtime.payTo,\n network: runtime.network,\n },\n });\n } catch (err) {\n return await respond402(runtime, {\n resource,\n priceUsdc,\n error: `invalid payment: ${err instanceof Error ? err.message : String(err)}`,\n });\n }\n\n // 2. Challenge-once — a signed payload is single-use even before it\n // settles (the settled digest is separately consumed inside\n // settleX402Payment, digest-once).\n const challengeKey = `challenge:${payment.payload.challengeId}`;\n if (await runtime.store.has(challengeKey)) {\n return await respond402(runtime, {\n resource,\n priceUsdc,\n error: 'payment challenge already used — sign a fresh payment',\n });\n }\n\n // 3 + 4. Validate, then compute the result. Any failure here returns\n // WITHOUT settling — the buyer-signed bytes are never submitted.\n let served: Response;\n try {\n served = await runHandler(payment.payload.senderAddress);\n } catch (err) {\n console.error(`[serve] Route \"${path}\" handler failed (payment NOT settled):`, err);\n return json(500, { error: 'internal error — you were not charged' });\n }\n if (served.status >= 400) return served; // 422 etc. — not charged\n\n // 5. Settle — submit the buyer-signed gasless bytes, confirm the\n // on-chain balance change, record the digest (digest-once).\n let settle: X402SettleResponse;\n try {\n settle = await settleX402Payment({\n payment,\n client: getGrpcClient(runtime.network, runtime.rpcUrl),\n store: runtime.store,\n expected: {\n challengeId: payment.payload.challengeId,\n amount: priceUsdc,\n currency: runtime.currency,\n recipient: runtime.payTo,\n network: runtime.network,\n },\n });\n } catch (err) {\n return await respond402(runtime, {\n resource,\n priceUsdc,\n error: `settlement failed: ${err instanceof Error ? err.message : String(err)}`,\n });\n }\n\n // 6. Consume the challenge + attach the receipt.\n try {\n await runtime.store.set(challengeKey);\n } catch {\n // Digest-once already holds; challenge-once is defense in depth.\n }\n\n // B2: attributed activity report — AFTER a successful settle only,\n // strictly fire-and-forget (a dead report can never change the\n // buyer's 200 or the settle; SPEC_T2_ACTIVITY_X402 §7 lock 6).\n reportActivity(runtime, {\n digest: settle.transaction,\n payer: settle.payer,\n priceUsdc,\n resource,\n });\n\n const headers = new Headers(served.headers);\n headers.set(X402_PAYMENT_RESPONSE_HEADER, encodeX402Response(settle));\n return new Response(served.body, { status: served.status, headers });\n }) as BuiltRoute;\n\n route.meta = {\n path,\n priceUsdc,\n description,\n bodySchema,\n inputSchema: this.inputSchema,\n outputSchema: this.outputSchema,\n };\n this.register(route);\n return route;\n }\n}\n\n/** Fire-and-forget x402.paid report (B2). Never awaited into the response\n * path; short timeout; every failure swallowed. The report endpoint\n * chain-verifies the digest, so this carries claims, not trust. */\nfunction reportActivity(\n runtime: RouteRuntime,\n args: { digest: string; payer: string; priceUsdc: string; resource: string },\n): void {\n const url = runtime.activityReportUrl;\n if (!url) return;\n try {\n void fetch(url, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n digest: args.digest,\n payTo: runtime.payTo,\n payer: args.payer,\n amountMicroUsdc: Math.round(Number(args.priceUsdc) * 1_000_000),\n network: `sui:${runtime.network}`,\n route: args.resource,\n source: 'serve',\n }),\n signal: AbortSignal.timeout(1500),\n }).catch(() => undefined);\n } catch {\n // even a sync throw (bad URL) must not touch the buyer's response\n }\n}\n\nasync function respond402(\n runtime: RouteRuntime,\n args: { resource: string; priceUsdc: string; error?: string },\n): Promise<Response> {\n try {\n const { chain, epoch } = await getChainInfo(runtime.network, runtime.rpcUrl);\n const requirements = createX402Requirements({\n challengeId: crypto.randomUUID(),\n amount: args.priceUsdc,\n currency: runtime.currency,\n recipient: runtime.payTo,\n resource: args.resource,\n network: runtime.network,\n chain,\n currentEpoch: epoch,\n });\n // Belt-and-suspenders for pre-0.2.2 discovery clients and dual-dialect\n // consumers: mirror the challenge into the MPP WWW-Authenticate shape.\n // The accepts[] body stays the authoritative envelope — the header carries\n // the same recipient/currency and the DECIMAL amount that dialect uses.\n const host = (() => {\n try {\n return new URL(args.resource).hostname;\n } catch {\n return undefined;\n }\n })();\n const wwwAuth = `Payment realm=\"${host ?? 'x402'}\", recipient=\"${runtime.payTo}\", currency=\"${runtime.currency}\", amount=\"${args.priceUsdc}\"`;\n return json(\n 402,\n {\n x402Version: X402_VERSION,\n error: args.error ?? 'Payment required',\n accepts: [requirements],\n },\n { 'WWW-Authenticate': wwwAuth },\n );\n } catch (err) {\n // Chain info unreachable — a 402 without the envelope is unpayable, so\n // be honest about the outage instead of serving a dead challenge.\n console.error('[serve] failed to build 402 challenge:', err);\n return json(503, { error: 'payment challenge temporarily unavailable' });\n }\n}\n\n","import type { DigestStore } from '@t2000/sui-x402';\n\nexport { InMemoryDigestStore } from '@t2000/sui-x402';\nexport type { DigestStore } from '@t2000/sui-x402';\n\n// ---------------------------------------------------------------------------\n// Upstash-REST digest store — the production replay store for serverless\n// hosts. Mirrors the gateway's upstash-digest-store.ts but speaks the\n// Upstash REST API over plain fetch (no @upstash/redis dependency).\n//\n// TTL: 72h. x402 payments are chain-valid for the whole ValidDuring window\n// ([minEpoch, minEpoch+1] ≈ up to ~48h on mainnet). Sui resubmission of an\n// executed tx is idempotent, so if the digest/challenge keys expired BEFORE\n// the window closed, a replayed X-PAYMENT would re-settle \"successfully\"\n// and serve again on a single payment. 72h > max window + drift.\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_TTL_SECONDS = 72 * 60 * 60;\nconst PREFIX = 'serve:digest:';\n\nexport interface UpstashDigestStoreOptions {\n url: string;\n token: string;\n /** Key TTL in seconds. Default 72h — do not lower below ~50h (see above). */\n ttlSeconds?: number;\n}\n\nexport class UpstashDigestStore implements DigestStore {\n private readonly url: string;\n private readonly token: string;\n private readonly ttlSeconds: number;\n\n constructor(options: UpstashDigestStoreOptions) {\n this.url = options.url.replace(/\\/$/, '');\n this.token = options.token;\n this.ttlSeconds = options.ttlSeconds ?? DEFAULT_TTL_SECONDS;\n }\n\n private async command(segments: string[]): Promise<unknown> {\n const res = await fetch(`${this.url}/${segments.map(encodeURIComponent).join('/')}`, {\n headers: { authorization: `Bearer ${this.token}` },\n });\n if (!res.ok) {\n throw new Error(`Upstash command failed: ${res.status} ${await res.text()}`);\n }\n const body = (await res.json()) as { result?: unknown; error?: string };\n if (body.error) throw new Error(`Upstash error: ${body.error}`);\n return body.result;\n }\n\n async has(digest: string): Promise<boolean> {\n const result = await this.command(['GET', PREFIX + digest]);\n return result !== null && result !== undefined;\n }\n\n async set(digest: string): Promise<void> {\n // SET key 1 EX <ttl> NX — atomic set-if-absent. A null result means the\n // key already existed: the digest (or challenge) was already consumed.\n const result = await this.command([\n 'SET',\n PREFIX + digest,\n '1',\n 'EX',\n String(this.ttlSeconds),\n 'NX',\n ]);\n if (result === null || result === undefined) {\n throw new Error(`Digest already used: ${digest}`);\n }\n }\n}\n","import { isValidSuiAddress, normalizeSuiAddress } from '@mysten/sui/utils';\nimport { InMemoryDigestStore, USDC, USDC_TESTNET, type Currency } from '@t2000/sui-x402';\nimport { buildLlmsTxt, buildOpenApiDocument } from './discovery.js';\nimport { RouteBuilder, type RouteOptions, type RouteRuntime } from './route.js';\nimport { UpstashDigestStore } from './store.js';\nimport type { BuiltRoute, ServeConfig, ServeNetwork } from './types.js';\n\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 activityReportUrl: config.activityReportUrl,\n };\n }\n\n /** Start building a route. Chain `.paid()` / `.body()` / `.handler()`. */\n route(options: RouteOptions): RouteBuilder {\n const path = options.path.replace(/^\\/+/, '').replace(/\\/+$/, '');\n if (!path) throw new Error('[serve] route path must be non-empty');\n return new RouteBuilder({ ...this.runtime }, { ...options, path }, (route) => {\n this.routes.set(path, route);\n });\n }\n\n /**\n * Discovery: GET handler for /openapi.json. OpenAPI 3.1 with the\n * `x-payment-info` pricing extension on every paid operation — the shape\n * x402 tooling (and any catalog built on it) indexes.\n *\n * export const GET = serve.openapi(); // app/openapi.json/route.ts\n */\n openapi(): (req: Request) => Response {\n return (req: Request) =>\n new Response(JSON.stringify(buildOpenApiDocument(this, new URL(req.url).origin), null, 2), {\n headers: { 'content-type': 'application/json', 'access-control-allow-origin': '*' },\n });\n }\n\n /**\n * Discovery: GET handler for /llms.txt — plain-text guidance agents read\n * to understand what the API sells, what it costs, and how to pay.\n *\n * export const GET = serve.llms(); // app/llms.txt/route.ts\n */\n llms(): (req: Request) => Response {\n return (req: Request) =>\n new Response(buildLlmsTxt(this, new URL(req.url).origin), {\n headers: { 'content-type': 'text/plain; charset=utf-8', 'access-control-allow-origin': '*' },\n });\n }\n\n /**\n * One fetch handler for the whole app — routes + discovery docs. For\n * fetch-native runtimes (Bun.serve, Deno.serve, Hono, Cloudflare Workers):\n *\n * Bun.serve({ fetch: serve.fetch });\n * app.all('*', (c) => serve.fetch(c.req.raw)); // Hono\n *\n * Next.js apps can skip this and export route handlers directly.\n */\n readonly fetch = async (req: Request): Promise<Response> => {\n const pathname = new URL(req.url).pathname.replace(/^\\/+/, '').replace(/\\/+$/, '');\n if (pathname === 'openapi.json') return this.openapi()(req);\n if (pathname === 'llms.txt') return this.llms()(req);\n const route = this.routes.get(pathname);\n if (route) return route(req);\n return new Response(\n JSON.stringify({ error: 'not found', discovery: ['/openapi.json', '/llms.txt'] }),\n { status: 404, headers: { 'content-type': 'application/json' } },\n );\n };\n\n /**\n * The command that sells this API as an x402 Service on your Agent ID,\n * once it is deployed. Listing is a separate, explicit step: the endpoint\n * is live-probed (it must answer 402 with a Sui challenge that pays YOUR\n * wallet) and then recorded on-chain, sponsored and gasless.\n *\n * This used to emit curls against the hosted mpp.t2000.ai catalog. That\n * proxy mall was purged 2026-08-01 (SPEC_T2_CLEANUP_USDC_ONLY) — there is\n * no central catalog to submit to. Your Agent ID IS the listing, and\n * buyers find it with `t2 services`.\n */\n catalogSubmitCommand(deployedUrl?: string): string {\n const base = (deployedUrl ?? this.baseUrl ?? 'https://<your-deployed-app>').replace(/\\/$/, '');\n const paidPaths = [...this.routes.values()].filter((r) => r.meta.priceUsdc);\n const example = paidPaths[0]?.meta.path ?? '<route>';\n return [\n '# Sell it as an x402 Service on your Agent ID (live-probed, gasless):',\n `npx @t2000/cli agent sell ${base}/${example}`,\n '# Buyers then find it with `t2 services` and pay per call with `t2 pay`.',\n ].join('\\n');\n }\n}\n\nexport function createServe(config: ServeConfig): Serve {\n return new Serve(config);\n}\n\n/**\n * Build a Serve from environment variables — the template-app path where\n * config lives in the host's env UI, not code.\n *\n * T2000_PAY_TO required — the seller's Sui address\n * T2000_NETWORK optional — 'mainnet' (default) | 'testnet'\n * T2000_BASE_URL optional — public URL of the deployed app\n * T2000_NAME optional — service name for discovery docs\n * T2000_DESCRIPTION optional — one-liner for discovery docs\n * T2000_ACTIVITY_REPORT_URL\n * optional — fire-and-forget x402.paid reports after each\n * successful settle; set https://t2000.ai/api/activity/x402\n * to appear on the t2000.ai activity tape (chain-verified\n * server-side, never affects buyer responses)\n * KV_REST_API_URL / KV_REST_API_TOKEN\n * optional — enables the durable Upstash replay store\n * (REQUIRED in serverless production; without it replay\n * state is per-instance memory)\n *\n * Empty strings are treated as unset (the Vercel empty-env bug class).\n */\nexport function createServeFromEnv(env: Record<string, string | undefined> = process.env): Serve {\n const read = (key: string): string | undefined => {\n const v = env[key]?.trim();\n return v && v.length > 0 ? v : undefined;\n };\n\n const payTo = read('T2000_PAY_TO');\n if (!payTo) {\n throw new Error(\n '[serve] T2000_PAY_TO is not set (or is empty). Set it to the Sui address your payments should settle to — `t2 address` prints yours.',\n );\n }\n\n const network = read('T2000_NETWORK');\n if (network && network !== 'mainnet' && network !== 'testnet') {\n throw new Error(`[serve] T2000_NETWORK must be 'mainnet' or 'testnet', got \"${network}\"`);\n }\n\n const kvUrl = read('KV_REST_API_URL');\n const kvToken = read('KV_REST_API_TOKEN');\n const store =\n kvUrl && kvToken ? new UpstashDigestStore({ url: kvUrl, token: kvToken }) : undefined;\n\n if (!store) {\n console.warn(\n '[serve] No KV_REST_API_URL/KV_REST_API_TOKEN — using the in-memory replay store. ' +\n 'Fine for a single long-lived process; on serverless hosts set both so replay protection is durable.',\n );\n }\n\n return new Serve({\n payTo,\n network: (network as ServeNetwork | undefined) ?? 'mainnet',\n baseUrl: read('T2000_BASE_URL'),\n name: read('T2000_NAME'),\n description: read('T2000_DESCRIPTION'),\n activityReportUrl: read('T2000_ACTIVITY_REPORT_URL'),\n store,\n });\n}\n","import type { BuiltRoute } from './types.js';\n\n/**\n * Export a built route the way Next.js App Router needs it.\n *\n * Next dispatches ONLY the methods a route.ts exports — serve's own CORS\n * handling (OPTIONS → 204 with the ACAO headers) never runs if the file\n * exports just `POST`: the browser preflight gets Next's bare 204 with no\n * CORS headers, and every browser buyer (Passport, the store's Try it)\n * fails while CLI/server buyers — who never preflight — work fine. Fetch\n * runtimes mounted via a single handler (`serve.fetch`-style) don't have\n * this hole; it is a Next export contract, not a serve one.\n *\n * export const { POST, OPTIONS } = asNextRoute(\n * serve.route({ path: 'haiku' }).paid('0.01').handler(fn),\n * );\n */\nexport function asNextRoute(route: BuiltRoute): {\n POST: BuiltRoute;\n OPTIONS: BuiltRoute;\n} {\n return { POST: route, OPTIONS: route };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@t2000/serve",
3
- "version": "10.20.2",
3
+ "version": "10.21.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",
@@ -36,7 +36,7 @@
36
36
  "homepage": "https://docs.t2000.ai/sell-to-agents/overview",
37
37
  "dependencies": {
38
38
  "@mysten/sui": "^2.17.0",
39
- "@t2000/sui-x402": "10.20.2"
39
+ "@t2000/sui-x402": "10.21.1"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/node": "^20",
@@ -45,7 +45,7 @@
45
45
  "typescript": "^5",
46
46
  "typescript-eslint": "^8.58.0",
47
47
  "vitest": "^3",
48
- "@t2000/discovery": "10.20.2"
48
+ "@t2000/discovery": "10.21.1"
49
49
  },
50
50
  "license": "MIT",
51
51
  "scripts": {