@absol-labs/agent 0.10.0 → 0.11.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 (141) hide show
  1. package/README.md +107 -23
  2. package/dist/capability/invocation-capability.d.ts +18 -6
  3. package/dist/capability/invocation-capability.d.ts.map +1 -1
  4. package/dist/capability/invocation-capability.js.map +1 -1
  5. package/dist/cli/commands/claim.d.ts.map +1 -1
  6. package/dist/cli/commands/claim.js +20 -4
  7. package/dist/cli/commands/claim.js.map +1 -1
  8. package/dist/cli/commands/close.d.ts.map +1 -1
  9. package/dist/cli/commands/close.js +16 -4
  10. package/dist/cli/commands/close.js.map +1 -1
  11. package/dist/cli/commands/invoke.d.ts.map +1 -1
  12. package/dist/cli/commands/invoke.js +1 -0
  13. package/dist/cli/commands/invoke.js.map +1 -1
  14. package/dist/cli/commands/open.d.ts.map +1 -1
  15. package/dist/cli/commands/open.js +63 -11
  16. package/dist/cli/commands/open.js.map +1 -1
  17. package/dist/cli/commands/reclaim-unverified.d.ts.map +1 -1
  18. package/dist/cli/commands/reclaim-unverified.js +12 -4
  19. package/dist/cli/commands/reclaim-unverified.js.map +1 -1
  20. package/dist/cli/commands/reclaim.d.ts.map +1 -1
  21. package/dist/cli/commands/reclaim.js +16 -5
  22. package/dist/cli/commands/reclaim.js.map +1 -1
  23. package/dist/cli/commands/streams.js +1 -1
  24. package/dist/cli/commands/streams.js.map +1 -1
  25. package/dist/cli/deps.d.ts +53 -7
  26. package/dist/cli/deps.d.ts.map +1 -1
  27. package/dist/cli/deps.js +65 -15
  28. package/dist/cli/deps.js.map +1 -1
  29. package/dist/cli/privy.d.ts +83 -0
  30. package/dist/cli/privy.d.ts.map +1 -0
  31. package/dist/cli/privy.js +230 -0
  32. package/dist/cli/privy.js.map +1 -0
  33. package/dist/cli/spend-policy.d.ts +60 -0
  34. package/dist/cli/spend-policy.d.ts.map +1 -0
  35. package/dist/cli/spend-policy.js +65 -0
  36. package/dist/cli/spend-policy.js.map +1 -0
  37. package/dist/cli/wallet.d.ts +108 -39
  38. package/dist/cli/wallet.d.ts.map +1 -1
  39. package/dist/cli/wallet.js +108 -43
  40. package/dist/cli/wallet.js.map +1 -1
  41. package/dist/gateway/caller-auth-gateway.d.ts +38 -3
  42. package/dist/gateway/caller-auth-gateway.d.ts.map +1 -1
  43. package/dist/gateway/caller-auth-gateway.js +25 -1
  44. package/dist/gateway/caller-auth-gateway.js.map +1 -1
  45. package/dist/gateway/http-server.d.ts +53 -0
  46. package/dist/gateway/http-server.d.ts.map +1 -1
  47. package/dist/gateway/http-server.js +189 -4
  48. package/dist/gateway/http-server.js.map +1 -1
  49. package/dist/gateway/x402-mode.d.ts +123 -0
  50. package/dist/gateway/x402-mode.d.ts.map +1 -0
  51. package/dist/gateway/x402-mode.js +212 -0
  52. package/dist/gateway/x402-mode.js.map +1 -0
  53. package/dist/index.d.ts +6 -4
  54. package/dist/index.d.ts.map +1 -1
  55. package/dist/index.js +8 -3
  56. package/dist/index.js.map +1 -1
  57. package/dist/mandates/env.d.ts +3 -2
  58. package/dist/mandates/env.d.ts.map +1 -1
  59. package/dist/mandates/env.js +3 -2
  60. package/dist/mandates/env.js.map +1 -1
  61. package/dist/mcp/server.d.ts +49 -0
  62. package/dist/mcp/server.d.ts.map +1 -1
  63. package/dist/mcp/server.js +513 -24
  64. package/dist/mcp/server.js.map +1 -1
  65. package/dist/mcp/service-invoker.d.ts +97 -0
  66. package/dist/mcp/service-invoker.d.ts.map +1 -0
  67. package/dist/mcp/service-invoker.js +167 -0
  68. package/dist/mcp/service-invoker.js.map +1 -0
  69. package/dist/sdk/invoke.d.ts +19 -4
  70. package/dist/sdk/invoke.d.ts.map +1 -1
  71. package/dist/sdk/invoke.js +69 -5
  72. package/dist/sdk/invoke.js.map +1 -1
  73. package/dist/x402/delivery-oracle.d.ts +108 -0
  74. package/dist/x402/delivery-oracle.d.ts.map +1 -0
  75. package/dist/x402/delivery-oracle.js +174 -0
  76. package/dist/x402/delivery-oracle.js.map +1 -0
  77. package/dist/x402/facilitator-server-entry.d.ts +3 -0
  78. package/dist/x402/facilitator-server-entry.d.ts.map +1 -0
  79. package/dist/x402/facilitator-server-entry.js +27 -0
  80. package/dist/x402/facilitator-server-entry.js.map +1 -0
  81. package/dist/x402/facilitator-server.d.ts +73 -0
  82. package/dist/x402/facilitator-server.d.ts.map +1 -0
  83. package/dist/x402/facilitator-server.js +305 -0
  84. package/dist/x402/facilitator-server.js.map +1 -0
  85. package/dist/x402/facilitator.d.ts +69 -17
  86. package/dist/x402/facilitator.d.ts.map +1 -1
  87. package/dist/x402/facilitator.js +76 -33
  88. package/dist/x402/facilitator.js.map +1 -1
  89. package/dist/x402/payment-requirements.d.ts +106 -0
  90. package/dist/x402/payment-requirements.d.ts.map +1 -0
  91. package/dist/x402/payment-requirements.js +138 -0
  92. package/dist/x402/payment-requirements.js.map +1 -0
  93. package/dist/x402/relayer.d.ts +41 -0
  94. package/dist/x402/relayer.d.ts.map +1 -0
  95. package/dist/x402/relayer.js +64 -0
  96. package/dist/x402/relayer.js.map +1 -0
  97. package/dist/x402/resource-index.d.ts +75 -0
  98. package/dist/x402/resource-index.d.ts.map +1 -0
  99. package/dist/x402/resource-index.js +126 -0
  100. package/dist/x402/resource-index.js.map +1 -0
  101. package/dist/x402/verified-delivery-facilitator.d.ts +285 -0
  102. package/dist/x402/verified-delivery-facilitator.d.ts.map +1 -0
  103. package/dist/x402/verified-delivery-facilitator.js +423 -0
  104. package/dist/x402/verified-delivery-facilitator.js.map +1 -0
  105. package/dist/zktls/t2-delivery-proof.d.ts +6 -6
  106. package/docs/agent-layer.md +12 -8
  107. package/docs/cli.md +158 -22
  108. package/docs/mcp-hosted.md +4 -3
  109. package/docs/mcp-reference.md +175 -0
  110. package/docs/quickstart.md +18 -4
  111. package/docs/threat-model.md +4 -3
  112. package/docs/x402.md +648 -0
  113. package/package.json +18 -7
  114. package/src/capability/invocation-capability.ts +17 -1
  115. package/src/cli/commands/claim.ts +30 -4
  116. package/src/cli/commands/close.ts +20 -4
  117. package/src/cli/commands/invoke.ts +1 -0
  118. package/src/cli/commands/open.ts +76 -10
  119. package/src/cli/commands/reclaim-unverified.ts +16 -4
  120. package/src/cli/commands/reclaim.ts +22 -5
  121. package/src/cli/commands/streams.ts +1 -1
  122. package/src/cli/deps.ts +115 -24
  123. package/src/cli/privy.ts +396 -0
  124. package/src/cli/spend-policy.ts +139 -0
  125. package/src/cli/wallet.ts +188 -57
  126. package/src/gateway/caller-auth-gateway.ts +77 -6
  127. package/src/gateway/http-server.ts +280 -6
  128. package/src/gateway/x402-mode.ts +350 -0
  129. package/src/index.ts +40 -5
  130. package/src/mandates/env.ts +3 -2
  131. package/src/mcp/server.ts +681 -29
  132. package/src/mcp/service-invoker.ts +285 -0
  133. package/src/sdk/invoke.ts +90 -12
  134. package/src/x402/delivery-oracle.ts +285 -0
  135. package/src/x402/facilitator-server-entry.ts +35 -0
  136. package/src/x402/facilitator-server.ts +445 -0
  137. package/src/x402/facilitator.ts +125 -46
  138. package/src/x402/payment-requirements.ts +231 -0
  139. package/src/x402/relayer.ts +122 -0
  140. package/src/x402/resource-index.ts +228 -0
  141. package/src/x402/verified-delivery-facilitator.ts +744 -0
