@agent-score/commerce 2.3.0 → 2.5.0

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.
Files changed (80) hide show
  1. package/README.md +6 -6
  2. package/dist/challenge/index.d.mts +9 -5
  3. package/dist/challenge/index.d.ts +9 -5
  4. package/dist/challenge/index.js +11 -4
  5. package/dist/challenge/index.js.map +1 -1
  6. package/dist/challenge/index.mjs +11 -4
  7. package/dist/challenge/index.mjs.map +1 -1
  8. package/dist/{checkout-ChyOi7aU.d.ts → checkout-McfNpZJf.d.ts} +80 -12
  9. package/dist/{checkout-Ceo1_rVJ.d.mts → checkout-o17dIxHi.d.mts} +80 -12
  10. package/dist/core.d.mts +27 -7
  11. package/dist/core.d.ts +27 -7
  12. package/dist/core.js +25 -11
  13. package/dist/core.js.map +1 -1
  14. package/dist/core.mjs +25 -11
  15. package/dist/core.mjs.map +1 -1
  16. package/dist/discovery/index.d.mts +26 -10
  17. package/dist/discovery/index.d.ts +26 -10
  18. package/dist/discovery/index.js +58 -10
  19. package/dist/discovery/index.js.map +1 -1
  20. package/dist/discovery/index.mjs +58 -10
  21. package/dist/discovery/index.mjs.map +1 -1
  22. package/dist/gate-CWP10xPQ.d.mts +339 -0
  23. package/dist/gate-CWP10xPQ.d.ts +339 -0
  24. package/dist/identity/express.d.mts +26 -1
  25. package/dist/identity/express.d.ts +26 -1
  26. package/dist/identity/express.js +599 -25
  27. package/dist/identity/express.js.map +1 -1
  28. package/dist/identity/express.mjs +595 -24
  29. package/dist/identity/express.mjs.map +1 -1
  30. package/dist/identity/fastify.d.mts +12 -2
  31. package/dist/identity/fastify.d.ts +12 -2
  32. package/dist/identity/fastify.js +607 -25
  33. package/dist/identity/fastify.js.map +1 -1
  34. package/dist/identity/fastify.mjs +603 -24
  35. package/dist/identity/fastify.mjs.map +1 -1
  36. package/dist/identity/hono.d.mts +26 -1
  37. package/dist/identity/hono.d.ts +26 -1
  38. package/dist/identity/hono.js +588 -25
  39. package/dist/identity/hono.js.map +1 -1
  40. package/dist/identity/hono.mjs +584 -24
  41. package/dist/identity/hono.mjs.map +1 -1
  42. package/dist/identity/nextjs.d.mts +3 -0
  43. package/dist/identity/nextjs.d.ts +3 -0
  44. package/dist/identity/nextjs.js +593 -25
  45. package/dist/identity/nextjs.js.map +1 -1
  46. package/dist/identity/nextjs.mjs +589 -24
  47. package/dist/identity/nextjs.mjs.map +1 -1
  48. package/dist/identity/policy.js.map +1 -1
  49. package/dist/identity/policy.mjs.map +1 -1
  50. package/dist/identity/web.d.mts +24 -1
  51. package/dist/identity/web.d.ts +24 -1
  52. package/dist/identity/web.js +593 -25
  53. package/dist/identity/web.js.map +1 -1
  54. package/dist/identity/web.mjs +589 -24
  55. package/dist/identity/web.mjs.map +1 -1
  56. package/dist/index.d.mts +129 -14
  57. package/dist/index.d.ts +129 -14
  58. package/dist/index.js +978 -99
  59. package/dist/index.js.map +1 -1
  60. package/dist/index.mjs +956 -99
  61. package/dist/index.mjs.map +1 -1
  62. package/dist/{default_rails-DtR_E9N9.d.ts → network_kind-BIJM2peR.d.ts} +22 -8
  63. package/dist/{default_rails-K25PtWrL.d.mts → network_kind-C0EMkdzz.d.mts} +22 -8
  64. package/dist/payment/index.d.mts +16 -26
  65. package/dist/payment/index.d.ts +16 -26
  66. package/dist/payment/index.js +62 -57
  67. package/dist/payment/index.js.map +1 -1
  68. package/dist/payment/index.mjs +62 -57
  69. package/dist/payment/index.mjs.map +1 -1
  70. package/dist/{pricing-B3-aKxSz.d.ts → pricing-CytRwhC2.d.ts} +1 -1
  71. package/dist/{pricing-BReyZiqN.d.mts → pricing-KHDqMLd7.d.mts} +1 -1
  72. package/dist/{rail_spec-B1239jPp.d.mts → rail_spec-BFZmW9RN.d.mts} +3 -4
  73. package/dist/{rail_spec-B1239jPp.d.ts → rail_spec-BFZmW9RN.d.ts} +3 -4
  74. package/dist/stripe-multichain/index.d.mts +2 -9
  75. package/dist/stripe-multichain/index.d.ts +2 -9
  76. package/dist/stripe-multichain/index.js.map +1 -1
  77. package/dist/stripe-multichain/index.mjs.map +1 -1
  78. package/dist/{wwwauthenticate-D_FMnPgU.d.mts → wwwauthenticate-CVaGUMjU.d.mts} +8 -6
  79. package/dist/{wwwauthenticate-D_FMnPgU.d.ts → wwwauthenticate-CVaGUMjU.d.ts} +8 -6
  80. package/package.json +14 -13
