@temporalabs/treasury 0.1.1 → 0.1.3
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 +100 -44
- package/THIRD_PARTY_NOTICES.connect-page.md +7836 -0
- package/THIRD_PARTY_NOTICES.md +543 -162
- package/dist/cli.d.ts +6 -0
- package/dist/cli.js +243 -0
- package/dist/cli.js.map +1 -0
- package/dist/client.d.ts +366 -239
- package/dist/client.js +202 -25
- package/dist/client.js.map +1 -1
- package/dist/config/earn.d.ts +48 -12
- package/dist/config/earn.js +48 -12
- package/dist/config/earn.js.map +1 -1
- package/dist/connect/ack.d.ts +76 -0
- package/dist/connect/ack.js +147 -0
- package/dist/connect/ack.js.map +1 -0
- package/dist/connect/commands.d.ts +81 -0
- package/dist/connect/commands.js +555 -0
- package/dist/connect/commands.js.map +1 -0
- package/dist/connect/config.d.ts +24 -0
- package/dist/connect/config.js +35 -0
- package/dist/connect/config.js.map +1 -0
- package/dist/connect/gate-solana.d.ts +8 -0
- package/dist/connect/gate-solana.js +147 -0
- package/dist/connect/gate-solana.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 +60 -0
- package/dist/connect/http.js +235 -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 +39 -0
- package/dist/connect/session.js +198 -0
- package/dist/connect/session.js.map +1 -0
- package/dist/connect/solana.d.ts +73 -0
- package/dist/connect/solana.js +267 -0
- package/dist/connect/solana.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 +5143 -0
- package/dist/disclosures.d.ts +22 -6
- package/dist/disclosures.js +34 -8
- package/dist/disclosures.js.map +1 -1
- package/dist/earn/commands.d.ts +46 -0
- package/dist/earn/commands.js +556 -0
- package/dist/earn/commands.js.map +1 -0
- package/dist/earn/solana.d.ts +278 -0
- package/dist/earn/solana.js +302 -0
- package/dist/earn/solana.js.map +1 -0
- package/dist/guide.d.ts +15 -0
- package/dist/guide.js +50 -0
- package/dist/guide.js.map +1 -0
- package/dist/links.d.ts +2 -0
- package/dist/links.js +40 -14
- package/dist/links.js.map +1 -1
- package/dist/position.d.ts +9 -6
- package/dist/position.js +39 -19
- 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 +82 -5
- package/dist/registry-schema.js +105 -15
- package/dist/registry-schema.js.map +1 -1
- package/dist/registry.d.ts +50 -7
- package/dist/registry.js +122 -21
- package/dist/registry.js.map +1 -1
- package/dist/solana/constants.d.ts +49 -0
- package/dist/solana/constants.js +50 -0
- package/dist/solana/constants.js.map +1 -0
- package/dist/solana/kvault.d.ts +99 -0
- package/dist/solana/kvault.js +192 -0
- package/dist/solana/kvault.js.map +1 -0
- package/dist/solana/layout.d.ts +143 -0
- package/dist/solana/layout.js +209 -0
- package/dist/solana/layout.js.map +1 -0
- package/dist/solana/rpc.d.ts +24 -0
- package/dist/solana/rpc.js +66 -0
- package/dist/solana/rpc.js.map +1 -0
- package/dist/solana/vault.d.ts +153 -0
- package/dist/solana/vault.js +324 -0
- package/dist/solana/vault.js.map +1 -0
- package/dist/{mcp-server.mjs → treasury.mjs} +41101 -49486
- package/dist/version.js +5 -10
- package/dist/version.js.map +1 -1
- package/llms.txt +621 -0
- package/package.json +12 -9
- package/registry/vaults.json +218 -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,556 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Treasury — the earn commands (earn skill), run headless by `src/cli.ts` as `treasury earn <command>`.
|
|
3
|
+
*
|
|
4
|
+
* Read commands, quotes, and UNSIGNED call builders only. There is no `sign` and no `send` command, and
|
|
5
|
+
* there will not be one here: the skill supplies intent, the consumer supplies the signer. Anything
|
|
6
|
+
* that holds a key lives outside this process and receives the calls these commands emit.
|
|
7
|
+
*
|
|
8
|
+
* Eight commands. Each is keyed by its tool name, `earn_`-prefixed so later skills can sit beside it
|
|
9
|
+
* in one namespace; on the command line `earn_quote` is `treasury earn quote`:
|
|
10
|
+
*
|
|
11
|
+
* earn_vaults earn_terms earn_quote (direction) earn_status (no args = health)
|
|
12
|
+
* earn_balance earn_claim earn_prepare_deposit earn_prepare_withdraw
|
|
13
|
+
*
|
|
14
|
+
* Three contracts worth stating here because they are easy to erode:
|
|
15
|
+
*
|
|
16
|
+
* 1. `earn_prepare_*` return an ENVELOPE, `{ requires_signature, status: "unsigned", calls }`,
|
|
17
|
+
* not a bare array. This cannot stop a model reporting "deposited" — nothing at this boundary
|
|
18
|
+
* can — but it makes an unsigned build structurally distinguishable from a completed one, so a
|
|
19
|
+
* consumer or a test can assert on it. Wrapped HERE only: `buildDeposit`/`buildWithdraw` still
|
|
20
|
+
* return arrays, so a direct library consumer (see docs/runbooks/sign_and_send.md) gets the
|
|
21
|
+
* naked calls exactly as before.
|
|
22
|
+
* 2. The address argument is `account` everywhere. It was `depositor`, `owner` and `principal` in
|
|
23
|
+
* three different tools. `receiver` stays distinct because it genuinely is: `account` owns the
|
|
24
|
+
* shares, `receiver` is where the money lands.
|
|
25
|
+
* 3. A vault lives on ONE chain, and every tool that takes `vault` also takes `chain`. Naming a
|
|
26
|
+
* chain alone selects that chain's default vault; naming both and having them disagree is
|
|
27
|
+
* refused (`resolveVault`), never settled by picking one. Every response that names a vault says
|
|
28
|
+
* which chain it is on, because a prepared call is only correct on that chain.
|
|
29
|
+
*/
|
|
30
|
+
import { z } from "zod";
|
|
31
|
+
import { redactEndpoints, registerSecretSource } from "../redact.js";
|
|
32
|
+
import { isAddress, getAddress } from "viem";
|
|
33
|
+
import { solanaPublicRpcHint } from "../client.js";
|
|
34
|
+
import { isAddress as isSolanaAddress } from "@solana/kit";
|
|
35
|
+
import { onSolana, solanaBalance, solanaHealth, solanaPrepareDeposit, solanaPrepareWithdraw, solanaPreflight, solanaQuoteDeposit, solanaQuoteWithdraw, solanaVaultRow } from "./solana.js";
|
|
36
|
+
import { CHAIN_INFO, isSupportedChainId, makePublicClient, rpcUrlFromEnv, logsRpcUrlFromEnv, rpcSourceForEnv, logsRpcSourceForEnv, resolvedRpcSecrets, publicRpcHint, logsFallbackUrlFromEnv, endpointChainId, firstEndpointOnWrongChain, supportedChainIds } from "../client.js";
|
|
37
|
+
import { defaultChainId, defaultVault, depositableSolanaVaults, depositableVaults, listSolanaVaults, listVaults, loadRegistry, offeredChainKeys, offeredChains, resolveAnyVault, resolveVault } from "../registry.js";
|
|
38
|
+
import { linksFor } from "../links.js";
|
|
39
|
+
import { PACKAGE_VERSION } from "../version.js";
|
|
40
|
+
import { preflightDeposit } from "../preflight.js";
|
|
41
|
+
import { getPosition } from "../position.js";
|
|
42
|
+
import { quoteDeposit, quoteWithdraw } from "../quote.js";
|
|
43
|
+
import { buildDeposit, buildWithdraw } from "../build.js";
|
|
44
|
+
import { DISCLOSURES } from "../disclosures.js";
|
|
45
|
+
/**
|
|
46
|
+
* An address, in either family's form: `0x…` for a vault on an EVM chain, base58 for a vault on Solana. Which
|
|
47
|
+
* one a command needs depends on the vault, which is resolved after the arguments parse, so each handler checks
|
|
48
|
+
* the family it got (`evm` below, `solanaAccount` in ./solana.ts) and refuses the other.
|
|
49
|
+
*/
|
|
50
|
+
const addressArg = z.string().refine((s) => isAddress(s) || isSolanaAddress(s), "must be an EVM address (0x…), or a Solana address for a vault on Solana");
|
|
51
|
+
/** The EVM form of an address argument, checksummed; a Solana address here is refused, naming the slot. */
|
|
52
|
+
function evm(v, what) {
|
|
53
|
+
if (!isAddress(v))
|
|
54
|
+
throw new Error(`${what} must be an EVM address (0x…) for a vault on an EVM chain; got ${v}`);
|
|
55
|
+
return getAddress(v);
|
|
56
|
+
}
|
|
57
|
+
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"');
|
|
58
|
+
const vaultArg = z.string().optional().describe("the vault's ticker, e.g. tlCashPlusUSDC2 (`earn vaults` lists them); omit for the default vault of `chain`, or of the default chain when `chain` is omitted too");
|
|
59
|
+
const accountArg = addressArg.describe("the account whose shares these are — the depositor, the owner, the holder");
|
|
60
|
+
/**
|
|
61
|
+
* `chain`, as every vault-taking tool accepts it: one of the chains that have a vault in the
|
|
62
|
+
* registry, so a caller cannot name a chain there is nothing to do on. Built per `buildCommands()`
|
|
63
|
+
* call because the list comes from the registry.
|
|
64
|
+
*
|
|
65
|
+
* The schema is a plain string rather than an enum, for three reasons: the set of chains comes from
|
|
66
|
+
* the registry, which can be swapped after this schema is built; `vault` and `chain` are settled
|
|
67
|
+
* together in ONE place (`resolveVault`), so there is one refusal path to test; and that refusal
|
|
68
|
+
* says what to do next — which chain the vault is on, and which vaults the named chain has.
|
|
69
|
+
*
|
|
70
|
+
* 🔴 It must not throw. This runs while the commands are being BUILT, and it reads the registry: a
|
|
71
|
+
* registry that does not parse would stop every command from running at all, `--help` included.
|
|
72
|
+
* Falling back to every supported chain lets the CLI start, and each command then reports the
|
|
73
|
+
* registry's own violation by name, as it did before `chain` existed.
|
|
74
|
+
*/
|
|
75
|
+
const chainArg = () => {
|
|
76
|
+
let offered;
|
|
77
|
+
try {
|
|
78
|
+
offered = offeredChainKeys();
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
offered = supportedChainIds.map((id) => CHAIN_INFO[id].key);
|
|
82
|
+
}
|
|
83
|
+
return z
|
|
84
|
+
.string()
|
|
85
|
+
.optional()
|
|
86
|
+
.describe(`which chain: ${offered.map((k) => `"${k}"`).join(" or ")}. Omit for ${CHAIN_INFO[defaultChainId()].key} (the default), or when \`vault\` already names a vault. ` +
|
|
87
|
+
"If the operator has not said which chain to deposit on, ASK them before preparing a deposit. A `vault` that is on a different chain than `chain` is refused.");
|
|
88
|
+
};
|
|
89
|
+
function supportedVault(symbol, chain) {
|
|
90
|
+
const vault = resolveVault(symbol, chain);
|
|
91
|
+
if (!isSupportedChainId(vault.chainId))
|
|
92
|
+
throw new Error(`chain ${vault.chainId} unsupported`);
|
|
93
|
+
return vault;
|
|
94
|
+
}
|
|
95
|
+
function clientFor(symbol, chain) {
|
|
96
|
+
const vault = supportedVault(symbol, chain);
|
|
97
|
+
const url = rpcUrlFromEnv(vault.chainId);
|
|
98
|
+
const client = makePublicClient(vault.chainId, url);
|
|
99
|
+
return { vault, client, endpoints: [{ client, url, source: rpcSourceForEnv(vault.chainId).source }] };
|
|
100
|
+
}
|
|
101
|
+
/** The sentence for the first endpoint that answers for a chain other than the vault's, or `undefined`. */
|
|
102
|
+
async function wrongChainReason(vault, endpoints) {
|
|
103
|
+
const wrong = await firstEndpointOnWrongChain(vault.chainId, endpoints);
|
|
104
|
+
if (wrong === undefined)
|
|
105
|
+
return undefined;
|
|
106
|
+
const info = CHAIN_INFO[vault.chainId];
|
|
107
|
+
return `the endpoint in ${wrong.source} answers for chain ${wrong.answersFor}, not ${info.name} (${vault.chainId}). It must be an endpoint for ${info.name}; until it is, no read for this chain can be trusted.`;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Runs a tool's reads WHILE checking that each configured endpoint answers for the vault's chain.
|
|
111
|
+
* A mismatch is reported INSTEAD of whatever the reads returned or threw.
|
|
112
|
+
*
|
|
113
|
+
* Why instead: through an endpoint for another chain, the vault's address has no contract, so the
|
|
114
|
+
* reads fail with "returned no data … the address is not a contract" (measured in review, on every
|
|
115
|
+
* RPC-touching tool, in both directions). That is loud, and it names the wrong thing: it reads as a
|
|
116
|
+
* broken vault. The check runs alongside the reads, so it adds no round trip to a healthy call.
|
|
117
|
+
*/
|
|
118
|
+
async function onItsChain(vault, endpoints, work) {
|
|
119
|
+
const [reason, settled] = await Promise.all([
|
|
120
|
+
wrongChainReason(vault, endpoints),
|
|
121
|
+
work().then((value) => ({ ok: true, value }), (error) => ({ ok: false, error })),
|
|
122
|
+
]);
|
|
123
|
+
if (reason !== undefined)
|
|
124
|
+
throw new Error(reason);
|
|
125
|
+
if (!settled.ok)
|
|
126
|
+
throw settled.error;
|
|
127
|
+
return settled.value;
|
|
128
|
+
}
|
|
129
|
+
/** Which chain a response is about — the name a caller passes back as `chain`, and the id a signer checks. */
|
|
130
|
+
const onChain = (vault) => ({ chain: CHAIN_INFO[vault.chainId].key, chainId: vault.chainId });
|
|
131
|
+
/**
|
|
132
|
+
* The chain a failed call was aimed at, for the setup hint — resolved from the call's own arguments
|
|
133
|
+
* and never throwing: a call that failed BECAUSE its vault or chain did not resolve falls back to
|
|
134
|
+
* the default chain, which is what the hint named before there was more than one.
|
|
135
|
+
*/
|
|
136
|
+
function hintChain(args) {
|
|
137
|
+
try {
|
|
138
|
+
const a = (args ?? {});
|
|
139
|
+
const t = resolveAnyVault(typeof a.vault === "string" ? a.vault : undefined, typeof a.chain === "string" ? a.chain : undefined);
|
|
140
|
+
return t.family === "solana" ? "solana" : t.vault.chainId;
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
return defaultChainId();
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/** The setup sentence for a transport failure on the chain's unconfigured public endpoint. */
|
|
147
|
+
const hintFor = (chain) => (chain === "solana" ? solanaPublicRpcHint() : publicRpcHint(chain));
|
|
148
|
+
/**
|
|
149
|
+
* Shapes that mean "the transport failed", as opposed to a verdict about the vault. `HTTP error (429)` and
|
|
150
|
+
* `HTTP error (5xx)` are how the Solana client reports a rate limit or a failing endpoint.
|
|
151
|
+
*/
|
|
152
|
+
const RPC_FAILURE = /RPC Request failed|HTTP request failed|HTTP error \((?:429|5\d\d)\)|reads failed|over rate limit|rate.?limit|"unreachable"|fetch failed|ETIMEDOUT|ECONNREFUSED/i;
|
|
153
|
+
/**
|
|
154
|
+
* Serialise a tool result, and when the payload shows a TRANSPORT failure while no RPC is
|
|
155
|
+
* configured, attach the one sentence that turns "this is broken" into "set this variable".
|
|
156
|
+
* Attached as a FIELD rather than appended to prose, so a consumer can branch on it.
|
|
157
|
+
*/
|
|
158
|
+
const text = (v, chainId = defaultChainId()) => {
|
|
159
|
+
let body = typeof v === "string" ? v : JSON.stringify(v, null, 2);
|
|
160
|
+
if (RPC_FAILURE.test(body)) {
|
|
161
|
+
const hint = hintFor(chainId);
|
|
162
|
+
if (hint) {
|
|
163
|
+
body =
|
|
164
|
+
typeof v === "string"
|
|
165
|
+
? `${body}\n\n${hint}`
|
|
166
|
+
: JSON.stringify({ ...v, setup_required: hint }, null, 2);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return body;
|
|
170
|
+
};
|
|
171
|
+
/** An unsigned build never leaves these commands as a bare array. See contract 1 in the file header. */
|
|
172
|
+
/**
|
|
173
|
+
* 🔴 THE ONE PLACE THE VAULT'S WARNING IS ATTACHED TO A RESPONSE. Every response that can be the
|
|
174
|
+
* last thing an agent reads before a signer sees calldata goes through here.
|
|
175
|
+
*
|
|
176
|
+
* It exists as a chokepoint rather than three tidy literals for a reason worth keeping. The warning
|
|
177
|
+
* first shipped on `earn_vaults` alone — a DISCOVERY call — while the warning's own text says to
|
|
178
|
+
* show it before preparing a deposit. A caller who names a vault directly never makes that call, so
|
|
179
|
+
* the disclosure reached whoever happened to have listed recently and nobody else. The repair added
|
|
180
|
+
* it to three call sites, and two of those three were then unguarded: deleting the field from them
|
|
181
|
+
* left the whole suite green.
|
|
182
|
+
*
|
|
183
|
+
* A test per call site would only have guarded the sites someone remembered to write a test for,
|
|
184
|
+
* which is the same defect one level up. So: attach it HERE, and `commands.unit.test.ts` asserts this
|
|
185
|
+
* is the only place in the file that writes a `warning` field. A fourth money-committing tool then
|
|
186
|
+
* gets the disclosure by going through this helper, and a hand-rolled one is caught by that test
|
|
187
|
+
* rather than by someone noticing.
|
|
188
|
+
*
|
|
189
|
+
* Withdrawals deliberately do NOT call this. The warning is about COMMITTING money, not retrieving
|
|
190
|
+
* it, and a disclosure repeated where it does not apply is what teaches a reader to skip the one
|
|
191
|
+
* that does. That absence is asserted too.
|
|
192
|
+
*/
|
|
193
|
+
const commitsMoney = (vault) => ({ warning: vault.warning });
|
|
194
|
+
const unsigned = (calls, vault, kind) => text({
|
|
195
|
+
requires_signature: true,
|
|
196
|
+
status: "unsigned",
|
|
197
|
+
// The chain FIRST: these calls are correct on this chain and on no other.
|
|
198
|
+
...onChain(vault),
|
|
199
|
+
// before `next_step`, so it is not past the field a reader stops at
|
|
200
|
+
...(kind === "deposit" ? commitsMoney(vault) : {}),
|
|
201
|
+
next_step: `These calls are for ${CHAIN_INFO[vault.chainId].name} (chainId ${vault.chainId}): tell the operator which chain, and send them on that chain only. Hand these calls to a signer IN ORDER, following \`signer_rules\`. A call carrying \`precondition\` must not be estimated or sent until that read holds on the RPC the signer sends through. Nothing has been submitted; no funds have moved.`,
|
|
202
|
+
signer_rules: SIGNER_RULES,
|
|
203
|
+
calls,
|
|
204
|
+
}, vault.chainId);
|
|
205
|
+
/**
|
|
206
|
+
* What a signer must do for these calls to land exactly once. Every rule but the first is a failure
|
|
207
|
+
* measured on a real Base round trip, not a precaution (2026-09-13, two runs through these tools).
|
|
208
|
+
* The first exists because the registry spans chains: a call's `to` is an address, and an address
|
|
209
|
+
* with no contract on the chain it is sent on accepts the transaction and does nothing.
|
|
210
|
+
* These commands cannot enforce any of them — they never sign — so they state them with every build.
|
|
211
|
+
*/
|
|
212
|
+
export const SIGNER_RULES = [
|
|
213
|
+
"Send each call on the chain its `chainId` names, and on no other: check the signer's network before signing. Sent on a different chain, a call can be mined there without doing anything — the approve or the deposit never happened, and gas was still spent.",
|
|
214
|
+
"Before signing, check every call's destination against the addresses the operator gave: `to`, and the receiver/owner named in `description`. Do not sign a call whose destination you did not confirm.",
|
|
215
|
+
"Set the nonce explicitly from eth_getTransactionCount(account, \"pending\") immediately before each send. A load-balanced RPC can hand a signing library a stale nonce, and the send is then rejected as \"nonce too low\" (measured 2026-09-14, mainnet.base.org).",
|
|
216
|
+
"Set the gas limit to the call's gasAdvice (estimate × 1.5).",
|
|
217
|
+
"Wait for each receipt before sending the next call, and poll for it on a provider that serves receipts: a public endpoint may refuse eth_getTransactionReceipt (measured 2026-09-14, publicnode). A failed receipt poll does not mean the transaction failed.",
|
|
218
|
+
"If a send or receipt poll fails for any reason other than an on-chain revert, read the account's nonce on a DIFFERENT provider before re-sending. A nonce that moved means the transaction was accepted; re-sending it would repeat the deposit or withdrawal.",
|
|
219
|
+
];
|
|
220
|
+
/**
|
|
221
|
+
* Every handler runs inside this. The CLI prints a thrown error's `.message` to the caller verbatim,
|
|
222
|
+
* and viem's messages carry the transport URL — a keyed provider URL is a secret. Anything that
|
|
223
|
+
* escapes a handler is re-thrown with endpoints masked.
|
|
224
|
+
*/
|
|
225
|
+
const guarded = (fn) => async (...a) => {
|
|
226
|
+
try {
|
|
227
|
+
return await fn(...a);
|
|
228
|
+
}
|
|
229
|
+
catch (e) {
|
|
230
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
231
|
+
const redacted = redactEndpoints(msg);
|
|
232
|
+
// A thrown transport error on the public endpoint gets the same sentence a returned one does.
|
|
233
|
+
const hint = RPC_FAILURE.test(redacted) ? hintFor(hintChain(a[0])) : undefined;
|
|
234
|
+
throw new Error(hint ? `${redacted}\n\n${hint}` : redacted);
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
export function buildCommands() {
|
|
238
|
+
// 🔴 Value-based redaction, registered before any handler can run. `redactEndpoints` masks the
|
|
239
|
+
// resolved RPC URL and its credential-bearing parts wherever they appear — including inside a
|
|
240
|
+
// provider's own error body, which is prose in JSON and which no shape rule matches
|
|
241
|
+
// (review, reproduced against a real viem client and a real 401).
|
|
242
|
+
registerSecretSource(resolvedRpcSecrets);
|
|
243
|
+
const commands = {};
|
|
244
|
+
const register = (name, meta, handler) => {
|
|
245
|
+
commands[name] = { ...meta, inputSchema: z.object(meta.inputSchema), handler: handler };
|
|
246
|
+
};
|
|
247
|
+
const chain = chainArg();
|
|
248
|
+
register("earn_vaults", {
|
|
249
|
+
title: "List vaults",
|
|
250
|
+
description: "Every vault in the registry, on every chain. `symbol` is the vault's ticker — its own on-chain ERC-20 ticker on the EVM chains, one the registry assigns on Solana — the value every other tool takes as `vault`, and `name` its name; `chain` is the chain it is on, the value every other tool takes as `chain`; `links` are openable without any RPC endpoint, so an operator can verify the contract independently. SHOW `warning` TO THE DEPOSITOR — every vault offered today is a test vault. Each row also carries its backend, chassis, decimals and MEASURED deposit-open status. `chains` lists the chains a deposit can go to, the default chain first, each with its own default vault: if the operator has not said which chain, show them these and ASK before preparing a deposit. `default` is used when a tool is called with neither `vault` nor `chain`, and is on `defaultChain`; `depositable` is the subset any account can put money into today, across all chains: an ERC-4626 chassis (or the Kamino vault on Solana) + measured open. `defaultAccess` says whether a default takes deposits from any account (`open`) or only whitelisted ones (`whitelist`); for `whitelist`, run `earn status` for the account before preparing a deposit.",
|
|
251
|
+
inputSchema: {},
|
|
252
|
+
}, guarded(async () => {
|
|
253
|
+
const reg = loadRegistry();
|
|
254
|
+
return text({
|
|
255
|
+
reconciledAtIso: reg.reconciledAtIso,
|
|
256
|
+
defaultChain: CHAIN_INFO[defaultChainId()].key,
|
|
257
|
+
default: defaultVault().symbol,
|
|
258
|
+
defaultAccess: defaultVault().depositOpen.open ? "open" : "whitelist",
|
|
259
|
+
depositable: [...depositableVaults().map((v) => v.symbol), ...depositableSolanaVaults().map((v) => v.symbol)],
|
|
260
|
+
chains: [
|
|
261
|
+
...offeredChains().map((c) => {
|
|
262
|
+
const d = defaultVault(c.chainId);
|
|
263
|
+
return {
|
|
264
|
+
chain: c.key,
|
|
265
|
+
chainId: c.chainId,
|
|
266
|
+
name: c.name,
|
|
267
|
+
default: d.symbol,
|
|
268
|
+
defaultAccess: d.depositOpen.open ? "open" : "whitelist",
|
|
269
|
+
depositable: depositableVaults().filter((v) => v.chainId === c.chainId).map((v) => v.symbol),
|
|
270
|
+
};
|
|
271
|
+
}),
|
|
272
|
+
// Solana, when the registry has a vault there: no chain id; the cluster is in each Solana row.
|
|
273
|
+
...(listSolanaVaults().length === 0
|
|
274
|
+
? []
|
|
275
|
+
: [
|
|
276
|
+
{
|
|
277
|
+
chain: onSolana.chain,
|
|
278
|
+
chainId: null,
|
|
279
|
+
name: "Solana",
|
|
280
|
+
default: listSolanaVaults().find((v) => v.isDefault).symbol,
|
|
281
|
+
defaultAccess: "open",
|
|
282
|
+
depositable: depositableSolanaVaults().map((v) => v.symbol),
|
|
283
|
+
},
|
|
284
|
+
]),
|
|
285
|
+
],
|
|
286
|
+
vaults: [
|
|
287
|
+
...listVaults().map((v) => ({
|
|
288
|
+
symbol: v.symbol,
|
|
289
|
+
name: v.name,
|
|
290
|
+
warning: v.warning,
|
|
291
|
+
links: linksFor(v),
|
|
292
|
+
backend: v.backend,
|
|
293
|
+
isDefault: v.isDefault,
|
|
294
|
+
chain: CHAIN_INFO[v.chainId].key,
|
|
295
|
+
chainId: v.chainId,
|
|
296
|
+
address: v.address,
|
|
297
|
+
chassis: v.chassis,
|
|
298
|
+
asset: v.asset,
|
|
299
|
+
shareDecimals: v.shareDecimals,
|
|
300
|
+
depositOpen: v.depositOpen,
|
|
301
|
+
notes: v.notes,
|
|
302
|
+
})),
|
|
303
|
+
...listSolanaVaults().map(solanaVaultRow),
|
|
304
|
+
],
|
|
305
|
+
});
|
|
306
|
+
}));
|
|
307
|
+
register("earn_terms", {
|
|
308
|
+
title: "Pre-deposit disclosures",
|
|
309
|
+
description: "The disclosures every distribution surface must present before a depositor's first deposit. Show these to the operator and record acknowledgement before building any deposit.",
|
|
310
|
+
inputSchema: {},
|
|
311
|
+
}, guarded(async () => text(DISCLOSURES)));
|
|
312
|
+
register("earn_status", {
|
|
313
|
+
title: "Health check, or a deposit pre-flight verdict",
|
|
314
|
+
description: "With NO `account`: is the CLI working and the chain's RPC reachable — chain, chain id, latest block, registry version, and which env var supplied the RPC (never the URL). Each chain has its own RPC, so pass `chain` to check the one you are about to use; `rpc` is `ok`, `unreachable`, or `wrong_chain` when the configured endpoint answers for a different chain. `chainVerified: false` beside `ok` means the endpoint answered but did not say which chain it is. When a separate logs RPC is set, `logsRpc` reports it the same way. With `account`: simulates deposit() from that address and reports OPEN_READY, NEEDS_APPROVAL, WHITELIST_GATED, REVERTED_OTHER, REFUSED_BY_CLIENT or UNRESOLVED, never trusting maxDeposit(); on Solana it simulates the deposit transaction and reports OPEN_READY, NEEDS_FUNDS (the account lacks the USDC, or SOL for fees and rent), REVERTED_OTHER or UNRESOLVED. The `mode` field says which answer you got.",
|
|
315
|
+
inputSchema: { vault: vaultArg, chain, account: accountArg.optional(), amount_usdc: amountArg.optional() },
|
|
316
|
+
}, guarded(async ({ vault: symbol, chain, account, amount_usdc }) => {
|
|
317
|
+
const target = resolveAnyVault(symbol, chain);
|
|
318
|
+
if (target.family === "solana") {
|
|
319
|
+
const v = target.vault;
|
|
320
|
+
if (account !== undefined) {
|
|
321
|
+
return text({ ...(await solanaPreflight(v, account, amount_usdc)), mode: "preflight", account, ...onSolana, ...commitsMoney(v) }, "solana");
|
|
322
|
+
}
|
|
323
|
+
return text(await solanaHealth(v, symbol !== undefined ? { requested: "preflight", missing: ["account"] } : {}), "solana");
|
|
324
|
+
}
|
|
325
|
+
if (account !== undefined) {
|
|
326
|
+
const { vault, client, endpoints } = clientFor(symbol, chain);
|
|
327
|
+
const depositor = evm(account, "account");
|
|
328
|
+
const args = amount_usdc === undefined ? { vault, depositor, client } : { vault, depositor, client, assetsHuman: amount_usdc };
|
|
329
|
+
const verdict = await onItsChain(vault, endpoints, () => preflightDeposit(args));
|
|
330
|
+
// spread FIRST so the discriminant cannot be overwritten by a field of the same name
|
|
331
|
+
// `account` is echoed checksummed, as every other result names an address.
|
|
332
|
+
return text({ ...verdict, mode: "preflight", account: depositor, ...onChain(vault), ...commitsMoney(vault) }, vault.chainId);
|
|
333
|
+
}
|
|
334
|
+
// Health. A partial call (a vault but no account) is answered here too, and says so in
|
|
335
|
+
// STRUCTURE rather than in prose — a note is exactly what a consumer skips, and the risk is
|
|
336
|
+
// a loud health result being read as a preflight pass.
|
|
337
|
+
//
|
|
338
|
+
// A schema error would also close this. It is not taken because a structural carrier is more
|
|
339
|
+
// forgiving to an exploring agent: `earn_status` stays answerable in every state, including
|
|
340
|
+
// a malformed call. This is NOT rejected on the must-never-throw rule below — that rule governs
|
|
341
|
+
// a RUNTIME failure on the health path (a dead RPC must yield a verdict, not an exception),
|
|
342
|
+
// whereas a partial-args call is an INPUT problem settled by the CLI's schema check (`src/cli.ts`)
|
|
343
|
+
// before the handler body runs. The two are different layers, and conflating them would license
|
|
344
|
+
// "never validate inputs on a path that must not throw", which is not the rule.
|
|
345
|
+
//
|
|
346
|
+
// Only the account-missing case is "partial": `vault` HAS a default (documented as "omit for
|
|
347
|
+
// the default vault" across the whole tool surface), `account` has none. So {account, no vault}
|
|
348
|
+
// is a complete preflight against the default, not a partial call.
|
|
349
|
+
const partial = symbol !== undefined ? { requested: "preflight", missing: ["account"] } : {};
|
|
350
|
+
const vault = supportedVault(symbol, chain);
|
|
351
|
+
const src = rpcSourceForEnv(vault.chainId);
|
|
352
|
+
const base = {
|
|
353
|
+
mode: "health",
|
|
354
|
+
...partial,
|
|
355
|
+
server: "treasury",
|
|
356
|
+
version: PACKAGE_VERSION,
|
|
357
|
+
registry: { schemaVersion: loadRegistry().schemaVersion, vaults: loadRegistry().vaults.length, reconciledAtIso: loadRegistry().reconciledAtIso },
|
|
358
|
+
...onChain(vault),
|
|
359
|
+
rpcSource: src.source,
|
|
360
|
+
rpcConfigured: src.configured,
|
|
361
|
+
};
|
|
362
|
+
// 🔴 The health path RETURNS a verdict when the RPC is unreachable. It must never throw: a
|
|
363
|
+
// tool that throws on a dead RPC answers nothing, which is the whole point of having it.
|
|
364
|
+
try {
|
|
365
|
+
const info = CHAIN_INFO[vault.chainId];
|
|
366
|
+
const url = rpcUrlFromEnv(vault.chainId);
|
|
367
|
+
const client = makePublicClient(vault.chainId, url);
|
|
368
|
+
// Two chains mean two RPC variables, and one pointed at the other chain is the likeliest
|
|
369
|
+
// mistake. Asked only of an endpoint the operator configured, alongside the block read, and
|
|
370
|
+
// bounded — so a healthy answer is never held up waiting for a second one.
|
|
371
|
+
const logsSrc = logsRpcSourceForEnv(vault.chainId);
|
|
372
|
+
const logsUrl = logsRpcUrlFromEnv(vault.chainId);
|
|
373
|
+
const separateLogs = logsUrl !== url;
|
|
374
|
+
const [said, logsSaid, latest] = await Promise.all([
|
|
375
|
+
src.configured ? endpointChainId(client, url) : Promise.resolve(undefined),
|
|
376
|
+
separateLogs ? endpointChainId(makePublicClient(vault.chainId, logsUrl), logsUrl) : Promise.resolve(undefined),
|
|
377
|
+
client.getBlockNumber(),
|
|
378
|
+
]);
|
|
379
|
+
// The endpoint `earn_balance` scans through is a different variable, and it can be wrong on
|
|
380
|
+
// its own. Reported beside the main verdict, only when it IS a separate endpoint.
|
|
381
|
+
const logs = separateLogs
|
|
382
|
+
? {
|
|
383
|
+
logsRpcSource: logsSrc.source,
|
|
384
|
+
logsRpc: logsSaid === undefined ? "unreachable" : logsSaid === vault.chainId ? "ok" : "wrong_chain",
|
|
385
|
+
...(logsSaid !== undefined && logsSaid !== vault.chainId ? { logsRpcChainId: logsSaid } : {}),
|
|
386
|
+
}
|
|
387
|
+
: {};
|
|
388
|
+
if (said !== undefined && said !== vault.chainId) {
|
|
389
|
+
return text({
|
|
390
|
+
...base,
|
|
391
|
+
rpc: "wrong_chain",
|
|
392
|
+
rpcChainId: said,
|
|
393
|
+
latestBlock: null,
|
|
394
|
+
reason: `the endpoint in ${src.source} answers for chain ${said}, not ${info.name} (${vault.chainId}). Point ${info.rpcEnv[0]} at an endpoint for ${info.name}; until then no read for this chain can be trusted.`,
|
|
395
|
+
...logs,
|
|
396
|
+
}, vault.chainId);
|
|
397
|
+
}
|
|
398
|
+
// `chainVerified` is the difference between "it answered, and for this chain" and "it
|
|
399
|
+
// answered a block number, and did not say which chain". Present only for a configured endpoint.
|
|
400
|
+
const verified = src.configured ? { chainVerified: said === vault.chainId } : {};
|
|
401
|
+
return text({ ...base, rpc: "ok", ...verified, latestBlock: latest.toString(), ...logs }, vault.chainId);
|
|
402
|
+
}
|
|
403
|
+
catch (e) {
|
|
404
|
+
const reason = redactEndpoints(e instanceof Error ? e.message : String(e));
|
|
405
|
+
return text({ ...base, rpc: "unreachable", latestBlock: null, reason }, vault.chainId);
|
|
406
|
+
}
|
|
407
|
+
}));
|
|
408
|
+
register("earn_quote", {
|
|
409
|
+
title: "Quote a deposit or a withdrawal",
|
|
410
|
+
description: "Pre-trade quote, in the vault's asset (USDC; USDG on Robinhood Chain). direction=deposit: expected shares (previewDeposit), share price, and the access verdict from a simulated deposit(). This client quotes no rate: an ERC-4626 vault exposes none, and it calls no yield API. direction=withdraw: shares burned (previewWithdraw), shares held, a simulated withdraw() verdict, `instantLiquidity` — the vault's own liquid balance of the asset, which is chassis-specific in BOTH directions: a Fusion vault without instant-withdrawal fuses pays only from it, so there it is the ceiling maxWithdraw() does not know; a Morpho V2 vault holds almost none and still pays out of its markets, so there it is near zero and NOT a ceiling — the simulated verdict is what decides — maxWithdraw advisory only (Morpho V2 returns 0 by design), and queue depth. Run before the matching `earn prepare_*` command.",
|
|
411
|
+
inputSchema: {
|
|
412
|
+
vault: vaultArg,
|
|
413
|
+
chain,
|
|
414
|
+
account: accountArg,
|
|
415
|
+
amount_usdc: amountArg,
|
|
416
|
+
direction: z.enum(["deposit", "withdraw"]).describe("which side to quote — required, there is no default"),
|
|
417
|
+
},
|
|
418
|
+
}, guarded(async ({ vault: symbol, chain, account: rawAccount, amount_usdc, direction }) => {
|
|
419
|
+
const target = resolveAnyVault(symbol, chain);
|
|
420
|
+
if (target.family === "solana") {
|
|
421
|
+
const v = target.vault;
|
|
422
|
+
if (direction === "deposit")
|
|
423
|
+
return text({ direction: "deposit", ...onSolana, ...commitsMoney(v), ...(await solanaQuoteDeposit(v, rawAccount, amount_usdc)) }, "solana");
|
|
424
|
+
return text({ direction: "withdraw", ...onSolana, ...(await solanaQuoteWithdraw(v, rawAccount, amount_usdc)) }, "solana");
|
|
425
|
+
}
|
|
426
|
+
const account = evm(rawAccount, "account");
|
|
427
|
+
const { vault, client, endpoints } = clientFor(symbol, chain);
|
|
428
|
+
// 🔴 The tag is emitted from INSIDE each branch, beside the fields that branch produces —
|
|
429
|
+
// never `{ direction, ...quote }` from the input argument. Measured in review: with the tag
|
|
430
|
+
// taken from the input, swapping these two branches left `tsc -b` clean and all 61 tests
|
|
431
|
+
// passing, and the result read `{ direction: "deposit", sharesToBurn: … }` — the tag said
|
|
432
|
+
// deposit while the body was a withdrawal. A guard derived from the wrong side of the thing
|
|
433
|
+
// it guards cannot detect the bug it exists for. Emitted here, tag and body are consistent
|
|
434
|
+
// BY CONSTRUCTION; a swapped route is then wrong about the REQUEST, which the handler test
|
|
435
|
+
// catches by asserting requested === returned, and never lying about the BODY.
|
|
436
|
+
if (direction === "deposit") {
|
|
437
|
+
return text({
|
|
438
|
+
direction: "deposit",
|
|
439
|
+
...onChain(vault),
|
|
440
|
+
...commitsMoney(vault),
|
|
441
|
+
...(await onItsChain(vault, endpoints, () => quoteDeposit({ vault, depositor: account, assetsHuman: amount_usdc, client }))),
|
|
442
|
+
}, vault.chainId);
|
|
443
|
+
}
|
|
444
|
+
return text({ direction: "withdraw", ...onChain(vault), ...(await onItsChain(vault, endpoints, () => quoteWithdraw({ vault, owner: account, assetsHuman: amount_usdc, client }))) }, vault.chainId);
|
|
445
|
+
}));
|
|
446
|
+
register("earn_prepare_deposit", {
|
|
447
|
+
title: "Prepare an unsigned deposit",
|
|
448
|
+
description: "Returns the UNSIGNED calls for a deposit — [approve(asset → vault), deposit(assets, receiver)] on the EVM chains, ONE unsigned transaction (`transaction.wire`) on Solana — inside an envelope with requires_signature: true. Amount is in the vault's asset — USDC, or USDG on Robinhood Chain; `amount_usdc` keeps its name for every asset. The envelope names the `chain` and `chainId` the calls are for: say which chain to the operator, and if they have not chosen one, ask before calling this. NOTHING IS SUBMITTED: hand the calls to a signer in order. This tool cannot sign or send, and the deposit has not happened until the signer's transactions confirm. On the EVM chains each call also carries `function` and `args` — the same call `data` encodes, decoded, e.g. `approve(address spender, uint256 value)` with `{ spender, value }` — so an operator without a CLI signer can fill a block explorer's Write Contract form directly. `args` values are RAW contract units, which is what the form takes; `description` is the human sentence.",
|
|
449
|
+
inputSchema: {
|
|
450
|
+
vault: vaultArg,
|
|
451
|
+
chain,
|
|
452
|
+
account: accountArg.describe("the depositing account — the one that signs both calls; step 2's allowance precondition is read for it"),
|
|
453
|
+
amount_usdc: amountArg,
|
|
454
|
+
receiver: addressArg.describe("where the SHARES land — usually the account, not necessarily"),
|
|
455
|
+
},
|
|
456
|
+
}, guarded(async ({ vault: symbol, chain, account, amount_usdc, receiver }) => {
|
|
457
|
+
const target = resolveAnyVault(symbol, chain);
|
|
458
|
+
if (target.family === "solana") {
|
|
459
|
+
// The warning before `next_step`, through the chokepoint, exactly as on EVM.
|
|
460
|
+
const { requires_signature, status, ...rest } = await solanaPrepareDeposit(target.vault, account, amount_usdc, receiver);
|
|
461
|
+
return text({ requires_signature, status, ...onSolana, ...commitsMoney(target.vault), ...rest }, "solana");
|
|
462
|
+
}
|
|
463
|
+
const vault = supportedVault(symbol, chain);
|
|
464
|
+
return unsigned(buildDeposit(vault, { assetsHuman: amount_usdc, receiver: evm(receiver, "receiver"), account: evm(account, "account") }), vault, "deposit");
|
|
465
|
+
}));
|
|
466
|
+
register("earn_prepare_withdraw", {
|
|
467
|
+
title: "Prepare an unsigned withdrawal",
|
|
468
|
+
description: "Returns the UNSIGNED call for a withdrawal in asset terms — withdraw(assets, receiver, owner) on the EVM chains, ONE unsigned transaction (`transaction.wire`) on Solana — inside an envelope with requires_signature: true, which names the `chain` the call is for: a position is withdrawn on the chain it is on, so name the vault (or its chain) and never ask the operator to choose one. To empty the account pass --all (a switch: it takes no value) with shares_exact copied verbatim from sharesExact from `earn balance` (redeem of the exact balance; never a rounded number). NOTHING IS SUBMITTED and no funds have moved until a signer confirms. On the EVM chains each call also carries `function` and `args` — the same call `data` encodes, decoded, e.g. `withdraw(uint256 assets, address receiver, address owner)` with `{ assets, receiver, owner }` — so an operator without a CLI signer can fill a block explorer's Write Contract form directly. `args` values are RAW contract units, which is what the form takes; `description` is the human sentence.",
|
|
469
|
+
inputSchema: {
|
|
470
|
+
vault: vaultArg,
|
|
471
|
+
chain,
|
|
472
|
+
receiver: addressArg.describe("where the asset lands — NOT necessarily the account"),
|
|
473
|
+
account: accountArg.describe("whose shares are burnt"),
|
|
474
|
+
amount_usdc: amountArg.optional(),
|
|
475
|
+
all: z.boolean().optional(),
|
|
476
|
+
shares_exact: z.string().regex(/^\d+(\.\d+)?$/).optional(),
|
|
477
|
+
},
|
|
478
|
+
}, guarded(async ({ vault: symbol, chain, receiver: rawReceiver, account: rawAccount, amount_usdc, all, shares_exact }) => {
|
|
479
|
+
const target = resolveAnyVault(symbol, chain);
|
|
480
|
+
if (all && amount_usdc)
|
|
481
|
+
throw new Error("give --amount_usdc or --all with --shares_exact, not both");
|
|
482
|
+
if (!all && shares_exact)
|
|
483
|
+
throw new Error("--shares_exact goes with --all; for an amount in the asset, use --amount_usdc alone");
|
|
484
|
+
if (all && !shares_exact)
|
|
485
|
+
throw new Error("--all requires --shares_exact (copy sharesExact from `earn balance` verbatim)");
|
|
486
|
+
if (!all && !amount_usdc)
|
|
487
|
+
throw new Error("provide --amount_usdc, or --all with --shares_exact");
|
|
488
|
+
if (target.family === "solana") {
|
|
489
|
+
return text(await solanaPrepareWithdraw(target.vault, rawAccount, rawReceiver, all ? { sharesExact: shares_exact } : { amountHuman: amount_usdc }), "solana");
|
|
490
|
+
}
|
|
491
|
+
const vault = supportedVault(symbol, chain);
|
|
492
|
+
const receiver = evm(rawReceiver, "receiver");
|
|
493
|
+
const account = evm(rawAccount, "account");
|
|
494
|
+
// ⚠️ `receiver` and `account` are DIFFERENT slots and both are addresses, so a transposition
|
|
495
|
+
// here type-checks. `account` is the owner whose shares burn; `receiver` is the payee.
|
|
496
|
+
if (all) {
|
|
497
|
+
if (!shares_exact)
|
|
498
|
+
throw new Error("--all requires --shares_exact (copy sharesExact from `earn balance` verbatim)");
|
|
499
|
+
return unsigned(buildWithdraw(vault, { receiver, owner: account, all: true, sharesExact: shares_exact }), vault, "withdraw");
|
|
500
|
+
}
|
|
501
|
+
if (!amount_usdc)
|
|
502
|
+
throw new Error("provide --amount_usdc, or --all with --shares_exact");
|
|
503
|
+
return unsigned(buildWithdraw(vault, { receiver, owner: account, assetsHuman: amount_usdc }), vault, "withdraw");
|
|
504
|
+
}));
|
|
505
|
+
register("earn_balance", {
|
|
506
|
+
title: "Earn position",
|
|
507
|
+
description: "A position in ONE vault, on that vault's chain (`chain` in the result) — an account's positions on different chains are separate calls. Shares held (exact string + display), current value in the vault's asset (`usdcValue` keeps its name; on Robinhood Chain it is USDG), WHAT CAN ACTUALLY BE WITHDRAWN NOW (`exit`, measured by simulating the withdrawal — `usdcValue` is what the position is worth, `exit.exitableNow` is what the vault can pay, `exit.instantLiquidity` is the vault's own liquid balance of the asset, chassis-specific in both directions — a Fusion vault without instant-withdrawal fuses pays only from it, so there it is the ceiling and `usdcValue` can exceed `exitableNow` by 10x while `maxWithdraw()` — `exit.maxWithdrawSays` — reports the larger one; a Morpho V2 vault holds almost none and still pays out of its markets, so there a near-zero `instantLiquidity` is not a ceiling and `exitableNow` is the verdict), entry basis and accrued yield derived from the vault's own Deposit/Withdraw events for this account, and share price. `scan.complete` says whether the event window covered the whole position; `sharesExact` is what `earn prepare_withdraw --all` needs. `scan.depositTxs` and `scan.withdrawTxs` carry the transactions behind those events — `{ txHash, blockNumber, amountUsdc }`, oldest first — so an operator can be shown an explorer link without anyone rebuilding the log query; each list holds at most the 100 most recent, while `scan.deposits`/`scan.withdrawals` stay the totals.",
|
|
508
|
+
inputSchema: {
|
|
509
|
+
vault: vaultArg,
|
|
510
|
+
chain,
|
|
511
|
+
account: accountArg,
|
|
512
|
+
lookback_blocks: z.number().int().positive().optional().describe("how far back to scan for Deposit/Withdraw events; default: from the vault's deployment block, i.e. the whole history. The EFFECTIVE window is max_log_requests × the provider's eth_getLogs cap (Alchemy free 10 blocks, Base public 2,000, Infura on Arbitrum 10,000); if the configured RPC cannot cover it, the chain's public endpoint serves the scan and scan.source says so"),
|
|
513
|
+
max_log_requests: z.number().int().positive().max(400).optional().describe("cap on eth_getLogs calls per event per scan; default 100 (= 1,000 blocks on Alchemy free, 200,000 on Base public). scan.wholeHistory says whether the scan actually covered every block since the vault was deployed — scan.complete alone is only a reconciliation and can be vacuously true. For an older vault, a provider with a wide eth_getLogs range (TREASURY_LOGS_RPC_BASE; TREASURY_LOGS_RPC_ARBITRUM on Arbitrum One; TREASURY_LOGS_RPC_ROBINHOOD on Robinhood Chain; TREASURY_LOGS_RPC_ETHEREUM on Ethereum; TREASURY_LOGS_RPC_MONAD on Monad, whose public endpoint serves only 100 blocks per request) is what makes it whole"),
|
|
514
|
+
},
|
|
515
|
+
}, guarded(async ({ vault: symbol, chain, account: rawAccount, lookback_blocks, max_log_requests }) => {
|
|
516
|
+
const target = resolveAnyVault(symbol, chain);
|
|
517
|
+
if (target.family === "solana")
|
|
518
|
+
return text({ ...onSolana, ...(await solanaBalance(target.vault, rawAccount)) }, "solana");
|
|
519
|
+
const account = evm(rawAccount, "account");
|
|
520
|
+
const vault = supportedVault(symbol, chain);
|
|
521
|
+
const logsUrl = logsRpcUrlFromEnv(vault.chainId);
|
|
522
|
+
const client = makePublicClient(vault.chainId, logsUrl);
|
|
523
|
+
// `logsFallbackUrlFromEnv` returns undefined when the operator opted out or when the fallback
|
|
524
|
+
// would be the primary itself — the wiring is a one-liner precisely so it can be unit-tested
|
|
525
|
+
// (measured in review: mutating this line to `undefined` left every position-layer test green;
|
|
526
|
+
// `commands.unit.test.ts` is what fails now).
|
|
527
|
+
const fallbackUrl = logsFallbackUrlFromEnv(vault.chainId, logsUrl);
|
|
528
|
+
const fallbackClient = fallbackUrl === undefined ? undefined : makePublicClient(vault.chainId, fallbackUrl);
|
|
529
|
+
// Every endpoint this read can go through: the logs RPC, and the fallback when the operator
|
|
530
|
+
// named one. A fallback on the wrong chain answers an event scan with an EMPTY list, which
|
|
531
|
+
// would be reported as a history that was read in full.
|
|
532
|
+
const endpoints = [{ client, url: logsUrl, source: logsRpcSourceForEnv(vault.chainId).source }];
|
|
533
|
+
if (fallbackClient && fallbackUrl !== undefined)
|
|
534
|
+
endpoints.push({ client: fallbackClient, url: fallbackUrl, source: "TREASURY_LOGS_FALLBACK" });
|
|
535
|
+
const position = await onItsChain(vault, endpoints, () => getPosition({
|
|
536
|
+
vault,
|
|
537
|
+
principal: account,
|
|
538
|
+
client,
|
|
539
|
+
...(fallbackClient ? { fallbackClient } : {}),
|
|
540
|
+
...(lookback_blocks === undefined ? {} : { lookbackBlocks: BigInt(lookback_blocks) }),
|
|
541
|
+
...(max_log_requests === undefined ? {} : { maxLogRequests: max_log_requests }),
|
|
542
|
+
}));
|
|
543
|
+
return text({ ...onChain(vault), ...position }, vault.chainId);
|
|
544
|
+
}));
|
|
545
|
+
register("earn_claim", {
|
|
546
|
+
title: "Claim a queued withdrawal",
|
|
547
|
+
description: "Finalizes a queued withdrawal on chassis that settle asynchronously. No vault in the current registry queues — Morpho V2 and Fusion settle in the withdraw transaction — so this reports that nothing is claimable. Present so callers can code against the full contract before an async chassis (e.g. a queued-redemption fund) is added.",
|
|
548
|
+
inputSchema: { receipt_id: z.string() },
|
|
549
|
+
}, guarded(async ({ receipt_id }) => text({
|
|
550
|
+
receipt_id,
|
|
551
|
+
status: "nothing_to_claim",
|
|
552
|
+
note: "No chassis in the registry queues withdrawals; a withdraw() that succeeded already delivered the asset (USDC; USDG on Robinhood Chain). When an async chassis is added, this tool will finalize its claim handle.",
|
|
553
|
+
})));
|
|
554
|
+
return commands;
|
|
555
|
+
}
|
|
556
|
+
//# sourceMappingURL=commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/earn/commands.ts"],"names":[],"mappings":"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"}
|