@@ -1,4 +1,6 @@
1
- import type { LocalAccount } from "viem";
1
+ import type { Account, LocalAccount, Transport } from "viem";
2
+ import type { AutonomousWalletCredentialStore } from "../wallet/autonomous-wallet.js";
3
+ import { type PrivyCliWalletSource, type PrivySpendPolicy } from "./privy.js";
2
4
  /**
3
5
  * The ONLY place the CLI resolves a signing wallet.
4
6
  *
@@ -13,36 +15,38 @@ import type { LocalAccount } from "viem";
13
15
  * 1. `METRIK_AGENT_PRIVATE_KEY` — a raw Base Sepolia test key.
14
16
  * 2. The `CDP_*` / `METRIK_AGENT_CDP_*` quartet — a Coinbase CDP Server Wallet
15
17
  * v2 account, resolved through this package's own `resolveAgentWallet()`.
18
+ * 3. The `METRIK_AGENT_PRIVY_*` variables — a Privy wallet reached through a
19
+ * broker, either agent-owned (`METRIK_AGENT_PRIVY_WALLET_KEY`) or a
20
+ * user-owned broker session. See `./privy.ts`.
16
21
  *
17
- * The order matches `parseAgentWalletEnv()` (the MCP server's resolution), so
18
- * one environment configures every surface the same way. It is checked in a
19
- * FIXED order rather than "whichever is configured", because an environment
20
- * carrying both is ambiguous about which address funds the stream — and that
21
- * ambiguity is a fund-moving one. When both are present the private key wins
22
- * and `resolveCliWallet` says so on stderr rather than silently picking.
22
+ * The first two match `parseAgentWalletEnv()` (the MCP server's resolution), so
23
+ * one environment configures those surfaces the same way. The order is FIXED
24
+ * rather than "whichever is configured", because an environment carrying two is
25
+ * ambiguous about which address funds the stream — and that ambiguity is a
26
+ * fund-moving one. When more than one is present the earlier entry wins and
27
+ * `resolveCliWallet` says so on stderr rather than silently picking.
23
28
  *
24
- * ## Why CDP is wired and Privy is not
29
+ * ## What is different about Privy
25
30
  *
26
- * CDP is the only wallet path in this package with live CI evidence
27
- * (`scripts/e2e-cdp.ts` drives the full journey against the real Base Sepolia
28
- * escrow), and its account signs LOCALLY — `toAccount(cdpServerAccount)` is a
29
- * viem local account, so it drops straight into the CLI's existing
30
- * `http(rpcUrl)` transport with no other change.
31
+ * A private key and a CDP account both sign LOCALLY: `privateKeyToAccount()`
32
+ * and `toAccount(cdpServerAccount)` are viem local accounts, so they drop
33
+ * straight into the CLI's `http(rpcUrl)` transport with no other change.
31
34
  *
32
- * Privy does not. Both Privy adapters in `src/wallet/` produce a JSON-RPC
33
- * account with no `signTransaction`: they sign and broadcast by sending
34
- * `eth_sendTransaction` / `eth_signTypedData_v4` to a provider, so they need the
35
- * wallet client's TRANSPORT to be that provider rather than a plain RPC. Wiring
36
- * that into the CLI is not a matter of reading three more variables — it
37
- * changes the transport for every fund-moving command, and `metrik invoke`
38
- * additionally requires a local signer (`InvokeOptions.buyer: LocalAccount`).
39
- * `assertLocalSigner` below therefore REFUSES a non-local account with that
40
- * fact, instead of accepting one and failing later inside viem. See
41
- * `docs/cli.md` § Wallet.
35
+ * Privy does not. Its account is a JSON-RPC account with no `signTransaction`:
36
+ * it signs and broadcasts by sending `eth_sendTransaction` /
37
+ * `eth_signTypedData_v4` to a provider, so the wallet client's TRANSPORT must
38
+ * be that provider rather than a plain RPC. That is what {@link CliWallet.transport}
39
+ * carries, and the only reason this file knows Privy exists. The signer check
40
+ * below is therefore about CAPABILITY, not about locality: it refuses an
41
+ * account that genuinely cannot sign, and refuses a non-local account only on
42
+ * the paths that broadcast through `--rpc-url`.
43
+ *
44
+ * See `docs/cli.md` § Wallet.
42
45
  */
