@absol-labs/agent 0.10.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 +106 -30
- package/dist/capability/invocation-capability.d.ts +20 -8
- package/dist/capability/invocation-capability.d.ts.map +1 -1
- package/dist/capability/invocation-capability.js.map +1 -1
- 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.map +1 -1
- package/dist/cli/commands/claim.js +21 -5
- 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 +51 -7
- 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 +3 -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 +121 -15
- 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 +15 -6
- 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 +200 -21
- 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 +9 -13
- 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 +86 -7
- package/dist/cli/deps.d.ts.map +1 -1
- package/dist/cli/deps.js +102 -16
- 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 +83 -0
- package/dist/cli/privy.d.ts.map +1 -0
- package/dist/cli/privy.js +232 -0
- package/dist/cli/privy.js.map +1 -0
- 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/spend-policy.d.ts +60 -0
- package/dist/cli/spend-policy.d.ts.map +1 -0
- package/dist/cli/spend-policy.js +65 -0
- package/dist/cli/spend-policy.js.map +1 -0
- 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 +109 -40
- package/dist/cli/wallet.d.ts.map +1 -1
- package/dist/cli/wallet.js +109 -44
- 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 +91 -4
- package/dist/gateway/caller-auth-gateway.d.ts.map +1 -1
- package/dist/gateway/caller-auth-gateway.js +184 -7
- package/dist/gateway/caller-auth-gateway.js.map +1 -1
- package/dist/gateway/http-server.d.ts +121 -1
- package/dist/gateway/http-server.d.ts.map +1 -1
- package/dist/gateway/http-server.js +474 -5
- 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 +11 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -5
- package/dist/index.js.map +1 -1
- package/dist/mandates/env.d.ts +3 -2
- package/dist/mandates/env.d.ts.map +1 -1
- package/dist/mandates/env.js +3 -2
- package/dist/mandates/env.js.map +1 -1
- package/dist/mcp/server.d.ts +100 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +719 -39
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/service-invoker.d.ts +97 -0
- package/dist/mcp/service-invoker.d.ts.map +1 -0
- package/dist/mcp/service-invoker.js +167 -0
- package/dist/mcp/service-invoker.js.map +1 -0
- 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 +23 -4
- package/dist/sdk/invoke.d.ts.map +1 -1
- package/dist/sdk/invoke.js +71 -10
- 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 +42 -17
- package/dist/x402/facilitator.d.ts.map +1 -1
- package/dist/x402/facilitator.js +49 -33
- 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/docs/agent-layer.md +13 -8
- package/docs/autonomous-privy-wallet.md +188 -0
- package/docs/cli.md +342 -53
- package/docs/langchain.md +5 -0
- package/docs/mcp-hosted.md +4 -3
- package/docs/mcp-reference.md +245 -0
- package/docs/probe-capability.md +191 -0
- package/docs/quickstart.md +54 -5
- package/docs/threat-model.md +24 -3
- package/docs/x402.md +681 -0
- package/package.json +19 -6
- package/src/capability/invocation-capability.ts +17 -1
- package/src/capability/probe-capability.ts +355 -0
- package/src/cli/args.ts +29 -0
- package/src/cli/commands/claim.ts +31 -5
- package/src/cli/commands/close.ts +56 -7
- package/src/cli/commands/invoke.ts +6 -2
- package/src/cli/commands/mcp.ts +18 -2
- package/src/cli/commands/open.ts +151 -14
- package/src/cli/commands/pay.ts +442 -0
- package/src/cli/commands/reclaim-unverified.ts +24 -6
- package/src/cli/commands/reclaim.ts +274 -19
- package/src/cli/commands/refund.ts +277 -0
- package/src/cli/commands/status.ts +17 -1
- package/src/cli/commands/streams.ts +11 -15
- package/src/cli/commands/watch.ts +7 -1
- package/src/cli/config.ts +139 -52
- package/src/cli/deps.ts +189 -25
- 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 +398 -0
- 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/spend-policy.ts +139 -0
- package/src/cli/status.ts +14 -1
- package/src/cli/wallet.ts +189 -58
- 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 +336 -13
- package/src/gateway/http-server.ts +690 -7
- 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 +112 -14
- package/src/mandates/env.ts +3 -2
- package/src/mcp/server.ts +973 -44
- package/src/mcp/service-invoker.ts +285 -0
- package/src/mcp/x402-tools.ts +621 -0
- package/src/network.ts +302 -0
- package/src/sdk/invoke.ts +96 -17
- 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 +85 -46
- 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/src/cli/commands/mcp.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { booleanFlag, stringFlag } from "../args.js";
|
|
2
2
|
import { packageVersion } from "../version.js";
|
|
3
|
-
import { CDP_ENV_VARS, PRIVATE_KEY_ENV } from "../wallet.js";
|
|
3
|
+
import { CDP_ENV_VARS, PRIVATE_KEY_ENV, PRIVY_ENV_VARS } from "../wallet.js";
|
|
4
4
|
import type { CommandContext, CommandSpec } from "../context.js";
|
|
5
5
|
|
|
6
6
|
/** The published executable an MCP host starts. Declared in `package.json#bin`. */
|
|
@@ -82,6 +82,17 @@ export const mcpCommand: CommandSpec = {
|
|
|
82
82
|
},
|
|
83
83
|
};
|
|
84
84
|
|
|
85
|
+
// Honesty about the one wallet source this block cannot carry. The CLI
|
|
86
|
+
// resolves a Privy wallet (step 3), but the MCP server's own resolver,
|
|
87
|
+
// `parseAgentWalletEnv()`, reads a raw key or CDP and nothing else — there
|
|
88
|
+
// is no Privy path from the environment there. Printing Privy variables
|
|
89
|
+
// into a config the server would ignore is the failure this says out loud.
|
|
90
|
+
if (PRIVY_ENV_VARS.some((variable) => (env[variable] ?? "").length > 0)) {
|
|
91
|
+
out.note(
|
|
92
|
+
`note: this environment configures a Privy wallet, which the CLI can use but \`${MCP_BIN}\` cannot — its wallet resolver reads ${PRIVATE_KEY_ENV} or the CDP variables only. The block below therefore carries a key placeholder; give the MCP server a raw key or a CDP account.`,
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
85
96
|
out.result(document);
|
|
86
97
|
out.print(
|
|
87
98
|
`Paste this into your MCP client's config (Claude Desktop: claude_desktop_config.json), then replace every <…> placeholder:`,
|
|
@@ -102,6 +113,11 @@ export const mcpCommand: CommandSpec = {
|
|
|
102
113
|
* Wallet variables, shaped to match how the environment running this command is
|
|
103
114
|
* already configured — CDP if that is what is set, a raw key otherwise.
|
|
104
115
|
*
|
|
116
|
+
* Privy is deliberately absent: `parseAgentWalletEnv()`, which is what the MCP
|
|
117
|
+
* server resolves its wallet with, has no Privy branch. A Privy block here
|
|
118
|
+
* would print a config that cannot start the server. The command says so on
|
|
119
|
+
* stderr instead.
|
|
120
|
+
*
|
|
105
121
|
* Values are ALWAYS placeholders. `metrik` prints derived addresses and never
|
|
106
122
|
* echoes a credential, and a config block is the single most likely thing to be
|
|
107
123
|
* pasted into a chat window or an issue.
|
|
@@ -116,7 +132,7 @@ function walletEnv(env: NodeJS.ProcessEnv): Record<string, string> {
|
|
|
116
132
|
);
|
|
117
133
|
}
|
|
118
134
|
return {
|
|
119
|
-
[PRIVATE_KEY_ENV]: "<0x… a funded
|
|
135
|
+
[PRIVATE_KEY_ENV]: "<0x… a funded testnet key>",
|
|
120
136
|
};
|
|
121
137
|
}
|
|
122
138
|
|
package/src/cli/commands/open.ts
CHANGED
|
@@ -8,15 +8,27 @@ import {
|
|
|
8
8
|
parseUsdcAmount,
|
|
9
9
|
} from "../amounts.js";
|
|
10
10
|
import { assertTestnetRpc, parseBytes32 } from "../config.js";
|
|
11
|
+
import { writeClientOptions } from "../deps.js";
|
|
11
12
|
import { CliError, configError } from "../errors.js";
|
|
13
|
+
import type { PrivySpendPolicy } from "../privy.js";
|
|
14
|
+
import {
|
|
15
|
+
assertWithinOperatorCaps,
|
|
16
|
+
assertWithinSpendPolicy,
|
|
17
|
+
} from "../spend-policy.js";
|
|
12
18
|
import { cliMandateCaps, signCliMandate } from "../mandate.js";
|
|
13
19
|
import { assertCanFundStream, assertCanPayGas } from "../preflight.js";
|
|
14
20
|
import {
|
|
21
|
+
isPolicyEnforced,
|
|
15
22
|
optionalCliWallet,
|
|
16
23
|
resolveCliWallet,
|
|
17
24
|
PRIVATE_KEY_ENV,
|
|
18
25
|
} from "../wallet.js";
|
|
19
|
-
import {
|
|
26
|
+
import { resolveListingRecord } from "../listings.js";
|
|
27
|
+
import {
|
|
28
|
+
listingRateBand,
|
|
29
|
+
rateBandRefusal,
|
|
30
|
+
SignedRateBoundsError,
|
|
31
|
+
} from "../../discovery/rate-band.js";
|
|
20
32
|
import type { CommandContext, CommandSpec } from "../context.js";
|
|
21
33
|
|
|
22
34
|
export const openCommand: CommandSpec = {
|
|
@@ -74,22 +86,29 @@ export const openCommand: CommandSpec = {
|
|
|
74
86
|
// the intended call and says which parts (allowance, simulation, mandate
|
|
75
87
|
// signature) could not be produced, rather than inventing them.
|
|
76
88
|
const wallet = dryRun
|
|
77
|
-
? await optionalCliWallet(env, { note: out.note })
|
|
78
|
-
: await resolveCliWallet(env, { note: out.note });
|
|
89
|
+
? await optionalCliWallet(env, { note: out.note, rpcUrl: config.rpcUrl })
|
|
90
|
+
: await resolveCliWallet(env, { note: out.note, rpcUrl: config.rpcUrl });
|
|
79
91
|
const account = wallet?.account ?? null;
|
|
80
92
|
const read = deps.createReadClient(config);
|
|
81
93
|
await assertTestnetRpc(config, () => read.getChainId());
|
|
82
94
|
if (account !== null && !dryRun) {
|
|
83
95
|
// Both balances, before anything is signed. Gas first: a wallet with no
|
|
84
96
|
// ETH cannot send the approval that the USDC check exists to protect.
|
|
85
|
-
await assertCanPayGas(read, account.address);
|
|
86
|
-
await assertCanFundStream(
|
|
97
|
+
await assertCanPayGas(read, account.address, config.network);
|
|
98
|
+
await assertCanFundStream(
|
|
99
|
+
read,
|
|
100
|
+
account.address,
|
|
101
|
+
budgetUsdc,
|
|
102
|
+
config.network,
|
|
103
|
+
);
|
|
87
104
|
}
|
|
88
105
|
|
|
89
106
|
const operatorOverride = stringFlag(args, "operator");
|
|
90
|
-
const
|
|
107
|
+
const resolution = await resolveListingRecord(context, serviceRef, {
|
|
91
108
|
required: operatorOverride === undefined,
|
|
92
109
|
});
|
|
110
|
+
const listing = resolution.listing;
|
|
111
|
+
await assertRateInSignedBand(context, resolution, ratePerSecondUsdc);
|
|
93
112
|
const operator = (operatorOverride ?? listing?.operator) as
|
|
94
113
|
| `0x${string}`
|
|
95
114
|
| undefined;
|
|
@@ -101,16 +120,41 @@ export const openCommand: CommandSpec = {
|
|
|
101
120
|
}
|
|
102
121
|
|
|
103
122
|
const spend = { operator, budgetUsdc, ratePerSecondUsdc, durationSeconds };
|
|
123
|
+
const mandateCaps = cliMandateCaps(spend, env);
|
|
124
|
+
|
|
125
|
+
// A policy-enforced wallet (Privy) is capped by its broker, not by a
|
|
126
|
+
// mandate this process signs for itself. Read the REAL ceiling and hold it
|
|
127
|
+
// to that instead — see `../spend-policy.ts` for why that substitution is
|
|
128
|
+
// the stronger of the two, and why re-adding the self-signed mandate here
|
|
129
|
+
// would both weaken it and break the wallet outright.
|
|
130
|
+
const policy: PrivySpendPolicy | null =
|
|
131
|
+
wallet !== null && isPolicyEnforced(wallet)
|
|
132
|
+
? await wallet.readSpendPolicy()
|
|
133
|
+
: null;
|
|
134
|
+
if (policy !== null && !dryRun) {
|
|
135
|
+
assertWithinSpendPolicy(policy, spend);
|
|
136
|
+
// The operator's own standing ceiling still applies, and may be TIGHTER
|
|
137
|
+
// than the broker's. Enforced here because no mandate is signed to carry
|
|
138
|
+
// it — "policy-enforced" retires the self-signed mandate, not the caps
|
|
139
|
+
// the operator deliberately configured.
|
|
140
|
+
if (mandateCaps.source === "env") {
|
|
141
|
+
assertWithinOperatorCaps(mandateCaps.caps, spend);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
104
145
|
const mandate =
|
|
105
|
-
account === null
|
|
146
|
+
account === null || policy !== null
|
|
106
147
|
? null
|
|
107
148
|
: await signCliMandate(account, spend, {
|
|
108
149
|
chainId: config.chainId,
|
|
109
150
|
env,
|
|
110
151
|
});
|
|
111
|
-
const mandateCaps = cliMandateCaps(spend, env);
|
|
112
152
|
|
|
113
|
-
const write = deps.createWriteClient(
|
|
153
|
+
const write = deps.createWriteClient(
|
|
154
|
+
config,
|
|
155
|
+
account,
|
|
156
|
+
writeClientOptions(wallet),
|
|
157
|
+
);
|
|
114
158
|
const hire = {
|
|
115
159
|
operator,
|
|
116
160
|
serviceRef,
|
|
@@ -145,6 +189,19 @@ export const openCommand: CommandSpec = {
|
|
|
145
189
|
durationSeconds,
|
|
146
190
|
mandateSource: mandateCaps.source,
|
|
147
191
|
mandateSigned: mandate !== null,
|
|
192
|
+
spendPolicy:
|
|
193
|
+
policy === null
|
|
194
|
+
? null
|
|
195
|
+
: {
|
|
196
|
+
brokerUrl: policy.brokerUrl,
|
|
197
|
+
maxTotalUsdc: policy.maxTotalUsdc,
|
|
198
|
+
maxRatePerSecondUsdc: policy.maxRatePerSecondUsdc,
|
|
199
|
+
maxDurationSeconds: policy.maxDurationSeconds,
|
|
200
|
+
fits:
|
|
201
|
+
budgetUsdc <= policy.maxTotalUsdc &&
|
|
202
|
+
ratePerSecondUsdc <= policy.maxRatePerSecondUsdc &&
|
|
203
|
+
durationSeconds <= policy.maxDurationSeconds,
|
|
204
|
+
},
|
|
148
205
|
to: preview.to,
|
|
149
206
|
data: preview.data,
|
|
150
207
|
chainId: preview.chainId,
|
|
@@ -180,10 +237,28 @@ export const openCommand: CommandSpec = {
|
|
|
180
237
|
["duration", formatDuration(durationSeconds)],
|
|
181
238
|
[
|
|
182
239
|
"mandate",
|
|
183
|
-
mandate
|
|
184
|
-
? `
|
|
185
|
-
:
|
|
240
|
+
mandate !== null
|
|
241
|
+
? `self-signed, caps from ${mandateCaps.source}`
|
|
242
|
+
: policy !== null
|
|
243
|
+
? "not signed — this wallet's ceiling is enforced by its broker, which is stronger"
|
|
244
|
+
: `not signed (no wallet); caps would come from ${mandateCaps.source}`,
|
|
186
245
|
],
|
|
246
|
+
...(policy === null
|
|
247
|
+
? []
|
|
248
|
+
: ([
|
|
249
|
+
[
|
|
250
|
+
"spend policy",
|
|
251
|
+
`${formatUsdc(policy.maxTotalUsdc)} total, ${policy.maxRatePerSecondUsdc} atomic/second, ${formatDuration(policy.maxDurationSeconds)} max — enforced by ${policy.brokerUrl}`,
|
|
252
|
+
],
|
|
253
|
+
[
|
|
254
|
+
"fits policy",
|
|
255
|
+
budgetUsdc <= policy.maxTotalUsdc &&
|
|
256
|
+
ratePerSecondUsdc <= policy.maxRatePerSecondUsdc &&
|
|
257
|
+
durationSeconds <= policy.maxDurationSeconds
|
|
258
|
+
? "yes"
|
|
259
|
+
: "NO — a real open would be refused before broadcasting",
|
|
260
|
+
],
|
|
261
|
+
] as [string, string][])),
|
|
187
262
|
["escrow", preview.to],
|
|
188
263
|
[
|
|
189
264
|
"usdc balance",
|
|
@@ -219,7 +294,7 @@ export const openCommand: CommandSpec = {
|
|
|
219
294
|
);
|
|
220
295
|
// Unreachable without a wallet: `resolveCliWallet` above throws when the
|
|
221
296
|
// command is not a dry run. The narrowing keeps that a type-level fact.
|
|
222
|
-
if (account === null
|
|
297
|
+
if (account === null) {
|
|
223
298
|
throw configError(
|
|
224
299
|
"this command signs a transaction and needs a wallet, and none was resolved",
|
|
225
300
|
);
|
|
@@ -233,7 +308,10 @@ export const openCommand: CommandSpec = {
|
|
|
233
308
|
budgetUsdc,
|
|
234
309
|
ratePerSecondUsdc,
|
|
235
310
|
maxDurationSeconds: durationSeconds,
|
|
236
|
-
|
|
311
|
+
// `null` for a policy-enforced wallet: the ceiling was checked against
|
|
312
|
+
// the broker's own policy above, and the broker checks it again on the
|
|
313
|
+
// transaction it signs.
|
|
314
|
+
signedMandate: mandate === null ? null : mandate.signed,
|
|
237
315
|
spentSoFarUsdc: 0n,
|
|
238
316
|
nowSeconds: deps.nowSeconds(),
|
|
239
317
|
});
|
|
@@ -282,6 +360,65 @@ export const openCommand: CommandSpec = {
|
|
|
282
360
|
},
|
|
283
361
|
};
|
|
284
362
|
|
|
363
|
+
/**
|
|
364
|
+
* Refuse a `--rate` outside the band the operator SIGNED, before anything is
|
|
365
|
+
* signed or broadcast — dry run included, because the rate is an invalid input
|
|
366
|
+
* for this service exactly like `--rate 0` is.
|
|
367
|
+
*
|
|
368
|
+
* The escrow accepts any non-zero rate; the seller's capability gateway does
|
|
369
|
+
* not, and answers every request on an out-of-band stream with
|
|
370
|
+
* `403 stream-rate-out-of-bounds`. Without this check the CLI locked a buyer's
|
|
371
|
+
* deposit in a stream that could never be served, and said nothing.
|
|
372
|
+
*
|
|
373
|
+
* - Listing found: its signed descriptor is re-verified and the band enforced.
|
|
374
|
+
* A descriptor that does not verify is a refusal (exit 4), never "no band".
|
|
375
|
+
* A legacy binding signs no commercial terms, so there is nothing to enforce.
|
|
376
|
+
* - No listing: only reachable with `--operator`, the CLI's existing,
|
|
377
|
+
* explicit escape hatch for a service the registry cannot vouch for. The
|
|
378
|
+
* check cannot run, so it is skipped LOUDLY rather than silently. Without
|
|
379
|
+
* `--operator` an unreachable registry or a missing listing has already
|
|
380
|
+
* failed the command before this point (`resolveListingRecord`).
|
|
381
|
+
*/
|
|
382
|
+
async function assertRateInSignedBand(
|
|
383
|
+
context: CommandContext,
|
|
384
|
+
resolution: Awaited<ReturnType<typeof resolveListingRecord>>,
|
|
385
|
+
ratePerSecondUsdc: bigint,
|
|
386
|
+
): Promise<void> {
|
|
387
|
+
const { out } = context;
|
|
388
|
+
if (resolution.record === null) {
|
|
389
|
+
out.note(
|
|
390
|
+
resolution.registryUnreachable
|
|
391
|
+
? "warning: the operator-signed rate band could NOT be checked because the registry is unreachable. If --rate is outside the band the operator signed, the service's gateway will refuse every request while the deposit stays escrowed. Re-run when the registry answers to have it checked."
|
|
392
|
+
: "note: this serviceRef has no verified listing, so there is no operator-signed rate band to check --rate against.",
|
|
393
|
+
);
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
let bounds;
|
|
397
|
+
try {
|
|
398
|
+
bounds = await listingRateBand(resolution.record);
|
|
399
|
+
} catch (error) {
|
|
400
|
+
if (error instanceof SignedRateBoundsError) {
|
|
401
|
+
throw new CliError(
|
|
402
|
+
`the listing's operator-signed rate band could not be verified: ${error.message}`,
|
|
403
|
+
{
|
|
404
|
+
exitCode: 4,
|
|
405
|
+
hint: "nothing was broadcast. The CLI will not open a stream against a rate band it cannot verify.",
|
|
406
|
+
cause: error,
|
|
407
|
+
},
|
|
408
|
+
);
|
|
409
|
+
}
|
|
410
|
+
throw error;
|
|
411
|
+
}
|
|
412
|
+
if (bounds === null) return;
|
|
413
|
+
const refusal = rateBandRefusal(ratePerSecondUsdc, bounds, "--rate");
|
|
414
|
+
if (refusal !== undefined) {
|
|
415
|
+
throw new CliError(refusal, {
|
|
416
|
+
exitCode: 2,
|
|
417
|
+
hint: "pick a --rate inside the signed band (`--units atomic` takes base units; see `metrik discover` for each listing's band).",
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
285
422
|
/**
|
|
286
423
|
* What the buyer is actually paying for.
|
|
287
424
|
*
|