@bondedhq/sdk 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +483 -2
  3. package/dist/actions.d.ts +76 -0
  4. package/dist/actions.js +115 -0
  5. package/dist/agent-url.d.ts +101 -0
  6. package/dist/agent-url.js +234 -0
  7. package/dist/agentkit.d.ts +104 -0
  8. package/dist/agentkit.js +206 -0
  9. package/dist/ai-sdk.d.ts +39 -0
  10. package/dist/ai-sdk.js +86 -0
  11. package/dist/breaches.d.ts +50 -0
  12. package/dist/breaches.js +57 -0
  13. package/dist/done.d.ts +14 -0
  14. package/dist/done.js +16 -0
  15. package/dist/eliza.d.ts +118 -0
  16. package/dist/eliza.js +281 -0
  17. package/dist/episode.d.ts +108 -0
  18. package/dist/episode.js +65 -0
  19. package/dist/errors.d.ts +93 -0
  20. package/dist/errors.js +97 -0
  21. package/dist/guarded.d.ts +80 -0
  22. package/dist/guarded.js +97 -0
  23. package/dist/index.d.ts +20 -0
  24. package/dist/index.js +19 -0
  25. package/dist/json-schema-zod3.d.ts +9 -0
  26. package/dist/json-schema-zod3.js +54 -0
  27. package/dist/langchain.d.ts +39 -0
  28. package/dist/langchain.js +53 -0
  29. package/dist/mandate.d.ts +36 -0
  30. package/dist/mandate.js +26 -0
  31. package/dist/mcp-config-cli.d.ts +3 -0
  32. package/dist/mcp-config-cli.js +44 -0
  33. package/dist/mcp.d.ts +131 -0
  34. package/dist/mcp.js +111 -0
  35. package/dist/module.d.ts +37 -0
  36. package/dist/module.js +32 -0
  37. package/dist/revert.d.ts +12 -0
  38. package/dist/revert.js +71 -0
  39. package/dist/sentinel.d.ts +43 -0
  40. package/dist/sentinel.js +94 -0
  41. package/dist/signature.d.ts +34 -0
  42. package/dist/signature.js +52 -0
  43. package/dist/solana-agent-kit.d.ts +141 -0
  44. package/dist/solana-agent-kit.js +333 -0
  45. package/dist/vault-tools.d.ts +67 -0
  46. package/dist/vault-tools.js +335 -0
  47. package/dist/vault.d.ts +116 -0
  48. package/dist/vault.js +326 -0
  49. package/package.json +134 -3