@@ -1,3 +1,42 @@
1
+ // src/payment/amounts.ts
2
+ function usdToAtomic(usd, opts) {
3
+ const { decimals } = opts;
4
+ if (!Number.isInteger(decimals) || decimals < 0) {
5
+ throw new RangeError(`decimals must be a non-negative integer, got ${decimals}`);
6
+ }
7
+ if (typeof usd === "number") {
8
+ if (!Number.isFinite(usd)) {
9
+ throw new RangeError(`usd must be finite, got ${usd}`);
10
+ }
11
+ if (usd < 0) {
12
+ throw new RangeError(`usd must be non-negative, got ${usd}`);
13
+ }
14
+ }
15
+ const s = (typeof usd === "number" ? usd.toString() : usd).trim();
16
+ if (s.startsWith("-")) {
17
+ throw new RangeError(`usd must be non-negative, got ${s}`);
18
+ }
19
+ if (s === "NaN" || s === "Infinity") {
20
+ throw new RangeError(`usd must be finite, got ${s}`);
21
+ }
22
+ const match = /^(\d*)(?:\.(\d*))?$/.exec(s);
23
+ if (!match || match[1] === "" && (match[2] === void 0 || match[2] === "")) {
24
+ throw new SyntaxError(`invalid usd value: ${JSON.stringify(usd)}`);
25
+ }
26
+ const intPart = match[1] || "0";
27
+ const fracPart = match[2] ?? "";
28
+ if (fracPart.length <= decimals) {
29
+ return BigInt(intPart + fracPart.padEnd(decimals, "0"));
30
+ }
31
+ const kept = fracPart.slice(0, decimals);
32
+ const roundDigit = fracPart[decimals];
33
+ let result = BigInt(intPart + kept);
34
+ if (roundDigit >= "5") {
35
+ result += 1n;
36
+ }
37
+ return result;
38
+ }
39
+
1
40
  // src/payment/networks.ts
