@absol-labs/agent 0.11.0 → 0.12.0-rc.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 +42 -50
- package/dist/capability/invocation-capability.d.ts +2 -2
- package/dist/capability/probe-capability.d.ts +225 -0
- package/dist/capability/probe-capability.d.ts.map +1 -0
- package/dist/capability/probe-capability.js +248 -0
- package/dist/capability/probe-capability.js.map +1 -0
- package/dist/cli/args.d.ts +11 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +23 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/commands/claim.js +1 -1
- package/dist/cli/commands/claim.js.map +1 -1
- package/dist/cli/commands/close.d.ts.map +1 -1
- package/dist/cli/commands/close.js +35 -3
- package/dist/cli/commands/close.js.map +1 -1
- package/dist/cli/commands/invoke.d.ts +2 -0
- package/dist/cli/commands/invoke.d.ts.map +1 -1
- package/dist/cli/commands/invoke.js +2 -2
- package/dist/cli/commands/invoke.js.map +1 -1
- package/dist/cli/commands/mcp.d.ts.map +1 -1
- package/dist/cli/commands/mcp.js +15 -2
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/commands/open.d.ts.map +1 -1
- package/dist/cli/commands/open.js +58 -4
- package/dist/cli/commands/open.js.map +1 -1
- package/dist/cli/commands/pay.d.ts +19 -0
- package/dist/cli/commands/pay.d.ts.map +1 -0
- package/dist/cli/commands/pay.js +355 -0
- package/dist/cli/commands/pay.js.map +1 -0
- package/dist/cli/commands/reclaim-unverified.d.ts.map +1 -1
- package/dist/cli/commands/reclaim-unverified.js +3 -2
- package/dist/cli/commands/reclaim-unverified.js.map +1 -1
- package/dist/cli/commands/reclaim.d.ts +23 -2
- package/dist/cli/commands/reclaim.d.ts.map +1 -1
- package/dist/cli/commands/reclaim.js +184 -16
- package/dist/cli/commands/reclaim.js.map +1 -1
- package/dist/cli/commands/refund.d.ts +13 -0
- package/dist/cli/commands/refund.d.ts.map +1 -0
- package/dist/cli/commands/refund.js +224 -0
- package/dist/cli/commands/refund.js.map +1 -0
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/status.js +10 -1
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/commands/streams.js +8 -12
- package/dist/cli/commands/streams.js.map +1 -1
- package/dist/cli/commands/watch.d.ts.map +1 -1
- package/dist/cli/commands/watch.js +2 -1
- package/dist/cli/commands/watch.js.map +1 -1
- package/dist/cli/config.d.ts +44 -26
- package/dist/cli/config.d.ts.map +1 -1
- package/dist/cli/config.js +88 -38
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/deps.d.ts +33 -0
- package/dist/cli/deps.d.ts.map +1 -1
- package/dist/cli/deps.js +37 -1
- package/dist/cli/deps.js.map +1 -1
- package/dist/cli/errors.d.ts.map +1 -1
- package/dist/cli/errors.js +21 -1
- package/dist/cli/errors.js.map +1 -1
- package/dist/cli/escape-hatch.d.ts +6 -4
- package/dist/cli/escape-hatch.d.ts.map +1 -1
- package/dist/cli/escape-hatch.js +6 -2
- package/dist/cli/escape-hatch.js.map +1 -1
- package/dist/cli/listings.d.ts +18 -0
- package/dist/cli/listings.d.ts.map +1 -1
- package/dist/cli/listings.js +22 -12
- package/dist/cli/listings.js.map +1 -1
- package/dist/cli/preflight.d.ts +20 -14
- package/dist/cli/preflight.d.ts.map +1 -1
- package/dist/cli/preflight.js +34 -20
- package/dist/cli/preflight.js.map +1 -1
- package/dist/cli/privy.d.ts.map +1 -1
- package/dist/cli/privy.js +4 -2
- package/dist/cli/privy.js.map +1 -1
- package/dist/cli/reclaimability.d.ts +82 -0
- package/dist/cli/reclaimability.d.ts.map +1 -0
- package/dist/cli/reclaimability.js +80 -0
- package/dist/cli/reclaimability.js.map +1 -0
- package/dist/cli/run.d.ts +2 -1
- package/dist/cli/run.d.ts.map +1 -1
- package/dist/cli/run.js +40 -11
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/scan-range.d.ts +2 -2
- package/dist/cli/scan-range.js +2 -2
- package/dist/cli/status.d.ts +3 -1
- package/dist/cli/status.d.ts.map +1 -1
- package/dist/cli/status.js +15 -3
- package/dist/cli/status.js.map +1 -1
- package/dist/cli/wallet.d.ts +1 -1
- package/dist/cli/wallet.js +2 -2
- package/dist/cli/wallet.js.map +1 -1
- package/dist/discovery/rate-band.d.ts +74 -0
- package/dist/discovery/rate-band.d.ts.map +1 -0
- package/dist/discovery/rate-band.js +114 -0
- package/dist/discovery/rate-band.js.map +1 -0
- package/dist/escrow-generation.d.ts +81 -0
- package/dist/escrow-generation.d.ts.map +1 -0
- package/dist/escrow-generation.js +76 -0
- package/dist/escrow-generation.js.map +1 -0
- package/dist/frameworks/agentkit.d.ts +8 -4
- package/dist/frameworks/agentkit.d.ts.map +1 -1
- package/dist/frameworks/agentkit.js +27 -10
- package/dist/frameworks/agentkit.js.map +1 -1
- package/dist/frameworks/eliza.d.ts +3 -3
- package/dist/frameworks/eliza.d.ts.map +1 -1
- package/dist/frameworks/eliza.js +15 -6
- package/dist/frameworks/eliza.js.map +1 -1
- package/dist/frameworks/langchain.d.ts.map +1 -1
- package/dist/frameworks/langchain.js +8 -0
- package/dist/frameworks/langchain.js.map +1 -1
- package/dist/gateway/caller-auth-gateway.d.ts +83 -31
- package/dist/gateway/caller-auth-gateway.d.ts.map +1 -1
- package/dist/gateway/caller-auth-gateway.js +180 -27
- package/dist/gateway/caller-auth-gateway.js.map +1 -1
- package/dist/gateway/http-server.d.ts +111 -44
- package/dist/gateway/http-server.d.ts.map +1 -1
- package/dist/gateway/http-server.js +439 -155
- package/dist/gateway/http-server.js.map +1 -1
- package/dist/gateway/probe-auth.d.ts +112 -0
- package/dist/gateway/probe-auth.d.ts.map +1 -0
- package/dist/gateway/probe-auth.js +127 -0
- package/dist/gateway/probe-auth.js.map +1 -0
- package/dist/gateway/signed-rate-bounds.d.ts +51 -0
- package/dist/gateway/signed-rate-bounds.d.ts.map +1 -0
- package/dist/gateway/signed-rate-bounds.js +94 -0
- package/dist/gateway/signed-rate-bounds.js.map +1 -0
- package/dist/gateway/x402-opener-mode.d.ts +215 -0
- package/dist/gateway/x402-opener-mode.d.ts.map +1 -0
- package/dist/gateway/x402-opener-mode.js +639 -0
- package/dist/gateway/x402-opener-mode.js.map +1 -0
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -5
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.d.ts +52 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +228 -37
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/x402-tools.d.ts +104 -0
- package/dist/mcp/x402-tools.d.ts.map +1 -0
- package/dist/mcp/x402-tools.js +434 -0
- package/dist/mcp/x402-tools.js.map +1 -0
- package/dist/network.d.ts +119 -0
- package/dist/network.d.ts.map +1 -0
- package/dist/network.js +199 -0
- package/dist/network.js.map +1 -0
- package/dist/sdk/invoke.d.ts +4 -0
- package/dist/sdk/invoke.d.ts.map +1 -1
- package/dist/sdk/invoke.js +2 -5
- package/dist/sdk/invoke.js.map +1 -1
- package/dist/wallet/autonomous-wallet-broker.d.ts +3 -0
- package/dist/wallet/autonomous-wallet-broker.d.ts.map +1 -1
- package/dist/wallet/autonomous-wallet-broker.js +27 -23
- package/dist/wallet/autonomous-wallet-broker.js.map +1 -1
- package/dist/wallet/autonomous-wallet-protocol.d.ts +8 -2
- package/dist/wallet/autonomous-wallet-protocol.d.ts.map +1 -1
- package/dist/wallet/autonomous-wallet-protocol.js +9 -2
- package/dist/wallet/autonomous-wallet-protocol.js.map +1 -1
- package/dist/wallet/autonomous-wallet.d.ts.map +1 -1
- package/dist/wallet/autonomous-wallet.js +3 -2
- package/dist/wallet/autonomous-wallet.js.map +1 -1
- package/dist/wallet/broker-escrows.d.ts +222 -0
- package/dist/wallet/broker-escrows.d.ts.map +1 -0
- package/dist/wallet/broker-escrows.js +36 -0
- package/dist/wallet/broker-escrows.js.map +1 -0
- package/dist/wallet/lifecycle.d.ts +21 -5
- package/dist/wallet/lifecycle.d.ts.map +1 -1
- package/dist/wallet/lifecycle.js +32 -12
- package/dist/wallet/lifecycle.js.map +1 -1
- package/dist/wallet/privy-broker-server.d.ts.map +1 -1
- package/dist/wallet/privy-broker-server.js +31 -26
- package/dist/wallet/privy-broker-server.js.map +1 -1
- package/dist/wallet/privy-session-broker.d.ts +14 -5
- package/dist/wallet/privy-session-broker.d.ts.map +1 -1
- package/dist/wallet/privy-session-broker.js +29 -17
- package/dist/wallet/privy-session-broker.js.map +1 -1
- package/dist/wallet/privy-session-provider.d.ts +3 -1
- package/dist/wallet/privy-session-provider.d.ts.map +1 -1
- package/dist/wallet/privy-session-provider.js +5 -3
- package/dist/wallet/privy-session-provider.js.map +1 -1
- package/dist/wallet/provider.d.ts.map +1 -1
- package/dist/wallet/provider.js +15 -8
- package/dist/wallet/provider.js.map +1 -1
- package/dist/x402/facilitator.d.ts +3 -30
- package/dist/x402/facilitator.d.ts.map +1 -1
- package/dist/x402/facilitator.js +0 -27
- package/dist/x402/facilitator.js.map +1 -1
- package/dist/x402-buyer/guarded-fetch.d.ts +51 -0
- package/dist/x402-buyer/guarded-fetch.d.ts.map +1 -0
- package/dist/x402-buyer/guarded-fetch.js +147 -0
- package/dist/x402-buyer/guarded-fetch.js.map +1 -0
- package/dist/x402-buyer/index.d.ts +10 -0
- package/dist/x402-buyer/index.d.ts.map +1 -0
- package/dist/x402-buyer/index.js +10 -0
- package/dist/x402-buyer/index.js.map +1 -0
- package/dist/x402-buyer/pay.d.ts +135 -0
- package/dist/x402-buyer/pay.d.ts.map +1 -0
- package/dist/x402-buyer/pay.js +336 -0
- package/dist/x402-buyer/pay.js.map +1 -0
- package/dist/x402-opener/abi.d.ts +684 -0
- package/dist/x402-opener/abi.d.ts.map +1 -0
- package/dist/x402-opener/abi.js +880 -0
- package/dist/x402-opener/abi.js.map +1 -0
- package/dist/x402-opener/facilitator-entry.d.ts +3 -0
- package/dist/x402-opener/facilitator-entry.d.ts.map +1 -0
- package/dist/x402-opener/facilitator-entry.js +37 -0
- package/dist/x402-opener/facilitator-entry.js.map +1 -0
- package/dist/x402-opener/facilitator-server.d.ts +180 -0
- package/dist/x402-opener/facilitator-server.d.ts.map +1 -0
- package/dist/x402-opener/facilitator-server.js +696 -0
- package/dist/x402-opener/facilitator-server.js.map +1 -0
- package/dist/x402-opener/index.d.ts +14 -0
- package/dist/x402-opener/index.d.ts.map +1 -0
- package/dist/x402-opener/index.js +14 -0
- package/dist/x402-opener/index.js.map +1 -0
- package/dist/x402-opener/listing-resolver.d.ts +55 -0
- package/dist/x402-opener/listing-resolver.d.ts.map +1 -0
- package/dist/x402-opener/listing-resolver.js +125 -0
- package/dist/x402-opener/listing-resolver.js.map +1 -0
- package/dist/x402-opener/refund-relay.d.ts +240 -0
- package/dist/x402-opener/refund-relay.d.ts.map +1 -0
- package/dist/x402-opener/refund-relay.js +1240 -0
- package/dist/x402-opener/refund-relay.js.map +1 -0
- package/dist/x402-opener/relayer-queue.d.ts +14 -0
- package/dist/x402-opener/relayer-queue.d.ts.map +1 -0
- package/dist/x402-opener/relayer-queue.js +18 -0
- package/dist/x402-opener/relayer-queue.js.map +1 -0
- package/dist/x402-opener/scheme.d.ts +217 -0
- package/dist/x402-opener/scheme.d.ts.map +1 -0
- package/dist/x402-opener/scheme.js +749 -0
- package/dist/x402-opener/scheme.js.map +1 -0
- package/dist/x402-opener/terms.d.ts +105 -0
- package/dist/x402-opener/terms.d.ts.map +1 -0
- package/dist/x402-opener/terms.js +212 -0
- package/dist/x402-opener/terms.js.map +1 -0
- package/dist/zktls/reclaim.d.ts +2 -2
- package/dist/zktls/t2-delivery-proof.d.ts +6 -6
- package/docs/agent-layer.md +3 -2
- package/docs/autonomous-privy-wallet.md +188 -0
- package/docs/cli.md +184 -31
- package/docs/langchain.md +5 -0
- package/docs/mcp-reference.md +75 -5
- package/docs/probe-capability.md +191 -0
- package/docs/quickstart.md +36 -1
- package/docs/threat-model.md +20 -0
- package/docs/x402.md +628 -595
- package/package.json +19 -17
- package/src/capability/probe-capability.ts +355 -0
- package/src/cli/args.ts +29 -0
- package/src/cli/commands/claim.ts +1 -1
- package/src/cli/commands/close.ts +36 -3
- package/src/cli/commands/invoke.ts +5 -2
- package/src/cli/commands/mcp.ts +18 -2
- package/src/cli/commands/open.ts +75 -4
- package/src/cli/commands/pay.ts +442 -0
- package/src/cli/commands/reclaim-unverified.ts +8 -2
- package/src/cli/commands/reclaim.ts +252 -14
- package/src/cli/commands/refund.ts +277 -0
- package/src/cli/commands/status.ts +17 -1
- package/src/cli/commands/streams.ts +10 -14
- package/src/cli/commands/watch.ts +7 -1
- package/src/cli/config.ts +139 -52
- package/src/cli/deps.ts +74 -1
- package/src/cli/errors.ts +24 -1
- package/src/cli/escape-hatch.ts +19 -5
- package/src/cli/listings.ts +43 -10
- package/src/cli/preflight.ts +36 -21
- package/src/cli/privy.ts +4 -2
- package/src/cli/reclaimability.ts +154 -0
- package/src/cli/run.ts +54 -11
- package/src/cli/scan-range.ts +2 -2
- package/src/cli/status.ts +14 -1
- package/src/cli/wallet.ts +2 -2
- package/src/discovery/rate-band.ts +172 -0
- package/src/escrow-generation.ts +135 -0
- package/src/frameworks/agentkit.ts +45 -11
- package/src/frameworks/eliza.ts +27 -5
- package/src/frameworks/langchain.ts +14 -0
- package/src/gateway/caller-auth-gateway.ts +320 -68
- package/src/gateway/http-server.ts +629 -220
- package/src/gateway/probe-auth.ts +191 -0
- package/src/gateway/signed-rate-bounds.ts +164 -0
- package/src/gateway/x402-opener-mode.ts +974 -0
- package/src/index.ts +82 -19
- package/src/mcp/server.ts +319 -42
- package/src/mcp/x402-tools.ts +621 -0
- package/src/network.ts +302 -0
- package/src/sdk/invoke.ts +6 -5
- package/src/wallet/autonomous-wallet-broker.ts +46 -20
- package/src/wallet/autonomous-wallet-protocol.ts +11 -2
- package/src/wallet/autonomous-wallet.ts +4 -2
- package/src/wallet/broker-escrows.ts +66 -0
- package/src/wallet/lifecycle.ts +53 -18
- package/src/wallet/privy-broker-server.ts +35 -25
- package/src/wallet/privy-session-broker.ts +58 -25
- package/src/wallet/privy-session-provider.ts +7 -3
- package/src/wallet/provider.ts +20 -15
- package/src/x402/facilitator.ts +3 -43
- package/src/x402-buyer/guarded-fetch.ts +213 -0
- package/src/x402-buyer/index.ts +9 -0
- package/src/x402-buyer/pay.ts +517 -0
- package/src/x402-opener/abi.ts +881 -0
- package/src/x402-opener/facilitator-entry.ts +45 -0
- package/src/x402-opener/facilitator-server.ts +1014 -0
- package/src/x402-opener/index.ts +13 -0
- package/src/x402-opener/listing-resolver.ts +202 -0
- package/src/x402-opener/refund-relay.ts +1743 -0
- package/src/x402-opener/relayer-queue.ts +18 -0
- package/src/x402-opener/scheme.ts +1133 -0
- package/src/x402-opener/terms.ts +300 -0
- package/dist/gateway/x402-mode.d.ts +0 -123
- package/dist/gateway/x402-mode.d.ts.map +0 -1
- package/dist/gateway/x402-mode.js +0 -212
- package/dist/gateway/x402-mode.js.map +0 -1
- package/dist/x402/delivery-oracle.d.ts +0 -108
- package/dist/x402/delivery-oracle.d.ts.map +0 -1
- package/dist/x402/delivery-oracle.js +0 -174
- package/dist/x402/delivery-oracle.js.map +0 -1
- package/dist/x402/facilitator-server-entry.d.ts +0 -3
- package/dist/x402/facilitator-server-entry.d.ts.map +0 -1
- package/dist/x402/facilitator-server-entry.js +0 -27
- package/dist/x402/facilitator-server-entry.js.map +0 -1
- package/dist/x402/facilitator-server.d.ts +0 -73
- package/dist/x402/facilitator-server.d.ts.map +0 -1
- package/dist/x402/facilitator-server.js +0 -305
- package/dist/x402/facilitator-server.js.map +0 -1
- package/dist/x402/payment-requirements.d.ts +0 -106
- package/dist/x402/payment-requirements.d.ts.map +0 -1
- package/dist/x402/payment-requirements.js +0 -138
- package/dist/x402/payment-requirements.js.map +0 -1
- package/dist/x402/relayer.d.ts +0 -41
- package/dist/x402/relayer.d.ts.map +0 -1
- package/dist/x402/relayer.js +0 -64
- package/dist/x402/relayer.js.map +0 -1
- package/dist/x402/resource-index.d.ts +0 -75
- package/dist/x402/resource-index.d.ts.map +0 -1
- package/dist/x402/resource-index.js +0 -126
- package/dist/x402/resource-index.js.map +0 -1
- package/dist/x402/verified-delivery-facilitator.d.ts +0 -285
- package/dist/x402/verified-delivery-facilitator.d.ts.map +0 -1
- package/dist/x402/verified-delivery-facilitator.js +0 -423
- package/dist/x402/verified-delivery-facilitator.js.map +0 -1
- package/src/gateway/x402-mode.ts +0 -350
- package/src/x402/delivery-oracle.ts +0 -285
- package/src/x402/facilitator-server-entry.ts +0 -35
- package/src/x402/facilitator-server.ts +0 -445
- package/src/x402/payment-requirements.ts +0 -231
- package/src/x402/relayer.ts +0 -122
- package/src/x402/resource-index.ts +0 -228
- package/src/x402/verified-delivery-facilitator.ts +0 -744
|
@@ -131,3 +131,191 @@ capability typed-data requests only. It does not claim ERC-4337, EIP-1271,
|
|
|
131
131
|
smart-account, or gas-sponsorship support. The broker deployment and its real
|
|
132
132
|
Privy policy remain integration dependencies and must be health-checked before
|
|
133
133
|
use.
|
|
134
|
+
|
|
135
|
+
## Escrow cutover (V2 → V3): what the broker allows, and the Privy policy change it needs
|
|
136
|
+
|
|
137
|
+
The broker (both the agent-owned and the session paths) sends transactions to
|
|
138
|
+
exactly two kinds of escrow, read from the registries rather than hardcoded
|
|
139
|
+
(`src/wallet/broker-escrows.ts`):
|
|
140
|
+
|
|
141
|
+
| Target | Allowed calls |
|
|
142
|
+
| ----------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
|
|
143
|
+
| **Current escrow** (the SDK network registry's escrow for the broker's network) | `openStream`, `close`, `reclaim`, `reclaimUnverified` |
|
|
144
|
+
| **Legacy escrow(s)** (`@absol-labs/shared` deployments with `status: "legacy"`, other than the current one) | `close`, `reclaim`, `reclaimUnverified` **only** — no `openStream` |
|
|
145
|
+
| **USDC** | `approve(spender, amount)` with `spender` = the **current** escrow only (never a legacy escrow), `amount` within the existing cap |
|
|
146
|
+
|
|
147
|
+
Everything else is unchanged: chain id, zero `value`, `from` = the wallet, the
|
|
148
|
+
mandate/spend-cap checks on `openStream`, `stream.buyer == wallet` on every exit
|
|
149
|
+
(read from the escrow the exit targets), and invocation-capability typed data
|
|
150
|
+
bound to the current escrow. V2 and V3 share the selectors of every allowed
|
|
151
|
+
method, so one decoder (the union of the V2/V3 ABIs) serves both.
|
|
152
|
+
|
|
153
|
+
While the SDK default is still `StreamEscrowV2` (`@absol-labs/sdk@0.10.0-rc.1`),
|
|
154
|
+
V2 is current and nothing is legacy: behaviour is identical to before. With
|
|
155
|
+
`0.10.0-rc.2` the default becomes `StreamEscrowV3` and V2 becomes exit-only, so
|
|
156
|
+
agents holding open V2 streams can still close and reclaim them.
|
|
157
|
+
|
|
158
|
+
### Privy policy rules to apply at cutover
|
|
159
|
+
|
|
160
|
+
The broker's checks are a second line; the Privy policy is what Privy itself
|
|
161
|
+
enforces. At the V3 cutover, the policy (`PRIVY_POLICY_ID`) must change as
|
|
162
|
+
follows. Base Sepolia addresses (from `@absol-labs/shared` `escrowDeployments`
|
|
163
|
+
and the SDK registry):
|
|
164
|
+
|
|
165
|
+
- current escrow (V3): `0x0643ba482C6A7aF31a1f8225e7e7e79Cfc467b13`
|
|
166
|
+
- legacy escrow (V2): `0x0f09f36Ccc05A7c9882F438721C08De314dFd46C`
|
|
167
|
+
- USDC: `0x036CbD53842c5426634e7929541eC2318f3dCF7e`
|
|
168
|
+
|
|
169
|
+
Keep every existing numeric bound exactly as it is (`openStream`
|
|
170
|
+
`deposit <= 1000000`, `ratePerSecond <= 1000`, `maxDuration <= 3600`; USDC
|
|
171
|
+
`approve` `amount <= 1000000`; chain `eip155:84532`; `value == 0`).
|
|
172
|
+
|
|
173
|
+
1. **Contract allowlist, escrow — `openStream`**: change the target from the V2
|
|
174
|
+
escrow to the **V3** escrow only. The legacy V2 escrow must NOT be allowed
|
|
175
|
+
`openStream`.
|
|
176
|
+
2. **Contract allowlist, escrow — exits** (`close(bytes32)` `0x39c79e0c`,
|
|
177
|
+
`reclaim(bytes32,uint256,bytes32[])` `0x2c307c9c`,
|
|
178
|
+
`reclaimUnverified(bytes32)` `0x5fcdce22`): allow them on **both** the V3
|
|
179
|
+
escrow and the V2 escrow (`to` IN [V3, V2]).
|
|
180
|
+
3. **USDC `approve`** (`0x095ea7b3`): change the allowed `spender` from the V2
|
|
181
|
+
escrow to the **V3** escrow only. No approval to V2.
|
|
182
|
+
4. Remove any rule that allows the V2 escrow for a method other than the three
|
|
183
|
+
exits above.
|
|
184
|
+
|
|
185
|
+
The same, as Privy policy rules (ALLOW rules, `eth_sendTransaction`,
|
|
186
|
+
`chain_type: "ethereum"`; DENY is the default):
|
|
187
|
+
|
|
188
|
+
```json
|
|
189
|
+
[
|
|
190
|
+
{
|
|
191
|
+
"name": "metrik-open-stream-current-escrow",
|
|
192
|
+
"method": "eth_sendTransaction",
|
|
193
|
+
"action": "ALLOW",
|
|
194
|
+
"conditions": [
|
|
195
|
+
{
|
|
196
|
+
"field_source": "ethereum_transaction",
|
|
197
|
+
"field": "chain_id",
|
|
198
|
+
"operator": "eq",
|
|
199
|
+
"value": "84532"
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
"field_source": "ethereum_transaction",
|
|
203
|
+
"field": "to",
|
|
204
|
+
"operator": "eq",
|
|
205
|
+
"value": "0x0643ba482C6A7aF31a1f8225e7e7e79Cfc467b13"
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
"field_source": "ethereum_transaction",
|
|
209
|
+
"field": "value",
|
|
210
|
+
"operator": "eq",
|
|
211
|
+
"value": "0"
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
"field_source": "ethereum_calldata",
|
|
215
|
+
"field": "openStream.deposit",
|
|
216
|
+
"operator": "lte",
|
|
217
|
+
"value": "1000000",
|
|
218
|
+
"abi": "<StreamEscrowV3 openStream ABI>"
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
"field_source": "ethereum_calldata",
|
|
222
|
+
"field": "openStream.ratePerSecond",
|
|
223
|
+
"operator": "lte",
|
|
224
|
+
"value": "1000",
|
|
225
|
+
"abi": "<StreamEscrowV3 openStream ABI>"
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
"field_source": "ethereum_calldata",
|
|
229
|
+
"field": "openStream.maxDuration",
|
|
230
|
+
"operator": "lte",
|
|
231
|
+
"value": "3600",
|
|
232
|
+
"abi": "<StreamEscrowV3 openStream ABI>"
|
|
233
|
+
}
|
|
234
|
+
]
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
"name": "metrik-exits-current-and-legacy-escrow",
|
|
238
|
+
"method": "eth_sendTransaction",
|
|
239
|
+
"action": "ALLOW",
|
|
240
|
+
"conditions": [
|
|
241
|
+
{
|
|
242
|
+
"field_source": "ethereum_transaction",
|
|
243
|
+
"field": "chain_id",
|
|
244
|
+
"operator": "eq",
|
|
245
|
+
"value": "84532"
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
"field_source": "ethereum_transaction",
|
|
249
|
+
"field": "to",
|
|
250
|
+
"operator": "in",
|
|
251
|
+
"value": [
|
|
252
|
+
"0x0643ba482C6A7aF31a1f8225e7e7e79Cfc467b13",
|
|
253
|
+
"0x0f09f36Ccc05A7c9882F438721C08De314dFd46C"
|
|
254
|
+
]
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
"field_source": "ethereum_transaction",
|
|
258
|
+
"field": "value",
|
|
259
|
+
"operator": "eq",
|
|
260
|
+
"value": "0"
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
"field_source": "ethereum_calldata",
|
|
264
|
+
"field": "function_selector",
|
|
265
|
+
"operator": "in",
|
|
266
|
+
"value": ["0x39c79e0c", "0x2c307c9c", "0x5fcdce22"]
|
|
267
|
+
}
|
|
268
|
+
]
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
"name": "metrik-usdc-approve-current-escrow",
|
|
272
|
+
"method": "eth_sendTransaction",
|
|
273
|
+
"action": "ALLOW",
|
|
274
|
+
"conditions": [
|
|
275
|
+
{
|
|
276
|
+
"field_source": "ethereum_transaction",
|
|
277
|
+
"field": "chain_id",
|
|
278
|
+
"operator": "eq",
|
|
279
|
+
"value": "84532"
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
"field_source": "ethereum_transaction",
|
|
283
|
+
"field": "to",
|
|
284
|
+
"operator": "eq",
|
|
285
|
+
"value": "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
"field_source": "ethereum_transaction",
|
|
289
|
+
"field": "value",
|
|
290
|
+
"operator": "eq",
|
|
291
|
+
"value": "0"
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
"field_source": "ethereum_calldata",
|
|
295
|
+
"field": "approve.spender",
|
|
296
|
+
"operator": "eq",
|
|
297
|
+
"value": "0x0643ba482C6A7aF31a1f8225e7e7e79Cfc467b13",
|
|
298
|
+
"abi": "<ERC-20 approve ABI>"
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
"field_source": "ethereum_calldata",
|
|
302
|
+
"field": "approve.amount",
|
|
303
|
+
"operator": "lte",
|
|
304
|
+
"value": "1000000",
|
|
305
|
+
"abi": "<ERC-20 approve ABI>"
|
|
306
|
+
}
|
|
307
|
+
]
|
|
308
|
+
}
|
|
309
|
+
]
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
Express the selector restriction in whatever form the live policy already uses
|
|
313
|
+
(a `function_selector` condition, or one calldata-field rule per exit method
|
|
314
|
+
with its ABI). What matters is the set: `openStream` → V3 only; the three exits
|
|
315
|
+
→ V3 and V2; `approve.spender` → V3 only. The existing invocation-capability
|
|
316
|
+
typed-data rule must change its `verifyingContract` to the V3 escrow at the
|
|
317
|
+
same time (the broker already binds it to the current escrow).
|
|
318
|
+
|
|
319
|
+
Apply the policy change and the `@absol-labs/sdk@0.10.0-rc.2` bump together: the
|
|
320
|
+
broker refuses a V2 `openStream` as soon as the registry default is V3, and the
|
|
321
|
+
policy should too.
|
package/docs/cli.md
CHANGED
|
@@ -46,7 +46,8 @@ consumer who installed the package could not run at all. `metrik mcp
|
|
|
46
46
|
## Testnet only
|
|
47
47
|
|
|
48
48
|
The CLI signs with a raw private key and moves USDC, so the chain is an **allowlist**,
|
|
49
|
-
not a default: only
|
|
49
|
+
not a default: only networks the `@absol-labs/sdk` network registry knows **and marks as
|
|
50
|
+
a testnet** are accepted (today: Base Sepolia, `84532`). There is deliberately **no
|
|
50
51
|
override flag** — an escape hatch that re-enabled real funds would defeat the guarantee,
|
|
51
52
|
and there is no mainnet deployment for it to reach anyway.
|
|
52
53
|
|
|
@@ -104,6 +105,17 @@ A Privy wallet differs from the other two in one structural way: its account has
|
|
|
104
105
|
client's transport** instead of the plain `http(--rpc-url)` a local signer uses. That is
|
|
105
106
|
the whole of the wiring. Private-key and CDP runs are unchanged, byte for byte.
|
|
106
107
|
|
|
108
|
+
**`metrik claim` does not work on a Privy wallet.** The broker's transaction allowlist
|
|
109
|
+
carries the BUYER actions only (`openStream`, `close`, `reclaim`, `reclaimUnverified`), so
|
|
110
|
+
an operator claim is refused server-side and the client cannot raise that ceiling. Claim
|
|
111
|
+
with the operator's own `METRIK_AGENT_PRIVATE_KEY`. Every other command works. The CLI
|
|
112
|
+
warns when you try it, and `metrik --help` / `metrik claim --help` say so up front.
|
|
113
|
+
|
|
114
|
+
**`metrik mcp` does not carry a Privy wallet either.** The MCP server resolves its wallet
|
|
115
|
+
with `parseAgentWalletEnv()`, which reads `METRIK_AGENT_PRIVATE_KEY` or the CDP variables
|
|
116
|
+
and has no Privy branch — so `metrik mcp --print-config` prints a key placeholder and says
|
|
117
|
+
why on stderr rather than emitting Privy variables the server would ignore.
|
|
118
|
+
|
|
107
119
|
There are two shapes. Set one; setting both uses the agent-owned wallet and says so.
|
|
108
120
|
|
|
109
121
|
**Agent-owned (`privy-autonomous`)** — headless, no browser, no user login:
|
|
@@ -245,19 +257,21 @@ that needs no key at all — it builds and prints the intended call and says whi
|
|
|
245
257
|
|
|
246
258
|
## Commands
|
|
247
259
|
|
|
248
|
-
| Command | Needs a wallet? | Broadcasts a tx?
|
|
249
|
-
| -------------------- | ------------------------------ |
|
|
250
|
-
| `discover` | no | no
|
|
251
|
-
| `open` | **yes** (not with `--dry-run`) | **yes**
|
|
252
|
-
| `status` | no | no
|
|
253
|
-
| `streams` | no (with `--address`) | no
|
|
254
|
-
| `watch` | no | no
|
|
255
|
-
| `invoke` | **yes** (off-chain capability) | no
|
|
256
|
-
| `
|
|
257
|
-
| `
|
|
258
|
-
| `
|
|
259
|
-
| `
|
|
260
|
-
| `
|
|
260
|
+
| Command | Needs a wallet? | Broadcasts a tx? | What it does |
|
|
261
|
+
| -------------------- | ------------------------------ | ----------------- | ------------------------------------------------ |
|
|
262
|
+
| `discover` | no | no | Lists verified registry listings |
|
|
263
|
+
| `open` | **yes** (not with `--dry-run`) | **yes** | Escrows USDC into a metered stream |
|
|
264
|
+
| `status` | no | no | One stream's on-chain state + verified accrual |
|
|
265
|
+
| `streams` | no (with `--address`) | no | Lists a wallet's streams from the escrow's logs |
|
|
266
|
+
| `watch` | no | no | Polls that until the stream closes |
|
|
267
|
+
| `invoke` | **yes** (off-chain capability) | no | Calls the paid service, authorized by the stream |
|
|
268
|
+
| `pay` | **yes** (EIP-3009 signature) | no (relayer does) | Pays an x402 endpoint into an escrow stream |
|
|
269
|
+
| `refund` | only for `--close` | no (relay does) | Gasless close/reclaim of an x402 stream |
|
|
270
|
+
| `close` | **yes** | **yes** | Stops the clock |
|
|
271
|
+
| `reclaim` | **yes** | **yes** | Takes back what was never earned |
|
|
272
|
+
| `reclaim-unverified` | **yes** | **yes** | Buyer escape hatch: reclaim with no proof |
|
|
273
|
+
| `claim` | **yes** (the operator's) | **yes** | Operator: redeem what verified |
|
|
274
|
+
| `mcp` | no | no | Prints the MCP client config for `metrik-mcp` |
|
|
261
275
|
|
|
262
276
|
### `metrik discover`
|
|
263
277
|
|
|
@@ -358,6 +372,21 @@ as `simulationPendingApproval: true`, with no `simulationError` — a script bra
|
|
|
358
372
|
that field no longer sees the expected path as a failure. An allowance-shaped revert when
|
|
359
373
|
the allowance IS already sufficient, and every other revert, are still surfaced as errors.
|
|
360
374
|
|
|
375
|
+
**The operator-signed rate band.** Before anything is signed or broadcast — `--dry-run`
|
|
376
|
+
included — `open` re-verifies the listing's operator-signed descriptor (the same check the
|
|
377
|
+
seller's gateway runs) and refuses at exit `2` when `--rate` is outside its
|
|
378
|
+
`minRatePerSecond`..`maxRatePerSecond` band, e.g. `the operator signed rates 100..10000
|
|
379
|
+
atomic/s (0.0001..0.01 USDC/s); --rate 20000 (0.02 USDC/s) would be refused by the
|
|
380
|
+
service's gateway`. The escrow accepts any non-zero rate, but the gateway answers every
|
|
381
|
+
request on an out-of-band stream with `403 stream-rate-out-of-bounds`, so the deposit
|
|
382
|
+
would sit in a stream that can never be served. Bounds are inclusive; a bound the operator
|
|
383
|
+
did not sign is not enforced, and a legacy binding signs none. A descriptor that does not
|
|
384
|
+
verify is a refusal (exit `4`), never "no band". Without `--operator`, an unreachable
|
|
385
|
+
registry already fails `open` (exit `4`). With `--operator` — the existing escape hatch for
|
|
386
|
+
a service the registry cannot vouch for — the band cannot be read, so the open proceeds
|
|
387
|
+
with a warning saying the rate was **not** checked. There is no flag to override a band
|
|
388
|
+
the CLI can read.
|
|
389
|
+
|
|
361
390
|
**Amounts.** `--budget` and `--rate` are decimal USDC by default; `--units atomic`
|
|
362
391
|
switches both to raw 6-decimal base units (what the escrow, the oracle and every
|
|
363
392
|
`METRIK_E2E_*` fixture use). The unit is explicit rather than inferred from magnitude,
|
|
@@ -520,7 +549,10 @@ Configured mandate ceilings are carried through verbatim — they are policy, no
|
|
|
520
549
|
and re-typing four caps from memory is where a wrong ceiling comes from. **Credentials are
|
|
521
550
|
always placeholders.** This command never reads a key out of your environment and prints
|
|
522
551
|
it back; the wallet block is simply shaped like the environment it ran in (the CDP
|
|
523
|
-
variables if those are what you have set, `METRIK_AGENT_PRIVATE_KEY` otherwise).
|
|
552
|
+
variables if those are what you have set, `METRIK_AGENT_PRIVATE_KEY` otherwise). A Privy
|
|
553
|
+
wallet is **not** an option here — `parseAgentWalletEnv()` has no Privy branch — so when
|
|
554
|
+
the environment carries one the command says so on stderr and prints a key placeholder
|
|
555
|
+
instead of a config the server could not start from.
|
|
524
556
|
|
|
525
557
|
### `metrik invoke`
|
|
526
558
|
|
|
@@ -550,6 +582,96 @@ listings ("consumer-attested T2 invocation is not supported for gated listings")
|
|
|
550
582
|
live listings are gated — so a `metrik prove` would be a command that fails for almost
|
|
551
583
|
everyone who ran it. It is left out until that constraint lifts.
|
|
552
584
|
|
|
585
|
+
### `metrik pay` (x402)
|
|
586
|
+
|
|
587
|
+
```bash
|
|
588
|
+
metrik pay https://x402.example/transform --json '{"text":"# hi"}' --max-amount 0.1
|
|
589
|
+
metrik pay <url> [--json <body> | --data <body>] [--method POST] [--header "K: V"] \
|
|
590
|
+
--max-amount <usdc> [--max-rate <usdc/s>] [--max-duration <s>] [--min-duration <s>] \
|
|
591
|
+
[--operator <address>] [--units atomic]
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
Pays any **x402 v2 `exact`** endpoint through `@absol-labs/sdk/x402`'s `payWithX402`,
|
|
595
|
+
with every SDK protection intact (network and USDC from the registry, EIP-3009 only,
|
|
596
|
+
registered opener factory, `payTo == factory.predict(terms)` read on-chain, bounded
|
|
597
|
+
authorization lifetime, a plain transfer to the seller refused). A Metrik seller's
|
|
598
|
+
payment opens an escrow stream with `deposit = price`; the seller earns
|
|
599
|
+
`ratePerSecond x verified seconds`, capped at the deposit.
|
|
600
|
+
|
|
601
|
+
The payer needs **USDC only, no gas** (the facilitator's relayer submits the
|
|
602
|
+
authorization). A Privy wallet cannot pay: its broker does not sign EIP-3009.
|
|
603
|
+
|
|
604
|
+
**How the spend mandate bounds an x402 payment.** No spend without a mandate: a
|
|
605
|
+
payment IS a stream open, so its opener terms are checked by `checkMandate()` exactly
|
|
606
|
+
like `metrik open`, inside the SDK's `onQuote` hook, after the SDK's own checks and
|
|
607
|
+
**before anything is signed**:
|
|
608
|
+
|
|
609
|
+
| Mandate cap | Checked against |
|
|
610
|
+
| ---------------------- | ---------------------------------------------- |
|
|
611
|
+
| `maxPerStreamUsdc` | the quote's `amount` (= the deposit) |
|
|
612
|
+
| `maxTotalUsdc` | spent so far + `amount` |
|
|
613
|
+
| `maxRatePerSecondUsdc` | `ratePerSecond` (how fast the seller can earn) |
|
|
614
|
+
| `maxDurationSeconds` | `maxDuration` (the stream window) |
|
|
615
|
+
| `allowedOperators` | `operator` (who the stream pays) |
|
|
616
|
+
|
|
617
|
+
The caps are also handed to the SDK as `maxAmount` / `maxRatePerSecond`, so the price is
|
|
618
|
+
enforced twice. A quote with no opener terms is refused. The mandate comes from
|
|
619
|
+
`METRIK_AGENT_MANDATE_*` when set, otherwise it is sized to this command:
|
|
620
|
+
`--max-amount` (required then) is the per-stream and total cap, `--max-rate` the rate cap
|
|
621
|
+
(default: no tighter than the price), `--max-duration` the window cap (default 1 day),
|
|
622
|
+
`--operator` the only allowed operator. With a standing mandate, every flag
|
|
623
|
+
**intersects** it (the most restrictive value wins; an `--operator` outside
|
|
624
|
+
`METRIK_AGENT_MANDATE_ALLOWED_OPERATORS` is refused): a flag can tighten the
|
|
625
|
+
standing ceiling, never loosen or bypass it. Like every CLI mandate it covers one
|
|
626
|
+
invocation.
|
|
627
|
+
|
|
628
|
+
If anything fails after the authorization was handed to the seller, `metrik pay`
|
|
629
|
+
establishes the outcome on-chain (USDC `authorizationState`, the opener's
|
|
630
|
+
`StreamOpenedFor` log for that nonce), exits `4`, and says whether the money left
|
|
631
|
+
the payer — with the `streamId` and the recovery command when the stream is found.
|
|
632
|
+
It never reports "nothing moved" unless the authorization was unused and expired.
|
|
633
|
+
|
|
634
|
+
A quote naming a **legacy** deployment's factory (for example a seller still on
|
|
635
|
+
StreamEscrowV2 after the default moved to V3) is refused by the SDK unless you pass
|
|
636
|
+
`--allow-legacy-factory`; that stream is then closed and reclaimed on the legacy
|
|
637
|
+
escrow, and the printed recovery command carries `--escrow <legacy escrow>`.
|
|
638
|
+
|
|
639
|
+
`--json <body>` is the request body (curl-style, sets `content-type: application/json`);
|
|
640
|
+
a bare `--json` still selects JSON output, and both can be combined. The output is the
|
|
641
|
+
response, the `streamId`, the opener, the deposit and rate, `minEarnSeconds` (after how
|
|
642
|
+
many verified seconds nothing is left to reclaim) and the **refund URL**.
|
|
643
|
+
**Refunds are not automatic** — see `metrik refund`.
|
|
644
|
+
|
|
645
|
+
Exit codes: `2` usage (including no ceiling), `3` refused by the mandate or the SDK
|
|
646
|
+
(nothing signed), `4` the settlement failed after signing (the error says whether the
|
|
647
|
+
authorization was used and how to cancel it; see [x402.md](./x402.md)).
|
|
648
|
+
|
|
649
|
+
### `metrik refund`
|
|
650
|
+
|
|
651
|
+
```bash
|
|
652
|
+
metrik refund <streamId> --refund-url <url> [--close] [--reclaim] [--attempts 5] [--max-wait 60]
|
|
653
|
+
```
|
|
654
|
+
|
|
655
|
+
Drives the seller's **gasless refund relay** through the SDK's `refundClient`, bound to
|
|
656
|
+
the stream and to the opener read **from chain** (`factory.isOpener`), never from the
|
|
657
|
+
relay. With no action flag it prints the status and the next step. `--close` signs the
|
|
658
|
+
opener's EIP-712 `Close` as the payer (the relay pays the gas; authorized on the mandate
|
|
659
|
+
owner's signature only, like `metrik close`). `--reclaim` sends the permissionless
|
|
660
|
+
`opener.reclaim` (no wallet needed; the refund always goes to `payerOf(streamId)`) and
|
|
661
|
+
retries a bounded number of times while the settlement window is open, honouring
|
|
662
|
+
`Retry-After`; a longer wait exits `3` with the time to retry. Every relay "success" is
|
|
663
|
+
checked against the transaction receipt on the configured chain. `--refund-url` accepts
|
|
664
|
+
the full URL `metrik pay` printed, a `{streamId}` template or the relay's origin; it can
|
|
665
|
+
also come from `METRIK_AGENT_REFUND_URL`.
|
|
666
|
+
|
|
667
|
+
Nothing is refunded automatically, and the relay is a convenience: a payer can always
|
|
668
|
+
recover on-chain without it (`metrik close` as the payer, with gas; `metrik reclaim` by
|
|
669
|
+
anyone).
|
|
670
|
+
|
|
671
|
+
`status`, `close` and `reclaim` understand opener-bought streams: they show the opener and the
|
|
672
|
+
payer, `close` routes through the opener (payer only), and `reclaim` sends the
|
|
673
|
+
permissionless opener reclaim and reports the refund to the payer.
|
|
674
|
+
|
|
553
675
|
### `metrik close` and `metrik reclaim`
|
|
554
676
|
|
|
555
677
|
```bash
|
|
@@ -563,12 +685,32 @@ returns the unspent budget, and the buyer sends it. `close` now points at
|
|
|
563
685
|
`--close-first` for next time, rather than leaving the one-shot form visible only in
|
|
564
686
|
`metrik reclaim --help`.
|
|
565
687
|
|
|
688
|
+
**`reclaim` names the condition before it spends anything.** Three different on-chain
|
|
689
|
+
states stop a reclaim, and they have three completely different answers: the stream was
|
|
690
|
+
already reclaimed (you have the money), the stream is still running (close it first), or
|
|
691
|
+
its stop time is not checkpointed yet (wait ~20 seconds). The CLI reads `getStream`,
|
|
692
|
+
`latestCheckpointCheckedAt` and the chain clock up front and says which one it is, rather
|
|
693
|
+
than sending a simulation and repeating whatever the endpoint's revert data decoded to —
|
|
694
|
+
on the public Base Sepolia RPC all three came back as `Execution reverted for an unknown
|
|
695
|
+
reason`. The pre-flight **fails open**: a read that does not answer never blocks the
|
|
696
|
+
reclaim, because refusing to return a buyer's deposit over a dropped view call is worse
|
|
697
|
+
than a wasted simulation.
|
|
698
|
+
|
|
566
699
|
**`reclaim` waits, by design.** `reclaimWithProof` reverts with `SettlementWindowOpen`
|
|
567
700
|
until a checkpoint whose `checkedAt` is at or after the stream's stop time has posted.
|
|
568
701
|
That is the normal ordering of a checkpoint rail, not a fault — in practice the first
|
|
569
|
-
attempt fails and one roughly 30 seconds later succeeds. The CLI retries
|
|
570
|
-
|
|
571
|
-
|
|
702
|
+
attempt fails and one roughly 30 seconds later succeeds. The CLI retries on a bounded
|
|
703
|
+
schedule and narrates the wait on stderr; every other failure is surfaced immediately and
|
|
704
|
+
unretried.
|
|
705
|
+
|
|
706
|
+
The wait shows up in three shapes, and all three retry: the escrow's decoded
|
|
707
|
+
`SettlementWindowOpen`; the **oracle** refusing a proof for a stream it has not
|
|
708
|
+
checkpointed yet (the SDK fetches the proof before it simulates, so the escrow's revert
|
|
709
|
+
never happens and the error is `StreamNotInCheckpointError` / `CheckpointNotReadyError`);
|
|
710
|
+
and a reclaim revert the ABI could not decode, where the chain's state is read to decide.
|
|
711
|
+
Only recognising the first of those is what made `--close-first` die on its first attempt
|
|
712
|
+
against a stream closed before its first covering checkpoint — the ordinary result of a
|
|
713
|
+
short trial run.
|
|
572
714
|
|
|
573
715
|
If it is still blocked when the budget runs out, the message does **not** just say "retry
|
|
574
716
|
later" — every attempt this command makes needs a proof from the oracle, so when the
|
|
@@ -584,8 +726,10 @@ lands on another that has not imported the block.) If the stream is **already**
|
|
|
584
726
|
the close is skipped and the command goes straight to reclaim — so re-running it is always
|
|
585
727
|
safe and never dead-ends on `StreamClosedAlready()`.
|
|
586
728
|
|
|
587
|
-
`
|
|
588
|
-
|
|
729
|
+
`--close-first` is also the one caller allowed past the still-running refusal, since
|
|
730
|
+
clearing that state is the whole point of the flag. Once the close has landed it reports
|
|
731
|
+
what the following retries are waiting for — the stop time, and how far the oracle has
|
|
732
|
+
published — so the wait reads as the advertised wait rather than as a stalled command.
|
|
589
733
|
|
|
590
734
|
Close and reclaim are buyer-recovery actions: `VerifiedStreamAgentClient` authorizes them
|
|
591
735
|
on the mandate owner's signature alone, never on caps or expiry, so a lapsed mandate can
|
|
@@ -682,17 +826,26 @@ that wait legible.
|
|
|
682
826
|
|
|
683
827
|
## Settlement configuration
|
|
684
828
|
|
|
685
|
-
Everything defaults to
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
|
690
|
-
|
|
|
691
|
-
| `--
|
|
692
|
-
| `--
|
|
693
|
-
| `--
|
|
694
|
-
| `--
|
|
695
|
-
| `--
|
|
829
|
+
Everything defaults to the selected network's entry in the `@absol-labs/sdk` network
|
|
830
|
+
registry (the default network is Base Sepolia), and every value is overridable per
|
|
831
|
+
command or through the environment. Nothing chain-specific is hardcoded in the CLI.
|
|
832
|
+
|
|
833
|
+
| Flag | Env | Default |
|
|
834
|
+
| --------------------- | -------------------------------- | ---------------------------------------------------------------------- |
|
|
835
|
+
| `--network` | `METRIK_NETWORK` | the registry default (id, chain id or CAIP-2) |
|
|
836
|
+
| `--chain-id` | `METRIK_AGENT_CHAIN_ID` | the network's chain id (must agree if both set) |
|
|
837
|
+
| `--rpc-url` | `METRIK_AGENT_RPC_URL` | the network's first registered RPC |
|
|
838
|
+
| `--escrow` | `METRIK_AGENT_ESCROW` | the network's current escrow (V3); a `legacy` one (V2) for its streams |
|
|
839
|
+
| `--escrow-generation` | `METRIK_AGENT_ESCROW_GENERATION` | the registry's; REQUIRED only for an unregistered escrow |
|
|
840
|
+
| `--usdc` | `METRIK_AGENT_USDC` | the network's registered USDC |
|
|
841
|
+
| `--oracle-url` | `METRIK_AGENT_ORACLE_URL` | the network's oracle |
|
|
842
|
+
| `--registry-url` | `METRIK_AGENT_REGISTRY_URL` | the network's public listings endpoint |
|
|
843
|
+
|
|
844
|
+
The gas preflight names the network's gas token and faucet (from its gas-token
|
|
845
|
+
metadata) instead of assuming ETH; on a network whose gas IS the settlement USDC it
|
|
846
|
+
checks the one USDC balance and requires the deposit to leave room for gas. An
|
|
847
|
+
`--escrow` the registry does not record has no log-scan anchor, so `metrik streams`
|
|
848
|
+
needs `--from-block` for it.
|
|
696
849
|
|
|
697
850
|
## Embedding it
|
|
698
851
|
|
package/docs/langchain.md
CHANGED
|
@@ -12,6 +12,11 @@ Create them with [`createLangChainVerifiedStreamTools()`](../src/frameworks/lang
|
|
|
12
12
|
## Safety model
|
|
13
13
|
|
|
14
14
|
- `hire_verified_service` checks the signed mandate before any stream open.
|
|
15
|
+
- It then refuses a `ratePerSecondUsdc` outside the listing's operator-signed rate
|
|
16
|
+
band (the seller's gateway would refuse every request on that stream), and fails
|
|
17
|
+
closed when the registry cannot be read. An unlisted `serviceRef` has no signed
|
|
18
|
+
band and is not constrained. The same check runs in the ElizaOS and AgentKit
|
|
19
|
+
adapters.
|
|
15
20
|
- `reclaim_unspent` passes the same signed-mandate context into the agent client,
|
|
16
21
|
which re-checks authorization before the SDK can write.
|
|
17
22
|
- `check_stream_status` is read-only and also returns `shouldStop` for a closed
|
package/docs/mcp-reference.md
CHANGED
|
@@ -36,11 +36,16 @@ an economic question, not a cryptographic one.
|
|
|
36
36
|
| `reclaim_unspent` | **yes** | Closes the stream (**stops the meter**) and returns unspent USDC to the buyer. |
|
|
37
37
|
| `list_streams` | no | Lists the streams this server opened. |
|
|
38
38
|
| `prove_https_response` | no | Buyer-side zkTLS proof of a response. Registered only with Reclaim credentials. |
|
|
39
|
+
| `x402_pay` | **yes** | Pays an x402 endpoint (opener path, docs/x402.md) under the spend mandate. |
|
|
40
|
+
| `refund_status` | no | Refund state of an x402 stream, from the seller's gasless refund relay. |
|
|
41
|
+
| `refund` | **yes** | Gasless close (payer-signed) and reclaim of an opener stream via the relay. |
|
|
39
42
|
|
|
40
43
|
### `discover_services`
|
|
41
44
|
|
|
42
45
|
`category?`, `limit?`. Returns `serviceRef`, `operator`, `publicUrl`, `access`,
|
|
43
|
-
`accessUrl` per listing
|
|
46
|
+
`accessUrl` per listing, plus `ratePerSecondBand` (`minRatePerSecondUsdc` /
|
|
47
|
+
`maxRatePerSecondUsdc`, atomic units, `null` for an unsigned side) when the
|
|
48
|
+
operator's signed descriptor carries one.
|
|
44
49
|
|
|
45
50
|
The registry is an **untrusted transport**: every `serviceRef` is re-derived
|
|
46
51
|
from the signed record and the operator's signature recovered, so a compromised
|
|
@@ -80,6 +85,16 @@ warning on the result. It is operator-set input only — never a tool argument,
|
|
|
80
85
|
because the caller being asked to relax a fund-safety check is the LLM the check
|
|
81
86
|
exists to constrain — and it never overrides a positive contradiction.
|
|
82
87
|
|
|
88
|
+
`ratePerSecondUsdc` must sit inside the listing's operator-signed rate band
|
|
89
|
+
(inclusive). The descriptor is re-verified with the gateway's own check, and an
|
|
90
|
+
out-of-band rate is refused before any approval or open is sent: the escrow
|
|
91
|
+
accepts any non-zero rate, but the seller's gateway answers every request on
|
|
92
|
+
such a stream with `403 stream-rate-out-of-bounds`. A descriptor that does not
|
|
93
|
+
verify is a refusal. Under `METRIK_AGENT_ALLOW_UNVERIFIED_OPERATOR=true` an
|
|
94
|
+
unverifiable pairing has no listing to read a band from, and the result's
|
|
95
|
+
warning says the rate was not checked; the override never widens a band the
|
|
96
|
+
server can read.
|
|
97
|
+
|
|
83
98
|
The result carries a `metering` block: the rate, the budget, the maximum this
|
|
84
99
|
stream can ever spend, and what starts and stops the clock.
|
|
85
100
|
|
|
@@ -151,6 +166,56 @@ evidence of a delivery that did not happen here.
|
|
|
151
166
|
This is an L2 signal to be cross-checked with oracle/L1 evidence — not a
|
|
152
167
|
substitute for it.
|
|
153
168
|
|
|
169
|
+
### `x402_pay`
|
|
170
|
+
|
|
171
|
+
Arguments: `url` (https; http only for localhost), optional `method`, `headers`,
|
|
172
|
+
`body`, `maxAmountUsdc`, `maxRatePerSecondUsdc` (base units; these can only TIGHTEN
|
|
173
|
+
the server mandate) and `minDurationSeconds`. Pays through `@absol-labs/sdk/x402`'s
|
|
174
|
+
`payWithX402` with every SDK protection intact, and is gated exactly like
|
|
175
|
+
`hire_verified_service`: the same server mandate, the same cumulative spend, the
|
|
176
|
+
same per-owner serialization. The payment's opener terms are checked by
|
|
177
|
+
`checkMandate()` before anything is signed — `amount` (the deposit) against the
|
|
178
|
+
per-stream and total caps, `ratePerSecond`, `maxDuration` and `operator` against
|
|
179
|
+
theirs — and the stream it opens is recorded, so it counts against `maxTotalUsdc`.
|
|
180
|
+
A caller-supplied `PAYMENT-SIGNATURE` / `X-PAYMENT` header is refused. The result
|
|
181
|
+
carries the response (bounded), `streamId`, `opener`, `refundUrl`, the deposit and
|
|
182
|
+
rate, and `refundIsAutomatic: false`.
|
|
183
|
+
|
|
184
|
+
### `refund_status` / `refund`
|
|
185
|
+
|
|
186
|
+
Arguments: `streamId`, optional `refundUrl` (not needed for a stream this server
|
|
187
|
+
paid for — it was recorded); `refund` also takes `close` (stop the stream first;
|
|
188
|
+
this wallet signs the opener's `Close`, authorized on the mandate owner's signature
|
|
189
|
+
alone like `reclaim_unspent`) and `reclaim` (default `true`; the permissionless
|
|
190
|
+
reclaim, the refund always goes to the payer). Every relay success is verified
|
|
191
|
+
against the transaction receipt. A settlement window that is still open is reported
|
|
192
|
+
with when to retry. Nothing is refunded automatically.
|
|
193
|
+
|
|
194
|
+
The three x402 tools are **opt-in**: set `METRIK_AGENT_X402=1` to register them
|
|
195
|
+
(any other value, or none, leaves them off).
|
|
196
|
+
|
|
197
|
+
**Spend is reserved before anything is signed.** When the mandate approves a
|
|
198
|
+
quote, `x402_pay` records a reservation for its amount in the stream registry
|
|
199
|
+
— inside the same per-owner queue as `hire_verified_service` — before the SDK
|
|
200
|
+
signs the EIP-3009 authorization. If anything fails after the signature has
|
|
201
|
+
been handed out (a malformed or missing `PAYMENT-RESPONSE`, an unconfirmed
|
|
202
|
+
settlement, a dropped connection), the outcome is established from the chain,
|
|
203
|
+
never from the seller: USDC `authorizationState(from, nonce)` and the opener's
|
|
204
|
+
`StreamOpenedFor(streamId, payer, authorizationNonce, …)` log. The reservation
|
|
205
|
+
is released only if the authorization was never used AND has expired; a stream
|
|
206
|
+
found on-chain replaces it under its real `streamId`; otherwise it stays
|
|
207
|
+
counted, and the tool says the money may have moved — never "not settled".
|
|
208
|
+
|
|
209
|
+
**Outbound requests are guarded.** The URLs the payment tool, `refund` and
|
|
210
|
+
`refund_status` contact come from the model, so every request must be `https:`
|
|
211
|
+
to a host whose every resolved address is public (loopback, private,
|
|
212
|
+
link-local, unique-local, CGNAT, multicast and reserved ranges are refused),
|
|
213
|
+
redirects are never followed, and `METRIK_AGENT_X402_ALLOWED_HOSTS`
|
|
214
|
+
(comma-separated, exact or `*.domain`) restricts it further — list the seller
|
|
215
|
+
AND its refund relay. A response that did not ask for payment is not returned
|
|
216
|
+
(status only). The address is checked at lookup time; use the allowlist where
|
|
217
|
+
DNS rebinding matters.
|
|
218
|
+
|
|
154
219
|
## Configuration
|
|
155
220
|
|
|
156
221
|
`metrik mcp --print-config` prints the `mcpServers` block to paste into an MCP
|
|
@@ -159,11 +224,15 @@ in it are placeholders by design.
|
|
|
159
224
|
|
|
160
225
|
| Variable | Required | Meaning |
|
|
161
226
|
| ---------------------------------------- | -------- | ----------------------------------------------------------------------------------------------- |
|
|
162
|
-
| `METRIK_AGENT_RPC_URL` | **yes** |
|
|
163
|
-
| `METRIK_AGENT_ESCROW` | **yes** | The **StreamEscrowV2
|
|
227
|
+
| `METRIK_AGENT_RPC_URL` | **yes** | RPC of the selected network. |
|
|
228
|
+
| `METRIK_AGENT_ESCROW` | **yes** | The network's registered **StreamEscrowV2**. Anything else is refused (see below). |
|
|
164
229
|
| `METRIK_AGENT_USDC` | **yes** | Settlement token. |
|
|
165
230
|
| `METRIK_AGENT_ESCROW_GENERATION` | no | `v2` (default, and the only supported value). Declared, not probed. |
|
|
166
|
-
| `
|
|
231
|
+
| `METRIK_NETWORK` | no | Registry id, chain id or CAIP-2 id; default the registry's default network. Testnets only. |
|
|
232
|
+
| `METRIK_AGENT_CHAIN_ID` | no | Alternative selector; must agree with `METRIK_NETWORK` when both are set. |
|
|
233
|
+
| `METRIK_AGENT_ALLOW_UNREGISTERED_ESCROW` | no | `true` accepts an escrow the registry does not record (a deliberate private deployment). |
|
|
234
|
+
| `METRIK_AGENT_X402` | no | `1` registers `x402_pay`, `refund_status`, `refund`. **Off by default.** |
|
|
235
|
+
| `METRIK_AGENT_X402_ALLOWED_HOSTS` | no | Comma-separated hosts (`*.domain` allowed) the x402 tools may contact. Unset = any public host. |
|
|
167
236
|
| `METRIK_AGENT_REGISTRY_URL` | no | Registry the invocation origin is verified against. |
|
|
168
237
|
| `METRIK_AGENT_ALLOW_UNVERIFIED_OPERATOR` | no | `true` downgrades an unverifiable operator pairing from a refusal to a warning. Off by default. |
|
|
169
238
|
| `METRIK_AGENT_MCP_STATE_FILE` | no | Persists the stream registry across restarts. |
|
|
@@ -171,5 +240,6 @@ in it are placeholders by design.
|
|
|
171
240
|
| wallet vars | **yes** | `METRIK_AGENT_PRIVATE_KEY`, or the CDP/Privy set. |
|
|
172
241
|
|
|
173
242
|
The escrow generation is a **declared fact, not an inference**: the server
|
|
174
|
-
refuses
|
|
243
|
+
refuses any escrow that is not the network's registered `StreamEscrowV2` (the
|
|
244
|
+
retired V1 escrow included) unless `METRIK_AGENT_ALLOW_UNREGISTERED_ESCROW=true`, because a wrong-generation read does not
|
|
175
245
|
revert — it returns confident nonsense about someone's money.
|