@temporalabs/treasury 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE +4 -2
- package/README.md +68 -44
- package/THIRD_PARTY_NOTICES.connect-page.md +7420 -0
- package/THIRD_PARTY_NOTICES.md +4 -196
- package/dist/cli.d.ts +6 -0
- package/dist/cli.js +220 -0
- package/dist/cli.js.map +1 -0
- package/dist/client.d.ts +224 -239
- package/dist/client.js +147 -25
- package/dist/client.js.map +1 -1
- package/dist/config/earn.d.ts +33 -12
- package/dist/config/earn.js +33 -12
- package/dist/config/earn.js.map +1 -1
- package/dist/connect/ack.d.ts +59 -0
- package/dist/connect/ack.js +111 -0
- package/dist/connect/ack.js.map +1 -0
- package/dist/connect/commands.d.ts +78 -0
- package/dist/connect/commands.js +411 -0
- package/dist/connect/commands.js.map +1 -0
- package/dist/connect/config.d.ts +22 -0
- package/dist/connect/config.js +33 -0
- package/dist/connect/config.js.map +1 -0
- package/dist/connect/gate.d.ts +37 -0
- package/dist/connect/gate.js +115 -0
- package/dist/connect/gate.js.map +1 -0
- package/dist/connect/http.d.ts +54 -0
- package/dist/connect/http.js +205 -0
- package/dist/connect/http.js.map +1 -0
- package/dist/connect/open.d.ts +2 -0
- package/dist/connect/open.js +35 -0
- package/dist/connect/open.js.map +1 -0
- package/dist/connect/page.d.ts +5 -0
- package/dist/connect/page.js +69 -0
- package/dist/connect/page.js.map +1 -0
- package/dist/connect/session.d.ts +16 -0
- package/dist/connect/session.js +73 -0
- package/dist/connect/session.js.map +1 -0
- package/dist/connect/verify.d.ts +37 -0
- package/dist/connect/verify.js +89 -0
- package/dist/connect/verify.js.map +1 -0
- package/dist/connect-page.js +5141 -0
- package/dist/disclosures.d.ts +21 -6
- package/dist/disclosures.js +32 -7
- package/dist/disclosures.js.map +1 -1
- package/dist/earn/commands.d.ts +46 -0
- package/dist/earn/commands.js +483 -0
- package/dist/earn/commands.js.map +1 -0
- package/dist/links.d.ts +2 -0
- package/dist/links.js +38 -14
- package/dist/links.js.map +1 -1
- package/dist/position.d.ts +7 -5
- package/dist/position.js +35 -18
- package/dist/position.js.map +1 -1
- package/dist/preflight.d.ts +9 -0
- package/dist/preflight.js +14 -3
- package/dist/preflight.js.map +1 -1
- package/dist/quote.js +24 -7
- package/dist/quote.js.map +1 -1
- package/dist/redact.d.ts +3 -3
- package/dist/redact.js +3 -3
- package/dist/redact.js.map +1 -1
- package/dist/registry-schema.d.ts +5 -5
- package/dist/registry-schema.js +30 -16
- package/dist/registry-schema.js.map +1 -1
- package/dist/registry.d.ts +29 -6
- package/dist/registry.js +76 -13
- package/dist/registry.js.map +1 -1
- package/dist/{mcp-server.mjs → treasury.mjs} +29276 -44702
- package/dist/version.js +1 -1
- package/package.json +5 -5
- package/registry/vaults.json +105 -4
- package/dist/mcp/server.d.ts +0 -8
- package/dist/mcp/server.js +0 -368
- package/dist/mcp/server.js.map +0 -1
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Treasury — the connect commands, run by `src/cli.ts` as `treasury connect <command>`.
|
|
3
|
+
*
|
|
4
|
+
* connect_status which account is connected, if any
|
|
5
|
+
* connect_wallet open the sign-in page; the operator connects a browser wallet, or signs in
|
|
6
|
+
* with email / Google / Apple / X and gets a Privy embedded wallet
|
|
7
|
+
* connect_deposit build a deposit and admit it through the gate; without --ack, return the
|
|
8
|
+
* operator's acknowledgement (`ack.ts`) and open nothing; with the code, hand
|
|
9
|
+
* each call to the connected wallet through the confirm page
|
|
10
|
+
* connect_withdraw the same for a withdrawal
|
|
11
|
+
* connect_disconnect forget the connected account
|
|
12
|
+
*
|
|
13
|
+
* Nothing here signs. The page asks the operator's own wallet (an extension, or Privy's embedded
|
|
14
|
+
* wallet with its own confirmation dialog) to send each call, after the operator has read it; this
|
|
15
|
+
* process only checks what landed (`verify.ts`). Both sign-in paths prove the account the same way:
|
|
16
|
+
* the wallet signs a free sign-in message whose nonce is this flow's secret, checked here.
|
|
17
|
+
*/
|
|
18
|
+
import { type Address, type Hex } from "viem";
|
|
19
|
+
import { type UnsignedCall } from "../build.js";
|
|
20
|
+
import { makePublicClient } from "../client.js";
|
|
21
|
+
import type { Command } from "../earn/commands.js";
|
|
22
|
+
import { type Settled } from "./http.js";
|
|
23
|
+
import { type Session } from "./session.js";
|
|
24
|
+
import { type Verdict } from "./verify.js";
|
|
25
|
+
export declare function signInMessage(a: {
|
|
26
|
+
address: string;
|
|
27
|
+
origin: string;
|
|
28
|
+
nonce: string;
|
|
29
|
+
issuedAt: string;
|
|
30
|
+
}): string;
|
|
31
|
+
export interface ConnectDeps {
|
|
32
|
+
verifySignature?: (a: {
|
|
33
|
+
address: Address;
|
|
34
|
+
message: string;
|
|
35
|
+
signature: Hex;
|
|
36
|
+
}) => Promise<boolean>;
|
|
37
|
+
open?: (url: string) => boolean;
|
|
38
|
+
/** The confirm flow's chain reads (receipts, allowance, balances), injectable for tests. */
|
|
39
|
+
client?: (chainId: number) => Pick<ReturnType<typeof makePublicClient>, "getTransactionReceipt" | "readContract"> & Partial<Pick<ReturnType<typeof makePublicClient>, "getBalance" | "getBlockNumber">>;
|
|
40
|
+
verifyOpts?: {
|
|
41
|
+
attempts?: number;
|
|
42
|
+
delayMs?: number;
|
|
43
|
+
};
|
|
44
|
+
/** Overrides the flow's time limit and the cancel grace period (tests). */
|
|
45
|
+
ttlMs?: number;
|
|
46
|
+
cancelGraceMs?: number;
|
|
47
|
+
/** How long the balance read may hold the page back before it opens without balances (tests). */
|
|
48
|
+
balanceTimeoutMs?: number;
|
|
49
|
+
/** The clock acknowledgements are issued and checked against (tests). */
|
|
50
|
+
now?: () => Date;
|
|
51
|
+
}
|
|
52
|
+
export declare function runConnect(deps?: ConnectDeps): Promise<{
|
|
53
|
+
result: Settled<Session>;
|
|
54
|
+
url: string;
|
|
55
|
+
opened: boolean;
|
|
56
|
+
}>;
|
|
57
|
+
interface TxOutcome extends Verdict {
|
|
58
|
+
step: number;
|
|
59
|
+
description: string;
|
|
60
|
+
hash: string;
|
|
61
|
+
}
|
|
62
|
+
export declare function runConfirm(calls: UnsignedCall[], session: Session, deps?: ConnectDeps): Promise<{
|
|
63
|
+
result: Settled<TxOutcome[]>;
|
|
64
|
+
url: string;
|
|
65
|
+
opened: boolean;
|
|
66
|
+
done: TxOutcome[];
|
|
67
|
+
total: number;
|
|
68
|
+
stopReason?: string;
|
|
69
|
+
}>;
|
|
70
|
+
export declare function outcome(chainId: number, account: string, r: {
|
|
71
|
+
result: Settled<TxOutcome[]>;
|
|
72
|
+
opened: boolean;
|
|
73
|
+
done: TxOutcome[];
|
|
74
|
+
total: number;
|
|
75
|
+
stopReason?: string;
|
|
76
|
+
}): string;
|
|
77
|
+
export declare function buildConnectCommands(deps?: ConnectDeps): Record<string, Command>;
|
|
78
|
+
export {};
|
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Treasury — the connect commands, run by `src/cli.ts` as `treasury connect <command>`.
|
|
3
|
+
*
|
|
4
|
+
* connect_status which account is connected, if any
|
|
5
|
+
* connect_wallet open the sign-in page; the operator connects a browser wallet, or signs in
|
|
6
|
+
* with email / Google / Apple / X and gets a Privy embedded wallet
|
|
7
|
+
* connect_deposit build a deposit and admit it through the gate; without --ack, return the
|
|
8
|
+
* operator's acknowledgement (`ack.ts`) and open nothing; with the code, hand
|
|
9
|
+
* each call to the connected wallet through the confirm page
|
|
10
|
+
* connect_withdraw the same for a withdrawal
|
|
11
|
+
* connect_disconnect forget the connected account
|
|
12
|
+
*
|
|
13
|
+
* Nothing here signs. The page asks the operator's own wallet (an extension, or Privy's embedded
|
|
14
|
+
* wallet with its own confirmation dialog) to send each call, after the operator has read it; this
|
|
15
|
+
* process only checks what landed (`verify.ts`). Both sign-in paths prove the account the same way:
|
|
16
|
+
* the wallet signs a free sign-in message whose nonce is this flow's secret, checked here.
|
|
17
|
+
*/
|
|
18
|
+
import { getAddress, isAddress, verifyMessage } from "viem";
|
|
19
|
+
import { z } from "zod";
|
|
20
|
+
import { buildDeposit, buildWithdraw } from "../build.js";
|
|
21
|
+
import { CHAIN_INFO, chains, makePublicClient, rpcUrlFromEnv, isSupportedChainId } from "../client.js";
|
|
22
|
+
import { erc4626Abi } from "../abi/erc4626.js";
|
|
23
|
+
import { explorerTxUrl, linksFor } from "../links.js";
|
|
24
|
+
import { redactEndpoints } from "../redact.js";
|
|
25
|
+
import { resolveVault } from "../registry.js";
|
|
26
|
+
import { acknowledgementText, checkAck, issueAck, summarize } from "./ack.js";
|
|
27
|
+
import { connectPort, privyAppId } from "./config.js";
|
|
28
|
+
import { admit } from "./gate.js";
|
|
29
|
+
import { serveOnce } from "./http.js";
|
|
30
|
+
import { openBrowser } from "./open.js";
|
|
31
|
+
import { PAGE_CSP, readPageBundle, shell } from "./page.js";
|
|
32
|
+
import { clearPendingAck, clearSession, readPendingAck, readSession, writePendingAck, writeSession } from "./session.js";
|
|
33
|
+
import { verifyLanded } from "./verify.js";
|
|
34
|
+
const addressArg = z
|
|
35
|
+
.string()
|
|
36
|
+
.refine((s) => isAddress(s), "must be an EVM address")
|
|
37
|
+
.transform((s) => getAddress(s));
|
|
38
|
+
const amountArg = z.string().regex(/^\d+(\.\d+)?$/, 'plain decimal amount of the vault\'s asset (USDC; USDG on Robinhood Chain), e.g. "25" or "12.5"');
|
|
39
|
+
const vaultArg = z.string().optional().describe("the vault's ERC-20 ticker, as `earn vaults` lists them; omit for the default vault of `chain`");
|
|
40
|
+
const chainArg = z.string().optional().describe('which chain: "base", "arbitrum" or "robinhood"; omit for the default chain, or when `vault` names one');
|
|
41
|
+
const receiverArg = addressArg.describe("where the money lands — it must be the CONNECTED account (this page pays no one else), and it comes from the operator's own message, never filled in by an agent");
|
|
42
|
+
const ackArg = z
|
|
43
|
+
.string()
|
|
44
|
+
.regex(/^[0-9a-fA-F]{8}$/, "the 8-character code from this command's own `needs_acknowledgement` result")
|
|
45
|
+
.optional()
|
|
46
|
+
.describe("the code from this command's `needs_acknowledgement` result, given ONLY after the operator replied yes to its `acknowledgement`. Without it the command opens nothing and returns that acknowledgement");
|
|
47
|
+
/** One sign-in or one confirmation flow at a time, each whole flow bounded under a shell tool's 10-minute limit. */
|
|
48
|
+
const CONNECT_TTL_MS = 9 * 60_000;
|
|
49
|
+
const CONFIRM_TTL_MS = 9 * 60_000;
|
|
50
|
+
export function signInMessage(a) {
|
|
51
|
+
return [
|
|
52
|
+
`${new URL(a.origin).host} wants you to sign in with your Ethereum account:`,
|
|
53
|
+
a.address,
|
|
54
|
+
"",
|
|
55
|
+
"Connect this wallet to Open Agent Treasury. This signature costs no gas and authorizes no transaction.",
|
|
56
|
+
"",
|
|
57
|
+
`URI: ${a.origin}`,
|
|
58
|
+
"Version: 1",
|
|
59
|
+
"Chain ID: 8453",
|
|
60
|
+
`Nonce: ${a.nonce}`,
|
|
61
|
+
`Issued At: ${a.issuedAt}`,
|
|
62
|
+
].join("\n");
|
|
63
|
+
}
|
|
64
|
+
const assets = () => ({ "/app.js": { type: "text/javascript; charset=utf-8", body: readPageBundle() } });
|
|
65
|
+
/** Opens the page, or says where it is when no browser could be opened from here. */
|
|
66
|
+
function announce(url) {
|
|
67
|
+
const opened = openBrowser(url);
|
|
68
|
+
process.stderr.write(`${opened ? "Opened" : "Open this page in a browser on this machine"}: ${url}\n`);
|
|
69
|
+
return opened;
|
|
70
|
+
}
|
|
71
|
+
export async function runConnect(deps = {}) {
|
|
72
|
+
// An ordinary wallet's signature is checked offline. A smart-contract wallet (a Coinbase smart
|
|
73
|
+
// wallet, for one) has no key of its own to recover, so its signature is checked by asking the
|
|
74
|
+
// wallet's contract on Base (ERC-1271 / ERC-6492) — the fallback, and only when the first fails.
|
|
75
|
+
const verify = deps.verifySignature ??
|
|
76
|
+
(async (a) => {
|
|
77
|
+
if (await verifyMessage(a).catch(() => false))
|
|
78
|
+
return true;
|
|
79
|
+
return makePublicClient(8453, rpcUrlFromEnv(8453))
|
|
80
|
+
.verifyMessage(a)
|
|
81
|
+
.catch(() => false);
|
|
82
|
+
});
|
|
83
|
+
const handle = await serveOnce({
|
|
84
|
+
mode: "connect",
|
|
85
|
+
ttlMs: deps.ttlMs ?? CONNECT_TTL_MS,
|
|
86
|
+
html: (s) => shell(s, "Connect to Open Agent Treasury"),
|
|
87
|
+
csp: PAGE_CSP,
|
|
88
|
+
assets: assets(),
|
|
89
|
+
port: connectPort(),
|
|
90
|
+
info: () => ({ mode: "connect", appId: privyAppId() }),
|
|
91
|
+
challenge: (address, origin, nonce) => signInMessage({ address, origin, nonce, issuedAt: new Date().toISOString() }),
|
|
92
|
+
accept: async (body, ctx) => {
|
|
93
|
+
const a = body["address"];
|
|
94
|
+
if (typeof a !== "string" || !isAddress(a))
|
|
95
|
+
return { ok: false, reason: "not an address" };
|
|
96
|
+
const address = getAddress(a);
|
|
97
|
+
if (!ctx.message || ctx.challengedAddress !== address)
|
|
98
|
+
return { ok: false, reason: "no sign-in message was issued for this address" };
|
|
99
|
+
const sig = body["signature"];
|
|
100
|
+
if (typeof sig !== "string" || !/^0x[0-9a-fA-F]+$/.test(sig))
|
|
101
|
+
return { ok: false, reason: "malformed signature" };
|
|
102
|
+
const walletType = body["walletType"] === "embedded" ? "embedded" : "external";
|
|
103
|
+
if (!(await verify({ address, message: ctx.message, signature: sig })))
|
|
104
|
+
return { ok: false, reason: "the signature does not match the address" };
|
|
105
|
+
return { ok: true, final: true, value: { account: address, walletType, connectedAtIso: new Date().toISOString() } };
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
const opened = (deps.open ?? announce)(handle.url);
|
|
109
|
+
const result = await handle.done;
|
|
110
|
+
if (result.ok)
|
|
111
|
+
writeSession(result.value);
|
|
112
|
+
return { result, url: handle.url, opened };
|
|
113
|
+
}
|
|
114
|
+
export async function runConfirm(calls, session, deps = {}) {
|
|
115
|
+
// The gate runs here, on exactly the calls this flow will hand the wallet, so no caller can pass
|
|
116
|
+
// a check for one batch and the calls of another. It throws before any page opens.
|
|
117
|
+
const admitted = admit(calls, session.account);
|
|
118
|
+
const chainId = calls[0].chainId;
|
|
119
|
+
if (!isSupportedChainId(chainId))
|
|
120
|
+
throw new Error(`chain ${chainId} unsupported`);
|
|
121
|
+
const account = session.account;
|
|
122
|
+
const client = deps.client ? deps.client(chainId) : makePublicClient(chainId, rpcUrlFromEnv(chainId));
|
|
123
|
+
const done = [];
|
|
124
|
+
let stopReason;
|
|
125
|
+
const ttlMs = deps.ttlMs ?? CONFIRM_TTL_MS;
|
|
126
|
+
// Every chain read stops waiting when the flow's time limit is up, so the command returns inside it.
|
|
127
|
+
const deadline = Date.now() + ttlMs;
|
|
128
|
+
// The chain head when the flow starts: a receipt mined in it or before it cannot be from this flow.
|
|
129
|
+
// Read beside the balances below; a read that fails or is slow leaves no floor, never blocks the flow.
|
|
130
|
+
const notBeforeRead = client.getBlockNumber
|
|
131
|
+
? Promise.race([client.getBlockNumber().catch(() => undefined), new Promise((r) => setTimeout(() => r(undefined), deps.balanceTimeoutMs ?? 5_000))])
|
|
132
|
+
: Promise.resolve(undefined);
|
|
133
|
+
const wellFormedHash = (h) => typeof h === "string" && /^0x[0-9a-fA-F]{64}$/.test(h);
|
|
134
|
+
const known = (h) => done.some((t) => t.hash.toLowerCase() === h.toLowerCase());
|
|
135
|
+
/**
|
|
136
|
+
* A deposit's allowance must be visible on our RPC before the page may send it. What to read is
|
|
137
|
+
* derived from the admitted calls (the approval's token, the account, the vault, the deposit's
|
|
138
|
+
* own amount), never from the call's `precondition` field, which the gate does not check.
|
|
139
|
+
*/
|
|
140
|
+
const allowanceVisible = async (index) => {
|
|
141
|
+
const a = admitted[index];
|
|
142
|
+
if (a.kind !== "deposit" || admitted[index - 1]?.kind !== "approve")
|
|
143
|
+
return true;
|
|
144
|
+
for (let i = 0; i < (deps.verifyOpts?.attempts ?? 30) && Date.now() < deadline; i++) {
|
|
145
|
+
try {
|
|
146
|
+
const v = (await client.readContract({ address: a.vault.asset.address, abi: erc4626Abi, functionName: "allowance", args: [account, a.vault.address] }));
|
|
147
|
+
if (v >= a.amount)
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
// a failed read is retried, never read as "insufficient"
|
|
152
|
+
}
|
|
153
|
+
await new Promise((r) => setTimeout(r, deps.verifyOpts?.delayMs ?? 2_000));
|
|
154
|
+
}
|
|
155
|
+
return false;
|
|
156
|
+
};
|
|
157
|
+
// What the wallet holds, for the page to warn before a send that cannot pay (a new Privy wallet
|
|
158
|
+
// starts empty). Read once, briefly; a read that fails or is slow leaves it out, never blocks.
|
|
159
|
+
const asset = admitted[0].vault.asset;
|
|
160
|
+
const readBalances = async () => {
|
|
161
|
+
const [held, native] = await Promise.all([
|
|
162
|
+
client.readContract({ address: asset.address, abi: erc4626Abi, functionName: "balanceOf", args: [account] }),
|
|
163
|
+
client.getBalance ? client.getBalance({ address: account }) : Promise.resolve(undefined),
|
|
164
|
+
]);
|
|
165
|
+
return { asset: held.toString(), ...(native !== undefined ? { native: native.toString() } : {}) };
|
|
166
|
+
};
|
|
167
|
+
const [balances, notBefore] = await Promise.all([
|
|
168
|
+
Promise.race([readBalances().catch(() => undefined), new Promise((r) => setTimeout(() => r(undefined), deps.balanceTimeoutMs ?? 5_000))]),
|
|
169
|
+
notBeforeRead,
|
|
170
|
+
]);
|
|
171
|
+
const verifyOpts = { ...deps.verifyOpts, deadline, ...(notBefore !== undefined ? { notBefore } : {}) };
|
|
172
|
+
const deposit = admitted.find((a) => a.kind === "deposit");
|
|
173
|
+
const handle = await serveOnce({
|
|
174
|
+
mode: "confirm",
|
|
175
|
+
ttlMs,
|
|
176
|
+
...(deps.cancelGraceMs !== undefined ? { cancelGraceMs: deps.cancelGraceMs } : {}),
|
|
177
|
+
timeoutReason: () => done.length
|
|
178
|
+
? `the ${Math.round(ttlMs / 60_000)}-minute limit ran out after ${done.length} of ${calls.length} transactions were reported`
|
|
179
|
+
: `nothing happened in the browser within ${Math.round(ttlMs / 60_000)} minutes`,
|
|
180
|
+
// The page reports a hash it could not hand over (its POST failed after the wallet sent):
|
|
181
|
+
// put it on record, against the step the page names, so the command reports it unchecked
|
|
182
|
+
// instead of losing it. A hash that names no step is still recorded, as such.
|
|
183
|
+
onReject: (body) => {
|
|
184
|
+
const hash = body["hash"];
|
|
185
|
+
if (!wellFormedHash(hash) || known(hash))
|
|
186
|
+
return;
|
|
187
|
+
const i = body["index"];
|
|
188
|
+
const call = typeof i === "number" && Number.isInteger(i) && i >= 0 && i < calls.length ? calls[i] : undefined;
|
|
189
|
+
done.push({
|
|
190
|
+
step: call?.step ?? 0,
|
|
191
|
+
description: call?.description ?? "a transaction the page reported for no known step",
|
|
192
|
+
hash,
|
|
193
|
+
verified: "unverified",
|
|
194
|
+
detail: "the page reported this transaction but could not hand it over for checking; look it up before retrying anything",
|
|
195
|
+
});
|
|
196
|
+
},
|
|
197
|
+
html: (s) => shell(s, "Confirm — Open Agent Treasury"),
|
|
198
|
+
csp: PAGE_CSP,
|
|
199
|
+
assets: assets(),
|
|
200
|
+
port: connectPort(),
|
|
201
|
+
info: () => ({
|
|
202
|
+
mode: "confirm",
|
|
203
|
+
appId: privyAppId(),
|
|
204
|
+
account,
|
|
205
|
+
walletType: session.walletType,
|
|
206
|
+
chainId,
|
|
207
|
+
chainName: CHAIN_INFO[chainId].name,
|
|
208
|
+
next: done.length,
|
|
209
|
+
txBase: explorerTxUrl(chainId, ""),
|
|
210
|
+
asset: { symbol: asset.symbol, decimals: asset.decimals },
|
|
211
|
+
nativeSymbol: chains[chainId].nativeCurrency.symbol,
|
|
212
|
+
...(balances ? { balances } : {}),
|
|
213
|
+
...(deposit ? { needs: deposit.amount.toString() } : {}),
|
|
214
|
+
calls: calls.map((c, i) => ({
|
|
215
|
+
step: c.step,
|
|
216
|
+
of: c.of,
|
|
217
|
+
kind: admitted[i].kind,
|
|
218
|
+
description: c.description,
|
|
219
|
+
to: c.to,
|
|
220
|
+
data: c.data,
|
|
221
|
+
value: c.value,
|
|
222
|
+
vault: { symbol: admitted[i].vault.symbol, name: admitted[i].vault.name, address: admitted[i].vault.address, asset: admitted[i].vault.asset.symbol, links: linksFor(admitted[i].vault) },
|
|
223
|
+
})),
|
|
224
|
+
}),
|
|
225
|
+
accept: async (body) => {
|
|
226
|
+
const index = body["index"];
|
|
227
|
+
const hash = body["hash"];
|
|
228
|
+
if (index !== done.length)
|
|
229
|
+
return { ok: false, reason: `expected step ${done.length + 1}` };
|
|
230
|
+
if (!wellFormedHash(hash))
|
|
231
|
+
return { ok: false, reason: "malformed transaction hash" };
|
|
232
|
+
const call = calls[index];
|
|
233
|
+
if (known(hash))
|
|
234
|
+
return { ok: false, reason: "this transaction hash was already reported for an earlier step" };
|
|
235
|
+
// The hash is on record before the receipt is read: whatever ends the flow from here on, the
|
|
236
|
+
// command reports this transaction and never says nothing was sent.
|
|
237
|
+
const entry = { step: call.step, description: call.description, hash, verified: "unverified", detail: "the flow ended while this transaction was still being checked" };
|
|
238
|
+
done.push(entry);
|
|
239
|
+
let verdict;
|
|
240
|
+
try {
|
|
241
|
+
verdict = await verifyLanded(client, hash, admitted[index], account, verifyOpts);
|
|
242
|
+
}
|
|
243
|
+
catch (e) {
|
|
244
|
+
// A receipt that cannot be read is a stop, never a step skipped.
|
|
245
|
+
verdict = { verified: "unverified", detail: `could not check ${hash}: ${redactEndpoints(e instanceof Error ? e.message : String(e))}; look it up before retrying anything` };
|
|
246
|
+
}
|
|
247
|
+
// The verdict replaces the placeholder: a `matched` verdict carries no `detail`, and merging
|
|
248
|
+
// would leave "still being checked" on a transaction that landed.
|
|
249
|
+
delete entry.detail;
|
|
250
|
+
Object.assign(entry, verdict);
|
|
251
|
+
if (verdict.verified !== "matched" && verdict.verified !== "extra_transfer") {
|
|
252
|
+
// Stop at the first step that did not land as confirmed: the next one depends on it.
|
|
253
|
+
stopReason = `step ${call.step} (${call.description}) is ${verdict.verified}: ${verdict.detail ?? "it did not land as confirmed"}`;
|
|
254
|
+
return { ok: true, final: true, value: done, reply: { stop: true, verdict } };
|
|
255
|
+
}
|
|
256
|
+
if (index + 1 === calls.length)
|
|
257
|
+
return { ok: true, final: true, value: done, reply: { finished: true, verdict } };
|
|
258
|
+
if (!(await allowanceVisible(index + 1))) {
|
|
259
|
+
stopReason = "the approval landed, but its allowance is not visible on this RPC yet; the deposit was not sent";
|
|
260
|
+
return { ok: true, final: true, value: done, reply: { stop: true, reason: stopReason } };
|
|
261
|
+
}
|
|
262
|
+
return { ok: true, final: false, reply: { next: index + 1, verdict } };
|
|
263
|
+
},
|
|
264
|
+
});
|
|
265
|
+
const opened = (deps.open ?? announce)(handle.url);
|
|
266
|
+
const result = await handle.done;
|
|
267
|
+
return { result, url: handle.url, opened, done, total: calls.length, ...(stopReason ? { stopReason } : {}) };
|
|
268
|
+
}
|
|
269
|
+
const notConnected = () => new Error("no wallet is connected — run `treasury connect wallet` first, and let the operator sign in");
|
|
270
|
+
export function outcome(chainId, account, r) {
|
|
271
|
+
const txs = r.result.ok ? r.result.value : r.done;
|
|
272
|
+
// Completed means every call of the flow landed, never only the ones that were reached.
|
|
273
|
+
const all = txs.length === r.total && txs.every((t) => t.verified === "matched" || t.verified === "extra_transfer");
|
|
274
|
+
const status = r.result.ok ? (all ? "completed" : "stopped") : txs.length ? "stopped" : "not_reported";
|
|
275
|
+
// A stopped flow always says why, even when no single step reported a reason.
|
|
276
|
+
const reason = (r.result.ok ? r.stopReason : r.result.reason) ?? (status === "stopped" ? `the flow ended after ${txs.length} of ${r.total} transactions` : undefined);
|
|
277
|
+
return JSON.stringify({
|
|
278
|
+
status,
|
|
279
|
+
chain: CHAIN_INFO[chainId].key,
|
|
280
|
+
chainId,
|
|
281
|
+
account,
|
|
282
|
+
opened: r.opened,
|
|
283
|
+
...(reason ? { reason } : {}),
|
|
284
|
+
calls_total: r.total,
|
|
285
|
+
txs,
|
|
286
|
+
next_step: status === "completed"
|
|
287
|
+
? "Every call landed as confirmed. Report each hash to the operator; any `extra_transfer` is money the wallet moved besides the call — say so."
|
|
288
|
+
: status === "stopped"
|
|
289
|
+
? "Stopped before every call landed. Do not retry blindly: read `reason` and the last transaction's `verified` and `detail`, check the account with `earn balance`, and tell the operator."
|
|
290
|
+
: "No transaction was reported to this command. That is not proof that none was sent: if the wallet showed a confirmation, check the account with `earn balance` before any retry. Tell the operator why (reason).",
|
|
291
|
+
}, null, 2);
|
|
292
|
+
}
|
|
293
|
+
export function buildConnectCommands(deps = {}) {
|
|
294
|
+
const commands = {};
|
|
295
|
+
const register = (name, meta, handler) => {
|
|
296
|
+
commands[name] = {
|
|
297
|
+
...meta,
|
|
298
|
+
inputSchema: z.object(meta.inputSchema),
|
|
299
|
+
handler: (async (args) => {
|
|
300
|
+
try {
|
|
301
|
+
return await handler(args);
|
|
302
|
+
}
|
|
303
|
+
catch (e) {
|
|
304
|
+
throw new Error(redactEndpoints(e instanceof Error ? e.message : String(e)));
|
|
305
|
+
}
|
|
306
|
+
}),
|
|
307
|
+
};
|
|
308
|
+
};
|
|
309
|
+
register("connect_status", { title: "Which wallet is connected", description: "The connected account and how it signed in (`external` browser wallet, or `embedded` Privy wallet from an email or social login), or `disconnected`. Reads a local file only.", inputSchema: {} }, async () => {
|
|
310
|
+
const s = readSession();
|
|
311
|
+
return JSON.stringify(s ? { status: "connected", ...s } : { status: "disconnected", next_step: "run `treasury connect wallet` to let the operator sign in" }, null, 2);
|
|
312
|
+
});
|
|
313
|
+
register("connect_wallet", {
|
|
314
|
+
title: "Connect a wallet",
|
|
315
|
+
description: "Opens the sign-in page in the operator's browser: one Connect button, then Privy's window with email, Google, Apple, X and browser wallets (MetaMask, Rabby, Coinbase Wallet). The operator signs a free sign-in message; nothing is spent. Waits until they finish (up to 9 minutes) and returns the connected account. Replaces any earlier connection.",
|
|
316
|
+
inputSchema: {},
|
|
317
|
+
}, async () => {
|
|
318
|
+
const r = await runConnect(deps);
|
|
319
|
+
if (!r.result.ok)
|
|
320
|
+
return Promise.reject(new Error(`not connected: ${r.result.reason}`));
|
|
321
|
+
return JSON.stringify({ status: "connected", ...r.result.value, opened: r.opened }, null, 2);
|
|
322
|
+
});
|
|
323
|
+
register("connect_disconnect", { title: "Forget the connected wallet", description: "Deletes the local connection record. It moves nothing and revokes nothing in the wallet itself.", inputSchema: {} }, async () => JSON.stringify({ status: "disconnected", hadConnection: clearSession() }, null, 2));
|
|
324
|
+
const now = deps.now ?? (() => new Date());
|
|
325
|
+
/**
|
|
326
|
+
* Without `ack`: gate-check the calls, record them as pending, and return the acknowledgement for
|
|
327
|
+
* the operator; nothing opens. With `ack`: open the confirm page only for the calls the operator
|
|
328
|
+
* acknowledged, spending the acknowledgement first so it can never open a second page.
|
|
329
|
+
*/
|
|
330
|
+
const confirmInWallet = async (action, calls, session, receiver, ack) => {
|
|
331
|
+
const account = session.account;
|
|
332
|
+
if (ack === undefined) {
|
|
333
|
+
const summary = summarize(action, calls, admit(calls, account), receiver);
|
|
334
|
+
const pending = issueAck(calls, account, now());
|
|
335
|
+
writePendingAck(pending);
|
|
336
|
+
return JSON.stringify({
|
|
337
|
+
status: "needs_acknowledgement",
|
|
338
|
+
opened: false,
|
|
339
|
+
action,
|
|
340
|
+
amount: summary.amount,
|
|
341
|
+
chain: CHAIN_INFO[summary.chainId].key,
|
|
342
|
+
chainId: summary.chainId,
|
|
343
|
+
vault: summary.vault,
|
|
344
|
+
account,
|
|
345
|
+
receiver,
|
|
346
|
+
acknowledgement: acknowledgementText(summary),
|
|
347
|
+
ack: pending.code,
|
|
348
|
+
expiresAtIso: pending.expiresAtIso,
|
|
349
|
+
next_step: `Post \`acknowledgement\` to the operator word for word, as it is, and wait for their reply. Only an explicit yes they give after reading it is an acknowledgement: not a "go" from before they saw it, and not your own reading of the conversation. On yes, run this same command again with --ack ${pending.code} added, and the signing page opens. On anything else, stop. The code works once, for exactly these calls, until ${pending.expiresAtIso}.`,
|
|
350
|
+
}, null, 2);
|
|
351
|
+
}
|
|
352
|
+
checkAck(ack, readPendingAck(), calls, account, now());
|
|
353
|
+
// Spent before the page opens, so a flow that fails to start leaves nothing to reuse. Two
|
|
354
|
+
// concurrent runs could both pass the check; only one page opens because the port is fixed.
|
|
355
|
+
clearPendingAck();
|
|
356
|
+
const r = await runConfirm(calls, session, deps);
|
|
357
|
+
return outcome(calls[0].chainId, session.account, r);
|
|
358
|
+
};
|
|
359
|
+
register("connect_deposit", {
|
|
360
|
+
title: "Deposit through the connected wallet",
|
|
361
|
+
description: "Builds the approve + deposit for the CONNECTED account and checks every call against the registry. Runs twice. Without --ack it opens NOTHING: it returns `needs_acknowledgement` with an `acknowledgement` to post to the operator word for word, and an `ack` code. Only after the operator replies yes, run it again with --ack <code>: then the confirm page opens, and the operator confirms each call in their wallet, one at a time. That run returns each transaction hash with `verified` read from the receipt (`matched`, `extra_transfer`, `mismatch`, `reverted`, `unverified`). Run `earn quote --direction deposit` first.",
|
|
362
|
+
inputSchema: { vault: vaultArg, chain: chainArg, amount_usdc: amountArg, receiver: receiverArg, ack: ackArg },
|
|
363
|
+
}, async ({ vault: symbol, chain, amount_usdc, receiver, ack }) => {
|
|
364
|
+
const session = readSession();
|
|
365
|
+
if (!session)
|
|
366
|
+
throw notConnected();
|
|
367
|
+
if (receiver !== session.account)
|
|
368
|
+
throw new Error(`refused: --receiver ${receiver} is not the connected account ${session.account}; this page pays only the connected account (use \`earn prepare_deposit\` with the operator's own signer for anything else)`);
|
|
369
|
+
const vault = resolveVault(symbol, chain);
|
|
370
|
+
return confirmInWallet("deposit", buildDeposit(vault, { assetsHuman: amount_usdc, receiver: receiver, account: session.account }), session, receiver, ack);
|
|
371
|
+
});
|
|
372
|
+
register("connect_withdraw", {
|
|
373
|
+
title: "Withdraw through the connected wallet",
|
|
374
|
+
description: "Builds the withdrawal for the CONNECTED account (the asset to that same account) and checks it against the registry. Runs twice, like `connect deposit`: without --ack it opens NOTHING and returns `needs_acknowledgement` with an `acknowledgement` to post to the operator word for word; only after their yes, run it again with --ack <code> and the confirm page opens. Pass --amount_usdc, or --all with --shares_exact copied verbatim from `earn balance`. Run `earn quote --direction withdraw` first. The second run returns the hash with `verified` read from the receipt.",
|
|
375
|
+
inputSchema: {
|
|
376
|
+
vault: vaultArg,
|
|
377
|
+
chain: chainArg,
|
|
378
|
+
receiver: receiverArg,
|
|
379
|
+
amount_usdc: amountArg.optional(),
|
|
380
|
+
all: z.boolean().optional(),
|
|
381
|
+
shares_exact: z.string().regex(/^\d+(\.\d+)?$/).optional(),
|
|
382
|
+
ack: ackArg,
|
|
383
|
+
},
|
|
384
|
+
}, async ({ vault: symbol, chain, receiver, amount_usdc, all, shares_exact, ack }) => {
|
|
385
|
+
const session = readSession();
|
|
386
|
+
if (!session)
|
|
387
|
+
throw notConnected();
|
|
388
|
+
if (receiver !== session.account)
|
|
389
|
+
throw new Error(`refused: --receiver ${receiver} is not the connected account ${session.account}; this page pays only the connected account`);
|
|
390
|
+
const vault = resolveVault(symbol, chain);
|
|
391
|
+
const owner = session.account;
|
|
392
|
+
let calls;
|
|
393
|
+
if (all && amount_usdc)
|
|
394
|
+
throw new Error("give --amount_usdc or --all with --shares_exact, not both");
|
|
395
|
+
if (!all && shares_exact)
|
|
396
|
+
throw new Error("--shares_exact goes with --all; for an amount in the asset, use --amount_usdc alone");
|
|
397
|
+
if (all) {
|
|
398
|
+
if (!shares_exact)
|
|
399
|
+
throw new Error("--all requires --shares_exact (copy it verbatim from `earn balance`)");
|
|
400
|
+
calls = buildWithdraw(vault, { receiver: receiver, owner, all: true, sharesExact: shares_exact });
|
|
401
|
+
}
|
|
402
|
+
else {
|
|
403
|
+
if (!amount_usdc)
|
|
404
|
+
throw new Error("provide --amount_usdc, or --all with --shares_exact");
|
|
405
|
+
calls = buildWithdraw(vault, { receiver: receiver, owner, assetsHuman: amount_usdc });
|
|
406
|
+
}
|
|
407
|
+
return confirmInWallet("withdraw", calls, session, receiver, ack);
|
|
408
|
+
});
|
|
409
|
+
return commands;
|
|
410
|
+
}
|
|
411
|
+
//# sourceMappingURL=commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/connect/commands.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settings for `treasury connect`. Every value has a working default; each environment variable
|
|
3
|
+
* here is optional and documented in docs/configuration.md.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* The Privy app the sign-in page uses. A Privy app ID is a PUBLIC identifier — it ships inside the
|
|
7
|
+
* page every browser downloads — so it is committed here. A fork or self-host can point at its own
|
|
8
|
+
* Privy app with `PRIVY_APP_ID`. The app SECRET is never used anywhere in this package.
|
|
9
|
+
*/
|
|
10
|
+
export declare const DEFAULT_PRIVY_APP_ID = "cmubfegl2028d0ci3n0f2u6z5";
|
|
11
|
+
/**
|
|
12
|
+
* The fixed local port. Privy accepts sign-in only from origins listed in its dashboard, by exact
|
|
13
|
+
* string, so the page must always be served from the same `http://localhost:<port>`. Change it with
|
|
14
|
+
* `TREASURY_CONNECT_PORT` only together with the Privy app's allowed domains.
|
|
15
|
+
*/
|
|
16
|
+
export declare const DEFAULT_CONNECT_PORT = 53682;
|
|
17
|
+
export declare const privyAppId: () => string;
|
|
18
|
+
export declare const connectPort: () => number;
|
|
19
|
+
/** Where the session file lives; `TREASURY_CONNECT_HOME` moves it (tests use a temporary directory). */
|
|
20
|
+
export declare const connectHome: () => string | undefined;
|
|
21
|
+
/** Set to anything to stop the CLI opening a browser itself (it prints the URL instead). */
|
|
22
|
+
export declare const noOpen: () => boolean;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settings for `treasury connect`. Every value has a working default; each environment variable
|
|
3
|
+
* here is optional and documented in docs/configuration.md.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* The Privy app the sign-in page uses. A Privy app ID is a PUBLIC identifier — it ships inside the
|
|
7
|
+
* page every browser downloads — so it is committed here. A fork or self-host can point at its own
|
|
8
|
+
* Privy app with `PRIVY_APP_ID`. The app SECRET is never used anywhere in this package.
|
|
9
|
+
*/
|
|
10
|
+
export const DEFAULT_PRIVY_APP_ID = "cmubfegl2028d0ci3n0f2u6z5";
|
|
11
|
+
/**
|
|
12
|
+
* The fixed local port. Privy accepts sign-in only from origins listed in its dashboard, by exact
|
|
13
|
+
* string, so the page must always be served from the same `http://localhost:<port>`. Change it with
|
|
14
|
+
* `TREASURY_CONNECT_PORT` only together with the Privy app's allowed domains.
|
|
15
|
+
*/
|
|
16
|
+
export const DEFAULT_CONNECT_PORT = 53682;
|
|
17
|
+
export const privyAppId = () => {
|
|
18
|
+
const v = (process.env["PRIVY_APP_ID"] ?? "").trim();
|
|
19
|
+
return v.length > 0 && !v.includes("${") ? v : DEFAULT_PRIVY_APP_ID;
|
|
20
|
+
};
|
|
21
|
+
export const connectPort = () => {
|
|
22
|
+
const raw = (process.env["TREASURY_CONNECT_PORT"] ?? "").trim();
|
|
23
|
+
const n = Number(raw);
|
|
24
|
+
return raw.length > 0 && Number.isInteger(n) && n > 0 && n < 65536 ? n : DEFAULT_CONNECT_PORT;
|
|
25
|
+
};
|
|
26
|
+
/** Where the session file lives; `TREASURY_CONNECT_HOME` moves it (tests use a temporary directory). */
|
|
27
|
+
export const connectHome = () => {
|
|
28
|
+
const v = (process.env["TREASURY_CONNECT_HOME"] ?? "").trim();
|
|
29
|
+
return v.length > 0 && !v.includes("${") ? v : undefined;
|
|
30
|
+
};
|
|
31
|
+
/** Set to anything to stop the CLI opening a browser itself (it prints the URL instead). */
|
|
32
|
+
export const noOpen = () => (process.env["TREASURY_CONNECT_NO_OPEN"] ?? "").trim().length > 0;
|
|
33
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/connect/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,2BAA2B,CAAC;AAEhE;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,KAAK,CAAC;AAE1C,MAAM,CAAC,MAAM,UAAU,GAAG,GAAW,EAAE;IACrC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACrD,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC;AACtE,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,GAAW,EAAE;IACtC,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAChE,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACtB,OAAO,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC;AAChG,CAAC,CAAC;AAEF,wGAAwG;AACxG,MAAM,CAAC,MAAM,WAAW,GAAG,GAAuB,EAAE;IAClD,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9D,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC3D,CAAC,CAAC;AAEF,4FAA4F;AAC5F,MAAM,CAAC,MAAM,MAAM,GAAG,GAAY,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The hard gate every call passes before a page opens: what `treasury connect` will put in front of
|
|
3
|
+
* the operator's wallet at all. It re-derives everything from the calldata and the registry and
|
|
4
|
+
* trusts nothing the call's own fields say about themselves (`description`, `args`, `function`).
|
|
5
|
+
*
|
|
6
|
+
* Allowed, and nothing else:
|
|
7
|
+
* - `approve(vault, n)` on a registry vault's own asset, for exactly the amount the deposit after
|
|
8
|
+
* it pulls — never unlimited, never to anything but that vault;
|
|
9
|
+
* - `deposit(assets, receiver)` on a registry vault, receiver = the connected account;
|
|
10
|
+
* - `withdraw(assets, receiver, owner)` / `redeem(shares, receiver, owner)` on a registry vault,
|
|
11
|
+
* receiver = owner = the connected account.
|
|
12
|
+
* Every call carries no value and names a supported chain that matches its vault.
|
|
13
|
+
*
|
|
14
|
+
* And one batch is one operation on one vault, on one chain, in one of the shapes the builders
|
|
15
|
+
* emit: `[approve, deposit]`, `[withdraw]` or `[redeem]`. Calldata must be exactly the canonical
|
|
16
|
+
* encoding of what it decodes to: no trailing bytes, no stray bits in an address word.
|
|
17
|
+
*
|
|
18
|
+
* This is the rule of AGENTS.md / CONTRIBUTING.md that the relay refuses any destination outside
|
|
19
|
+
* the registry, made executable. Paying an address other than the
|
|
20
|
+
* connected account is refused here on purpose: that is what the prepare commands are for, with the
|
|
21
|
+
* operator's own signer.
|
|
22
|
+
*/
|
|
23
|
+
import { type Address, type Hex } from "viem";
|
|
24
|
+
import type { VaultEntry } from "../registry-schema.js";
|
|
25
|
+
export interface GateCall {
|
|
26
|
+
chainId: number;
|
|
27
|
+
to: Address;
|
|
28
|
+
data: Hex;
|
|
29
|
+
value: string;
|
|
30
|
+
}
|
|
31
|
+
export interface Admitted {
|
|
32
|
+
kind: "approve" | "deposit" | "withdraw" | "redeem";
|
|
33
|
+
vault: VaultEntry;
|
|
34
|
+
/** Raw units: the approved/deposited/withdrawn assets, or the redeemed shares. */
|
|
35
|
+
amount: bigint;
|
|
36
|
+
}
|
|
37
|
+
export declare function admit(calls: GateCall[], account: Address): Admitted[];
|