2
41
  var networks = {
3
42
  base: {
@@ -121,8 +160,7 @@ function buildPaymentRequestBlob({
121
160
  const decimalsResolved = decimals ?? railDef?.decimals ?? 6;
122
161
  const currencyResolved = currency ?? railDef?.currency ?? "usd";
123
162
  const chainIdResolved = chainId ?? railDef?.chainId;
124
- const amountNum = typeof amountUsd === "string" ? Number(amountUsd) : amountUsd;
125
- const amountRaw = BigInt(Math.round(amountNum * 10 ** decimalsResolved)).toString();
163
+ const amountRaw = usdToAtomic(amountUsd, { decimals: decimalsResolved }).toString();
126
164
  const blob = { amount: amountRaw, currency: currencyResolved, decimals: decimalsResolved };
127
165
  if (recipient) blob.recipient = recipient;
128
166
  const methodDetails = {};
@@ -325,11 +363,13 @@ function buildWellKnownX402(input) {
325
363
  // src/discovery/llms_txt.ts
326
364
  function llmsTxtIdentitySection({
327
365
  agentscore,
328
- compliance
366
+ compliance,
367
+ aip
329
368
  } = {}) {
330
369
  if (!agentscore) {
331
370
  return "";
332
371
  }
372
+ const aipBullet = aip ? "\n- **`Agent-Identity: <JWT>` + RFC 9421 signature** \u2014 present an Agent Identity Token (AIP) from a trusted issuer (AgentScore is always trusted). Short-lived and bound to your key; sign the request (`Signature-Input` + `Signature` over `@method @authority @path agent-identity`, tag `agent-identity`) to prove possession. No long-lived token on the wire. Mint one with `agentscore-pay identity-mint` or let `agentscore-pay pay --identity aip` attach it automatically." : "";
333
373
  const complianceNote = compliance ? `
334
374
 
335
375
  Compliance: ${[
@@ -343,7 +383,7 @@ Compliance: ${[
343
383
  AgentScore identity is reusable across every AgentScore-gated merchant \u2014 one KYC, no re-verification per site. Pick a header:
344
384
 
345
385
  - **\`X-Wallet-Address: 0x...\` or base58** \u2014 works on signing rails (Tempo, x402, Solana MPP). The wallet you claim must sign the payment.
346
- - **\`X-Operator-Token: opc_...\`** \u2014 works on every rail, including Stripe SPT. Reusable across AgentScore merchants until expiry.
386
+ - **\`X-Operator-Token: opc_...\`** \u2014 works on every rail, including Stripe SPT. Reusable across AgentScore merchants until expiry.${aipBullet}
347
387
  - **Neither** \u2014 you get a 403 with \`verify_url\`. Complete the session flow once and reuse the resulting \`opc_...\` everywhere.${complianceNote}`;
348
388
  }
349
389
  function llmsTxtPaymentSection(input) {
@@ -484,6 +524,12 @@ function agentscoreSecuritySchemes() {
484
524
  name: "X-Wallet-Address",
485
525
  description: "Wallet-path identity (0x... or base58). Only works on rails that carry a wallet signature (Tempo MPP, x402 EIP-3009, x402 SPL Token). The wallet you claim MUST sign the payment."
486
526
  },
527
+ AgentIdentity: {
528
+ type: "apiKey",
529
+ in: "header",
530
+ name: "Agent-Identity",
531
+ description: "AIP Agent Identity Token path (a JWT from a trusted issuer; AgentScore is always trusted). Opt-in. The token is bound to the agent key via `cnf`; the request MUST also carry an RFC 9421 HTTP Message Signature (`Signature-Input` + `Signature` over `@method @authority @path agent-identity`, tag `agent-identity`) proving possession. A verified AIT is the sole identity and is evaluated against the merchant policy via its attested claims."
532
+ },
487
533
  siwx: siwxSecurityScheme()
488
534
  };
489
535
  }
@@ -847,14 +893,16 @@ function identitySection(input) {
847
893
  if (id.minAge) reqs.push(`age ${id.minAge}+`);
848
894
  if (id.allowedJurisdictions?.length) reqs.push(`${id.allowedJurisdictions.join("/")} only`);
849
895
  if (id.sanctionsClear) reqs.push("sanctions clear");
850
- if (reqs.length === 0) return "";
896
+ if (reqs.length === 0 && !id.aip) return "";
851
897
  const bootstrap = input.identityBootstrapUrl ? `
852
898
 
853
899
  If you don't have a Passport, fetch \`${input.identityBootstrapUrl}\` and follow the onboarding there first. Bring back the \`opc_...\` operator token in \`X-Operator-Token\` on every gated request.` : "";
900
+ const reqLine = reqs.length ? `This merchant uses AgentScore identity. Required: ${reqs.join(", ")}.${bootstrap}` : `This merchant uses AgentScore identity.${bootstrap}`;
901
+ const aipNote = id.aip ? "\n\nThis merchant accepts AIP Agent Identity Tokens. If you hold an AIT from a trusted issuer (AgentScore is always trusted), present the JWT in an `Agent-Identity` header plus an RFC 9421 HTTP Message Signature (`Signature-Input` + `Signature` over `@method @authority @path agent-identity`, tag `agent-identity`) signed with the token-bound cnf key \u2014 it satisfies identity in one round trip, no separate AgentScore credential needed. `agentscore-pay pay --identity aip` does this automatically." : "";
854
902
  return [
855
903
  "## Identity Prerequisite",
856
904
  "",
857
- `This merchant uses AgentScore identity. Required: ${reqs.join(", ")}.${bootstrap}`,
905
+ `${reqLine}${aipNote}`,
858
906
  "",
859
907
  "Denial bodies carry an `agent_instructions` block describing the recovery action \u2014 read the `action` field and follow it. See the identity-bootstrap skill for the canonical denial-code \u2192 action table."
860
908
  ].join("\n");
@@ -1428,19 +1476,19 @@ function stableStringify(value) {
1428
1476
  }
1429
1477
  if (!Number.isInteger(value)) {
1430
1478
  throw new Error(
1431
- `UCP profile canonicalization rejects non-integer Number ${value}. Use a decimal string (e.g. "9.99") for monetary or fractional fields to preserve cross-language byte-parity.`
1479
+ `UCP profile canonicalization rejects non-integer Number ${value}. Use a decimal string (e.g. "9.99") for monetary or fractional fields so the signed canonical bytes stay stable for any verifier.`
1432
1480
  );
1433
1481
  }
1434
1482
  if (!Number.isSafeInteger(value)) {
1435
1483
  throw new Error(
1436
- `stableStringify: integer ${value} exceeds Number.MAX_SAFE_INTEGER. For values >2^53, use a decimal string to preserve cross-language byte parity.`
1484
+ `stableStringify: integer ${value} exceeds Number.MAX_SAFE_INTEGER. For values >2^53, use a decimal string to keep the signed bytes stable across implementations.`
1437
1485
  );
1438
1486
  }
1439
1487
  }
1440
1488
  if (typeof value === "string") {
1441
1489
  if (value.includes("\u2028") || value.includes("\u2029")) {
1442
1490
  throw new Error(
1443
- "stableStringify: strings containing U+2028 (LINE SEPARATOR) or U+2029 (PARAGRAPH SEPARATOR) are not allowed; cross-language byte parity requires neither be present (Node JSON.stringify on older V8 escapes them; Python json.dumps with ensure_ascii=False does not)."
1491
+ "stableStringify: strings containing U+2028 (LINE SEPARATOR) or U+2029 (PARAGRAPH SEPARATOR) are not allowed; stable canonical bytes require neither be present (some JSON encoders escape them, others emit them raw)."
1444
1492
  );
1445
1493
  }
1446
1494
  return JSON.stringify(value);
@@ -1460,7 +1508,7 @@ function stableStringify(value) {
1460
1508
  for (const k of keys) {
1461
1509
  if (k.includes("\u2028") || k.includes("\u2029")) {
1462
1510
  throw new Error(
1463
- "stableStringify: object keys containing U+2028 (LINE SEPARATOR) or U+2029 (PARAGRAPH SEPARATOR) are not allowed; cross-language byte parity (Node JSON.stringify on older V8 escapes them; Python json.dumps with ensure_ascii=False does not)."
1511
+ "stableStringify: object keys containing U+2028 (LINE SEPARATOR) or U+2029 (PARAGRAPH SEPARATOR) are not allowed; stable canonical bytes require neither be present (some JSON encoders escape them, others emit them raw)."
1464
1512
  );
1465
1513
  }
1466
1514
  }