43
46
  export declare const PRIVATE_KEY_ENV = "METRIK_AGENT_PRIVATE_KEY";
44
47
  /** Every environment variable the CDP path reads. Named in errors, never printed. */
45
48
  export declare const CDP_ENV_VARS: readonly ["CDP_API_KEY_ID", "CDP_API_KEY_SECRET", "CDP_WALLET_SECRET", "METRIK_AGENT_CDP_OWNER_NAME"];
49
+ export { PRIVY_ENV_VARS, PRIVY_SESSION_ENV_VARS, PRIVY_WALLET_KEY_ENV, } from "./privy.js";
46
50
  /**
47
51
  * What the key is for, in the words of the command that needs it. `invoke`
48
52
  * signs an EIP-712 invocation capability and broadcasts NOTHING; telling its
@@ -50,29 +54,77 @@ export declare const CDP_ENV_VARS: readonly ["CDP_API_KEY_ID", "CDP_API_KEY_SECR
50
54
  */
51
55
  export type KeyPurpose = "transaction" | "capability";
52
56
  /** Which environment configured the signer, for output and for error text. */
53
- export type CliWalletSource = "private-key" | "cdp";
57
+ export type CliWalletSource = "private-key" | "cdp" | PrivyCliWalletSource;
58
+ /**
59
+ * An account every CLI signing path can actually use.
60
+ *
61
+ * `signTypedData` is required rather than optional because it is the one
62
+ * capability EVERY path needs: fund-moving commands self-sign an EIP-712
63
+ * `SpendMandate`, and `invoke` signs an EIP-712 `InvocationCapability`. An
64
+ * account without it type-checks as a viem `Account` and then fails at the
65
+ * first signature with a `TypeError`.
66
+ */
67
+ export type CliSignerAccount = Account & Pick<LocalAccount, "signTypedData">;
54
68
  export interface CliWallet {
55
69
  readonly source: CliWalletSource;
70
+ readonly account: CliSignerAccount;
56
71
  /**
57
- * A LOCAL signer. Every CLI path either broadcasts through `http(rpcUrl)`
58
- * (which cannot sign) or signs EIP-712 off-chain, so a signer that delegates
59
- * to a remote provider is refused at resolution rather than mid-command.
72
+ * The transport fund-moving commands must broadcast through, when the wallet
73
+ * REQUIRES one. `undefined` means "a plain `http(--rpc-url)` is correct"
74
+ * true for a local signer, false for Privy, whose provider IS the transport.
60
75
  */
61
- readonly account: LocalAccount;
76
+ readonly transport?: Transport;
62
77
  /** One line naming the signer's origin. Safe to print: no secret in it. */
63
78
  readonly description: string;
79
+ /**
80
+ * Set when this wallet's spend ceiling is enforced where the CLI cannot reach
81
+ * it — i.e. by a Privy broker policy, not by a locally self-signed mandate.
82
+ *
83
+ * Its presence is the signal that the CLI should NOT self-sign a
84
+ * `SpendMandate` for this wallet, and should read and enforce the real
85
+ * ceiling instead. See `./spend-policy.ts` for why that substitution is
86
+ * strictly stronger than the mandate it replaces, and why re-adding the
87
+ * mandate "for consistency" would be a regression.
88
+ */
89
+ readonly readSpendPolicy?: () => Promise<PrivySpendPolicy>;
90
+ }
91
+ export interface ResolveCliWalletOptions {
92
+ readonly purpose?: KeyPurpose;
93
+ /**
94
+ * `--rpc-url`. Only the Privy paths use it at resolution time: their provider
95
+ * serves the wallet client's READS as well as its writes, so without this a
96
+ * Privy command would read from a different endpoint than `--rpc-url` names.
97
+ */
98
+ readonly rpcUrl?: string;
99
+ readonly note?: (line: string) => void;
100
+ /**
101
+ * Test seam, same role as `ResolveAgentWalletOptions.createCdpClient`: the
102
+ * credential store an agent-owned Privy wallet is read from. Unset in every
103
+ * real run, where the store is selected from the environment.
104
+ */
105
+ readonly store?: AutonomousWalletCredentialStore;
106
+ /** Test seam: the `fetch` the Privy broker is reached through. */
107
+ readonly fetchImpl?: typeof fetch;
64
108
  }