@@ -0,0 +1,335 @@
1
+ import { EVM_CHAINS, evmChainById, mandateVaultAbi } from "@bondedhq/shared";
2
+ import { defineChain, erc20Abi, formatUnits, getAddress, isAddress, isHex, parseUnits, } from "viem";
3
+ import { privateKeyToAccount } from "viem/accounts";
4
+ import { z } from "zod";
5
+ import { BondedError } from "./errors.js";
6
+ import { GuardedVault, } from "./guarded.js";
7
+ import { BondedVault, isRatedProcess, markProductionVault, ratedProductionVaultError, refuseProductionVaultWhileRated, } from "./vault.js";
8
+ /** The tools' names: the same as the Arena episode's write tools, plus `vault_status`. */
9
+ export const BONDED_VAULT_TOOLS = ["swap", "transfer", "approve", "vault_status"];
10
+ const amount = z
11
+ .union([z.string(), z.number()])
12
+ .transform(String)
13
+ .pipe(z.string().regex(/^\d+(\.\d+)?$/, "a decimal amount in whole tokens, e.g. 250 or 12.5"));
14
+ const ARGS = {
15
+ swap: z.object({
16
+ tokenIn: z.string(),
17
+ tokenOut: z.string(),
18
+ amountIn: amount,
19
+ minOut: amount.optional(),
20
+ }),
21
+ transfer: z.object({ token: z.string(), to: z.string(), amount }),
22
+ approve: z.object({ token: z.string(), spender: z.string(), amount }),
23
+ vault_status: z.object({}),
24
+ };
25
+ const decimal = { type: "string", description: "A decimal amount in whole tokens, e.g. 250" };
26
+ const token = { type: "string", description: "A token symbol (e.g. tUSDG) or address" };
27
+ const SCHEMAS = {
28
+ swap: {
29
+ type: "object",
30
+ properties: {
31
+ tokenIn: { ...token, description: "The token to sell: a symbol or address" },
32
+ tokenOut: { ...token, description: "The token to buy: a symbol or address" },
33
+ amountIn: { ...decimal, description: "How much tokenIn to sell, in whole tokens" },
34
+ minOut: { ...decimal, description: "Optional: the least tokenOut to accept" },
35
+ },
36
+ required: ["tokenIn", "tokenOut", "amountIn"],
37
+ additionalProperties: false,
38
+ },
39
+ transfer: {
40
+ type: "object",
41
+ properties: {
42
+ token,
43
+ to: { type: "string", description: "The recipient's 0x address" },
44
+ amount: decimal,
45
+ },
46
+ required: ["token", "to", "amount"],
47
+ additionalProperties: false,
48
+ },
49
+ approve: {
50
+ type: "object",
51
+ properties: {
52
+ token,
53
+ spender: { type: "string", description: "The 0x address allowed to spend" },
54
+ amount: { ...decimal, description: "The most it may spend, in whole tokens; 0 revokes" },
55
+ },
56
+ required: ["token", "spender", "amount"],
57
+ additionalProperties: false,
58
+ },
59
+ vault_status: { type: "object", properties: {}, additionalProperties: false },
60
+ };
61
+ const DESCRIPTIONS = {
62
+ swap: "Swap one token for another with the funds in the agent's Bonded Mandate Vault. Every trade is checked against the agent's mandate.",
63
+ transfer: "Send tokens from the agent's Bonded Mandate Vault to an address. Only the mandate's destinations are allowed.",
64
+ approve: "Let an address spend tokens from the agent's Bonded Mandate Vault. Only the mandate's contracts are allowed.",
65
+ vault_status: "The agent's Bonded Mandate Vault: its mode, whether it is frozen, breaches recorded, and its token balances.",
66
+ };
67
+ /**
68
+ * The vault's trading tools, framework-neutral: `swap`, `transfer`, `approve` (the same names and
69
+ * arguments as the Arena episode's write tools, so the agent's prompts work the same while it is
70
+ * rated) and `vault_status`. Every write goes through `BondedVault`, so the vault checks it
71
+ * against the mandate; by default each is dry-run first and refused on a predicted breach.
72
+ * `bondedVaultLangChainTools` and `bondedVaultAiSdkTools` wrap these for their frameworks.
73
+ */
74
+ export function bondedVaultTools(options) {
75
+ // While rated, the production vault's tools are refused outright: use the episode's tools.
76
+ refuseProductionVaultWhileRated(options.vault, "bondedVaultTools");
77
+ const guard = options.guard ?? true;
78
+ const tokens = tokenBook(options);
79
+ // Sentinel sees symbols and whole units: the configured tokens, else the mandate's.
80
+ let guarded;
81
+ const guardedVault = async () => {
82
+ const s = options.sentinel;
83
+ guarded ??= new GuardedVault(options.vault, s ? { sentinel: { ...s, tokens: s.tokens ?? (await tokens.list()) } } : {});
84
+ return guarded;
85
+ };
86
+ const send = async (action, given) => {
87
+ if (!guard && !options.sentinel)
88
+ return options.vault.execute(action);
89
+ const context = given ?? (options.sentinel && options.context ? await options.context() : {});
90
+ return (await guardedVault()).execute(action, context);
91
+ };
92
+ const run = async (name, raw, context, call) => {
93
+ const write = async (action, given) => (call.confirmed = await send(action, given));
94
+ const parsed = ARGS[name].safeParse(raw);
95
+ if (!parsed.success)
96
+ throw new BondedError("INVALID_ACTION", `${name}: ${parsed.error.issues.map((i) => `${i.path.join(".") || "arguments"} ${i.message}`).join(", ")}`);
97
+ const args = parsed.data;
98
+ switch (name) {
99
+ case "swap": {
100
+ const tokenIn = await tokens.resolve(args.tokenIn);
101
+ const tokenOut = await tokens.resolve(args.tokenOut);
102
+ const { holder } = await options.vault.identify();
103
+ const before = await balance(options.vault, tokenOut.address, holder);
104
+ const result = await write({
105
+ type: "swap",
106
+ tokenIn: tokenIn.address,
107
+ tokenOut: tokenOut.address,
108
+ amountIn: parseUnits(args.amountIn, tokenIn.decimals),
109
+ ...(args.minOut ? { minOut: parseUnits(args.minOut, tokenOut.decimals) } : {}),
110
+ }, context);
111
+ // The trade is confirmed: reading what it bought is best-effort. Failing here would hide
112
+ // the transactions and invite the model to trade again.
113
+ const after = await balance(options.vault, tokenOut.address, holder).catch(() => undefined);
114
+ return outcome(result, {
115
+ sold: `${args.amountIn} ${tokenIn.symbol}`,
116
+ received: after === undefined
117
+ ? null
118
+ : `${formatUnits(after - before, tokenOut.decimals)} ${tokenOut.symbol}`,
119
+ }, after === undefined ? BALANCE_UNREAD : undefined);
120
+ }
121
+ case "transfer": {
122
+ const t = await tokens.resolve(args.token);
123
+ const to = address("to", args.to);
124
+ const result = await write({
125
+ type: "transfer",
126
+ token: t.address,
127
+ to,
128
+ amount: parseUnits(args.amount, t.decimals),
129
+ }, context);
130
+ return outcome(result, { sent: `${args.amount} ${t.symbol}`, to });
131
+ }
132
+ case "approve": {
133
+ const t = await tokens.resolve(args.token);
134
+ const spender = address("spender", args.spender);
135
+ const result = await write({
136
+ type: "approve",
137
+ token: t.address,
138
+ spender,
139
+ amount: parseUnits(args.amount, t.decimals),
140
+ }, context);
141
+ return outcome(result, { approved: `${args.amount} ${t.symbol}`, spender });
142
+ }
143
+ case "vault_status": {
144
+ const status = await options.vault.status();
145
+ const known = await tokens.list();
146
+ const balances = Object.fromEntries(await Promise.all(known.map(async (t) => [
147
+ t.symbol,
148
+ formatUnits(await balance(options.vault, t.address, status.holder), t.decimals),
149
+ ])));
150
+ return {
151
+ vault: options.vault.address,
152
+ kind: status.kind,
153
+ holder: status.holder,
154
+ mode: status.mode,
155
+ frozen: status.frozen,
156
+ breachCount: status.breachCount.toString(),
157
+ balances,
158
+ };
159
+ }
160
+ }
161
+ };
162
+ return BONDED_VAULT_TOOLS.map((name) => ({
163
+ name,
164
+ description: DESCRIPTIONS[name],
165
+ inputSchema: SCHEMAS[name],
166
+ call: async (args = {}, context) => {
167
+ const call = {};
168
+ try {
169
+ refuseProductionVaultWhileRated(options.vault, name);
170
+ const output = await run(name, args, context, call);
171
+ return { ok: true, output, text: JSON.stringify(output) };
172
+ }
173
+ catch (error) {
174
+ const message = error instanceof Error ? error.message : String(error);
175
+ // Anything that fails after the write confirmed is a read: report the write, never a
176
+ // failure the model would retry (a second trade).
177
+ if (call.confirmed) {
178
+ const output = outcome(call.confirmed, {}, `The ${name} is confirmed (see transactions), but reading its result failed (${message}). Don't repeat it: check vault_status.`);
179
+ return { ok: true, output, text: JSON.stringify(output) };
180
+ }
181
+ return { ok: false, error: message, text: message };
182
+ }
183
+ },
184
+ }));
185
+ }
186
+ const BALANCE_UNREAD = "Trade confirmed (see transactions); couldn't read the new balance, so what it received is unknown. Don't repeat the trade: check vault_status.";
187
+ /**
188
+ * A write's result as the model reads it: what moved, the transactions, and any breach the vault
189
+ * recorded or anything the tool couldn't read afterwards.
190
+ */
191
+ function outcome(result, moved, unread) {
192
+ const warnings = [
193
+ ...(result.breaches.length
194
+ ? [
195
+ "The vault ran this action but recorded a breach of the mandate. The vault may have frozen the agent.",
196
+ ]
197
+ : []),
198
+ ...(unread ? [unread] : []),
199
+ ];
200
+ return {
201
+ ...moved,
202
+ transactions: result.hashes,
203
+ ...(result.breaches.length ? { breaches: result.breaches.map(breachView) } : {}),
204
+ ...(warnings.length ? { warning: warnings.join(" ") } : {}),
205
+ };
206
+ }
207
+ function breachView(b) {
208
+ return { id: b.id.toString(), type: b.type, reason: b.reason, blocked: b.blocked };
209
+ }
210
+ function address(field, value) {
211
+ if (!isAddress(value, { strict: false }))
212
+ throw new BondedError("INVALID_ACTION", `${field} must be a 0x address, not "${value}"`);
213
+ return getAddress(value);
214
+ }
215
+ function balance(vault, token, holder) {
216
+ return vault.publicClient.readContract({
217
+ address: token,
218
+ abi: erc20Abi,
219
+ functionName: "balanceOf",
220
+ args: [holder],
221
+ });
222
+ }
223
+ /**
224
+ * The tokens the model can name: the configured ones, else the mandate's assets read from the
225
+ * vault once. An unknown address is looked up on chain.
226
+ */
227
+ function tokenBook(options) {
228
+ let known;
229
+ const list = () => {
230
+ if (options.tokens)
231
+ return Promise.resolve(options.tokens);
232
+ known ??= readMandateTokens(options.vault).catch(() => {
233
+ known = undefined;
234
+ return [];
235
+ });
236
+ return known;
237
+ };
238
+ const resolve = async (value) => {
239
+ const tokens = await list();
240
+ const found = tokens.find((t) => t.symbol.toLowerCase() === value.toLowerCase() ||
241
+ t.address.toLowerCase() === value.toLowerCase());
242
+ if (found)
243
+ return found;
244
+ if (!isAddress(value, { strict: false }))
245
+ throw new BondedError("INVALID_ACTION", `unknown token "${value}"; use one of ${tokens.map((t) => t.symbol).join(", ") || "the mandate's tokens"} or a token address`);
246
+ return tokenInfo(options.vault, getAddress(value));
247
+ };
248
+ return { list, resolve };
249
+ }
250
+ async function readMandateTokens(vault) {
251
+ const assets = await vault.publicClient.readContract({
252
+ address: vault.address,
253
+ abi: mandateVaultAbi,
254
+ functionName: "getAssets",
255
+ });
256
+ return Promise.all(assets.map((a) => tokenInfo(vault, a)));
257
+ }
258
+ async function tokenInfo(vault, address) {
259
+ const read = (functionName) => vault.publicClient.readContract({ address, abi: erc20Abi, functionName });
260
+ const [symbol, decimals] = await Promise.all([
261
+ read("symbol").catch(() => address),
262
+ read("decimals"),
263
+ ]);
264
+ return { symbol, address, decimals };
265
+ }
266
+ /**
267
+ * The production vault from the environment, or undefined when `BONDED_VAULT_ADDRESS` isn't set
268
+ * (so the same code runs before the agent has a vault):
269
+ *
270
+ * | Variable | Meaning |
271
+ * |---|---|
272
+ * | `BONDED_VAULT_ADDRESS` | The Mandate Vault (or MandateModule) |
273
+ * | `BONDED_AGENT_KEY` | The vault's agent key (0x private key), required with the address |
274
+ * | `BONDED_VAULT_CHAIN_ID` | Default 46630 (Robinhood Chain testnet) |
275
+ * | `BONDED_VAULT_RPC_URL` | Default: the chain's public RPC |
276
+ * | `BONDED_ROUTER_ADDRESS` | The swap venue your mandate allows (Bonded's `DemoRouter` on testnet) |
277
+ *
278
+ * These are different from the `BONDED_*` variables the runner sets for an episode, and the
279
+ * runner removes them from a rated agent's environment. If they come back anyway (a `.env` file
280
+ * reloaded with `node --env-file` or dotenv), this still returns undefined while the process is
281
+ * rated, and warns once: a rating never trades the production vault.
282
+ */
283
+ export function bondedVaultFromEnv(env = typeof process === "undefined" ? {} : process.env) {
284
+ const vault = env.BONDED_VAULT_ADDRESS?.trim();
285
+ // A rated process never builds the production vault, even when its variables are back (a
286
+ // .env file reloaded with `node --env-file` or dotenv): undefined, as if they weren't set.
287
+ if (isRatedProcess(env) || isRatedProcess()) {
288
+ if (vault || env.BONDED_AGENT_KEY?.trim())
289
+ warnRatedOnce();
290
+ return undefined;
291
+ }
292
+ if (!vault)
293
+ return undefined;
294
+ const problems = [];
295
+ if (!isAddress(vault, { strict: false }))
296
+ problems.push("BONDED_VAULT_ADDRESS isn't an address");
297
+ const key = env.BONDED_AGENT_KEY?.trim();
298
+ if (!key)
299
+ problems.push("BONDED_AGENT_KEY (the vault's agent key) isn't set");
300
+ else if (!isHex(key) || key.length !== 66)
301
+ problems.push("BONDED_AGENT_KEY must be a 0x-prefixed 32-byte private key");
302
+ const chainId = Number(env.BONDED_VAULT_CHAIN_ID?.trim() || EVM_CHAINS.robinhoodTestnet.chainId);
303
+ if (!Number.isSafeInteger(chainId) || chainId <= 0)
304
+ problems.push("BONDED_VAULT_CHAIN_ID must be a chain id");
305
+ const known = evmChainById(chainId);
306
+ const rpcUrl = env.BONDED_VAULT_RPC_URL?.trim() || known?.rpcUrl;
307
+ if (!rpcUrl)
308
+ problems.push(`BONDED_VAULT_RPC_URL isn't set (no default RPC for chain ${chainId})`);
309
+ const router = env.BONDED_ROUTER_ADDRESS?.trim();
310
+ if (router && !isAddress(router, { strict: false }))
311
+ problems.push("BONDED_ROUTER_ADDRESS isn't an address");
312
+ if (problems.length)
313
+ throw new BondedError("CONFIG", problems.join("; "));
314
+ const built = new BondedVault({
315
+ vault: vault,
316
+ chain: defineChain({
317
+ id: chainId,
318
+ name: known?.name ?? `Chain ${chainId}`,
319
+ nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
320
+ rpcUrls: { default: { http: [rpcUrl] } },
321
+ }),
322
+ rpcUrl: rpcUrl,
323
+ account: privateKeyToAccount(key),
324
+ ...(router ? { router: router } : {}),
325
+ });
326
+ return markProductionVault(built);
327
+ }
328
+ let warnedRated = false;
329
+ function warnRatedOnce() {
330
+ if (warnedRated)
331
+ return;
332
+ warnedRated = true;
333
+ console.warn(`[bonded] ${ratedProductionVaultError("bondedVaultFromEnv").message}`);
334
+ }
335
+ //# sourceMappingURL=vault-tools.js.map
@@ -0,0 +1,116 @@
1
+ import { type Account, type Address, type Chain, type Hex, type PublicClient, type Transport, type WalletClient } from "viem";
2
+ import { type ApproveParams, type CallParams, type SwapParams, type SwapRouter, type TransferParams, type VaultAction, type VaultCall } from "./actions.js";
3
+ import { type DryRunResult, type VaultBreach } from "./breaches.js";
4
+ import { BondedError } from "./errors.js";
5
+ export interface BondedVaultConfig {
6
+ /**
7
+ * The Mandate Vault's address, or a MandateModule's (the mandate on an ERC-7579 smart
8
+ * account). The SDK tells them apart on chain.
9
+ */
10
+ vault: Address;
11
+ /** Reads the chain. Built from `chain` (and `rpcUrl`) when left out. */
12
+ publicClient?: PublicClient<Transport, Chain | undefined>;
13
+ /** Sends as the vault's agent key. Built from `account` (and `chain`, `rpcUrl`) when left out. */
14
+ walletClient?: WalletClient<Transport, Chain | undefined, Account>;
15
+ /** The vault's agent key. Without it (or a wallet client) the vault is read-only. */
16
+ account?: Account;
17
+ chain?: Chain;
18
+ /** RPC URL. Defaults to the public client's, or the chain's own. */
19
+ rpcUrl?: string;
20
+ /**
21
+ * Where `swap` trades: an allowed target of the mandate. An address means Bonded's testnet
22
+ * market (`DemoRouter`); pass a `SwapRouter` for any other venue.
23
+ */
24
+ router?: Address | SwapRouter;
25
+ }
26
+ /** What the vault (or module) is and whether it will act. */
27
+ export interface VaultStatus {
28
+ /** A Mandate Vault holds the funds itself; a MandateModule guards a smart account's. */
29
+ kind: "vault" | "module";
30
+ /** Where the funds are: the vault itself, or the module's smart account. */
31
+ holder: Address;
32
+ /** The agent can't act until the guardian unfreezes the vault. */
33
+ frozen: boolean;
34
+ /** Monitor lets breaches through and records them; Enforce blocks and records them. */
35
+ mode: "monitor" | "enforce";
36
+ breachCount: bigint;
37
+ /** The key that can call `execute`. */
38
+ agent: Address;
39
+ /** Can freeze, unfreeze and rotate the agent key. */
40
+ guardian: Address;
41
+ mandateHash: Hex;
42
+ agentId: bigint;
43
+ freezeOnBreach: boolean;
44
+ }
45
+ /** What a write did. Monitor mode lets breaches through: check `breaches`. */
46
+ export interface ActionResult {
47
+ /** One transaction per `execute` sent (a swap may need an approval first). */
48
+ hashes: Hex[];
49
+ /** Breaches the vault recorded while running the action. Empty when it kept to the mandate. */
50
+ breaches: VaultBreach[];
51
+ }
52
+ /**
53
+ * A Mandate Vault, from the agent's side. Every write is `MandateVault.execute(target, data)`
54
+ * sent from the agent key, so the vault checks it against the mandate and records any breach.
55
+ *
56
+ * ```ts
57
+ * const vault = new BondedVault({ vault, chain, account: privateKeyToAccount(agentKey) });
58
+ * const check = await vault.dryRun({ type: "transfer", token, to, amount });
59
+ * if (check.ok) await vault.transfer({ token, to, amount });
60
+ * ```
61
+ */
62
+ export declare class BondedVault {
63
+ readonly address: Address;
64
+ readonly publicClient: PublicClient<Transport, Chain | undefined>;
65
+ readonly walletClient: WalletClient<Transport, Chain | undefined, Account> | undefined;
66
+ private readonly router;
67
+ private identity;
68
+ constructor(config: BondedVaultConfig);
69
+ /** The address that sends this vault's actions, if it can send. */
70
+ get agentAddress(): Address | undefined;
71
+ status(): Promise<VaultStatus>;
72
+ /**
73
+ * Whether this is a Mandate Vault or a MandateModule, and where its funds are (the vault
74
+ * itself, or the module's account). Read once from the chain: a module has `account()`.
75
+ */
76
+ identify(): Promise<{
77
+ kind: "vault" | "module";
78
+ holder: Address;
79
+ }>;
80
+ /** The vault's breach log, oldest first (from `fromId`, default 0). */
81
+ breaches(fromId?: bigint): Promise<VaultBreach[]>;
82
+ swap(params: SwapParams): Promise<ActionResult>;
83
+ transfer(params: TransferParams): Promise<ActionResult>;
84
+ approve(params: ApproveParams): Promise<ActionResult>;
85
+ call(params: CallParams): Promise<ActionResult>;
86
+ /**
87
+ * Sends an action through the vault and waits for it. Resolves when the vault ran it (in
88
+ * Monitor mode possibly with breaches recorded: see `breaches`). Throws `BlockedByMandateError`
89
+ * when Enforce mode stopped it, `VaultFrozenError` when the vault is or became frozen,
90
+ * `NotAgentError` for the wrong key and `CallRevertedError` when the call itself failed.
91
+ */
92
+ execute(action: VaultAction): Promise<ActionResult>;
93
+ /**
94
+ * What the vault would do with `action` right now: simulates `execute` from the agent key
95
+ * against the chain's current state (`eth_simulateV1`) and reads the vault's own events, so
96
+ * the verdict is the contract's, never a copy of its rules. Nothing is sent.
97
+ *
98
+ * Throws what sending would throw before the vault judges anything: `VaultFrozenError`,
99
+ * `NotAgentError`, `CallRevertedError`.
100
+ */
101
+ dryRun(action: VaultAction): Promise<DryRunResult>;
102
+ /** The `execute` calls an action takes, in order. A swap approves the router first if needed. */
103
+ plan(action: VaultAction): Promise<VaultCall[]>;
104
+ private requireWallet;
105
+ }
106
+ /**
107
+ * Whether this process is being rated: the runner set a Bonded episode's variables. Fails closed:
108
+ * a `BONDED_EPISODE_ID` alone counts, even when the rest of the episode's variables are malformed.
109
+ */
110
+ export declare function isRatedProcess(env?: Record<string, string | undefined>): boolean;
111
+ /** Marks `vault` as the production vault (internal: `bondedVaultFromEnv` calls it). */
112
+ export declare function markProductionVault(vault: BondedVault): BondedVault;
113
+ /** Throws `BondedError` (`RATED_PRODUCTION_VAULT`) when `vault` is the production vault and this process is rated. */
114
+ export declare function refuseProductionVaultWhileRated(vault: BondedVault, what: string): void;
115
+ export declare function ratedProductionVaultError(what: string): BondedError;
116
+ //# sourceMappingURL=vault.d.ts.map