@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,331 @@
|
|
|
1
|
+
import { MandateDeniedError } from "../../sdk/client.js";
|
|
2
|
+
import { booleanFlag, requiredStringFlag, stringFlag } from "../args.js";
|
|
3
|
+
import { formatDuration, formatUsdc, parseAmountUnits, parseDurationSeconds, parseUsdcAmount, } from "../amounts.js";
|
|
4
|
+
import { assertTestnetRpc, parseBytes32 } from "../config.js";
|
|
5
|
+
import { writeClientOptions } from "../deps.js";
|
|
6
|
+
import { CliError, configError } from "../errors.js";
|
|
7
|
+
import { assertWithinOperatorCaps, assertWithinSpendPolicy, } from "../spend-policy.js";
|
|
8
|
+
import { cliMandateCaps, signCliMandate } from "../mandate.js";
|
|
9
|
+
import { assertCanFundStream, assertCanPayGas } from "../preflight.js";
|
|
10
|
+
import { isPolicyEnforced, optionalCliWallet, resolveCliWallet, PRIVATE_KEY_ENV, } from "../wallet.js";
|
|
11
|
+
import { resolveListing } from "../listings.js";
|
|
12
|
+
export const openCommand = {
|
|
13
|
+
name: "open",
|
|
14
|
+
summary: "Hire a verified service: escrow USDC into a metered stream",
|
|
15
|
+
usage: "metrik open --service <serviceRef> --rate <usdc/s> --budget <usdc> --duration <seconds> [--units atomic] [--dry-run]",
|
|
16
|
+
flags: [
|
|
17
|
+
"service",
|
|
18
|
+
"rate",
|
|
19
|
+
"budget",
|
|
20
|
+
"duration",
|
|
21
|
+
"units",
|
|
22
|
+
"operator",
|
|
23
|
+
"dry-run",
|
|
24
|
+
],
|
|
25
|
+
signs: true,
|
|
26
|
+
async run(context) {
|
|
27
|
+
const { args, config, env, out, deps } = context;
|
|
28
|
+
const units = parseAmountUnits(stringFlag(args, "units"));
|
|
29
|
+
const serviceRef = parseBytes32(requiredStringFlag(args, "service"), "--service");
|
|
30
|
+
const budgetUsdc = parseUsdcAmount(requiredStringFlag(args, "budget"), units, "budget");
|
|
31
|
+
const ratePerSecondUsdc = parseUsdcAmount(requiredStringFlag(args, "rate"), units, "rate");
|
|
32
|
+
const durationSeconds = parseDurationSeconds(requiredStringFlag(args, "duration"));
|
|
33
|
+
const dryRun = booleanFlag(args, "dry-run");
|
|
34
|
+
if (budgetUsdc <= 0n || ratePerSecondUsdc <= 0n) {
|
|
35
|
+
throw new CliError("--budget and --rate must both be greater than zero", {
|
|
36
|
+
exitCode: 2,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
const maxSpend = ratePerSecondUsdc * BigInt(durationSeconds);
|
|
40
|
+
if (maxSpend > budgetUsdc) {
|
|
41
|
+
out.note(`note: --rate x --duration (${formatUsdc(maxSpend)}) exceeds --budget; accrual is capped at the deposit and the stream simply runs out of budget before it expires.`);
|
|
42
|
+
}
|
|
43
|
+
// `--dry-run` broadcasts nothing, so it does NOT require a key: it is the
|
|
44
|
+
// look-before-you-leap path, and the person most in need of it is exactly
|
|
45
|
+
// the one who has not funded a wallet yet. Without a key the preview prints
|
|
46
|
+
// the intended call and says which parts (allowance, simulation, mandate
|
|
47
|
+
// signature) could not be produced, rather than inventing them.
|
|
48
|
+
const wallet = dryRun
|
|
49
|
+
? await optionalCliWallet(env, { note: out.note, rpcUrl: config.rpcUrl })
|
|
50
|
+
: await resolveCliWallet(env, { note: out.note, rpcUrl: config.rpcUrl });
|
|
51
|
+
const account = wallet?.account ?? null;
|
|
52
|
+
const read = deps.createReadClient(config);
|
|
53
|
+
await assertTestnetRpc(config, () => read.getChainId());
|
|
54
|
+
if (account !== null && !dryRun) {
|
|
55
|
+
// Both balances, before anything is signed. Gas first: a wallet with no
|
|
56
|
+
// ETH cannot send the approval that the USDC check exists to protect.
|
|
57
|
+
await assertCanPayGas(read, account.address);
|
|
58
|
+
await assertCanFundStream(read, account.address, budgetUsdc);
|
|
59
|
+
}
|
|
60
|
+
const operatorOverride = stringFlag(args, "operator");
|
|
61
|
+
const listing = await resolveListing(context, serviceRef, {
|
|
62
|
+
required: operatorOverride === undefined,
|
|
63
|
+
});
|
|
64
|
+
const operator = (operatorOverride ?? listing?.operator);
|
|
65
|
+
if (operator === undefined) {
|
|
66
|
+
throw configError(`serviceRef ${serviceRef} is not in the registry and no --operator was given`, "run `metrik discover` to find a listed service, or pass --operator explicitly.");
|
|
67
|
+
}
|
|
68
|
+
const spend = { operator, budgetUsdc, ratePerSecondUsdc, durationSeconds };
|
|
69
|
+
const mandateCaps = cliMandateCaps(spend, env);
|
|
70
|
+
// A policy-enforced wallet (Privy) is capped by its broker, not by a
|
|
71
|
+
// mandate this process signs for itself. Read the REAL ceiling and hold it
|
|
72
|
+
// to that instead — see `../spend-policy.ts` for why that substitution is
|
|
73
|
+
// the stronger of the two, and why re-adding the self-signed mandate here
|
|
74
|
+
// would both weaken it and break the wallet outright.
|
|
75
|
+
const policy = wallet !== null && isPolicyEnforced(wallet)
|
|
76
|
+
? await wallet.readSpendPolicy()
|
|
77
|
+
: null;
|
|
78
|
+
if (policy !== null && !dryRun) {
|
|
79
|
+
assertWithinSpendPolicy(policy, spend);
|
|
80
|
+
// The operator's own standing ceiling still applies, and may be TIGHTER
|
|
81
|
+
// than the broker's. Enforced here because no mandate is signed to carry
|
|
82
|
+
// it — "policy-enforced" retires the self-signed mandate, not the caps
|
|
83
|
+
// the operator deliberately configured.
|
|
84
|
+
if (mandateCaps.source === "env") {
|
|
85
|
+
assertWithinOperatorCaps(mandateCaps.caps, spend);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
const mandate = account === null || policy !== null
|
|
89
|
+
? null
|
|
90
|
+
: await signCliMandate(account, spend, {
|
|
91
|
+
chainId: config.chainId,
|
|
92
|
+
env,
|
|
93
|
+
});
|
|
94
|
+
const write = deps.createWriteClient(config, account, writeClientOptions(wallet));
|
|
95
|
+
const hire = {
|
|
96
|
+
operator,
|
|
97
|
+
serviceRef,
|
|
98
|
+
budgetUsdc,
|
|
99
|
+
ratePerSecond: ratePerSecondUsdc,
|
|
100
|
+
maxDurationSeconds: durationSeconds,
|
|
101
|
+
};
|
|
102
|
+
if (dryRun) {
|
|
103
|
+
const preview = await write.buildHireTx(hire);
|
|
104
|
+
// A dry run simulates `openStream` from the CURRENT chain state, which
|
|
105
|
+
// does not include the USDC approval the real command sends first. So the
|
|
106
|
+
// simulation reverts on the allowance every time the allowance is not
|
|
107
|
+
// already in place — which, on a first hire, is always. Reporting that as
|
|
108
|
+
// `simulationError` made the one command meant to build confidence
|
|
109
|
+
// predict failure on first use. It is a known ordering step, not a fault.
|
|
110
|
+
const approvalBlocksSimulation = isApprovalOrdering(preview);
|
|
111
|
+
// Reported, never enforced: a dry run broadcasts nothing, so an
|
|
112
|
+
// underfunded wallet is information here, not a refusal. The same read
|
|
113
|
+
// IS a gate on the real path (`assertCanFundStream` above).
|
|
114
|
+
const usdcBalance = account === null
|
|
115
|
+
? null
|
|
116
|
+
: await read.usdcBalance(account.address).catch(() => null);
|
|
117
|
+
out.result({
|
|
118
|
+
dryRun: true,
|
|
119
|
+
buyer: account?.address ?? null,
|
|
120
|
+
operator,
|
|
121
|
+
serviceRef,
|
|
122
|
+
budgetUsdc,
|
|
123
|
+
ratePerSecondUsdc,
|
|
124
|
+
durationSeconds,
|
|
125
|
+
mandateSource: mandateCaps.source,
|
|
126
|
+
mandateSigned: mandate !== null,
|
|
127
|
+
spendPolicy: policy === null
|
|
128
|
+
? null
|
|
129
|
+
: {
|
|
130
|
+
brokerUrl: policy.brokerUrl,
|
|
131
|
+
maxTotalUsdc: policy.maxTotalUsdc,
|
|
132
|
+
maxRatePerSecondUsdc: policy.maxRatePerSecondUsdc,
|
|
133
|
+
maxDurationSeconds: policy.maxDurationSeconds,
|
|
134
|
+
fits: budgetUsdc <= policy.maxTotalUsdc &&
|
|
135
|
+
ratePerSecondUsdc <= policy.maxRatePerSecondUsdc &&
|
|
136
|
+
durationSeconds <= policy.maxDurationSeconds,
|
|
137
|
+
},
|
|
138
|
+
to: preview.to,
|
|
139
|
+
data: preview.data,
|
|
140
|
+
chainId: preview.chainId,
|
|
141
|
+
approval: {
|
|
142
|
+
required: preview.approval.required,
|
|
143
|
+
amount: preview.approval.amount,
|
|
144
|
+
spender: preview.approval.spender,
|
|
145
|
+
token: preview.approval.token,
|
|
146
|
+
},
|
|
147
|
+
usdcBalance,
|
|
148
|
+
usdcSufficient: usdcBalance === null ? null : usdcBalance >= budgetUsdc,
|
|
149
|
+
simulatedStreamId: preview.simulatedStreamId,
|
|
150
|
+
// Mutually exclusive by construction: an allowance-ordering revert is
|
|
151
|
+
// reported as `simulationPendingApproval`, never as an error, so a
|
|
152
|
+
// script branching on `simulationError` does not treat the expected
|
|
153
|
+
// first-hire path as a failure.
|
|
154
|
+
simulationPendingApproval: approvalBlocksSimulation,
|
|
155
|
+
...(preview.simulationError === undefined || approvalBlocksSimulation
|
|
156
|
+
? {}
|
|
157
|
+
: { simulationError: preview.simulationError }),
|
|
158
|
+
});
|
|
159
|
+
out.print("Dry run — nothing was broadcast.");
|
|
160
|
+
out.table([
|
|
161
|
+
[
|
|
162
|
+
"buyer",
|
|
163
|
+
account?.address ??
|
|
164
|
+
`unknown (no wallet configured — set ${PRIVATE_KEY_ENV} or the CDP variables to preview from a real address)`,
|
|
165
|
+
],
|
|
166
|
+
["operator", operator],
|
|
167
|
+
["serviceRef", serviceRef],
|
|
168
|
+
["budget", formatUsdc(budgetUsdc)],
|
|
169
|
+
["rate", `${formatUsdc(ratePerSecondUsdc)} / second`],
|
|
170
|
+
["duration", formatDuration(durationSeconds)],
|
|
171
|
+
[
|
|
172
|
+
"mandate",
|
|
173
|
+
mandate !== null
|
|
174
|
+
? `self-signed, caps from ${mandateCaps.source}`
|
|
175
|
+
: policy !== null
|
|
176
|
+
? "not signed — this wallet's ceiling is enforced by its broker, which is stronger"
|
|
177
|
+
: `not signed (no wallet); caps would come from ${mandateCaps.source}`,
|
|
178
|
+
],
|
|
179
|
+
...(policy === null
|
|
180
|
+
? []
|
|
181
|
+
: [
|
|
182
|
+
[
|
|
183
|
+
"spend policy",
|
|
184
|
+
`${formatUsdc(policy.maxTotalUsdc)} total, ${policy.maxRatePerSecondUsdc} atomic/second, ${formatDuration(policy.maxDurationSeconds)} max — enforced by ${policy.brokerUrl}`,
|
|
185
|
+
],
|
|
186
|
+
[
|
|
187
|
+
"fits policy",
|
|
188
|
+
budgetUsdc <= policy.maxTotalUsdc &&
|
|
189
|
+
ratePerSecondUsdc <= policy.maxRatePerSecondUsdc &&
|
|
190
|
+
durationSeconds <= policy.maxDurationSeconds
|
|
191
|
+
? "yes"
|
|
192
|
+
: "NO — a real open would be refused before broadcasting",
|
|
193
|
+
],
|
|
194
|
+
]),
|
|
195
|
+
["escrow", preview.to],
|
|
196
|
+
[
|
|
197
|
+
"usdc balance",
|
|
198
|
+
usdcBalance === null
|
|
199
|
+
? "unread (no wallet configured)"
|
|
200
|
+
: usdcBalance >= budgetUsdc
|
|
201
|
+
? `${formatUsdc(usdcBalance)} (covers the budget)`
|
|
202
|
+
: `${formatUsdc(usdcBalance)} — SHORT of the ${formatUsdc(budgetUsdc)} budget; a real open would be refused`,
|
|
203
|
+
],
|
|
204
|
+
[
|
|
205
|
+
"usdc approval",
|
|
206
|
+
preview.approval.required === null
|
|
207
|
+
? `${formatUsdc(preview.approval.amount)} (allowance unread)`
|
|
208
|
+
: preview.approval.required
|
|
209
|
+
? `${formatUsdc(preview.approval.amount)} (required)`
|
|
210
|
+
: "already sufficient",
|
|
211
|
+
],
|
|
212
|
+
[
|
|
213
|
+
"simulated streamId",
|
|
214
|
+
preview.simulatedStreamId ??
|
|
215
|
+
(approvalBlocksSimulation
|
|
216
|
+
? "not simulated yet — the bounded USDC approval above is sent FIRST by a real open, and the escrow cannot pull the deposit until it lands. Expected on a first hire, not a failure."
|
|
217
|
+
: `unavailable (${preview.simulationError ?? "simulation did not run"})`),
|
|
218
|
+
],
|
|
219
|
+
]);
|
|
220
|
+
out.print("");
|
|
221
|
+
out.print(METERING_NOTE);
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
out.note(`opening a stream on chain ${config.chainId} for ${formatUsdc(budgetUsdc)} …`);
|
|
225
|
+
// Unreachable without a wallet: `resolveCliWallet` above throws when the
|
|
226
|
+
// command is not a dry run. The narrowing keeps that a type-level fact.
|
|
227
|
+
if (account === null) {
|
|
228
|
+
throw configError("this command signs a transaction and needs a wallet, and none was resolved");
|
|
229
|
+
}
|
|
230
|
+
let result;
|
|
231
|
+
try {
|
|
232
|
+
result = await write.openVerifiedStream({
|
|
233
|
+
operator,
|
|
234
|
+
serviceRef,
|
|
235
|
+
budgetUsdc,
|
|
236
|
+
ratePerSecondUsdc,
|
|
237
|
+
maxDurationSeconds: durationSeconds,
|
|
238
|
+
// `null` for a policy-enforced wallet: the ceiling was checked against
|
|
239
|
+
// the broker's own policy above, and the broker checks it again on the
|
|
240
|
+
// transaction it signs.
|
|
241
|
+
signedMandate: mandate === null ? null : mandate.signed,
|
|
242
|
+
spentSoFarUsdc: 0n,
|
|
243
|
+
nowSeconds: deps.nowSeconds(),
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
catch (error) {
|
|
247
|
+
if (error instanceof MandateDeniedError) {
|
|
248
|
+
throw new CliError(`spend mandate denied this hire: ${error.reason}`, {
|
|
249
|
+
exitCode: 3,
|
|
250
|
+
hint: mandateCaps.source === "env"
|
|
251
|
+
? "the requested hire exceeds your METRIK_AGENT_MANDATE_* ceiling."
|
|
252
|
+
: "the hire does not satisfy the mandate signed for it.",
|
|
253
|
+
cause: error,
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
throw error;
|
|
257
|
+
}
|
|
258
|
+
out.result({
|
|
259
|
+
streamId: result.streamId,
|
|
260
|
+
txHash: result.txHash,
|
|
261
|
+
approveTxHash: result.approveTxHash,
|
|
262
|
+
buyer: account.address,
|
|
263
|
+
operator,
|
|
264
|
+
serviceRef,
|
|
265
|
+
budgetUsdc,
|
|
266
|
+
ratePerSecondUsdc,
|
|
267
|
+
durationSeconds,
|
|
268
|
+
escrow: result.handle.escrow,
|
|
269
|
+
chainId: result.handle.chainId,
|
|
270
|
+
});
|
|
271
|
+
out.print("Stream opened.");
|
|
272
|
+
out.table([
|
|
273
|
+
["streamId", result.streamId],
|
|
274
|
+
["tx", result.txHash],
|
|
275
|
+
["approve tx", result.approveTxHash ?? "not needed"],
|
|
276
|
+
["buyer", account.address],
|
|
277
|
+
["operator", operator],
|
|
278
|
+
["budget", formatUsdc(budgetUsdc)],
|
|
279
|
+
["rate", `${formatUsdc(ratePerSecondUsdc)} / second`],
|
|
280
|
+
["duration", formatDuration(durationSeconds)],
|
|
281
|
+
]);
|
|
282
|
+
out.print("");
|
|
283
|
+
out.print(METERING_NOTE);
|
|
284
|
+
out.print("");
|
|
285
|
+
out.print(`Next: metrik status ${result.streamId}`);
|
|
286
|
+
},
|
|
287
|
+
};
|
|
288
|
+
/**
|
|
289
|
+
* What the buyer is actually paying for.
|
|
290
|
+
*
|
|
291
|
+
* A live acceptance run made ONE `invoke` call and paid for 302 seconds, which
|
|
292
|
+
* is exactly the design — and exactly what nothing in the CLI said. "Pay for
|
|
293
|
+
* verified delivery" reads as "pay for delivery TO ME", so a buyer expects
|
|
294
|
+
* per-call billing and gets a rental meter. The meter runs on the oracle's
|
|
295
|
+
* probes of the endpoint, not on the buyer's own requests; one call and a
|
|
296
|
+
* thousand calls cost the same second.
|
|
297
|
+
*/
|
|
298
|
+
const METERING_NOTE = "How you are billed: this is TIME-metered rental of an endpoint the oracle keeps probing — not per-call billing. The meter runs on verified availability, so it charges the same whether you send one request or a thousand, and it keeps charging while you send none. `metrik close <streamId>` stops the clock; nothing else does.";
|
|
299
|
+
/**
|
|
300
|
+
* Shapes that mean "the spender's allowance is too small", across the OpenZeppelin
|
|
301
|
+
* string revert and the ERC-6093 custom error. Matched as phrases, never on the
|
|
302
|
+
* bare word `allowance`: the no-wallet preview reports `no account configured —
|
|
303
|
+
* allowance and simulation skipped`, which contains the word and is a COMPLETELY
|
|
304
|
+
* different fact. Excusing that as "an approval will be sent first" would state
|
|
305
|
+
* a reason the CLI does not have.
|
|
306
|
+
*/
|
|
307
|
+
const ALLOWANCE_SHORTFALL = [
|
|
308
|
+
/transfer amount exceeds allowance/i,
|
|
309
|
+
/insufficient allowance/i,
|
|
310
|
+
/ERC20InsufficientAllowance/,
|
|
311
|
+
];
|
|
312
|
+
/**
|
|
313
|
+
* True when the dry run's simulation failed ONLY because the USDC approval a
|
|
314
|
+
* real open sends first has not been sent.
|
|
315
|
+
*
|
|
316
|
+
* Deliberately narrow: it requires an actual REVERT, whose reason is an
|
|
317
|
+
* allowance shortfall, on a preview that says an approval is (or may be)
|
|
318
|
+
* needed. Anything else keeps being reported as a simulation error, because
|
|
319
|
+
* every other failure is a real one the buyer should see before spending.
|
|
320
|
+
*/
|
|
321
|
+
function isApprovalOrdering(preview) {
|
|
322
|
+
const error = preview.simulationError;
|
|
323
|
+
if (error === undefined || preview.simulatedStreamId != null)
|
|
324
|
+
return false;
|
|
325
|
+
if (preview.approval.required === false)
|
|
326
|
+
return false;
|
|
327
|
+
if (!/\brevert(ed)?\b/i.test(error))
|
|
328
|
+
return false;
|
|
329
|
+
return ALLOWANCE_SHORTFALL.some((pattern) => pattern.test(error));
|
|
330
|
+
}
|
|
331
|
+
//# sourceMappingURL=open.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"open.js","sourceRoot":"","sources":["../../../src/cli/commands/open.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reclaim-unverified.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/reclaim-unverified.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAkB,WAAW,EAAE,MAAM,eAAe,CAAC;AA2CjE,eAAO,MAAM,wBAAwB,EAAE,WAwGtC,CAAC"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { booleanFlag } from "../args.js";
|
|
2
|
+
import { formatDuration, formatUsdc } from "../amounts.js";
|
|
3
|
+
import { assertTestnetRpc, parseBytes32 } from "../config.js";
|
|
4
|
+
import { CliError, usageError } from "../errors.js";
|
|
5
|
+
import { escapeHatchWindow, formatTimestamp, readChainNow, } from "../escape-hatch.js";
|
|
6
|
+
import { signRecoveryMandate } from "../mandate.js";
|
|
7
|
+
import { assertCanPayGas } from "../preflight.js";
|
|
8
|
+
import { writeClientOptions } from "../deps.js";
|
|
9
|
+
import { isPolicyEnforced, resolveCliWallet } from "../wallet.js";
|
|
10
|
+
/**
|
|
11
|
+
* The acknowledgement this command will not run without.
|
|
12
|
+
*
|
|
13
|
+
* `reclaim-unverified` is deliberately BOTH a command of its own and a command
|
|
14
|
+
* that refuses to run on its arguments alone:
|
|
15
|
+
*
|
|
16
|
+
* - it is not `metrik reclaim --unverified`, because that is one token away
|
|
17
|
+
* from the safe path, sits in the same command's flag list (so a script that
|
|
18
|
+
* templates flags can pick it up), and shell completion offers it beside
|
|
19
|
+
* `--close-first`;
|
|
20
|
+
* - and the flag below has no default and no `--no-` form, so the only way to
|
|
21
|
+
* reach the transaction is to type a phrase that says what it costs.
|
|
22
|
+
*
|
|
23
|
+
* Nothing about this command is reachable by fat-fingering the ordinary one.
|
|
24
|
+
*/
|
|
25
|
+
const ACKNOWLEDGEMENT_FLAG = "forfeit-unclaimed";
|
|
26
|
+
/**
|
|
27
|
+
* Exactly what the escrow does, so the warning does not have to be trusted.
|
|
28
|
+
*
|
|
29
|
+
* `StreamEscrowV2.reclaimUnverified` sets `entitlement = stream.claimedCumulative`
|
|
30
|
+
* and then `settledCumulative = entitlement; deposit = entitlement`. The
|
|
31
|
+
* operator's own redemption path caps at that value once the stream is
|
|
32
|
+
* reclaimed (`if (stream.reclaimed && payableCumulative > stream.settledCumulative)
|
|
33
|
+
* payableCumulative = stream.settledCumulative;`) and then requires
|
|
34
|
+
* `payableCumulative > stream.claimedCumulative` — which can never hold again.
|
|
35
|
+
* Every voucher earned but not yet redeemed on-chain is therefore forfeit
|
|
36
|
+
* PERMANENTLY, and its value is paid to the buyer.
|
|
37
|
+
*/
|
|
38
|
+
const FORFEIT_WARNING = [
|
|
39
|
+
"This pays you deposit - claimedCumulative with NO proof and NO oracle.",
|
|
40
|
+
"What it costs the operator: everything they verifiably earned but have not yet",
|
|
41
|
+
"claimed on-chain is forfeited to you, permanently. The escrow caps their",
|
|
42
|
+
"entitlement at what they had already claimed, so every later claim reverts",
|
|
43
|
+
"NothingToClaim(). There is no way to pay it back afterwards.",
|
|
44
|
+
"",
|
|
45
|
+
"Use it when the oracle cannot give you a proof. Where `metrik reclaim` works,",
|
|
46
|
+
"use that instead — it settles the operator honestly and pays you the rest.",
|
|
47
|
+
];
|
|
48
|
+
export const reclaimUnverifiedCommand = {
|
|
49
|
+
name: "reclaim-unverified",
|
|
50
|
+
summary: "Escape hatch: reclaim with no proof when the oracle cannot give you one",
|
|
51
|
+
usage: `metrik reclaim-unverified <streamId> --${ACKNOWLEDGEMENT_FLAG}`,
|
|
52
|
+
flags: [ACKNOWLEDGEMENT_FLAG],
|
|
53
|
+
signs: true,
|
|
54
|
+
async run(context) {
|
|
55
|
+
const { args, config, env, out, deps } = context;
|
|
56
|
+
const [streamIdArg] = args.positionals;
|
|
57
|
+
if (streamIdArg === undefined) {
|
|
58
|
+
throw usageError("metrik reclaim-unverified requires a <streamId>");
|
|
59
|
+
}
|
|
60
|
+
const streamId = parseBytes32(streamIdArg, "<streamId>");
|
|
61
|
+
if (!booleanFlag(args, ACKNOWLEDGEMENT_FLAG)) {
|
|
62
|
+
throw usageError(`metrik reclaim-unverified forfeits the operator's unclaimed earnings, so it requires --${ACKNOWLEDGEMENT_FLAG}`, [
|
|
63
|
+
...FORFEIT_WARNING,
|
|
64
|
+
"",
|
|
65
|
+
`Re-run with --${ACKNOWLEDGEMENT_FLAG} once that is what you intend.`,
|
|
66
|
+
].join("\n "));
|
|
67
|
+
}
|
|
68
|
+
const wallet = await resolveCliWallet(env, {
|
|
69
|
+
note: out.note,
|
|
70
|
+
rpcUrl: config.rpcUrl,
|
|
71
|
+
});
|
|
72
|
+
const { account } = wallet;
|
|
73
|
+
const read = deps.createReadClient(config);
|
|
74
|
+
await assertTestnetRpc(config, () => read.getChainId());
|
|
75
|
+
await assertCanPayGas(read, account.address);
|
|
76
|
+
const stream = await read.getStreamV2(streamId);
|
|
77
|
+
if (stream.reclaimed) {
|
|
78
|
+
throw new CliError("this stream has already been reclaimed — there is nothing left to take back", {
|
|
79
|
+
exitCode: 4,
|
|
80
|
+
hint: `check where it went: metrik status ${streamId}`,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
// Readiness is computed against the chain's clock, because the escrow
|
|
84
|
+
// compares against `block.timestamp`. Spending gas on a guaranteed
|
|
85
|
+
// `EscapeHatchNotReady()` revert is exactly the failure this gate exists to
|
|
86
|
+
// prevent.
|
|
87
|
+
const grace = await readEscapeGrace(read);
|
|
88
|
+
const now = await readChainNow(read, deps.nowSeconds());
|
|
89
|
+
const window = escapeHatchWindow(stream, grace, now.seconds);
|
|
90
|
+
if (!window.ready) {
|
|
91
|
+
throw notReady(streamId, window, now.source);
|
|
92
|
+
}
|
|
93
|
+
// The amount at stake, when it is knowable. It usually is not: the reason to
|
|
94
|
+
// be on this path at all is that the oracle is not answering, and the
|
|
95
|
+
// operator's redeemable balance is derived from the oracle's proof.
|
|
96
|
+
const forfeit = await readForfeitEstimate(read, streamId);
|
|
97
|
+
out.note("");
|
|
98
|
+
for (const line of FORFEIT_WARNING)
|
|
99
|
+
out.note(line);
|
|
100
|
+
out.note(forfeit === null
|
|
101
|
+
? "Operator balance at stake: unknown — the oracle did not answer, which is the situation this command is for."
|
|
102
|
+
: `Operator balance at stake right now: ${formatUsdc(forfeit)} (net of protocol fee). This transaction forfeits it.`);
|
|
103
|
+
out.note("");
|
|
104
|
+
const write = deps.createWriteClient(config, account, writeClientOptions(wallet));
|
|
105
|
+
const result = await write.reclaimUnverifiedStream({
|
|
106
|
+
streamId,
|
|
107
|
+
// `null` for a policy-enforced wallet — see `../spend-policy.ts`.
|
|
108
|
+
signedMandate: isPolicyEnforced(wallet)
|
|
109
|
+
? null
|
|
110
|
+
: await signRecoveryMandate(account, config.chainId),
|
|
111
|
+
spentSoFarUsdc: 0n,
|
|
112
|
+
nowSeconds: deps.nowSeconds(),
|
|
113
|
+
});
|
|
114
|
+
out.result({
|
|
115
|
+
streamId,
|
|
116
|
+
txHash: result.txHash,
|
|
117
|
+
unverified: true,
|
|
118
|
+
escapeHatchReadyAt: window.readyAt,
|
|
119
|
+
escapeGraceSeconds: window.graceSeconds,
|
|
120
|
+
forfeitedOperatorClaimable: forfeit,
|
|
121
|
+
});
|
|
122
|
+
out.print("Reclaimed without a proof.");
|
|
123
|
+
out.table([
|
|
124
|
+
["streamId", streamId],
|
|
125
|
+
["tx", result.txHash],
|
|
126
|
+
["escape hatch opened", formatTimestamp(window.readyAt)],
|
|
127
|
+
[
|
|
128
|
+
"operator earnings forfeited",
|
|
129
|
+
forfeit === null ? "unknown (oracle unreachable)" : formatUsdc(forfeit),
|
|
130
|
+
],
|
|
131
|
+
]);
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
function notReady(streamId, window, clock) {
|
|
135
|
+
return new CliError(`the no-proof escape hatch is not open yet: it unlocks at ${formatTimestamp(window.readyAt)}, in ${formatDuration(window.secondsRemaining)}`, {
|
|
136
|
+
exitCode: 4,
|
|
137
|
+
hint: [
|
|
138
|
+
`The escrow gates this on expiresAt + escapeGraceSeconds (${window.graceSeconds}s), never on when you closed${clock === "chain"
|
|
139
|
+
? ""
|
|
140
|
+
: " — and the chain's own clock could not be read, so this is your machine's"}.`,
|
|
141
|
+
`Until then the honest path is the proof-based one: metrik reclaim ${streamId}`,
|
|
142
|
+
].join(" "),
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
/** `escapeGraceSeconds` is a public immutable; failing to read it is fatal here. */
|
|
146
|
+
async function readEscapeGrace(read) {
|
|
147
|
+
try {
|
|
148
|
+
return await read.escapeGraceSeconds();
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
throw new CliError("could not read escapeGraceSeconds from the escrow, so whether the escape hatch is open is unknown", {
|
|
152
|
+
exitCode: 4,
|
|
153
|
+
hint: "this command refuses to broadcast on a guess: retry when the RPC endpoint answers.",
|
|
154
|
+
cause: error,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* What the operator could redeem right now, i.e. what this transaction takes
|
|
160
|
+
* from them. `null` when the oracle cannot be reached — which is the normal case
|
|
161
|
+
* on this path and is reported as unknown rather than as zero.
|
|
162
|
+
*/
|
|
163
|
+
async function readForfeitEstimate(read, streamId) {
|
|
164
|
+
try {
|
|
165
|
+
const proof = await read.checkpointProof(streamId);
|
|
166
|
+
return await read.claimableForV2(streamId, proof.cumulativeAmount);
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=reclaim-unverified.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reclaim-unverified.js","sourceRoot":"","sources":["../../../src/cli/commands/reclaim-unverified.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { CommandSpec } from "../context.js";
|
|
2
|
+
import type { CliReadClient, CliWriteClient } from "../deps.js";
|
|
3
|
+
import type { ReclaimVerifiedStreamResult, StreamProofTransactionResult } from "../../sdk/client.js";
|
|
4
|
+
export declare const reclaimCommand: CommandSpec;
|
|
5
|
+
/**
|
|
6
|
+
* Send the close that `--close-first` asks for, tolerating the one race that
|
|
7
|
+
* matters: a stale read said "active" but the stream was in fact already closed.
|
|
8
|
+
* That is the state the caller wanted, so it is reported as `null` (no close
|
|
9
|
+
* sent) rather than as a failure — re-running the command must never dead-end on
|
|
10
|
+
* `StreamClosedAlready()` while the buyer's money is still reclaimable.
|
|
11
|
+
*
|
|
12
|
+
* Every OTHER close failure is rethrown untouched.
|
|
13
|
+
*/
|
|
14
|
+
export declare function closeBeforeReclaim(write: CliWriteClient, input: Parameters<CliWriteClient["closeStream"]>[0]): Promise<StreamProofTransactionResult | null>;
|
|
15
|
+
export declare function awaitClosed(read: Pick<CliReadClient, "getStreamV2">, streamId: `0x${string}`, sleep: (ms: number) => Promise<void>, closeTxHash: string): Promise<void>;
|
|
16
|
+
/**
|
|
17
|
+
* `reclaimWithProof` reverts with `SettlementWindowOpen` until the oracle has
|
|
18
|
+
* published a checkpoint whose `checkedAt` is at or after the stream's stop
|
|
19
|
+
* time. That is not an error condition — it is the normal ordering of a
|
|
20
|
+
* checkpoint rail, and it happens on the FIRST attempt essentially every time.
|
|
21
|
+
* A CLI that surfaced the raw revert would teach every user that reclaim is
|
|
22
|
+
* broken, so the wait is built in and narrated. Any other failure is rethrown
|
|
23
|
+
* immediately: only an open settlement window is retried.
|
|
24
|
+
*/
|
|
25
|
+
export declare function reclaimWithBoundedRetry(write: CliWriteClient, buildInput: () => Promise<Parameters<CliWriteClient["reclaimStream"]>[0]>, options: {
|
|
26
|
+
readonly attempts: number;
|
|
27
|
+
readonly intervalMs: number;
|
|
28
|
+
readonly sleep: (ms: number) => Promise<void>;
|
|
29
|
+
readonly onRetry: (attempt: number, reason: string) => void;
|
|
30
|
+
/** What to tell the buyer once the budget is spent. See `describeLastResort`. */
|
|
31
|
+
readonly exhaustedHint?: () => Promise<string>;
|
|
32
|
+
}): Promise<ReclaimVerifiedStreamResult>;
|
|
33
|
+
//# sourceMappingURL=reclaim.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reclaim.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/reclaim.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAkB,WAAW,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAChE,OAAO,KAAK,EACV,2BAA2B,EAC3B,4BAA4B,EAC7B,MAAM,qBAAqB,CAAC;AAW7B,eAAO,MAAM,cAAc,EAAE,WA4I5B,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,cAAc,EACrB,KAAK,EAAE,UAAU,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,GAClD,OAAO,CAAC,4BAA4B,GAAG,IAAI,CAAC,CAO9C;AA0BD,wBAAsB,WAAW,CAC/B,IAAI,EAAE,IAAI,CAAC,aAAa,EAAE,aAAa,CAAC,EACxC,QAAQ,EAAE,KAAK,MAAM,EAAE,EACvB,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,EACpC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAcf;AAED;;;;;;;;GAQG;AACH,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,cAAc,EACrB,UAAU,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EACzE,OAAO,EAAE;IACP,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,QAAQ,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5D,iFAAiF;IACjF,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CAChD,GACA,OAAO,CAAC,2BAA2B,CAAC,CAuBtC"}
|