65
109
  /**
66
110
  * Resolves the signing wallet, or throws an actionable configuration error.
67
111
  *
68
- * `note` receives one line when the environment is ambiguous (both wallet
69
- * sources configured). It is optional so `resolveCliWallet` stays usable from a
70
- * context with no printer; commands always pass `out.note`.
112
+ * `note` receives one line when the environment is ambiguous (more than one
113
+ * wallet source configured). It is optional so `resolveCliWallet` stays usable
114
+ * from a context with no printer; commands always pass `out.note`.
71
115
  */
72
- export declare function resolveCliWallet(env: NodeJS.ProcessEnv, options?: {
73
- readonly purpose?: KeyPurpose;
74
- readonly note?: (line: string) => void;
75
- }): Promise<CliWallet>;
116
+ export declare function resolveCliWallet(env: NodeJS.ProcessEnv, options?: ResolveCliWalletOptions): Promise<CliWallet>;
117
+ /** True for both Privy shapes, which reach their key through a broker. */
118
+ export declare function isPrivyWalletSource(source: CliWalletSource): source is PrivyCliWalletSource;
119
+ /**
120
+ * Whether this wallet's ceiling is enforced somewhere the CLI cannot reach.
121
+ *
122
+ * The one question every fund-moving command asks before deciding whether to
123
+ * self-sign a `SpendMandate`. See `./spend-policy.ts`.
124
+ */
125
+ export declare function isPolicyEnforced(wallet: CliWallet): wallet is CliWallet & {
126
+ readonly readSpendPolicy: () => Promise<PrivySpendPolicy>;
127
+ };
76
128
  /**
77
129
  * The same resolution, but "nothing configured" is not an error. Used by
78
130
  * look-before-you-leap paths (`open --dry-run`, `streams --address`) that
@@ -82,14 +134,31 @@ export declare function resolveCliWallet(env: NodeJS.ProcessEnv, options?: {
82
134
  * A wallet that is PARTIALLY configured is still an error here: "you set three
83
135
  * of the four CDP variables" and "you configured no wallet" are different
84
136
  * facts, and rendering the first as the second sends the reader looking in the
85
- * wrong place.
137
+ * wrong place. The same rule applies to a partial Privy setup.
86
138
  */
87
- export declare function optionalCliWallet(env: NodeJS.ProcessEnv, options?: {
88
- readonly note?: (line: string) => void;
89
- }): Promise<CliWallet | null>;
139
+ export declare function optionalCliWallet(env: NodeJS.ProcessEnv, options?: Omit<ResolveCliWalletOptions, "purpose">): Promise<CliWallet | null>;
90
140
  /**
91
141
  * The raw `METRIK_AGENT_PRIVATE_KEY` read, kept separate so the wallet-source
92
142
  * precedence above reads as one list rather than as nested conditionals.
93
143
  */
94
144
  export declare function optionalCliAccount(env: NodeJS.ProcessEnv): LocalAccount | null;
145
+ /**
146
+ * Refuses an account that genuinely cannot sign — and nothing else.
147
+ *
148
+ * Two distinct capabilities are checked, because two distinct things fail:
149
+ *
150
+ * - `signTypedData` is needed by EVERY command. Fund-moving commands self-sign
151
+ * an EIP-712 `SpendMandate`; `invoke` signs an EIP-712
152
+ * `InvocationCapability`. Without it the run dies at the first signature
153
+ * with a `TypeError` from inside viem.
154
+ * - A LOCAL account is needed only where the CLI broadcasts through
155
+ * `http(--rpc-url)`, which cannot sign. A Privy account is deliberately NOT
156
+ * local: its provider is the transport and performs `eth_sendTransaction`
157
+ * itself, so demanding locality there would reject a wallet that works.
158
+ *
159
+ * The earlier version of this guard collapsed both into "must be local", which
160
+ * is why Privy was refused. Deleting the guard outright was not the fix: it
161
+ * exists so a broken wallet fails here, named, instead of deep inside viem.
162
+ */
163
+ export declare function assertCliSigner(account: Account, source: CliWalletSource): CliSignerAccount;
95
164
  //# sourceMappingURL=wallet.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"wallet.d.ts","sourceRoot":"","sources":["../../src/cli/wallet.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAW,YAAY,EAAE,MAAM,MAAM,CAAC;AAKlD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,eAAO,MAAM,eAAe,6BAA6B,CAAC;AAE1D,qFAAqF;AACrF,eAAO,MAAM,YAAY,uGAKf,CAAC;AAEX;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG,aAAa,GAAG,YAAY,CAAC;AAQtD,8EAA8E;AAC9E,MAAM,MAAM,eAAe,GAAG,aAAa,GAAG,KAAK,CAAC;AAEpD,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,2EAA2E;IAC3E,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAMD;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,OAAO,GAAE;IACP,QAAQ,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC;IAC9B,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC,GACL,OAAO,CAAC,SAAS,CAAC,CASpB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,OAAO,GAAE;IAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CAAO,GACvD,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAqE3B;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,CAAC,UAAU,GACrB,YAAY,GAAG,IAAI,CASrB"}
