@haven_ai/sdk 0.1.33-alpha.0 → 0.1.34-alpha.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.
package/dist/index.cjs CHANGED
@@ -617,6 +617,7 @@ function normalizePaymentRequired(value) {
617
617
  const resourceUrl = candidate.resource?.url ?? first.resource;
618
618
  if (!resourceUrl) return null;
619
619
  const resource = {
620
+ ...candidate.resource && typeof candidate.resource === "object" ? candidate.resource : {},
620
621
  url: resourceUrl,
621
622
  description: candidate.resource?.description ?? first.description,
622
623
  mimeType: candidate.resource?.mimeType ?? first.mimeType
@@ -691,6 +692,17 @@ function x402PaymentHeaderNamesFor(paymentHeader) {
691
692
  function x402PaymentHeaderNamesSent(paymentHeader) {
692
693
  return x402PaymentHeaderNamesFor(paymentHeader).join(", ");
693
694
  }
695
+ function x402V2PaymentEnvelope(paymentRequired, accepted, payload) {
696
+ const resource = paymentRequired.resource;
697
+ const extensions = paymentRequired.extensions;
698
+ return {
699
+ x402Version: paymentRequired.x402Version,
700
+ ...resource && typeof resource === "object" && !Array.isArray(resource) ? { resource } : {},
701
+ accepted,
702
+ payload,
703
+ ...extensions && typeof extensions === "object" && !Array.isArray(extensions) ? { extensions } : {}
704
+ };
705
+ }
694
706
  function parsePaymentRequired(response) {
695
707
  const v2Header = response.headers.get("PAYMENT-REQUIRED");
696
708
  if (v2Header) {
@@ -870,7 +882,15 @@ async function validateStandardX402PaymentHeader(paymentHeader, context) {
870
882
  throw new Error("context");
871
883
  }
872
884
  } else {
873
- if (!hasOnlyKeys(decoded, ["x402Version", "accepted", "payload"])) throw new Error("shape");
885
+ if (!hasOnlyKeys(decoded, ["x402Version", "accepted", "payload"], ["resource", "extensions"])) {
886
+ throw new Error("shape");
887
+ }
888
+ if ("resource" in decoded && (!decoded.resource || typeof decoded.resource !== "object" || Array.isArray(decoded.resource))) {
889
+ throw new Error("shape");
890
+ }
891
+ if ("extensions" in decoded && (!decoded.extensions || typeof decoded.extensions !== "object" || Array.isArray(decoded.extensions))) {
892
+ throw new Error("shape");
893
+ }
874
894
  const accepted = selectStandardPaymentOption([decoded.accepted]);
875
895
  if (!accepted || !matchesHeaderContext(accepted, context)) throw new Error("context");
876
896
  }
@@ -922,8 +942,8 @@ async function validateStandardX402PaymentHeader(paymentHeader, context) {
922
942
  throw new X402PaymentHeaderValidationError();
923
943
  }
924
944
  }
925
- function hasOnlyKeys(value, allowed) {
926
- return Object.keys(value).every((key) => allowed.includes(key)) && allowed.every((key) => key in value);
945
+ function hasOnlyKeys(value, required, optional = []) {
946
+ return Object.keys(value).every((key) => required.includes(key) || optional.includes(key)) && required.every((key) => key in value);
927
947
  }
928
948
  function sameAddress2(left, right) {
929
949
  return left.toLowerCase() === right.toLowerCase();
@@ -2128,11 +2148,7 @@ var X402FundingLeg = class {
2128
2148
  );
2129
2149
  if (paymentRequired.x402Version < 2) return header;
2130
2150
  const payment = decodeBase64Json(header);
2131
- return encodeBase64Json({
2132
- x402Version: paymentRequired.x402Version,
2133
- accepted: option,
2134
- payload: payment.payload
2135
- });
2151
+ return encodeBase64Json(x402V2PaymentEnvelope(paymentRequired, option, payment.payload));
2136
2152
  }
2137
2153
  // ── Receipt mapping ──────────────────────────────────────────────
2138
2154
  receiptFromAuthorization(paymentRequired, option, paymentHeader, raw, execResult) {
@@ -2343,6 +2359,16 @@ var X402Erc7710 = class {
2343
2359
  const amountAtomic = x402AuthorizationAmount(option);
2344
2360
  const raw = await this.post("/x402", {
2345
2361
  url: options.resourceUrl ?? paymentRequired.resource?.url,
2362
+ // #2373: the full 402 challenge, persisted verbatim by the backend
2363
+ // (#1355) so the settle handoff can echo its resource/extensions into
2364
+ // the X-PAYMENT envelope (#2361). This scheme decomposes the challenge
2365
+ // into the fields below for AUTHORITY; the stored copy exists for the
2366
+ // echo, which cannot be reconstructed from the decomposition — omitting
2367
+ // it is how every erc7710 payment failed a merchant that enforces the
2368
+ // spec's extensions-echo MUST. Same ≤64KB guard and omission behaviour
2369
+ // as the 3009 path (client.ts): an oversized challenge omits the field
2370
+ // rather than failing the payment, and the settle echo then omits too.
2371
+ ...new TextEncoder().encode(JSON.stringify(paymentRequired)).length <= 65536 ? { paymentRequired } : {},
2346
2372
  // payTo = the MERCHANT is what selects direct settlement server-side.
2347
2373
  // The explicit settlementScheme must AGREE with that shape (#1360) —
2348
2374
  // disagreement is a 400 by design, so that a stale delegate address
@@ -4369,8 +4395,14 @@ The paid call always obtains a fresh quote before it creates any intent. Then
4369
4395
  continue \`mcp__haven__haven_pay_mcp_tool\` \u2192
4370
4396
  \`mcp__haven-signer__haven_sign\` \u2192 \`mcp__haven__haven_submit\` \u2192
4371
4397
  \`mcp__haven-signer__haven_x402_sign_header\` \u2192
4372
- \`mcp__haven__haven_complete_mcp_tool\`. Pass \`payment_required\`,
4373
- \`arguments\`, and \`mcp_transport\` verbatim from the quote/prepare result.
4398
+ \`mcp__haven__haven_complete_mcp_tool\`. Call that last step with
4399
+ \`payment_id\` and the signer's \`payment_header\` ONLY. It does not take
4400
+ \`payment_required\`: Haven rehydrates the merchant call context
4401
+ (\`merchant_url\`, \`tool_name\`, \`arguments\`, \`mcp_transport\`) and the
4402
+ 402 server-side from \`payment_id\`, exactly as at settle. Pass that context
4403
+ explicitly only as a version-skew fallback when Haven has no stored context
4404
+ for the id \u2014 \`merchant_url\` and \`tool_name\` both or none together, never
4405
+ just one.
4374
4406
  The returned \`expires_at\` is the signing window; if a tool returns
4375
4407
  \`PAYMENT_WINDOW_EXPIRED\`, re-run the same quote/prepare tool with the same
4376
4408
  \`idempotency_key\`. Do not call the merchant yourself \u2014 Haven completes the
@@ -4652,5 +4684,6 @@ exports.verifySignature = verifySignature;
4652
4684
  exports.x402AssetTransferMethod = x402AssetTransferMethod;
4653
4685
  exports.x402AuthorizationAmount = x402AuthorizationAmount;
4654
4686
  exports.x402FacilitatorAddresses = x402FacilitatorAddresses;
4687
+ exports.x402V2PaymentEnvelope = x402V2PaymentEnvelope;
4655
4688
  //# sourceMappingURL=index.cjs.map
4656
4689
  //# sourceMappingURL=index.cjs.map