@absol-labs/agent 0.11.0 → 0.12.0-rc.2
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 +43 -51
- 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.d.ts +32 -0
- package/dist/cli/commands/claim.d.ts.map +1 -1
- package/dist/cli/commands/claim.js +116 -28
- 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 +34 -0
- package/dist/cli/commands/pay.d.ts.map +1 -0
- package/dist/cli/commands/pay.js +479 -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 +204 -20
- package/dist/cli/commands/reclaim.js.map +1 -1
- package/dist/cli/commands/refund.d.ts +31 -0
- package/dist/cli/commands/refund.d.ts.map +1 -0
- package/dist/cli/commands/refund.js +397 -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 +21 -2
- 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 +4 -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/context.d.ts +19 -0
- package/dist/cli/context.d.ts.map +1 -1
- package/dist/cli/deps.d.ts +53 -0
- package/dist/cli/deps.d.ts.map +1 -1
- package/dist/cli/deps.js +51 -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/progress.d.ts +13 -1
- package/dist/cli/progress.d.ts.map +1 -1
- package/dist/cli/progress.js +7 -1
- package/dist/cli/progress.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 +62 -21
- 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 +106 -1
- package/dist/cli/status.d.ts.map +1 -1
- package/dist/cli/status.js +325 -44
- package/dist/cli/status.js.map +1 -1
- package/dist/cli/wallet.d.ts +2 -2
- package/dist/cli/wallet.d.ts.map +1 -1
- package/dist/cli/wallet.js +29 -5
- 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 +128 -44
- package/dist/gateway/http-server.d.ts.map +1 -1
- package/dist/gateway/http-server.js +506 -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 +252 -0
- package/dist/gateway/x402-opener-mode.d.ts.map +1 -0
- package/dist/gateway/x402-opener-mode.js +772 -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 +64 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +247 -37
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/x402-tools.d.ts +109 -0
- package/dist/mcp/x402-tools.d.ts.map +1 -0
- package/dist/mcp/x402-tools.js +554 -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/client.d.ts +13 -0
- package/dist/sdk/client.d.ts.map +1 -1
- package/dist/sdk/client.js +15 -0
- package/dist/sdk/client.js.map +1 -1
- 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 +157 -0
- package/dist/x402-buyer/pay.d.ts.map +1 -0
- package/dist/x402-buyer/pay.js +366 -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 +40 -0
- package/dist/x402-opener/facilitator-entry.js.map +1 -0
- package/dist/x402-opener/facilitator-server.d.ts +209 -0
- package/dist/x402-opener/facilitator-server.d.ts.map +1 -0
- package/dist/x402-opener/facilitator-server.js +762 -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 +266 -0
- package/dist/x402-opener/refund-relay.d.ts.map +1 -0
- package/dist/x402-opener/refund-relay.js +1341 -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 +296 -0
- package/dist/x402-opener/scheme.d.ts.map +1 -0
- package/dist/x402-opener/scheme.js +1035 -0
- package/dist/x402-opener/scheme.js.map +1 -0
- package/dist/x402-opener/terms.d.ts +165 -0
- package/dist/x402-opener/terms.d.ts.map +1 -0
- package/dist/x402-opener/terms.js +304 -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 +265 -34
- package/docs/langchain.md +5 -0
- package/docs/mcp-reference.md +91 -5
- package/docs/probe-capability.md +191 -0
- package/docs/quickstart.md +39 -4
- package/docs/threat-model.md +20 -0
- package/docs/x402.md +766 -593
- 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 +168 -33
- 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 +584 -0
- package/src/cli/commands/reclaim-unverified.ts +8 -2
- package/src/cli/commands/reclaim.ts +277 -19
- package/src/cli/commands/refund.ts +475 -0
- package/src/cli/commands/status.ts +28 -2
- package/src/cli/commands/streams.ts +10 -14
- package/src/cli/commands/watch.ts +11 -1
- package/src/cli/config.ts +139 -52
- package/src/cli/context.ts +16 -0
- package/src/cli/deps.ts +111 -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/progress.ts +21 -2
- package/src/cli/reclaimability.ts +154 -0
- package/src/cli/run.ts +77 -21
- package/src/cli/scan-range.ts +2 -2
- package/src/cli/status.ts +454 -44
- package/src/cli/wallet.ts +45 -8
- 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 +717 -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 +1171 -0
- package/src/index.ts +82 -19
- package/src/mcp/server.ts +351 -42
- package/src/mcp/x402-tools.ts +785 -0
- package/src/network.ts +302 -0
- package/src/sdk/client.ts +25 -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 +555 -0
- package/src/x402-opener/abi.ts +881 -0
- package/src/x402-opener/facilitator-entry.ts +48 -0
- package/src/x402-opener/facilitator-server.ts +1114 -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 +1873 -0
- package/src/x402-opener/relayer-queue.ts +18 -0
- package/src/x402-opener/scheme.ts +1551 -0
- package/src/x402-opener/terms.ts +453 -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
package/docs/agent-layer.md
CHANGED
|
@@ -25,8 +25,9 @@ challenge/response and reuses the protocol's existing settlement path. (`src/x40
|
|
|
25
25
|
|
|
26
26
|
It is **not the x402 protocol**: its scheme string, challenge body, payload and
|
|
27
27
|
`X-METRIK-PAYMENT` header are all Metrik's own, and it does not interoperate with
|
|
28
|
-
`x402-fetch`, `x402-axios`, or `x402-express`.
|
|
29
|
-
|
|
28
|
+
`x402-fetch`, `x402-axios`, or `x402-express`. Standard x402 v2 `exact` payments are
|
|
29
|
+
handled by a separate, opt-in path — the opener facilitator and the gateway's x402 v2
|
|
30
|
+
mode — described in [docs/x402.md](./x402.md).
|
|
30
31
|
|
|
31
32
|
### 2. MCP server
|
|
32
33
|
|
|
@@ -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
|
|
|
@@ -311,8 +325,8 @@ claim cannot be true. Every rendering of it is labelled unverified, in human out
|
|
|
311
325
|
### `metrik open`
|
|
312
326
|
|
|
313
327
|
```bash
|
|
314
|
-
metrik open --service <serviceRef> --rate 0.
|
|
315
|
-
metrik open --service <serviceRef> --rate
|
|
328
|
+
metrik open --service <serviceRef> --rate 0.0001 --budget 0.36 --duration 1h
|
|
329
|
+
metrik open --service <serviceRef> --rate 100 --budget 360000 --duration 3600 --units atomic
|
|
316
330
|
metrik open ... --dry-run
|
|
317
331
|
```
|
|
318
332
|
|
|
@@ -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,
|
|
@@ -430,6 +459,21 @@ escrow that grace is 900 seconds and immutable. An operator who has earned but n
|
|
|
430
459
|
loses it at that moment, and the only defence is to `metrik claim` before it — which
|
|
431
460
|
requires knowing the deadline exists.
|
|
432
461
|
|
|
462
|
+
**A stream with nothing left for anyone reads as finished.** Once a stream has stopped
|
|
463
|
+
(closed, or past expiry) and the operator's claimed amount — or on V3 the proven
|
|
464
|
+
high-water — already covers the whole deposit, both buyer exits would revert
|
|
465
|
+
`NothingToReclaim`, so `reclaimed` stays `false` forever. `status` renders it the way it
|
|
466
|
+
renders a reclaimed stream: `buyer side finished`, the operator's settled / claimed /
|
|
467
|
+
unclaimed amounts, and none of the buyer-reclaimable, escape-hatch or deadline rows. The
|
|
468
|
+
JSON sets `buyerSideFinished: true` and `finalSettlement.finishedBy: "deposit-exhausted"`
|
|
469
|
+
(`"reclaimed"` for a reclaimed stream). An unreadable proven high-water never makes a
|
|
470
|
+
stream look finished.
|
|
471
|
+
|
|
472
|
+
**Proven value is stated from chain.** On V3, when the latest checkpoint no longer contains
|
|
473
|
+
the stream but `provenCumulativeOf` is non-zero, `verified accrual` states that proven
|
|
474
|
+
amount (read from the escrow) instead of "not checkpointed yet", and `operator claimable`
|
|
475
|
+
is what `claimProven` would pay (`claimableSource: "proven-on-chain"` in the JSON).
|
|
476
|
+
|
|
433
477
|
StreamEscrowV2 has exactly two states, `active` and `closed`. There is no paused state
|
|
434
478
|
and the CLI never renders one.
|
|
435
479
|
|
|
@@ -520,7 +564,10 @@ Configured mandate ceilings are carried through verbatim — they are policy, no
|
|
|
520
564
|
and re-typing four caps from memory is where a wrong ceiling comes from. **Credentials are
|
|
521
565
|
always placeholders.** This command never reads a key out of your environment and prints
|
|
522
566
|
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).
|
|
567
|
+
variables if those are what you have set, `METRIK_AGENT_PRIVATE_KEY` otherwise). A Privy
|
|
568
|
+
wallet is **not** an option here — `parseAgentWalletEnv()` has no Privy branch — so when
|
|
569
|
+
the environment carries one the command says so on stderr and prints a key placeholder
|
|
570
|
+
instead of a config the server could not start from.
|
|
524
571
|
|
|
525
572
|
### `metrik invoke`
|
|
526
573
|
|
|
@@ -550,6 +597,136 @@ listings ("consumer-attested T2 invocation is not supported for gated listings")
|
|
|
550
597
|
live listings are gated — so a `metrik prove` would be a command that fails for almost
|
|
551
598
|
everyone who ran it. It is left out until that constraint lifts.
|
|
552
599
|
|
|
600
|
+
### `metrik pay` (x402)
|
|
601
|
+
|
|
602
|
+
```bash
|
|
603
|
+
metrik pay https://x402.example/transform --json '{"text":"# hi"}' --max-amount 0.1
|
|
604
|
+
metrik pay <url> [--json <body> | --data <body>] [--method POST] [--header "K: V"] \
|
|
605
|
+
--max-amount <usdc> [--max-rate <usdc/s>] [--max-upfront <usdc>] [--max-duration <s>] \
|
|
606
|
+
[--min-duration <s>] [--operator <address>] [--units atomic]
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
Pays any **x402 v2 `exact`** endpoint through `@absol-labs/sdk/x402`'s `payWithX402`,
|
|
610
|
+
with every SDK protection intact (network and USDC from the registry, EIP-3009 only,
|
|
611
|
+
registered opener factory, `payTo == factory.predict(terms)` read on-chain, bounded
|
|
612
|
+
authorization lifetime, a plain transfer to the seller refused). A Metrik seller's
|
|
613
|
+
payment opens an escrow stream with `deposit = price`; the seller earns
|
|
614
|
+
`ratePerSecond x verified seconds`, capped at the deposit.
|
|
615
|
+
|
|
616
|
+
**Upfront ("minimum charge") quotes.** A seller may instead quote the upfront opener:
|
|
617
|
+
the price splits into a **non-refundable** per-call charge (`upfrontAmount`, paid to the
|
|
618
|
+
seller at settlement whatever is delivered) and a **refundable**, metered part (`price -
|
|
619
|
+
upfrontAmount`, escrowed as above — the most any refund can return). `metrik pay` prints
|
|
620
|
+
the split before it signs (`quote: … = … NON-REFUNDABLE per-call charge + … metered and
|
|
621
|
+
refundable`) and again in the result (`non-refundable` / `refundable` rows; JSON
|
|
622
|
+
`openerKind`, `price`, `upfrontAmount`, `refundableAmount`, `upfrontFee`, `upfrontOnly`).
|
|
623
|
+
`--max-upfront <usdc>` caps the non-refundable part (the SDK's `maxUpfrontAmount`;
|
|
624
|
+
default 0.10 USDC, `0` refuses any upfront charge, never above the price ceiling). When
|
|
625
|
+
`upfrontAmount == price` no stream opens: the payment is **final**, `streamId` is
|
|
626
|
+
`null`, and no refund or reclaim command is printed, because there is nothing to
|
|
627
|
+
refund.
|
|
628
|
+
|
|
629
|
+
The payer needs **USDC only, no gas** (the facilitator's relayer submits the
|
|
630
|
+
authorization). A Privy wallet cannot pay: its broker does not sign EIP-3009.
|
|
631
|
+
|
|
632
|
+
**How the spend mandate bounds an x402 payment.** No spend without a mandate: a
|
|
633
|
+
payment IS a stream open, so its opener terms are checked by `checkMandate()` exactly
|
|
634
|
+
like `metrik open`, inside the SDK's `onQuote` hook, after the SDK's own checks and
|
|
635
|
+
**before anything is signed**:
|
|
636
|
+
|
|
637
|
+
| Mandate cap | Checked against |
|
|
638
|
+
| ---------------------- | ---------------------------------------------- |
|
|
639
|
+
| `maxPerStreamUsdc` | the quote's `amount` (the whole price) |
|
|
640
|
+
| `maxTotalUsdc` | spent so far + `amount` |
|
|
641
|
+
| `maxRatePerSecondUsdc` | `ratePerSecond` (how fast the seller can earn) |
|
|
642
|
+
| `maxDurationSeconds` | `maxDuration` (the stream window) |
|
|
643
|
+
| `allowedOperators` | `operator` (who the stream pays) |
|
|
644
|
+
|
|
645
|
+
The caps are also handed to the SDK as `maxAmount` / `maxRatePerSecond`, so the price is
|
|
646
|
+
enforced twice. A quote with no opener terms is refused. The mandate comes from
|
|
647
|
+
`METRIK_AGENT_MANDATE_*` when set, otherwise it is sized to this command:
|
|
648
|
+
`--max-amount` (required then) is the per-stream and total cap, `--max-rate` the rate cap
|
|
649
|
+
(default: no tighter than the price), `--max-duration` the window cap (default 1 day),
|
|
650
|
+
`--operator` the only allowed operator. With a standing mandate, every flag
|
|
651
|
+
**intersects** it (the most restrictive value wins; an `--operator` outside
|
|
652
|
+
`METRIK_AGENT_MANDATE_ALLOWED_OPERATORS` is refused): a flag can tighten the
|
|
653
|
+
standing ceiling, never loosen or bypass it. Like every CLI mandate it covers one
|
|
654
|
+
invocation.
|
|
655
|
+
|
|
656
|
+
If anything fails after the authorization was handed to the seller, `metrik pay`
|
|
657
|
+
establishes the outcome on-chain (USDC `authorizationState`, the opener's
|
|
658
|
+
`StreamOpenedFor` log for that nonce), exits `4`, and says whether the money left
|
|
659
|
+
the payer — with the `streamId` and the recovery command when the stream is found.
|
|
660
|
+
It never reports "nothing moved" unless the authorization was unused and expired.
|
|
661
|
+
For an upfront-only payment it says the money left the payer as a final, non-refundable
|
|
662
|
+
charge with nothing to recover.
|
|
663
|
+
|
|
664
|
+
A quote naming a **legacy** deployment's factory (for example a seller still on
|
|
665
|
+
StreamEscrowV2 after the default moved to V3) is refused by the SDK unless you pass
|
|
666
|
+
`--allow-legacy-factory`; that stream is then closed and reclaimed on the legacy
|
|
667
|
+
escrow, and the printed recovery command carries `--escrow <legacy escrow>`.
|
|
668
|
+
|
|
669
|
+
`--json <body>` is the request body (curl-style, sets `content-type: application/json`);
|
|
670
|
+
`--json-body <body>` is accepted as an alias (give the body once, with either). A bare
|
|
671
|
+
`--json` still selects JSON output, and both can be combined. The output is the
|
|
672
|
+
response, the `streamId`, the opener, the deposit and rate, `minEarnSeconds` (after how
|
|
673
|
+
many verified seconds nothing is left to reclaim) and the **refund URL**. When the
|
|
674
|
+
facilitator's `PAYMENT-RESPONSE` header (relayed by the seller) carries the settlement
|
|
675
|
+
transaction hash, it is printed as `settlement tx` and returned as
|
|
676
|
+
`settlementTransaction` with `settlementTransactionSource: "PAYMENT-RESPONSE"`: the
|
|
677
|
+
facilitator's relayer broadcast it, not the payer, and the CLI reports it as given.
|
|
678
|
+
**Refunds are not automatic** — see `metrik refund`.
|
|
679
|
+
|
|
680
|
+
Exit codes: `2` usage (including no ceiling), `3` refused by the mandate or the SDK
|
|
681
|
+
(nothing signed, including an upfront part above `--max-upfront`), `4` the settlement failed after signing (the error says whether the
|
|
682
|
+
authorization was used and how to cancel it; see [x402.md](./x402.md)).
|
|
683
|
+
|
|
684
|
+
### `metrik refund`
|
|
685
|
+
|
|
686
|
+
```bash
|
|
687
|
+
metrik refund <streamId> --refund-url <url> [--close] [--reclaim] [--attempts 5] [--max-wait 60]
|
|
688
|
+
```
|
|
689
|
+
|
|
690
|
+
Drives the seller's **gasless refund relay** through the SDK's `refundClient`, bound to
|
|
691
|
+
the stream and to the opener read **from chain** (`factory.isOpener`), never from the
|
|
692
|
+
relay. With no action flag it prints the status and the next step. `--close` signs the
|
|
693
|
+
opener's EIP-712 `Close` as the payer (the relay pays the gas; authorized on the mandate
|
|
694
|
+
owner's signature only, like `metrik close`). `--reclaim` sends the permissionless
|
|
695
|
+
`opener.reclaim` (no wallet needed; the refund always goes to `payerOf(streamId)`) and
|
|
696
|
+
retries a bounded number of times while the settlement window is open, honouring
|
|
697
|
+
`Retry-After`; a longer wait exits `3` with the time to retry. Every relay "success" is
|
|
698
|
+
checked against the transaction receipt on the configured chain. `--refund-url` accepts
|
|
699
|
+
the full URL `metrik pay` printed, a `{streamId}` template or the relay's origin; it can
|
|
700
|
+
also come from `METRIK_AGENT_REFUND_URL`.
|
|
701
|
+
|
|
702
|
+
`--close` needs the key that paid, and nothing else: it signs an off-chain EIP-712
|
|
703
|
+
`Close` message, so the key needs no ETH or USDC. It is skipped (nothing signed, no
|
|
704
|
+
wallet read) when the relay reports the stream already closed.
|
|
705
|
+
|
|
706
|
+
**An upfront-only payment has nothing to refund.** `metrik refund 0x000…000` (stream id
|
|
707
|
+
0, what an upfront-only payment amounts to) prints "Nothing to refund" and exits `0`
|
|
708
|
+
without reading the chain, contacting a relay or signing anything; the JSON carries
|
|
709
|
+
`finished: true`, `finishedReason: "upfront-only"`, `nothingToRefund: true`. For a
|
|
710
|
+
partial-upfront payment the stream is refunded as usual, but only its deposit (`price -
|
|
711
|
+
upfrontAmount`) can come back.
|
|
712
|
+
|
|
713
|
+
**A finished recovery exits `0`.** When the stream is already closed and reclaimed, or
|
|
714
|
+
the relay reports nothing to reclaim (`409 nothing-to-reclaim`: the verified delivery
|
|
715
|
+
covers the whole deposit), `refund` says "Already finished … nothing to recover" and
|
|
716
|
+
exits `0`; the JSON carries `finished: true`, `finishedReason` (`reclaimed` or
|
|
717
|
+
`nothing-to-reclaim`), `nothingToRecover: true`, and `closeSkipped` / `reclaimSkipped`
|
|
718
|
+
naming why a requested step sent nothing. It never suggests a gas-spending recovery when
|
|
719
|
+
nothing is recoverable. Real failures (relay down, settlement window still open, wrong
|
|
720
|
+
payer) still exit `3`.
|
|
721
|
+
|
|
722
|
+
Nothing is refunded automatically, and the relay is a convenience: a payer can always
|
|
723
|
+
recover on-chain without it (`metrik close` as the payer, with gas; `metrik reclaim` by
|
|
724
|
+
anyone).
|
|
725
|
+
|
|
726
|
+
`status`, `close` and `reclaim` understand opener-bought streams: they show the opener and the
|
|
727
|
+
payer, `close` routes through the opener (payer only), and `reclaim` sends the
|
|
728
|
+
permissionless opener reclaim and reports the refund to the payer.
|
|
729
|
+
|
|
553
730
|
### `metrik close` and `metrik reclaim`
|
|
554
731
|
|
|
555
732
|
```bash
|
|
@@ -563,12 +740,37 @@ returns the unspent budget, and the buyer sends it. `close` now points at
|
|
|
563
740
|
`--close-first` for next time, rather than leaving the one-shot form visible only in
|
|
564
741
|
`metrik reclaim --help`.
|
|
565
742
|
|
|
743
|
+
**`reclaim` names the condition before it spends anything.** Three different on-chain
|
|
744
|
+
states stop a reclaim, and they have three completely different answers: the stream was
|
|
745
|
+
already reclaimed (you have the money), the stream is still running (close it first), or
|
|
746
|
+
its stop time is not checkpointed yet (wait ~20 seconds). The CLI reads `getStream`,
|
|
747
|
+
`latestCheckpointCheckedAt` and the chain clock up front and says which one it is, rather
|
|
748
|
+
than sending a simulation and repeating whatever the endpoint's revert data decoded to —
|
|
749
|
+
on the public Base Sepolia RPC all three came back as `Execution reverted for an unknown
|
|
750
|
+
reason`. The pre-flight **fails open**: a read that does not answer never blocks the
|
|
751
|
+
reclaim, because refusing to return a buyer's deposit over a dropped view call is worse
|
|
752
|
+
than a wasted simulation.
|
|
753
|
+
|
|
754
|
+
**What `reclaim` prints for the operator.** The `operator entitled` row is the amount
|
|
755
|
+
the reclaim fixed as the operator's. No USDC moves to the operator at reclaim: the
|
|
756
|
+
operator claims it separately with `metrik claim`, and the protocol fee is taken at that
|
|
757
|
+
claim. `--json` keeps the field name `settledCumulative`.
|
|
758
|
+
|
|
566
759
|
**`reclaim` waits, by design.** `reclaimWithProof` reverts with `SettlementWindowOpen`
|
|
567
760
|
until a checkpoint whose `checkedAt` is at or after the stream's stop time has posted.
|
|
568
761
|
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
|
-
|
|
762
|
+
attempt fails and one roughly 30 seconds later succeeds. The CLI retries on a bounded
|
|
763
|
+
schedule and narrates the wait on stderr; every other failure is surfaced immediately and
|
|
764
|
+
unretried.
|
|
765
|
+
|
|
766
|
+
The wait shows up in three shapes, and all three retry: the escrow's decoded
|
|
767
|
+
`SettlementWindowOpen`; the **oracle** refusing a proof for a stream it has not
|
|
768
|
+
checkpointed yet (the SDK fetches the proof before it simulates, so the escrow's revert
|
|
769
|
+
never happens and the error is `StreamNotInCheckpointError` / `CheckpointNotReadyError`);
|
|
770
|
+
and a reclaim revert the ABI could not decode, where the chain's state is read to decide.
|
|
771
|
+
Only recognising the first of those is what made `--close-first` die on its first attempt
|
|
772
|
+
against a stream closed before its first covering checkpoint — the ordinary result of a
|
|
773
|
+
short trial run.
|
|
572
774
|
|
|
573
775
|
If it is still blocked when the budget runs out, the message does **not** just say "retry
|
|
574
776
|
later" — every attempt this command makes needs a proof from the oracle, so when the
|
|
@@ -584,8 +786,10 @@ lands on another that has not imported the block.) If the stream is **already**
|
|
|
584
786
|
the close is skipped and the command goes straight to reclaim — so re-running it is always
|
|
585
787
|
safe and never dead-ends on `StreamClosedAlready()`.
|
|
586
788
|
|
|
587
|
-
`
|
|
588
|
-
|
|
789
|
+
`--close-first` is also the one caller allowed past the still-running refusal, since
|
|
790
|
+
clearing that state is the whole point of the flag. Once the close has landed it reports
|
|
791
|
+
what the following retries are waiting for — the stop time, and how far the oracle has
|
|
792
|
+
published — so the wait reads as the advertised wait rather than as a stalled command.
|
|
589
793
|
|
|
590
794
|
Close and reclaim are buyer-recovery actions: `VerifiedStreamAgentClient` authorizes them
|
|
591
795
|
on the mandate owner's signature alone, never on caps or expiry, so a lapsed mandate can
|
|
@@ -608,6 +812,21 @@ learn a fact that was already free. Same for a missing checkpoint: accrual lives
|
|
|
608
812
|
oracle's proof, never in the stream tuple, so no proof means no claim is possible yet and
|
|
609
813
|
the command says that instead of paying for `NothingToClaim()`.
|
|
610
814
|
|
|
815
|
+
**On StreamEscrowV3 it falls back to `claimProven` automatically.** The escrow keeps a
|
|
816
|
+
proven high-water (`provenCumulativeOf`) for every stream, and `claimProven` pays
|
|
817
|
+
`provenCumulative − claimedCumulative` (net of the fee) with no proof. That is the only
|
|
818
|
+
way to collect proven value whose checkpoint root has rotated out of the retained set (or
|
|
819
|
+
that a later root regressed below). `claim` asks the escrow what each path would pay
|
|
820
|
+
(`claimableFor` at the current proof's cumulative, and at the proven high-water), sends the
|
|
821
|
+
larger, and prefers `claimWithProof` on a tie because it also raises the high-water. When
|
|
822
|
+
both pay zero it exits `4` without broadcasting — "nothing to claim" when everything proven
|
|
823
|
+
is already claimed. The JSON names the path in `method` (`claimWithProof` / `claimProven`)
|
|
824
|
+
and adds `provenCumulative`; `verifiedCumulative` is `null` when there was no current proof.
|
|
825
|
+
There is no flag: `claimProven` pays only an amount already proven against a signed root
|
|
826
|
+
and recorded on-chain, to the same operator, under the same mandate check, so it can never
|
|
827
|
+
pay more than a proof claim could have — and an opt-in would leave a seller reading "nothing
|
|
828
|
+
provable" while their proven earnings sat stranded.
|
|
829
|
+
|
|
611
830
|
### `metrik reclaim-unverified`
|
|
612
831
|
|
|
613
832
|
```bash
|
|
@@ -672,7 +891,10 @@ wallet, mandate denied), `4` the operation failed.
|
|
|
672
891
|
and the oracle fetch — an HTTP call the RPC transport does not cover — has its own 20s
|
|
673
892
|
budget that names the endpoint when it expires. Any command still working after 8 seconds
|
|
674
893
|
starts a heartbeat on stderr with the elapsed time, repeating every 10s, because with no
|
|
675
|
-
output at all a slow endpoint and a wedged process are indistinguishable.
|
|
894
|
+
output at all a slow endpoint and a wedged process are indistinguishable. While a command
|
|
895
|
+
is in a deliberate, announced wait — `reclaim` retrying until the oracle's next checkpoint
|
|
896
|
+
(`attempt n/N`), `refund` letting the relay wait out the settlement window, `watch`
|
|
897
|
+
polling — the heartbeat names that wait instead of blaming a slow RPC. The heartbeat is
|
|
676
898
|
stderr in both modes, so `--json` stdout stays a single parseable document.
|
|
677
899
|
|
|
678
900
|
Read paths time out; **broadcasts do not.** A transaction that has been sent may already be
|
|
@@ -682,17 +904,26 @@ that wait legible.
|
|
|
682
904
|
|
|
683
905
|
## Settlement configuration
|
|
684
906
|
|
|
685
|
-
Everything defaults to
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
|
690
|
-
|
|
|
691
|
-
| `--
|
|
692
|
-
| `--
|
|
693
|
-
| `--
|
|
694
|
-
| `--
|
|
695
|
-
| `--
|
|
907
|
+
Everything defaults to the selected network's entry in the `@absol-labs/sdk` network
|
|
908
|
+
registry (the default network is Base Sepolia), and every value is overridable per
|
|
909
|
+
command or through the environment. Nothing chain-specific is hardcoded in the CLI.
|
|
910
|
+
|
|
911
|
+
| Flag | Env | Default |
|
|
912
|
+
| --------------------- | -------------------------------- | ---------------------------------------------------------------------- |
|
|
913
|
+
| `--network` | `METRIK_NETWORK` | the registry default (id, chain id or CAIP-2) |
|
|
914
|
+
| `--chain-id` | `METRIK_AGENT_CHAIN_ID` | the network's chain id (must agree if both set) |
|
|
915
|
+
| `--rpc-url` | `METRIK_AGENT_RPC_URL` | the network's first registered RPC |
|
|
916
|
+
| `--escrow` | `METRIK_AGENT_ESCROW` | the network's current escrow (V3); a `legacy` one (V2) for its streams |
|
|
917
|
+
| `--escrow-generation` | `METRIK_AGENT_ESCROW_GENERATION` | the registry's; REQUIRED only for an unregistered escrow |
|
|
918
|
+
| `--usdc` | `METRIK_AGENT_USDC` | the network's registered USDC |
|
|
919
|
+
| `--oracle-url` | `METRIK_AGENT_ORACLE_URL` | the network's oracle |
|
|
920
|
+
| `--registry-url` | `METRIK_AGENT_REGISTRY_URL` | the network's public listings endpoint |
|
|
921
|
+
|
|
922
|
+
The gas preflight names the network's gas token and faucet (from its gas-token
|
|
923
|
+
metadata) instead of assuming ETH; on a network whose gas IS the settlement USDC it
|
|
924
|
+
checks the one USDC balance and requires the deposit to leave room for gas. An
|
|
925
|
+
`--escrow` the registry does not record has no log-scan anchor, so `metrik streams`
|
|
926
|
+
needs `--from-block` for it.
|
|
696
927
|
|
|
697
928
|
## Embedding it
|
|
698
929
|
|
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
|