1
+ {"version":3,"file":"wallet.d.ts","sourceRoot":"","sources":["../../src/cli/wallet.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AAE7D,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,gCAAgC,CAAC;AAGtF,OAAO,EAKL,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACtB,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,eAAO,MAAM,eAAe,6BAA6B,CAAC;AAE1D,qFAAqF;AACrF,eAAO,MAAM,YAAY,uGAKf,CAAC;AAEX,OAAO,EACL,cAAc,EACd,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAEpB;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG,aAAa,GAAG,YAAY,CAAC;AAQtD,8EAA8E;AAC9E,MAAM,MAAM,eAAe,GAAG,aAAa,GAAG,KAAK,GAAG,oBAAoB,CAAC;AAE3E;;;;;;;;GAQG;AACH,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,IAAI,CAAC,YAAY,EAAE,eAAe,CAAC,CAAC;AAE7E,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC;IACnC;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;IAC/B,2EAA2E;IAC3E,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B;;;;;;;;;OASG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,OAAO,CAAC,gBAAgB,CAAC,CAAC;CAC5D;AAOD,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,+BAA+B,CAAC;IACjD,kEAAkE;IAClE,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CACnC;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,SAAS,CAAC,CASpB;AAED,0EAA0E;AAC1E,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,eAAe,GACtB,MAAM,IAAI,oBAAoB,CAEhC;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,IAAI,SAAS,GAAG;IACzE,QAAQ,CAAC,eAAe,EAAE,MAAM,OAAO,CAAC,gBAAgB,CAAC,CAAC;CAC3D,CAEA;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,OAAO,GAAE,IAAI,CAAC,uBAAuB,EAAE,SAAS,CAAM,GACrD,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CA6C3B;AAuDD;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,CAAC,UAAU,GACrB,YAAY,GAAG,IAAI,CASrB;AAWD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,eAAe,GACtB,gBAAgB,CAclB"}
@@ -1,6 +1,7 @@
1
1
  import { privateKeyToAccount } from "viem/accounts";
2
2
  import { resolveAgentWallet } from "../wallet/provider.js";
3
3
  import { configError } from "./errors.js";
4
+ import { PRIVY_ENV_VARS, PRIVY_SESSION_ENV_VARS, PRIVY_WALLET_KEY_ENV, resolvePrivyCliWallet, } from "./privy.js";
4
5
  /**
5
6
  * The ONLY place the CLI resolves a signing wallet.
6
7
  *
@@ -15,32 +16,33 @@ import { configError } from "./errors.js";
15
16
  * 1. `METRIK_AGENT_PRIVATE_KEY` — a raw Base Sepolia test key.
16
17
  * 2. The `CDP_*` / `METRIK_AGENT_CDP_*` quartet — a Coinbase CDP Server Wallet
17
18
  * v2 account, resolved through this package's own `resolveAgentWallet()`.
19
+ * 3. The `METRIK_AGENT_PRIVY_*` variables — a Privy wallet reached through a
20
+ * broker, either agent-owned (`METRIK_AGENT_PRIVY_WALLET_KEY`) or a
21
+ * user-owned broker session. See `./privy.ts`.
18
22
  *
19
- * The order matches `parseAgentWalletEnv()` (the MCP server's resolution), so
20
- * one environment configures every surface the same way. It is checked in a
21
- * FIXED order rather than "whichever is configured", because an environment
22
- * carrying both is ambiguous about which address funds the stream — and that
23
- * ambiguity is a fund-moving one. When both are present the private key wins
24
- * and `resolveCliWallet` says so on stderr rather than silently picking.
23
+ * The first two match `parseAgentWalletEnv()` (the MCP server's resolution), so
24
+ * one environment configures those surfaces the same way. The order is FIXED
25
+ * rather than "whichever is configured", because an environment carrying two is
26
+ * ambiguous about which address funds the stream — and that ambiguity is a
27
+ * fund-moving one. When more than one is present the earlier entry wins and
28
+ * `resolveCliWallet` says so on stderr rather than silently picking.
25
29
  *
26
- * ## Why CDP is wired and Privy is not
30
+ * ## What is different about Privy
27
31
  *
28
- * CDP is the only wallet path in this package with live CI evidence
29
- * (`scripts/e2e-cdp.ts` drives the full journey against the real Base Sepolia
30
- * escrow), and its account signs LOCALLY — `toAccount(cdpServerAccount)` is a
31
- * viem local account, so it drops straight into the CLI's existing
32
- * `http(rpcUrl)` transport with no other change.
32
+ * A private key and a CDP account both sign LOCALLY: `privateKeyToAccount()`
33
+ * and `toAccount(cdpServerAccount)` are viem local accounts, so they drop
34
+ * straight into the CLI's `http(rpcUrl)` transport with no other change.
33
35
  *
34
- * Privy does not. Both Privy adapters in `src/wallet/` produce a JSON-RPC
35
- * account with no `signTransaction`: they sign and broadcast by sending
36
- * `eth_sendTransaction` / `eth_signTypedData_v4` to a provider, so they need the
37
- * wallet client's TRANSPORT to be that provider rather than a plain RPC. Wiring
38
- * that into the CLI is not a matter of reading three more variables — it
39
- * changes the transport for every fund-moving command, and `metrik invoke`
40
- * additionally requires a local signer (`InvokeOptions.buyer: LocalAccount`).
41
- * `assertLocalSigner` below therefore REFUSES a non-local account with that
42
- * fact, instead of accepting one and failing later inside viem. See
43
- * `docs/cli.md` § Wallet.
36
+ * Privy does not. Its account is a JSON-RPC account with no `signTransaction`:
37
+ * it signs and broadcasts by sending `eth_sendTransaction` /
38
+ * `eth_signTypedData_v4` to a provider, so the wallet client's TRANSPORT must
39
+ * be that provider rather than a plain RPC. That is what {@link CliWallet.transport}
40
+ * carries, and the only reason this file knows Privy exists. The signer check
41
+ * below is therefore about CAPABILITY, not about locality: it refuses an
42
+ * account that genuinely cannot sign, and refuses a non-local account only on
43
+ * the paths that broadcast through `--rpc-url`.
44
+ *
45
+ * See `docs/cli.md` § Wallet.
44
46
  */
45
47
  export const PRIVATE_KEY_ENV = "METRIK_AGENT_PRIVATE_KEY";
46
48
  /** Every environment variable the CDP path reads. Named in errors, never printed. */
@@ -50,26 +52,41 @@ export const CDP_ENV_VARS = [
50
52
  "CDP_WALLET_SECRET",
51
53
  "METRIK_AGENT_CDP_OWNER_NAME",
52
54
  ];
55
+ export { PRIVY_ENV_VARS, PRIVY_SESSION_ENV_VARS, PRIVY_WALLET_KEY_ENV, } from "./privy.js";
53
56
  const PURPOSE_TEXT = {
54
57
  transaction: "signs a transaction",
55
58
  capability: "signs an off-chain EIP-712 invocation capability (no transaction is broadcast)",
56
59
  };
57
- const WALLET_HINT = `export ${PRIVATE_KEY_ENV}=0x… (a funded Base Sepolia test key), or configure a Coinbase CDP wallet with ` +
58
- `${CDP_ENV_VARS.join(", ")}. Both are read from the environment only never pass a credential as a command-line flag.`;
60
+ const WALLET_HINT = `export ${PRIVATE_KEY_ENV}=0x… (a funded Base Sepolia test key), configure a Coinbase CDP wallet with ` +
61
+ `${CDP_ENV_VARS.join(", ")}, or configure a Privy wallet with ${PRIVY_WALLET_KEY_ENV} (agent-owned) or ` +
62
+ `${PRIVY_SESSION_ENV_VARS.join(", ")} (broker session). All are read from the environment only — never pass a credential as a command-line flag.`;
59
63
  /**
60
64
  * Resolves the signing wallet, or throws an actionable configuration error.
61
65
  *
62
- * `note` receives one line when the environment is ambiguous (both wallet
63
- * sources configured). It is optional so `resolveCliWallet` stays usable from a
64
- * context with no printer; commands always pass `out.note`.
66
+ * `note` receives one line when the environment is ambiguous (more than one
67
+ * wallet source configured). It is optional so `resolveCliWallet` stays usable
68
+ * from a context with no printer; commands always pass `out.note`.
65
69
  */
66
70
  export async function resolveCliWallet(env, options = {}) {
67
71
  const wallet = await optionalCliWallet(env, options);
68
72
  if (wallet === null) {
69
- throw configError(`this command ${PURPOSE_TEXT[options.purpose ?? "transaction"]} and needs a wallet: neither ${PRIVATE_KEY_ENV} nor the CDP variables are set`, WALLET_HINT);
73
+ throw configError(`this command ${PURPOSE_TEXT[options.purpose ?? "transaction"]} and needs a wallet: none of ${PRIVATE_KEY_ENV}, the CDP variables or the Privy variables are set`, WALLET_HINT);
70
74
  }
71
75
  return wallet;
72
76
  }
77
+ /** True for both Privy shapes, which reach their key through a broker. */
78
+ export function isPrivyWalletSource(source) {
79
+ return source === "privy-autonomous" || source === "privy-session";
80
+ }
81
+ /**
82
+ * Whether this wallet's ceiling is enforced somewhere the CLI cannot reach.
83
+ *
84
+ * The one question every fund-moving command asks before deciding whether to
85
+ * self-sign a `SpendMandate`. See `./spend-policy.ts`.
86
+ */
87
+ export function isPolicyEnforced(wallet) {
88
+ return wallet.readSpendPolicy !== undefined;
89
+ }
73
90
  /**
74
91
  * The same resolution, but "nothing configured" is not an error. Used by
75
92
  * look-before-you-leap paths (`open --dry-run`, `streams --address`) that
@@ -79,14 +96,19 @@ export async function resolveCliWallet(env, options = {}) {
79
96
  * A wallet that is PARTIALLY configured is still an error here: "you set three
80
97
  * of the four CDP variables" and "you configured no wallet" are different
81
98
  * facts, and rendering the first as the second sends the reader looking in the
82
- * wrong place.
99
+ * wrong place. The same rule applies to a partial Privy setup.
83
100
  */
84
101
  export async function optionalCliWallet(env, options = {}) {
85
102
  const privateKeyAccount = optionalCliAccount(env);
86
103
  const cdpConfigured = CDP_ENV_VARS.some((name) => isSet(env[name]));
104
+ const privyConfigured = PRIVY_ENV_VARS.some((name) => isSet(env[name]));
87
105
  if (privateKeyAccount !== null) {
88
- if (cdpConfigured) {
89
- options.note?.(`warning: both ${PRIVATE_KEY_ENV} and CDP wallet variables are set; using ${PRIVATE_KEY_ENV} (${privateKeyAccount.address}). Unset it to sign with the CDP wallet.`);
106
+ const shadowed = [
107
+ ...(cdpConfigured ? ["CDP"] : []),
108
+ ...(privyConfigured ? ["Privy"] : []),
109
+ ];
110
+ if (shadowed.length > 0) {
111
+ options.note?.(`warning: both ${PRIVATE_KEY_ENV} and ${shadowed.join(" and ")} wallet variables are set; using ${PRIVATE_KEY_ENV} (${privateKeyAccount.address}). Unset it to sign with the ${shadowed[0]} wallet.`);
90
112
  }
91
113
  return {
92
114
  source: "private-key",
@@ -94,8 +116,29 @@ export async function optionalCliWallet(env, options = {}) {
94
116
  description: `${privateKeyAccount.address} (from ${PRIVATE_KEY_ENV})`,
95
117
  };
96
118
  }
97
- if (!cdpConfigured)
119
+ if (cdpConfigured) {
120
+ if (privyConfigured) {
121
+ options.note?.("warning: both CDP and Privy wallet variables are set; using the CDP wallet. Unset the CDP variables to sign with the Privy wallet.");
122
+ }
123
+ return await resolveCdpWallet(env);
124
+ }
125
+ if (!privyConfigured)
98
126
  return null;
127
+ const privy = await resolvePrivyCliWallet(env, options);
128
+ // Unreachable: `privyConfigured` is exactly the condition under which
129
+ // `resolvePrivyCliWallet` returns non-null or throws. Kept so a future change
130
+ // to either predicate fails loudly here rather than as a null deref.
131
+ if (privy === null)
132
+ return null;
133
+ return {
134
+ source: privy.source,
135
+ account: assertCliSigner(privy.account, privy.source),
136
+ transport: privy.transport,
137
+ description: privy.description,
138
+ readSpendPolicy: privy.readSpendPolicy,
139
+ };
140
+ }
141
+ async function resolveCdpWallet(env) {
99
142
  const missing = CDP_ENV_VARS.filter((name) => !isSet(env[name]));
100
143
  if (missing.length > 0) {
101
144
  throw configError(`the CDP wallet is partially configured: ${missing.join(", ")} ${missing.length === 1 ? "is" : "are"} not set`, `a CDP wallet needs all of ${CDP_ENV_VARS.join(", ")}. Set the missing one${missing.length === 1 ? "" : "s"}, or unset the others and use ${PRIVATE_KEY_ENV} instead.`);
@@ -130,7 +173,7 @@ export async function optionalCliWallet(env, options = {}) {
130
173
  }
131
174
  return {
132
175
  source: "cdp",
133
- account: assertLocalSigner(account, "cdp"),
176
+ account: assertCliSigner(account, "cdp"),
134
177
  description: `${account.address} (CDP account "${ownerName}")`,
135
178
  };
136
179
  }
@@ -148,17 +191,39 @@ export function optionalCliAccount(env) {
148
191
  return privateKeyToAccount(raw);
149
192
  }
150
193
  /**
151
- * Every CLI signing path needs a LOCAL signer: fund-moving commands broadcast
152
- * through `http(--rpc-url)`, which cannot sign, and `invoke` needs a
153
- * `LocalAccount` to sign the EIP-712 capability. A JSON-RPC account (Privy's
154
- * adapters) would type-check as an `Account` and then fail somewhere inside
155
- * viem with a message about a missing method, so it is rejected here with the
156
- * actual reason.
194
+ * Whether this wallet source broadcasts through the CLI's own
195
+ * `http(--rpc-url)` transport, and therefore needs an account that can produce
196
+ * a signed raw transaction by itself.
197
+ */
198
+ function broadcastsLocally(source) {
199
+ return source === "private-key" || source === "cdp";
200
+ }
201
+ /**
202
+ * Refuses an account that genuinely cannot sign — and nothing else.
203
+ *
204
+ * Two distinct capabilities are checked, because two distinct things fail:
205
+ *
206
+ * - `signTypedData` is needed by EVERY command. Fund-moving commands self-sign
207
+ * an EIP-712 `SpendMandate`; `invoke` signs an EIP-712
208
+ * `InvocationCapability`. Without it the run dies at the first signature
209
+ * with a `TypeError` from inside viem.
210
+ * - A LOCAL account is needed only where the CLI broadcasts through
211
+ * `http(--rpc-url)`, which cannot sign. A Privy account is deliberately NOT
212
+ * local: its provider is the transport and performs `eth_sendTransaction`
213
+ * itself, so demanding locality there would reject a wallet that works.
214
+ *
215
+ * The earlier version of this guard collapsed both into "must be local", which
216
+ * is why Privy was refused. Deleting the guard outright was not the fix: it
217
+ * exists so a broken wallet fails here, named, instead of deep inside viem.
157
218
  */
158
- function assertLocalSigner(account, source) {
159
- if (account.type === "local")
160
- return account;
161
- throw configError(`the ${source} wallet returned a ${account.type} account, which cannot sign locally`, "the CLI broadcasts through --rpc-url and signs EIP-712 capabilities in-process, so it needs a local signer.");
219
+ export function assertCliSigner(account, source) {
220
+ if (typeof account.signTypedData !== "function") {
221
+ throw configError(`the ${source} wallet (${account.address}) cannot sign EIP-712 typed data`, "every command signs typed data: fund-moving commands self-sign a spend mandate, and `invoke` signs an invocation capability.");
222
+ }
223
+ if (broadcastsLocally(source) && account.type !== "local") {
224
+ throw configError(`the ${source} wallet returned a ${account.type} account, which cannot sign locally`, "this wallet source broadcasts through --rpc-url, which cannot sign, so it needs a local signer.");
225
+ }
226
+ return account;
162
227
  }
163
228
  function isSet(value) {
164
229
  return value !== undefined && value.length > 0;
@@ -1 +1 @@
1
- {"version":3,"file":"wallet.js","sourceRoot":"","sources":["../../src/cli/wallet.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"wallet.js","sourceRoot":"","sources":["../../src/cli/wallet.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,6 @@
1
1
  import { type Address, type Hex } from "viem";
2
+ import { type AcceptedX402Payment, type GatewayX402Mode } from "./x402-mode.js";
3
+ import type { X402PaymentRequiredBody } from "../x402/payment-requirements.js";
2
4
  import { type SignedInvocationCapability } from "../capability/invocation-capability.js";
3
5
  /**
4
6
  * Seller-side caller-auth gateway (metrik-agent#63, impl of #62 part 1/2).
@@ -43,7 +45,21 @@ import { type SignedInvocationCapability } from "../capability/invocation-capabi
43
45
  * direction here: negative, never positive.
44
46
  */
45
47
  /** Machine-readable, closed set of rejection reasons - every failure mode is distinct. */
46
- export type CallerAuthDenialReason = "missing-capability-header" | "malformed-capability-header" | "capability-expired" | "invalid-signature" | "method-mismatch" | "path-mismatch" | "service-ref-mismatch" | "nonce-replayed" | "stream-not-found" | "buyer-mismatch" | "stream-not-active" | "stream-expired" | "stream-not-funded" | "stream-state-stale";
48
+ export type CallerAuthDenialReason = "missing-capability-header" | "malformed-capability-header" | "capability-expired" | "invalid-signature" | "method-mismatch" | "path-mismatch" | "service-ref-mismatch" | "nonce-replayed" | "stream-not-found" | "buyer-mismatch" | "stream-not-active" | "stream-expired" | "stream-not-funded" | "stream-state-stale"
49
+ /**
50
+ * No Metrik capability, and x402 mode is enabled: the caller may pay per call
51
+ * instead. Carries an x402 `402` body in
52
+ * {@link CallerAuthDecision.x402PaymentRequired}. Emitted ONLY when
53
+ * {@link CallerAuthGatewayConfig.x402} is configured — without it, a missing
54
+ * capability is still `missing-capability-header` / `403`, unchanged.
55
+ */
56
+ | "x402-payment-required"
57
+ /**
58
+ * The request carried BOTH a Metrik capability and an `X-PAYMENT` header.
59
+ * Refused rather than guessed: serving it would charge the caller through one
60
+ * path while they believe they paid through the other.
61
+ */
62
+ | "ambiguous-payment-mode";
47
63
  /**
48
64
  * Default freshness bound for on-chain stream state, in seconds. Base blocks
49
65
  * are ~2s, so a healthy endpoint is a few seconds stale at most; this is a
@@ -57,11 +73,22 @@ export interface CallerAuthDecision {
57
73
  readonly authorized: boolean;
58
74
  readonly reason?: CallerAuthDenialReason;
59
75
  /** Set only when `authorized === false`. */
60
- readonly httpStatus?: 402 | 403;
61
- /** Set only when `authorized === true`. */
76
+ readonly httpStatus?: 400 | 402 | 403;
77
+ /** Set only when `authorized === true` via the Metrik stream path. */
62
78
  readonly stream?: GatewayStreamView;
63
79
  /** The decoded (but not necessarily valid) capability, when one was present. */
64
80
  readonly capability?: SignedInvocationCapability;
81
+ /**
82
+ * The x402 `402` body to return verbatim. Set only with
83
+ * `reason === "x402-payment-required"`.
84
+ */
85
+ readonly x402PaymentRequired?: X402PaymentRequiredBody;
86
+ /**
87
+ * A verified x402 payment. Set only when `authorized === true` via the x402
88
+ * path. The caller MUST settle it (see `./x402-mode.ts`) — verification alone
89
+ * moves no money.
90
+ */
91
+ readonly x402Payment?: AcceptedX402Payment;
65
92
  }
66
93
  /** The minimal on-chain stream fields the gateway needs to authorize a call. */
67
94
  export interface GatewayStreamView {
@@ -178,6 +205,13 @@ export interface CallerAuthGatewayConfig {
178
205
  readonly nonceCache?: NonceReplayCache;
179
206
  /** Injectable clock (unix seconds), for tests. */
180
207
  readonly now?: () => number;
208
+ /**
209
+ * Optional standard-x402 mode. When set, a request with NO Metrik capability
210
+ * gets a real x402 `402` challenge instead of a `403`, so a caller holding
211
+ * only `x402-fetch` can pay per call. Leaving it unset preserves today's
212
+ * behaviour byte for byte.
213
+ */
214
+ readonly x402?: GatewayX402Mode;
181
215
  }
182
216
  export interface CallerAuthRequestInput {
183
217
  /** Lower-cased-lookup-safe header map (e.g. Node's `IncomingMessage.headers`). */
@@ -201,6 +235,7 @@ export declare class CallerAuthGateway {
201
235
  private readonly domain;
202
236
  private readonly serviceRefs;
203
237
  private readonly now;
238
+ private readonly x402;
204
239
  constructor(config: CallerAuthGatewayConfig);
205
240
  authorize(request: CallerAuthRequestInput): Promise<CallerAuthDecision>;
206
241
  /** Returns the denial reason this single view produces, or `undefined` if it authorizes. */
@@ -1 +1 @@
1
- {"version":3,"file":"caller-auth-gateway.d.ts","sourceRoot":"","sources":["../../src/gateway/caller-auth-gateway.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"caller-auth-gateway.d.ts","sourceRoot":"","sources":["../../src/gateway/caller-auth-gateway.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { MetrikClient } from "@absol-labs/sdk";
2
2
  import { isAddress, isHex } from "viem";
3
+ import { evaluateX402Request, X402_PAYMENT_HEADER, } from "./x402-mode.js";
3
4
  import { CAPABILITY_HEADER_NAME, decodeCapabilityHeader, hashInvocationPath, InvalidCapabilityHeaderError, recoverInvocationCapabilitySigner, } from "../capability/invocation-capability.js";
4
5
  /**
5
6
  * Default freshness bound for on-chain stream state, in seconds. Base blocks
@@ -149,6 +150,7 @@ export class CallerAuthGateway {
149
150
  domain;
150
151
  serviceRefs;
151
152
  now;
153
+ x402;
152
154
  constructor(config) {
153
155
  if (!isAddress(config.escrowAddress)) {
154
156
  throw new Error("escrowAddress must be an EVM address");
@@ -191,10 +193,32 @@ export class CallerAuthGateway {
191
193
  verifyingContract: config.escrowAddress,
192
194
  };
193
195
  this.now = config.now ?? (() => Math.floor(Date.now() / 1000));
196
+ this.x402 = config.x402;
194
197
  }
195
198
  async authorize(request) {
196
199
  const headerValue = lookupHeader(request.headers, this.headerName);
197
- if (headerValue === undefined || headerValue.length === 0) {
200
+ const hasCapabilityHeader = headerValue !== undefined && headerValue.length > 0;
201
+ if (this.x402 !== undefined) {
202
+ const paymentHeader = lookupHeader(request.headers, X402_PAYMENT_HEADER);
203
+ const hasPaymentHeader = paymentHeader !== undefined && paymentHeader.trim().length > 0;
204
+ // Exactly one payment mode per request. See `./x402-mode.ts`.
205
+ if (hasCapabilityHeader && hasPaymentHeader) {
206
+ return deny("ambiguous-payment-mode", 400);
207
+ }
208
+ if (!hasCapabilityHeader) {
209
+ const evaluated = await evaluateX402Request({ method: request.method, path: request.path }, paymentHeader, this.x402);
210
+ if (evaluated.outcome === "accepted") {
211
+ return { authorized: true, x402Payment: evaluated.payment };
212
+ }
213
+ return {
214
+ authorized: false,
215
+ reason: "x402-payment-required",
216
+ httpStatus: 402,
217
+ x402PaymentRequired: evaluated.body,
218
+ };
219
+ }
220
+ }
221
+ if (!hasCapabilityHeader) {
198
222
  return deny("missing-capability-header", 403);
199
223
  }
200
224
  let capability;