@absol-labs/agent 0.9.1 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +184 -26
- package/dist/capability/invocation-capability.d.ts +18 -6
- package/dist/capability/invocation-capability.d.ts.map +1 -1
- package/dist/capability/invocation-capability.js.map +1 -1
- package/dist/cli/amounts.d.ts +26 -0
- package/dist/cli/amounts.d.ts.map +1 -0
- package/dist/cli/amounts.js +71 -0
- package/dist/cli/amounts.js.map +1 -0
- package/dist/cli/args.d.ts +32 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +119 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/attesters.d.ts +51 -0
- package/dist/cli/attesters.d.ts.map +1 -0
- package/dist/cli/attesters.js +58 -0
- package/dist/cli/attesters.js.map +1 -0
- package/dist/cli/bin.d.ts +3 -0
- package/dist/cli/bin.d.ts.map +1 -0
- package/dist/cli/bin.js +5 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/commands/claim.d.ts +13 -0
- package/dist/cli/commands/claim.d.ts.map +1 -0
- package/dist/cli/commands/claim.js +102 -0
- package/dist/cli/commands/claim.js.map +1 -0
- package/dist/cli/commands/close.d.ts +3 -0
- package/dist/cli/commands/close.d.ts.map +1 -0
- package/dist/cli/commands/close.js +55 -0
- package/dist/cli/commands/close.js.map +1 -0
- package/dist/cli/commands/discover.d.ts +3 -0
- package/dist/cli/commands/discover.d.ts.map +1 -0
- package/dist/cli/commands/discover.js +183 -0
- package/dist/cli/commands/discover.js.map +1 -0
- package/dist/cli/commands/invoke.d.ts +3 -0
- package/dist/cli/commands/invoke.d.ts.map +1 -0
- package/dist/cli/commands/invoke.js +142 -0
- package/dist/cli/commands/invoke.js.map +1 -0
- package/dist/cli/commands/mcp.d.ts +3 -0
- package/dist/cli/commands/mcp.d.ts.map +1 -0
- package/dist/cli/commands/mcp.js +113 -0
- package/dist/cli/commands/mcp.js.map +1 -0
- package/dist/cli/commands/open.d.ts +3 -0
- package/dist/cli/commands/open.d.ts.map +1 -0
- package/dist/cli/commands/open.js +331 -0
- package/dist/cli/commands/open.js.map +1 -0
- package/dist/cli/commands/reclaim-unverified.d.ts +3 -0
- package/dist/cli/commands/reclaim-unverified.d.ts.map +1 -0
- package/dist/cli/commands/reclaim-unverified.js +172 -0
- package/dist/cli/commands/reclaim-unverified.js.map +1 -0
- package/dist/cli/commands/reclaim.d.ts +33 -0
- package/dist/cli/commands/reclaim.d.ts.map +1 -0
- package/dist/cli/commands/reclaim.js +308 -0
- package/dist/cli/commands/reclaim.js.map +1 -0
- package/dist/cli/commands/status.d.ts +3 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +43 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/streams.d.ts +3 -0
- package/dist/cli/commands/streams.d.ts.map +1 -0
- package/dist/cli/commands/streams.js +257 -0
- package/dist/cli/commands/streams.js.map +1 -0
- package/dist/cli/commands/watch.d.ts +3 -0
- package/dist/cli/commands/watch.d.ts.map +1 -0
- package/dist/cli/commands/watch.js +55 -0
- package/dist/cli/commands/watch.js.map +1 -0
- package/dist/cli/config.d.ts +61 -0
- package/dist/cli/config.d.ts.map +1 -0
- package/dist/cli/config.js +140 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/context.d.ts +29 -0
- package/dist/cli/context.d.ts.map +1 -0
- package/dist/cli/context.js +2 -0
- package/dist/cli/context.js.map +1 -0
- package/dist/cli/deps.d.ts +191 -0
- package/dist/cli/deps.d.ts.map +1 -0
- package/dist/cli/deps.js +277 -0
- package/dist/cli/deps.js.map +1 -0
- package/dist/cli/descriptor.d.ts +61 -0
- package/dist/cli/descriptor.d.ts.map +1 -0
- package/dist/cli/descriptor.js +78 -0
- package/dist/cli/descriptor.js.map +1 -0
- package/dist/cli/errors.d.ts +48 -0
- package/dist/cli/errors.d.ts.map +1 -0
- package/dist/cli/errors.js +129 -0
- package/dist/cli/errors.js.map +1 -0
- package/dist/cli/escape-hatch.d.ts +50 -0
- package/dist/cli/escape-hatch.d.ts.map +1 -0
- package/dist/cli/escape-hatch.js +45 -0
- package/dist/cli/escape-hatch.js.map +1 -0
- package/dist/cli/index.d.ts +8 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +7 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/listings.d.ts +15 -0
- package/dist/cli/listings.d.ts.map +1 -0
- package/dist/cli/listings.js +56 -0
- package/dist/cli/listings.js.map +1 -0
- package/dist/cli/mandate.d.ts +66 -0
- package/dist/cli/mandate.d.ts.map +1 -0
- package/dist/cli/mandate.js +61 -0
- package/dist/cli/mandate.js.map +1 -0
- package/dist/cli/output.d.ts +33 -0
- package/dist/cli/output.d.ts.map +1 -0
- package/dist/cli/output.js +34 -0
- package/dist/cli/output.js.map +1 -0
- package/dist/cli/preflight.d.ts +38 -0
- package/dist/cli/preflight.d.ts.map +1 -0
- package/dist/cli/preflight.js +72 -0
- package/dist/cli/preflight.js.map +1 -0
- package/dist/cli/privy.d.ts +83 -0
- package/dist/cli/privy.d.ts.map +1 -0
- package/dist/cli/privy.js +230 -0
- package/dist/cli/privy.js.map +1 -0
- package/dist/cli/progress.d.ts +36 -0
- package/dist/cli/progress.d.ts.map +1 -0
- package/dist/cli/progress.js +40 -0
- package/dist/cli/progress.js.map +1 -0
- package/dist/cli/run.d.ts +25 -0
- package/dist/cli/run.d.ts.map +1 -0
- package/dist/cli/run.js +173 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/cli/scan-range.d.ts +55 -0
- package/dist/cli/scan-range.d.ts.map +1 -0
- package/dist/cli/scan-range.js +57 -0
- package/dist/cli/scan-range.js.map +1 -0
- 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 +90 -0
- package/dist/cli/status.d.ts.map +1 -0
- package/dist/cli/status.js +252 -0
- package/dist/cli/status.js.map +1 -0
- package/dist/cli/timeout.d.ts +30 -0
- package/dist/cli/timeout.d.ts.map +1 -0
- package/dist/cli/timeout.js +55 -0
- package/dist/cli/timeout.js.map +1 -0
- package/dist/cli/version.d.ts +12 -0
- package/dist/cli/version.d.ts.map +1 -0
- package/dist/cli/version.js +22 -0
- package/dist/cli/version.js.map +1 -0
- package/dist/cli/wallet.d.ts +164 -0
- package/dist/cli/wallet.d.ts.map +1 -0
- package/dist/cli/wallet.js +234 -0
- package/dist/cli/wallet.js.map +1 -0
- package/dist/frameworks/crewai.d.ts +10 -0
- package/dist/frameworks/crewai.d.ts.map +1 -1
- package/dist/frameworks/crewai.js +12 -2
- package/dist/frameworks/crewai.js.map +1 -1
- package/dist/gateway/caller-auth-gateway.d.ts +38 -3
- package/dist/gateway/caller-auth-gateway.d.ts.map +1 -1
- package/dist/gateway/caller-auth-gateway.js +25 -1
- package/dist/gateway/caller-auth-gateway.js.map +1 -1
- package/dist/gateway/http-server.d.ts +53 -0
- package/dist/gateway/http-server.d.ts.map +1 -1
- package/dist/gateway/http-server.js +189 -4
- package/dist/gateway/http-server.js.map +1 -1
- package/dist/gateway/server-entry.d.ts +1 -0
- package/dist/gateway/server-entry.js +1 -0
- package/dist/gateway/server-entry.js.map +1 -1
- package/dist/gateway/x402-mode.d.ts +123 -0
- package/dist/gateway/x402-mode.d.ts.map +1 -0
- package/dist/gateway/x402-mode.js +212 -0
- package/dist/gateway/x402-mode.js.map +1 -0
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -3
- 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/http-server.d.ts +1 -0
- package/dist/mcp/http-server.js +1 -0
- package/dist/mcp/http-server.js.map +1 -1
- package/dist/mcp/server.d.ts +49 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +533 -25
- 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/stdio.d.ts +1 -0
- package/dist/mcp/stdio.js +1 -0
- package/dist/mcp/stdio.js.map +1 -1
- package/dist/sdk/client.d.ts +25 -1
- package/dist/sdk/client.d.ts.map +1 -1
- package/dist/sdk/client.js +20 -1
- package/dist/sdk/client.js.map +1 -1
- package/dist/sdk/invoke.d.ts +19 -4
- package/dist/sdk/invoke.d.ts.map +1 -1
- package/dist/sdk/invoke.js +69 -5
- package/dist/sdk/invoke.js.map +1 -1
- package/dist/x402/delivery-oracle.d.ts +108 -0
- package/dist/x402/delivery-oracle.d.ts.map +1 -0
- package/dist/x402/delivery-oracle.js +174 -0
- package/dist/x402/delivery-oracle.js.map +1 -0
- package/dist/x402/facilitator-server-entry.d.ts +3 -0
- package/dist/x402/facilitator-server-entry.d.ts.map +1 -0
- package/dist/x402/facilitator-server-entry.js +27 -0
- package/dist/x402/facilitator-server-entry.js.map +1 -0
- package/dist/x402/facilitator-server.d.ts +73 -0
- package/dist/x402/facilitator-server.d.ts.map +1 -0
- package/dist/x402/facilitator-server.js +305 -0
- package/dist/x402/facilitator-server.js.map +1 -0
- package/dist/x402/facilitator.d.ts +69 -17
- package/dist/x402/facilitator.d.ts.map +1 -1
- package/dist/x402/facilitator.js +76 -33
- package/dist/x402/facilitator.js.map +1 -1
- package/dist/x402/payment-requirements.d.ts +106 -0
- package/dist/x402/payment-requirements.d.ts.map +1 -0
- package/dist/x402/payment-requirements.js +138 -0
- package/dist/x402/payment-requirements.js.map +1 -0
- package/dist/x402/relayer.d.ts +41 -0
- package/dist/x402/relayer.d.ts.map +1 -0
- package/dist/x402/relayer.js +64 -0
- package/dist/x402/relayer.js.map +1 -0
- package/dist/x402/resource-index.d.ts +75 -0
- package/dist/x402/resource-index.d.ts.map +1 -0
- package/dist/x402/resource-index.js +126 -0
- package/dist/x402/resource-index.js.map +1 -0
- package/dist/x402/verified-delivery-facilitator.d.ts +285 -0
- package/dist/x402/verified-delivery-facilitator.d.ts.map +1 -0
- package/dist/x402/verified-delivery-facilitator.js +423 -0
- package/dist/x402/verified-delivery-facilitator.js.map +1 -0
- package/dist/zktls/t2-delivery-proof.d.ts +6 -6
- package/docs/agent-layer.md +14 -9
- package/docs/cli.md +705 -0
- package/docs/crewai.md +6 -2
- package/docs/eliza.md +6 -1
- package/docs/mcp-hosted.md +7 -5
- package/docs/mcp-reference.md +175 -0
- package/docs/quickstart.md +36 -9
- package/docs/threat-model.md +4 -3
- package/docs/x402.md +648 -0
- package/package.json +33 -10
- package/src/capability/invocation-capability.ts +17 -1
- package/src/cli/amounts.ts +102 -0
- package/src/cli/args.ts +150 -0
- package/src/cli/attesters.ts +86 -0
- package/src/cli/bin.ts +5 -0
- package/src/cli/commands/claim.ts +126 -0
- package/src/cli/commands/close.ts +69 -0
- package/src/cli/commands/discover.ts +228 -0
- package/src/cli/commands/invoke.ts +178 -0
- package/src/cli/commands/mcp.ts +135 -0
- package/src/cli/commands/open.ts +397 -0
- package/src/cli/commands/reclaim-unverified.ts +218 -0
- package/src/cli/commands/reclaim.ts +377 -0
- package/src/cli/commands/status.ts +56 -0
- package/src/cli/commands/streams.ts +344 -0
- package/src/cli/commands/watch.ts +70 -0
- package/src/cli/config.ts +208 -0
- package/src/cli/context.ts +30 -0
- package/src/cli/deps.ts +528 -0
- package/src/cli/descriptor.ts +133 -0
- package/src/cli/errors.ts +162 -0
- package/src/cli/escape-hatch.ts +92 -0
- package/src/cli/index.ts +27 -0
- package/src/cli/listings.ts +77 -0
- package/src/cli/mandate.ts +126 -0
- package/src/cli/output.ts +63 -0
- package/src/cli/preflight.ts +88 -0
- package/src/cli/privy.ts +396 -0
- package/src/cli/progress.ts +75 -0
- package/src/cli/run.ts +209 -0
- package/src/cli/scan-range.ts +76 -0
- package/src/cli/spend-policy.ts +139 -0
- package/src/cli/status.ts +381 -0
- package/src/cli/timeout.ts +64 -0
- package/src/cli/version.ts +21 -0
- package/src/cli/wallet.ts +372 -0
- package/src/frameworks/crewai.ts +13 -2
- package/src/gateway/caller-auth-gateway.ts +77 -6
- package/src/gateway/http-server.ts +280 -6
- package/src/gateway/server-entry.ts +1 -0
- package/src/gateway/x402-mode.ts +350 -0
- package/src/index.ts +40 -5
- package/src/mandates/env.ts +3 -2
- package/src/mcp/http-server.ts +1 -0
- package/src/mcp/server.ts +706 -30
- package/src/mcp/service-invoker.ts +285 -0
- package/src/mcp/stdio.ts +1 -0
- package/src/sdk/client.ts +33 -1
- package/src/sdk/invoke.ts +90 -12
- package/src/x402/delivery-oracle.ts +285 -0
- package/src/x402/facilitator-server-entry.ts +35 -0
- package/src/x402/facilitator-server.ts +445 -0
- package/src/x402/facilitator.ts +125 -46
- package/src/x402/payment-requirements.ts +231 -0
- package/src/x402/relayer.ts +122 -0
- package/src/x402/resource-index.ts +228 -0
- package/src/x402/verified-delivery-facilitator.ts +744 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { StreamV2 } from "@absol-labs/sdk";
|
|
2
|
+
import type { CliReadClient } from "./deps.js";
|
|
3
|
+
/**
|
|
4
|
+
* The buyer's no-proof escape hatch, as the CLI reasons about it.
|
|
5
|
+
*
|
|
6
|
+
* Every OTHER route the CLI has to a buyer's money goes through
|
|
7
|
+
* `reclaimWithProof`, which needs a Merkle proof fetched from the oracle. So the
|
|
8
|
+
* whole proof-based path is only as available as the oracle is.
|
|
9
|
+
* `StreamEscrowV2.reclaimUnverified` is the path that is not: buyer-only, no
|
|
10
|
+
* proof, no signer quorum, no guardian. It is gated on one thing —
|
|
11
|
+
*
|
|
12
|
+
* block.timestamp >= expiresAt + escapeGraceSeconds
|
|
13
|
+
*
|
|
14
|
+
* — and `escapeGraceSeconds` is a public immutable on the escrow, so readiness
|
|
15
|
+
* is fully computable before a single wei of gas is spent.
|
|
16
|
+
*
|
|
17
|
+
* Note which timestamp the escrow uses: `expiresAt`, NEVER `closedAt`. Closing a
|
|
18
|
+
* stream early does not bring the escape hatch forward, and the CLI must not
|
|
19
|
+
* imply that it does.
|
|
20
|
+
*/
|
|
21
|
+
export interface EscapeHatchWindow {
|
|
22
|
+
/** `escapeGraceSeconds` as read from the escrow. */
|
|
23
|
+
readonly graceSeconds: number;
|
|
24
|
+
/** The exact unix second at which `reclaimUnverified` stops reverting. */
|
|
25
|
+
readonly readyAt: number;
|
|
26
|
+
readonly ready: boolean;
|
|
27
|
+
/** Seconds left until `readyAt`; `0` once the window is open. */
|
|
28
|
+
readonly secondsRemaining: number;
|
|
29
|
+
}
|
|
30
|
+
export declare function escapeHatchWindow(stream: Pick<StreamV2, "expiresAt">, graceSeconds: number, nowSeconds: number): EscapeHatchWindow;
|
|
31
|
+
/** `2026-09-17T09:15:00.000Z (1789…)`, or `-` for an unset timestamp. */
|
|
32
|
+
export declare function formatTimestamp(seconds: number): string;
|
|
33
|
+
/** One line describing where the escape hatch stands, for humans. */
|
|
34
|
+
export declare function describeEscapeHatch(window: EscapeHatchWindow): string;
|
|
35
|
+
export interface ChainNow {
|
|
36
|
+
readonly seconds: number;
|
|
37
|
+
/** `local` means the chain would not answer and the caller's clock was used. */
|
|
38
|
+
readonly source: "chain" | "local";
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The time the ESCROW will compare against, not the time this machine thinks it
|
|
42
|
+
* is. `reclaimUnverified` reverts on `block.timestamp`, so a readiness answer
|
|
43
|
+
* computed from a skewed laptop clock could tell a buyer to spend gas on a
|
|
44
|
+
* guaranteed revert — or tell them to wait when the hatch is already open.
|
|
45
|
+
*
|
|
46
|
+
* A failed read is not fatal: the caller's clock is the fallback, and the
|
|
47
|
+
* `source` field is reported so the difference is never hidden.
|
|
48
|
+
*/
|
|
49
|
+
export declare function readChainNow(read: Pick<CliReadClient, "latestBlockTimestamp">, fallbackSeconds: number): Promise<ChainNow>;
|
|
50
|
+
//# sourceMappingURL=escape-hatch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"escape-hatch.d.ts","sourceRoot":"","sources":["../../src/cli/escape-hatch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAGhD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,iBAAiB;IAChC,oDAAoD;IACpD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,0EAA0E;IAC1E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,iEAAiE;IACjE,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;CACnC;AAED,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,EACnC,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GACjB,iBAAiB,CASnB;AAED,yEAAyE;AACzE,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGvD;AAED,qEAAqE;AACrE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAMrE;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,gFAAgF;IAChF,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC;CACpC;AAED;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,IAAI,CAAC,aAAa,EAAE,sBAAsB,CAAC,EACjD,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,QAAQ,CAAC,CAUnB"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { formatDuration } from "./amounts.js";
|
|
2
|
+
export function escapeHatchWindow(stream, graceSeconds, nowSeconds) {
|
|
3
|
+
const readyAt = stream.expiresAt + graceSeconds;
|
|
4
|
+
const secondsRemaining = readyAt - nowSeconds;
|
|
5
|
+
return {
|
|
6
|
+
graceSeconds,
|
|
7
|
+
readyAt,
|
|
8
|
+
ready: secondsRemaining <= 0,
|
|
9
|
+
secondsRemaining: secondsRemaining > 0 ? secondsRemaining : 0,
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
/** `2026-09-17T09:15:00.000Z (1789…)`, or `-` for an unset timestamp. */
|
|
13
|
+
export function formatTimestamp(seconds) {
|
|
14
|
+
if (seconds <= 0)
|
|
15
|
+
return "-";
|
|
16
|
+
return `${new Date(seconds * 1000).toISOString()} (${seconds})`;
|
|
17
|
+
}
|
|
18
|
+
/** One line describing where the escape hatch stands, for humans. */
|
|
19
|
+
export function describeEscapeHatch(window) {
|
|
20
|
+
return window.ready
|
|
21
|
+
? `open since ${formatTimestamp(window.readyAt)}`
|
|
22
|
+
: `opens ${formatTimestamp(window.readyAt)} — in ${formatDuration(window.secondsRemaining)}`;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The time the ESCROW will compare against, not the time this machine thinks it
|
|
26
|
+
* is. `reclaimUnverified` reverts on `block.timestamp`, so a readiness answer
|
|
27
|
+
* computed from a skewed laptop clock could tell a buyer to spend gas on a
|
|
28
|
+
* guaranteed revert — or tell them to wait when the hatch is already open.
|
|
29
|
+
*
|
|
30
|
+
* A failed read is not fatal: the caller's clock is the fallback, and the
|
|
31
|
+
* `source` field is reported so the difference is never hidden.
|
|
32
|
+
*/
|
|
33
|
+
export async function readChainNow(read, fallbackSeconds) {
|
|
34
|
+
try {
|
|
35
|
+
const seconds = await read.latestBlockTimestamp();
|
|
36
|
+
if (Number.isFinite(seconds) && seconds > 0) {
|
|
37
|
+
return { seconds, source: "chain" };
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
// fall through to the caller's clock
|
|
42
|
+
}
|
|
43
|
+
return { seconds: fallbackSeconds, source: "local" };
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=escape-hatch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"escape-hatch.js","sourceRoot":"","sources":["../../src/cli/escape-hatch.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AA+B9C,MAAM,UAAU,iBAAiB,CAC/B,MAAmC,EACnC,YAAoB,EACpB,UAAkB;IAElB,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,GAAG,YAAY,CAAC;IAChD,MAAM,gBAAgB,GAAG,OAAO,GAAG,UAAU,CAAC;IAC9C,OAAO;QACL,YAAY;QACZ,OAAO;QACP,KAAK,EAAE,gBAAgB,IAAI,CAAC;QAC5B,gBAAgB,EAAE,gBAAgB,GAAG,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC;KAC9D,CAAC;AACJ,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,IAAI,OAAO,IAAI,CAAC;QAAE,OAAO,GAAG,CAAC;IAC7B,OAAO,GAAG,IAAI,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,KAAK,OAAO,GAAG,CAAC;AAClE,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,mBAAmB,CAAC,MAAyB;IAC3D,OAAO,MAAM,CAAC,KAAK;QACjB,CAAC,CAAC,cAAc,eAAe,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE;QACjD,CAAC,CAAC,SAAS,eAAe,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,cAAc,CAC7D,MAAM,CAAC,gBAAgB,CACxB,EAAE,CAAC;AACV,CAAC;AAQD;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAiD,EACjD,eAAuB;IAEvB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAClD,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;YAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;QACtC,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,qCAAqC;IACvC,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AACvD,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { runCli, renderHelp, COMMANDS, type RunCliOptions } from "./run.js";
|
|
2
|
+
export { parseArgs, type ParsedArgs } from "./args.js";
|
|
3
|
+
export { TESTNET_CHAIN_IDS, assertTestnetChainId, assertTestnetRpc, resolveConfig, type CliConfig, } from "./config.js";
|
|
4
|
+
export { CliError, describeError } from "./errors.js";
|
|
5
|
+
export { defaultCliDependencies, type CliDependencies, type CliReadClient, type CliWriteClient, type OpenedStream, type StreamOpenedQuery, } from "./deps.js";
|
|
6
|
+
export { CDP_ENV_VARS, PRIVATE_KEY_ENV, optionalCliWallet, resolveCliWallet, type CliWallet, type CliWalletSource, } from "./wallet.js";
|
|
7
|
+
export type { CommandContext, CommandSpec } from "./context.js";
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAC5E,OAAO,EAAE,SAAS,EAAE,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,aAAa,EACb,KAAK,SAAS,GACf,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EACL,sBAAsB,EACtB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,iBAAiB,GACvB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,YAAY,EACZ,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,KAAK,SAAS,EACd,KAAK,eAAe,GACrB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { runCli, renderHelp, COMMANDS } from "./run.js";
|
|
2
|
+
export { parseArgs } from "./args.js";
|
|
3
|
+
export { TESTNET_CHAIN_IDS, assertTestnetChainId, assertTestnetRpc, resolveConfig, } from "./config.js";
|
|
4
|
+
export { CliError, describeError } from "./errors.js";
|
|
5
|
+
export { defaultCliDependencies, } from "./deps.js";
|
|
6
|
+
export { CDP_ENV_VARS, PRIVATE_KEY_ENV, optionalCliWallet, resolveCliWallet, } from "./wallet.js";
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAsB,MAAM,UAAU,CAAC;AAC5E,OAAO,EAAE,SAAS,EAAmB,MAAM,WAAW,CAAC;AACvD,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,aAAa,GAEd,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EACL,sBAAsB,GAMvB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,YAAY,EACZ,eAAe,EACf,iBAAiB,EACjB,gBAAgB,GAGjB,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { CommandContext } from "./context.js";
|
|
2
|
+
import type { ServiceListing } from "./deps.js";
|
|
3
|
+
/**
|
|
4
|
+
* Finds the verified listing for a `serviceRef`.
|
|
5
|
+
*
|
|
6
|
+
* The registry is an untrusted transport: `discoverServices` re-derives every
|
|
7
|
+
* `serviceRef` from the signed record and recovers the operator signature, so a
|
|
8
|
+
* compromised registry can neither invent an operator to pay nor redirect an
|
|
9
|
+
* invocation URL. That verification is the reason the CLI routes through
|
|
10
|
+
* discovery instead of taking a `--url`.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveListing(context: CommandContext, serviceRef: `0x${string}`, options: {
|
|
13
|
+
readonly required: boolean;
|
|
14
|
+
}): Promise<ServiceListing | null>;
|
|
15
|
+
//# sourceMappingURL=listings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listings.d.ts","sourceRoot":"","sources":["../../src/cli/listings.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEhD;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,cAAc,EACvB,UAAU,EAAE,KAAK,MAAM,EAAE,EACzB,OAAO,EAAE;IAAE,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,GACtC,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAyDhC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { RegistryUnavailableError } from "../discovery/registry.js";
|
|
2
|
+
import { CliError } from "./errors.js";
|
|
3
|
+
/**
|
|
4
|
+
* Finds the verified listing for a `serviceRef`.
|
|
5
|
+
*
|
|
6
|
+
* The registry is an untrusted transport: `discoverServices` re-derives every
|
|
7
|
+
* `serviceRef` from the signed record and recovers the operator signature, so a
|
|
8
|
+
* compromised registry can neither invent an operator to pay nor redirect an
|
|
9
|
+
* invocation URL. That verification is the reason the CLI routes through
|
|
10
|
+
* discovery instead of taking a `--url`.
|
|
11
|
+
*/
|
|
12
|
+
export async function resolveListing(context, serviceRef, options) {
|
|
13
|
+
const { config, out, deps } = context;
|
|
14
|
+
let services;
|
|
15
|
+
try {
|
|
16
|
+
services = (await deps.discover({
|
|
17
|
+
registryUrl: config.registryUrl,
|
|
18
|
+
logger: { warn: (...parts) => out.note(parts.map(String).join(" ")) },
|
|
19
|
+
})).services;
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
if (error instanceof RegistryUnavailableError && !options.required) {
|
|
23
|
+
out.note(`warning: the registry at ${config.registryUrl} is unreachable; continuing without a verified listing.`);
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
throw new CliError(`the service registry at ${config.registryUrl} could not be read`, { exitCode: 4, cause: error });
|
|
27
|
+
}
|
|
28
|
+
const wanted = serviceRef.toLowerCase();
|
|
29
|
+
const match = services.find((service) => service.serviceRef.toLowerCase() === wanted);
|
|
30
|
+
if (match === undefined) {
|
|
31
|
+
if (!options.required)
|
|
32
|
+
return null;
|
|
33
|
+
throw new CliError(`no verified listing in the registry matches serviceRef ${serviceRef}`, {
|
|
34
|
+
exitCode: 4,
|
|
35
|
+
hint: "run `metrik discover` to see what is listed. A listing that fails signature verification is dropped, so it will not appear here.",
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
if (match.accessUrl === null) {
|
|
39
|
+
if (!options.required)
|
|
40
|
+
return null;
|
|
41
|
+
throw new CliError(`listing ${serviceRef} carries no signed invocation URL`, {
|
|
42
|
+
exitCode: 4,
|
|
43
|
+
hint: "the CLI refuses to call an origin that the operator did not sign.",
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
serviceRef: match.serviceRef,
|
|
48
|
+
operator: match.operator,
|
|
49
|
+
publicUrl: match.publicUrl,
|
|
50
|
+
access: match.access,
|
|
51
|
+
accessUrl: match.accessUrl,
|
|
52
|
+
signed: match.signed,
|
|
53
|
+
category: match.category,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=listings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listings.js","sourceRoot":"","sources":["../../src/cli/listings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAEpE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAIvC;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAAuB,EACvB,UAAyB,EACzB,OAAuC;IAEvC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IACtC,IAAI,QAAQ,CAAC;IACb,IAAI,CAAC;QACH,QAAQ,GAAG,CACT,MAAM,IAAI,CAAC,QAAQ,CAAC;YAClB,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,GAAG,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE;SACtE,CAAC,CACH,CAAC,QAAQ,CAAC;IACb,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,wBAAwB,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YACnE,GAAG,CAAC,IAAI,CACN,4BAA4B,MAAM,CAAC,WAAW,yDAAyD,CACxG,CAAC;YACF,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,IAAI,QAAQ,CAChB,2BAA2B,MAAM,CAAC,WAAW,oBAAoB,EACjE,EAAE,QAAQ,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAC9B,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;IACxC,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CACzB,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,WAAW,EAAE,KAAK,MAAM,CACzD,CAAC;IACF,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,IAAI,CAAC,OAAO,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAC;QACnC,MAAM,IAAI,QAAQ,CAChB,0DAA0D,UAAU,EAAE,EACtE;YACE,QAAQ,EAAE,CAAC;YACX,IAAI,EAAE,kIAAkI;SACzI,CACF,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,SAAS,KAAK,IAAI,EAAE,CAAC;QAC7B,IAAI,CAAC,OAAO,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAC;QACnC,MAAM,IAAI,QAAQ,CAChB,WAAW,UAAU,mCAAmC,EACxD;YACE,QAAQ,EAAE,CAAC;YACX,IAAI,EAAE,mEAAmE;SAC1E,CACF,CAAC;IACJ,CAAC;IAED,OAAO;QACL,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,QAAQ,EAAE,KAAK,CAAC,QAAQ;KACzB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { Account } from "viem";
|
|
2
|
+
import { type ServerMandateCaps } from "../mandates/env.js";
|
|
3
|
+
import type { SignedSpendMandate } from "../mandates/mandate.js";
|
|
4
|
+
/**
|
|
5
|
+
* Spend mandates in the CLI.
|
|
6
|
+
*
|
|
7
|
+
* Every fund-moving path in this package goes through `checkMandate()` — that is
|
|
8
|
+
* a golden rule of the agent layer, and the CLI is not exempt. The CLI's twist
|
|
9
|
+
* is that the person typing the command IS the mandate owner: they hold the key
|
|
10
|
+
* and they just stated the exact spend on the command line. So the mandate is
|
|
11
|
+
* self-signed from the same wallet that funds the stream, exactly as the MCP
|
|
12
|
+
* server does (`signServerMandate`).
|
|
13
|
+
*
|
|
14
|
+
* Two sources, in priority order:
|
|
15
|
+
*
|
|
16
|
+
* 1. `METRIK_AGENT_MANDATE_*` in the environment — an explicit standing ceiling.
|
|
17
|
+
* If the requested hire exceeds it, `checkMandate` DENIES it. This is the
|
|
18
|
+
* path to use when a CLI runs unattended under a policy.
|
|
19
|
+
* 2. No env caps configured — the mandate is sized to exactly this hire and
|
|
20
|
+
* scoped to exactly this operator. It authorizes the command that was typed
|
|
21
|
+
* and nothing wider.
|
|
22
|
+
*
|
|
23
|
+
* Neither path is an unbounded mandate.
|
|
24
|
+
*/
|
|
25
|
+
export interface RequestedSpend {
|
|
26
|
+
readonly operator: `0x${string}`;
|
|
27
|
+
readonly budgetUsdc: bigint;
|
|
28
|
+
readonly ratePerSecondUsdc: bigint;
|
|
29
|
+
readonly durationSeconds: number;
|
|
30
|
+
}
|
|
31
|
+
export interface CliMandate {
|
|
32
|
+
readonly signed: SignedSpendMandate;
|
|
33
|
+
/** Where the caps came from, for the human-readable output. */
|
|
34
|
+
readonly source: "env" | "request";
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The caps this hire would be authorized under, WITHOUT signing anything. Split
|
|
38
|
+
* out so `open --dry-run` can report the mandate it would use even when there is
|
|
39
|
+
* no key to sign it with.
|
|
40
|
+
*/
|
|
41
|
+
export declare function cliMandateCaps(request: RequestedSpend, env: NodeJS.ProcessEnv): {
|
|
42
|
+
readonly caps: ServerMandateCaps;
|
|
43
|
+
readonly source: "env" | "request";
|
|
44
|
+
};
|
|
45
|
+
export declare function signCliMandate(account: Account, request: RequestedSpend, options: {
|
|
46
|
+
readonly chainId: number;
|
|
47
|
+
readonly env: NodeJS.ProcessEnv;
|
|
48
|
+
}): Promise<CliMandate>;
|
|
49
|
+
/**
|
|
50
|
+
* The operator's claim is not a SPEND: it redeems value the stream already
|
|
51
|
+
* earned under an oracle-verified checkpoint, and the escrow pays it to the
|
|
52
|
+
* stream's operator and nobody else. But `checkMandate()` gates every
|
|
53
|
+
* fund-moving path in this package without exception, so the claim carries a
|
|
54
|
+
* mandate too. The caps below are placeholders that satisfy the schema against a
|
|
55
|
+
* zero-valued request; the real gate is the escrow's own `NotOperator()`.
|
|
56
|
+
*/
|
|
57
|
+
export declare function signClaimMandate(account: Account, chainId: number): Promise<SignedSpendMandate>;
|
|
58
|
+
/**
|
|
59
|
+
* Close and reclaim are BUYER-RECOVERY actions: they stop payment or return
|
|
60
|
+
* unspent funds to the buyer, and `VerifiedStreamAgentClient` authorizes them on
|
|
61
|
+
* the mandate owner's signature alone — never on caps or expiry, so a lapsed
|
|
62
|
+
* mandate can never strand a buyer's own money. The caps below are therefore
|
|
63
|
+
* placeholders that satisfy the schema; they gate nothing.
|
|
64
|
+
*/
|
|
65
|
+
export declare function signRecoveryMandate(account: Account, chainId: number): Promise<SignedSpendMandate>;
|
|
66
|
+
//# sourceMappingURL=mandate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mandate.d.ts","sourceRoot":"","sources":["../../src/cli/mandate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAEpC,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEjE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,QAAQ,EAAE,KAAK,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;IACpC,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,EAAE,KAAK,GAAG,SAAS,CAAC;CACpC;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,cAAc,EACvB,GAAG,EAAE,MAAM,CAAC,UAAU,GACrB;IAAE,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,GAAG,SAAS,CAAA;CAAE,CAc1E;AAED,wBAAsB,cAAc,CAClC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAA;CAAE,GACrE,OAAO,CAAC,UAAU,CAAC,CAMrB;AAED;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,kBAAkB,CAAC,CAE7B;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,kBAAkB,CAAC,CAE7B"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { parseServerMandateCapsEnv, signServerMandate, DEFAULT_SERVER_MANDATE_TTL_SECONDS, } from "../mandates/env.js";
|
|
2
|
+
/**
|
|
3
|
+
* The caps this hire would be authorized under, WITHOUT signing anything. Split
|
|
4
|
+
* out so `open --dry-run` can report the mandate it would use even when there is
|
|
5
|
+
* no key to sign it with.
|
|
6
|
+
*/
|
|
7
|
+
export function cliMandateCaps(request, env) {
|
|
8
|
+
const envCaps = parseServerMandateCapsEnv(env);
|
|
9
|
+
if (envCaps !== null)
|
|
10
|
+
return { caps: envCaps, source: "env" };
|
|
11
|
+
return {
|
|
12
|
+
caps: {
|
|
13
|
+
maxPerStreamUsdc: request.budgetUsdc,
|
|
14
|
+
maxTotalUsdc: request.budgetUsdc,
|
|
15
|
+
maxRatePerSecondUsdc: request.ratePerSecondUsdc,
|
|
16
|
+
maxDurationSeconds: request.durationSeconds,
|
|
17
|
+
allowedOperators: [request.operator],
|
|
18
|
+
ttlSeconds: DEFAULT_SERVER_MANDATE_TTL_SECONDS,
|
|
19
|
+
},
|
|
20
|
+
source: "request",
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export async function signCliMandate(account, request, options) {
|
|
24
|
+
const { caps, source } = cliMandateCaps(request, options.env);
|
|
25
|
+
const signed = await signServerMandate(account, caps, {
|
|
26
|
+
chainId: options.chainId,
|
|
27
|
+
});
|
|
28
|
+
return { signed, source };
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The operator's claim is not a SPEND: it redeems value the stream already
|
|
32
|
+
* earned under an oracle-verified checkpoint, and the escrow pays it to the
|
|
33
|
+
* stream's operator and nobody else. But `checkMandate()` gates every
|
|
34
|
+
* fund-moving path in this package without exception, so the claim carries a
|
|
35
|
+
* mandate too. The caps below are placeholders that satisfy the schema against a
|
|
36
|
+
* zero-valued request; the real gate is the escrow's own `NotOperator()`.
|
|
37
|
+
*/
|
|
38
|
+
export async function signClaimMandate(account, chainId) {
|
|
39
|
+
return await signPlaceholderMandate(account, chainId);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Close and reclaim are BUYER-RECOVERY actions: they stop payment or return
|
|
43
|
+
* unspent funds to the buyer, and `VerifiedStreamAgentClient` authorizes them on
|
|
44
|
+
* the mandate owner's signature alone — never on caps or expiry, so a lapsed
|
|
45
|
+
* mandate can never strand a buyer's own money. The caps below are therefore
|
|
46
|
+
* placeholders that satisfy the schema; they gate nothing.
|
|
47
|
+
*/
|
|
48
|
+
export async function signRecoveryMandate(account, chainId) {
|
|
49
|
+
return await signPlaceholderMandate(account, chainId);
|
|
50
|
+
}
|
|
51
|
+
async function signPlaceholderMandate(account, chainId) {
|
|
52
|
+
return await signServerMandate(account, {
|
|
53
|
+
maxPerStreamUsdc: 1n,
|
|
54
|
+
maxTotalUsdc: 1n,
|
|
55
|
+
maxRatePerSecondUsdc: 1n,
|
|
56
|
+
maxDurationSeconds: 1,
|
|
57
|
+
allowedOperators: [],
|
|
58
|
+
ttlSeconds: DEFAULT_SERVER_MANDATE_TTL_SECONDS,
|
|
59
|
+
}, { chainId });
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=mandate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mandate.js","sourceRoot":"","sources":["../../src/cli/mandate.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,yBAAyB,EACzB,iBAAiB,EACjB,kCAAkC,GAEnC,MAAM,oBAAoB,CAAC;AAqC5B;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,OAAuB,EACvB,GAAsB;IAEtB,MAAM,OAAO,GAAG,yBAAyB,CAAC,GAAG,CAAC,CAAC;IAC/C,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAC9D,OAAO;QACL,IAAI,EAAE;YACJ,gBAAgB,EAAE,OAAO,CAAC,UAAU;YACpC,YAAY,EAAE,OAAO,CAAC,UAAU;YAChC,oBAAoB,EAAE,OAAO,CAAC,iBAAiB;YAC/C,kBAAkB,EAAE,OAAO,CAAC,eAAe;YAC3C,gBAAgB,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC;YACpC,UAAU,EAAE,kCAAkC;SAC/C;QACD,MAAM,EAAE,SAAS;KAClB,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAAgB,EAChB,OAAuB,EACvB,OAAsE;IAEtE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IAC9D,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,OAAO,EAAE,IAAI,EAAE;QACpD,OAAO,EAAE,OAAO,CAAC,OAAO;KACzB,CAAC,CAAC;IACH,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AAC5B,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAAgB,EAChB,OAAe;IAEf,OAAO,MAAM,sBAAsB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AACxD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,OAAgB,EAChB,OAAe;IAEf,OAAO,MAAM,sBAAsB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AACxD,CAAC;AAED,KAAK,UAAU,sBAAsB,CACnC,OAAgB,EAChB,OAAe;IAEf,OAAO,MAAM,iBAAiB,CAC5B,OAAO,EACP;QACE,gBAAgB,EAAE,EAAE;QACpB,YAAY,EAAE,EAAE;QAChB,oBAAoB,EAAE,EAAE;QACxB,kBAAkB,EAAE,CAAC;QACrB,gBAAgB,EAAE,EAAE;QACpB,UAAU,EAAE,kCAAkC;KAC/C,EACD,EAAE,OAAO,EAAE,CACZ,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output shape. Human-readable by default; `--json` emits one JSON object on
|
|
3
|
+
* stdout per command so a script can pipe it into `jq` without parsing prose.
|
|
4
|
+
*
|
|
5
|
+
* Warnings and progress go to stderr in BOTH modes, so `--json` stdout stays a
|
|
6
|
+
* single parseable document even when discovery drops a row or a reclaim
|
|
7
|
+
* retries.
|
|
8
|
+
*/
|
|
9
|
+
export interface CliStreams {
|
|
10
|
+
readonly stdout: (line: string) => void;
|
|
11
|
+
readonly stderr: (line: string) => void;
|
|
12
|
+
}
|
|
13
|
+
export interface Printer extends CliStreams {
|
|
14
|
+
readonly json: boolean;
|
|
15
|
+
/** Human-readable body. Suppressed entirely in `--json` mode. */
|
|
16
|
+
readonly print: (line: string) => void;
|
|
17
|
+
/** Key/value block, aligned. Suppressed in `--json` mode. */
|
|
18
|
+
readonly table: (rows: readonly (readonly [string, string])[]) => void;
|
|
19
|
+
/** Progress / warnings. Always stderr, always shown. */
|
|
20
|
+
readonly note: (line: string) => void;
|
|
21
|
+
/** The machine-readable result. Emitted only in `--json` mode. */
|
|
22
|
+
readonly result: (value: unknown) => void;
|
|
23
|
+
/**
|
|
24
|
+
* One COMPACT JSON object on a single stdout line — JSON Lines. Used by
|
|
25
|
+
* commands that emit a record per tick (`watch`), where every line must parse
|
|
26
|
+
* standalone so a consumer can react as each one lands. `result` is the
|
|
27
|
+
* pretty-printed single-document form and is wrong for a stream: a multi-line
|
|
28
|
+
* object means not one of its lines parses on its own.
|
|
29
|
+
*/
|
|
30
|
+
readonly resultLine: (value: unknown) => void;
|
|
31
|
+
}
|
|
32
|
+
export declare function createPrinter(streams: CliStreams, json: boolean): Printer;
|
|
33
|
+
//# sourceMappingURL=output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../src/cli/output.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAED,MAAM,WAAW,OAAQ,SAAQ,UAAU;IACzC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,iEAAiE;IACjE,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,6DAA6D;IAC7D,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC;IACvE,wDAAwD;IACxD,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,kEAAkE;IAClE,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAC1C;;;;;;OAMG;IACH,QAAQ,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAC/C;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAwBzE"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export function createPrinter(streams, json) {
|
|
2
|
+
return {
|
|
3
|
+
...streams,
|
|
4
|
+
json,
|
|
5
|
+
print(line) {
|
|
6
|
+
if (!json)
|
|
7
|
+
streams.stdout(line);
|
|
8
|
+
},
|
|
9
|
+
table(rows) {
|
|
10
|
+
if (json)
|
|
11
|
+
return;
|
|
12
|
+
const width = rows.reduce((max, [key]) => Math.max(max, key.length), 0);
|
|
13
|
+
for (const [key, value] of rows) {
|
|
14
|
+
streams.stdout(` ${key.padEnd(width)} ${value}`);
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
note(line) {
|
|
18
|
+
streams.stderr(line);
|
|
19
|
+
},
|
|
20
|
+
result(value) {
|
|
21
|
+
if (json)
|
|
22
|
+
streams.stdout(JSON.stringify(value, jsonReplacer, 2));
|
|
23
|
+
},
|
|
24
|
+
resultLine(value) {
|
|
25
|
+
if (json)
|
|
26
|
+
streams.stdout(JSON.stringify(value, jsonReplacer));
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/** bigints are the natural amount type here; JSON has no bigint. */
|
|
31
|
+
function jsonReplacer(_key, value) {
|
|
32
|
+
return typeof value === "bigint" ? value.toString() : value;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/cli/output.ts"],"names":[],"mappings":"AAiCA,MAAM,UAAU,aAAa,CAAC,OAAmB,EAAE,IAAa;IAC9D,OAAO;QACL,GAAG,OAAO;QACV,IAAI;QACJ,KAAK,CAAC,IAAI;YACR,IAAI,CAAC,IAAI;gBAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAClC,CAAC;QACD,KAAK,CAAC,IAAI;YACR,IAAI,IAAI;gBAAE,OAAO;YACjB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;YACxE,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC;gBAChC,OAAO,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC;YACrD,CAAC;QACH,CAAC;QACD,IAAI,CAAC,IAAI;YACP,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACvB,CAAC;QACD,MAAM,CAAC,KAAK;YACV,IAAI,IAAI;gBAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC;QACnE,CAAC;QACD,UAAU,CAAC,KAAK;YACd,IAAI,IAAI;gBAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC;QAChE,CAAC;KACF,CAAC;AACJ,CAAC;AAED,oEAAoE;AACpE,SAAS,YAAY,CAAC,IAAY,EAAE,KAAc;IAChD,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;AAC9D,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { CliReadClient } from "./deps.js";
|
|
2
|
+
/** Where a Base Sepolia test wallet gets its gas. */
|
|
3
|
+
export declare const BASE_SEPOLIA_FAUCET_URL = "https://www.alchemy.com/faucets/base-sepolia";
|
|
4
|
+
/** Where a Base Sepolia test wallet gets the USDC it escrows. */
|
|
5
|
+
export declare const CIRCLE_USDC_FAUCET_URL = "https://faucet.circle.com";
|
|
6
|
+
/**
|
|
7
|
+
* Refuse to broadcast from a wallet that cannot pay for gas.
|
|
8
|
+
*
|
|
9
|
+
* Without this, the first thing an unfunded wallet sees is the node's own
|
|
10
|
+
* phrasing — `USDC approve transaction failed: Execution reverted with reason:
|
|
11
|
+
* gas required exceeds allowance (0)` — which reads like a USDC allowance
|
|
12
|
+
* problem and sends the reader looking at approvals. The actual fact is "this
|
|
13
|
+
* address holds no ETH", and it is knowable with one read before anything is
|
|
14
|
+
* signed.
|
|
15
|
+
*
|
|
16
|
+
* Deliberately only a ZERO check, not an estimate: predicting the gas a hire
|
|
17
|
+
* will cost means simulating it, and a wallet with a little ETH that still runs
|
|
18
|
+
* short should get the real revert rather than a guess from this CLI.
|
|
19
|
+
*/
|
|
20
|
+
export declare function assertCanPayGas(read: CliReadClient, address: `0x${string}`): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Refuse to broadcast a hire the wallet cannot fund.
|
|
23
|
+
*
|
|
24
|
+
* The sibling of `assertCanPayGas`, for the OTHER balance. Gas is ETH and the
|
|
25
|
+
* deposit is USDC: they are separate balances on separate tokens, so a wallet
|
|
26
|
+
* that passes the gas check can still hold no USDC at all. Without this the
|
|
27
|
+
* `open` path sends the USDC approval FIRST — which succeeds, because approving
|
|
28
|
+
* an amount you do not hold is legal — and then reverts inside `transferFrom`,
|
|
29
|
+
* having already spent gas to learn something that was one `balanceOf` away.
|
|
30
|
+
*
|
|
31
|
+
* Deliberately NOT an allowance check. The CLI's own open path grants the
|
|
32
|
+
* bounded approval it needs (`approveTxHash` in the result), so a missing
|
|
33
|
+
* allowance is a step of the command, not a precondition for it; gating on it
|
|
34
|
+
* would refuse a hire that was about to work. Balance is the fact the CLI
|
|
35
|
+
* cannot fix for you.
|
|
36
|
+
*/
|
|
37
|
+
export declare function assertCanFundStream(read: CliReadClient, address: `0x${string}`, budgetUsdc: bigint): Promise<void>;
|
|
38
|
+
//# sourceMappingURL=preflight.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preflight.d.ts","sourceRoot":"","sources":["../../src/cli/preflight.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C,qDAAqD;AACrD,eAAO,MAAM,uBAAuB,iDACY,CAAC;AAEjD,iEAAiE;AACjE,eAAO,MAAM,sBAAsB,8BAA8B,CAAC;AAElE;;;;;;;;;;;;;GAaG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,KAAK,MAAM,EAAE,GACrB,OAAO,CAAC,IAAI,CAAC,CAkBf;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,KAAK,MAAM,EAAE,EACtB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAmBf"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { formatUsdc } from "./amounts.js";
|
|
2
|
+
import { CliError } from "./errors.js";
|
|
3
|
+
/** Where a Base Sepolia test wallet gets its gas. */
|
|
4
|
+
export const BASE_SEPOLIA_FAUCET_URL = "https://www.alchemy.com/faucets/base-sepolia";
|
|
5
|
+
/** Where a Base Sepolia test wallet gets the USDC it escrows. */
|
|
6
|
+
export const CIRCLE_USDC_FAUCET_URL = "https://faucet.circle.com";
|
|
7
|
+
/**
|
|
8
|
+
* Refuse to broadcast from a wallet that cannot pay for gas.
|
|
9
|
+
*
|
|
10
|
+
* Without this, the first thing an unfunded wallet sees is the node's own
|
|
11
|
+
* phrasing — `USDC approve transaction failed: Execution reverted with reason:
|
|
12
|
+
* gas required exceeds allowance (0)` — which reads like a USDC allowance
|
|
13
|
+
* problem and sends the reader looking at approvals. The actual fact is "this
|
|
14
|
+
* address holds no ETH", and it is knowable with one read before anything is
|
|
15
|
+
* signed.
|
|
16
|
+
*
|
|
17
|
+
* Deliberately only a ZERO check, not an estimate: predicting the gas a hire
|
|
18
|
+
* will cost means simulating it, and a wallet with a little ETH that still runs
|
|
19
|
+
* short should get the real revert rather than a guess from this CLI.
|
|
20
|
+
*/
|
|
21
|
+
export async function assertCanPayGas(read, address) {
|
|
22
|
+
let balance;
|
|
23
|
+
try {
|
|
24
|
+
balance = await read.nativeBalance(address);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// A balance read is a courtesy, not a gate. If the RPC will not answer it,
|
|
28
|
+
// let the command proceed and fail with the real error.
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (balance > 0n)
|
|
32
|
+
return;
|
|
33
|
+
throw new CliError(`wallet ${address} has 0 ETH on Base Sepolia, so it cannot pay for gas`, {
|
|
34
|
+
exitCode: 3,
|
|
35
|
+
hint: `fund it at ${BASE_SEPOLIA_FAUCET_URL}, then re-run. (Gas is ETH; the stream itself is escrowed in USDC, which is a separate balance.)`,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Refuse to broadcast a hire the wallet cannot fund.
|
|
40
|
+
*
|
|
41
|
+
* The sibling of `assertCanPayGas`, for the OTHER balance. Gas is ETH and the
|
|
42
|
+
* deposit is USDC: they are separate balances on separate tokens, so a wallet
|
|
43
|
+
* that passes the gas check can still hold no USDC at all. Without this the
|
|
44
|
+
* `open` path sends the USDC approval FIRST — which succeeds, because approving
|
|
45
|
+
* an amount you do not hold is legal — and then reverts inside `transferFrom`,
|
|
46
|
+
* having already spent gas to learn something that was one `balanceOf` away.
|
|
47
|
+
*
|
|
48
|
+
* Deliberately NOT an allowance check. The CLI's own open path grants the
|
|
49
|
+
* bounded approval it needs (`approveTxHash` in the result), so a missing
|
|
50
|
+
* allowance is a step of the command, not a precondition for it; gating on it
|
|
51
|
+
* would refuse a hire that was about to work. Balance is the fact the CLI
|
|
52
|
+
* cannot fix for you.
|
|
53
|
+
*/
|
|
54
|
+
export async function assertCanFundStream(read, address, budgetUsdc) {
|
|
55
|
+
let balance;
|
|
56
|
+
try {
|
|
57
|
+
balance = await read.usdcBalance(address);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
// Same courtesy rule as the gas check: an RPC that will not answer a
|
|
61
|
+
// balance read must not become this command's failure mode. Proceed and let
|
|
62
|
+
// the real error surface.
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (balance >= budgetUsdc)
|
|
66
|
+
return;
|
|
67
|
+
throw new CliError(`wallet ${address} holds ${formatUsdc(balance)} but --budget is ${formatUsdc(budgetUsdc)}`, {
|
|
68
|
+
exitCode: 3,
|
|
69
|
+
hint: `the deposit is escrowed in USDC — fund the wallet at ${CIRCLE_USDC_FAUCET_URL} (Base Sepolia), then re-run. (Gas is a separate ETH balance.)`,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=preflight.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preflight.js","sourceRoot":"","sources":["../../src/cli/preflight.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGvC,qDAAqD;AACrD,MAAM,CAAC,MAAM,uBAAuB,GAClC,8CAA8C,CAAC;AAEjD,iEAAiE;AACjE,MAAM,CAAC,MAAM,sBAAsB,GAAG,2BAA2B,CAAC;AAElE;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAAmB,EACnB,OAAsB;IAEtB,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,2EAA2E;QAC3E,wDAAwD;QACxD,OAAO;IACT,CAAC;IACD,IAAI,OAAO,GAAG,EAAE;QAAE,OAAO;IAEzB,MAAM,IAAI,QAAQ,CAChB,UAAU,OAAO,sDAAsD,EACvE;QACE,QAAQ,EAAE,CAAC;QACX,IAAI,EAAE,cAAc,uBAAuB,kGAAkG;KAC9I,CACF,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,IAAmB,EACnB,OAAsB,EACtB,UAAkB;IAElB,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,qEAAqE;QACrE,4EAA4E;QAC5E,0BAA0B;QAC1B,OAAO;IACT,CAAC;IACD,IAAI,OAAO,IAAI,UAAU;QAAE,OAAO;IAElC,MAAM,IAAI,QAAQ,CAChB,UAAU,OAAO,UAAU,UAAU,CAAC,OAAO,CAAC,oBAAoB,UAAU,CAAC,UAAU,CAAC,EAAE,EAC1F;QACE,QAAQ,EAAE,CAAC;QACX,IAAI,EAAE,wDAAwD,sBAAsB,gEAAgE;KACrJ,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { type Account, type Transport } from "viem";
|
|
2
|
+
import { type AutonomousWalletCredentialStore } from "../wallet/autonomous-wallet.js";
|
|
3
|
+
/**
|
|
4
|
+
* The CLI's two Privy wallet shapes.
|
|
5
|
+
*
|
|
6
|
+
* Privy differs from the private-key and CDP paths in ONE structural way: the
|
|
7
|
+
* account it yields has no local `signTransaction`. It signs and broadcasts by
|
|
8
|
+
* sending `eth_sendTransaction` / `eth_signTypedData_v4` to a provider, so the
|
|
9
|
+
* viem wallet client's TRANSPORT must be that provider rather than a plain HTTP
|
|
10
|
+
* RPC. That is the whole difference, and it is what `transport` below carries.
|
|
11
|
+
*
|
|
12
|
+
* Neither shape puts a wallet key on this machine. The signing key lives at
|
|
13
|
+
* Privy; the broker holds the Privy authorization key. What the CLI holds is
|
|
14
|
+
* either a short-lived session token (`session`) or a P-256 authorization key
|
|
15
|
+
* in the host credential store (`autonomous`) — a key that authorizes a
|
|
16
|
+
* policy-bounded request, not a key that can move funds by itself.
|
|
17
|
+
*/
|
|
18
|
+
export type PrivyCliWalletSource = "privy-autonomous" | "privy-session";
|
|
19
|
+
/** The store key naming the agent-owned wallet in the host credential store. */
|
|
20
|
+
export declare const PRIVY_WALLET_KEY_ENV = "METRIK_AGENT_PRIVY_WALLET_KEY";
|
|
21
|
+
/** Broker base URL. Optional for `autonomous`, REQUIRED for `session`. */
|
|
22
|
+
export declare const PRIVY_BROKER_URL_ENV = "METRIK_AGENT_PRIVY_BROKER_URL";
|
|
23
|
+
/** A scoped session token minted by the broker's `POST /v1/sessions`. */
|
|
24
|
+
export declare const PRIVY_SESSION_TOKEN_ENV = "METRIK_AGENT_PRIVY_SESSION_TOKEN";
|
|
25
|
+
/** The embedded wallet address the session is bound to. */
|
|
26
|
+
export declare const PRIVY_ADDRESS_ENV = "METRIK_AGENT_PRIVY_ADDRESS";
|
|
27
|
+
/** The PUBLIC Privy app id. Not a secret — the broker serves it at `/v1/config`. */
|
|
28
|
+
export declare const PRIVY_APP_ID_ENV = "METRIK_AGENT_PRIVY_APP_ID";
|
|
29
|
+
/** Every variable either Privy shape reads. Named in errors, never printed. */
|
|
30
|
+
export declare const PRIVY_ENV_VARS: readonly ["METRIK_AGENT_PRIVY_WALLET_KEY", "METRIK_AGENT_PRIVY_BROKER_URL", "METRIK_AGENT_PRIVY_SESSION_TOKEN", "METRIK_AGENT_PRIVY_ADDRESS", "METRIK_AGENT_PRIVY_APP_ID"];
|
|
31
|
+
/** The variables the user-owned session shape needs, all of them. */
|
|
32
|
+
export declare const PRIVY_SESSION_ENV_VARS: readonly ["METRIK_AGENT_PRIVY_BROKER_URL", "METRIK_AGENT_PRIVY_SESSION_TOKEN", "METRIK_AGENT_PRIVY_ADDRESS", "METRIK_AGENT_PRIVY_APP_ID"];
|
|
33
|
+
/**
|
|
34
|
+
* The spend ceiling a broker enforces server-side, read from `GET /v1/config`.
|
|
35
|
+
*
|
|
36
|
+
* These are the SAME numbers the broker checks `openStream` against
|
|
37
|
+
* (`deposit <= maxTotalUsdc`, `ratePerSecond <= maxRatePerSecondUsdc`,
|
|
38
|
+
* `duration <= maxDurationSeconds`), which is why the CLI can use them to
|
|
39
|
+
* refuse an over-ceiling hire locally instead of paying gas to learn a knowable
|
|
40
|
+
* fact. It reads them rather than hardcoding them: the ceiling belongs to the
|
|
41
|
+
* broker, and a copy in this file would be a second source of truth that goes
|
|
42
|
+
* stale silently.
|
|
43
|
+
*/
|
|
44
|
+
export interface PrivySpendPolicy {
|
|
45
|
+
readonly brokerUrl: string;
|
|
46
|
+
readonly chainId: number;
|
|
47
|
+
readonly maxTotalUsdc: bigint;
|
|
48
|
+
readonly maxRatePerSecondUsdc: bigint;
|
|
49
|
+
readonly maxDurationSeconds: number;
|
|
50
|
+
}
|
|
51
|
+
/** Reads a broker's public policy. No credential is sent; nothing secret is served. */
|
|
52
|
+
export declare function fetchPrivySpendPolicy(brokerUrl: string, fetchImpl?: typeof fetch): Promise<PrivySpendPolicy>;
|
|
53
|
+
export interface ResolvedPrivyCliWallet {
|
|
54
|
+
readonly source: PrivyCliWalletSource;
|
|
55
|
+
/** A JSON-RPC account: `signTypedData` works, `signTransaction` does not exist. */
|
|
56
|
+
readonly account: Account;
|
|
57
|
+
/** The provider-as-transport. Without this every write goes to a plain RPC and fails. */
|
|
58
|
+
readonly transport: Transport;
|
|
59
|
+
/** One line naming the wallet's origin. Safe to print: no credential in it. */
|
|
60
|
+
readonly description: string;
|
|
61
|
+
/** Reads the broker ceiling this wallet is capped at. Bound to its broker URL. */
|
|
62
|
+
readonly readSpendPolicy: () => Promise<PrivySpendPolicy>;
|
|
63
|
+
}
|
|
64
|
+
export interface ResolvePrivyCliWalletOptions {
|
|
65
|
+
/** `--rpc-url`, so a Privy wallet's READS use the same endpoint as everything else. */
|
|
66
|
+
readonly rpcUrl?: string;
|
|
67
|
+
readonly note?: (line: string) => void;
|
|
68
|
+
/** Test seam. Defaults to the real credential store selected from `env`. */
|
|
69
|
+
readonly store?: AutonomousWalletCredentialStore;
|
|
70
|
+
/** Test seam for the broker HTTP contract. */
|
|
71
|
+
readonly fetchImpl?: typeof fetch;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Resolves a Privy wallet from the environment, or `null` when no Privy
|
|
75
|
+
* variable is set at all.
|
|
76
|
+
*
|
|
77
|
+
* A PARTIALLY configured Privy setup is an error, not a `null` — "you set the
|
|
78
|
+
* session token but not the address" and "you configured no Privy wallet" are
|
|
79
|
+
* different facts, and rendering the first as the second sends the reader
|
|
80
|
+
* looking in the wrong place. This mirrors the CDP path exactly.
|
|
81
|
+
*/
|
|
82
|
+
export declare function resolvePrivyCliWallet(env: NodeJS.ProcessEnv, options?: ResolvePrivyCliWalletOptions): Promise<ResolvedPrivyCliWallet | null>;
|
|
83
|
+
//# sourceMappingURL=privy.d.ts.map
|