@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.
Files changed (74) hide show
  1. package/NOTICE +4 -2
  2. package/README.md +68 -44
  3. package/THIRD_PARTY_NOTICES.connect-page.md +7420 -0
  4. package/THIRD_PARTY_NOTICES.md +4 -196
  5. package/dist/cli.d.ts +6 -0
  6. package/dist/cli.js +220 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/client.d.ts +224 -239
  9. package/dist/client.js +147 -25
  10. package/dist/client.js.map +1 -1
  11. package/dist/config/earn.d.ts +33 -12
  12. package/dist/config/earn.js +33 -12
  13. package/dist/config/earn.js.map +1 -1
  14. package/dist/connect/ack.d.ts +59 -0
  15. package/dist/connect/ack.js +111 -0
  16. package/dist/connect/ack.js.map +1 -0
  17. package/dist/connect/commands.d.ts +78 -0
  18. package/dist/connect/commands.js +411 -0
  19. package/dist/connect/commands.js.map +1 -0
  20. package/dist/connect/config.d.ts +22 -0
  21. package/dist/connect/config.js +33 -0
  22. package/dist/connect/config.js.map +1 -0
  23. package/dist/connect/gate.d.ts +37 -0
  24. package/dist/connect/gate.js +115 -0
  25. package/dist/connect/gate.js.map +1 -0
  26. package/dist/connect/http.d.ts +54 -0
  27. package/dist/connect/http.js +205 -0
  28. package/dist/connect/http.js.map +1 -0
  29. package/dist/connect/open.d.ts +2 -0
  30. package/dist/connect/open.js +35 -0
  31. package/dist/connect/open.js.map +1 -0
  32. package/dist/connect/page.d.ts +5 -0
  33. package/dist/connect/page.js +69 -0
  34. package/dist/connect/page.js.map +1 -0
  35. package/dist/connect/session.d.ts +16 -0
  36. package/dist/connect/session.js +73 -0
  37. package/dist/connect/session.js.map +1 -0
  38. package/dist/connect/verify.d.ts +37 -0
  39. package/dist/connect/verify.js +89 -0
  40. package/dist/connect/verify.js.map +1 -0
  41. package/dist/connect-page.js +5141 -0
  42. package/dist/disclosures.d.ts +21 -6
  43. package/dist/disclosures.js +32 -7
  44. package/dist/disclosures.js.map +1 -1
  45. package/dist/earn/commands.d.ts +46 -0
  46. package/dist/earn/commands.js +483 -0
  47. package/dist/earn/commands.js.map +1 -0
  48. package/dist/links.d.ts +2 -0
  49. package/dist/links.js +38 -14
  50. package/dist/links.js.map +1 -1
  51. package/dist/position.d.ts +7 -5
  52. package/dist/position.js +35 -18
  53. package/dist/position.js.map +1 -1
  54. package/dist/preflight.d.ts +9 -0
  55. package/dist/preflight.js +14 -3
  56. package/dist/preflight.js.map +1 -1
  57. package/dist/quote.js +24 -7
  58. package/dist/quote.js.map +1 -1
  59. package/dist/redact.d.ts +3 -3
  60. package/dist/redact.js +3 -3
  61. package/dist/redact.js.map +1 -1
  62. package/dist/registry-schema.d.ts +5 -5
  63. package/dist/registry-schema.js +30 -16
  64. package/dist/registry-schema.js.map +1 -1
  65. package/dist/registry.d.ts +29 -6
  66. package/dist/registry.js +76 -13
  67. package/dist/registry.js.map +1 -1
  68. package/dist/{mcp-server.mjs → treasury.mjs} +29276 -44702
  69. package/dist/version.js +1 -1
  70. package/package.json +5 -5
  71. package/registry/vaults.json +105 -4
  72. package/dist/mcp/server.d.ts +0 -8
  73. package/dist/mcp/server.js +0 -368
  74. package/dist/mcp/server.js.map +0 -1
package/dist/client.js CHANGED
@@ -1,11 +1,43 @@
1
1
  import { createPublicClient, http } from "viem";
2
- import { base } from "viem/chains";
3
- export const chains = { 8453: base };
2
+ import { arbitrum, base, robinhood } from "viem/chains";
3
+ export const chains = { 8453: base, 42161: arbitrum, 4663: robinhood };
4
4
  export function isSupportedChainId(id) {
5
5
  return id in chains;
6
6
  }
7
+ export const CHAIN_INFO = {
8
+ 8453: { key: "base", name: "Base", rpcEnv: ["TREASURY_RPC_BASE", "BASE_RPC_URL"], logsRpcEnv: "TREASURY_LOGS_RPC_BASE", publicRpc: "https://mainnet.base.org" },
9
+ 42161: {
10
+ key: "arbitrum",
11
+ name: "Arbitrum One",
12
+ rpcEnv: ["TREASURY_RPC_ARBITRUM", "ARBITRUM_RPC_URL"],
13
+ logsRpcEnv: "TREASURY_LOGS_RPC_ARBITRUM",
14
+ publicRpc: "https://arb1.arbitrum.io/rpc",
15
+ },
16
+ 4663: {
17
+ key: "robinhood",
18
+ name: "Robinhood Chain",
19
+ rpcEnv: ["TREASURY_RPC_ROBINHOOD", "ROBINHOOD_RPC_URL"],
20
+ logsRpcEnv: "TREASURY_LOGS_RPC_ROBINHOOD",
21
+ publicRpc: "https://rpc.mainnet.chain.robinhood.com",
22
+ },
23
+ };
24
+ /**
25
+ * Every supported chain, in the order chains were added: Base first, then Arbitrum One, then Robinhood
26
+ * Chain. Listed rather than read from `Object.keys(chains)`, whose integer keys enumerate in numeric
27
+ * order and would put Robinhood Chain (4663) ahead of Base everywhere a list of chains is shown.
28
+ * `client.unit.test.ts` holds this list equal to the keys of `chains`.
29
+ */
30
+ export const supportedChainIds = [8453, 42161, 4663];
31
+ /** `"arbitrum"` → 42161. `undefined` for a name this client does not know — the caller says so. */
32
+ export function chainIdForKey(key) {
33
+ return supportedChainIds.find((id) => CHAIN_INFO[id].key === key);
34
+ }
7
35
  /** The public endpoint used when nothing is configured, and the fallback for event scans. */
8
- export const PUBLIC_RPC = { 8453: "https://mainnet.base.org" };
36
+ export const PUBLIC_RPC = {
37
+ 8453: CHAIN_INFO[8453].publicRpc,
38
+ 42161: CHAIN_INFO[42161].publicRpc,
39
+ 4663: CHAIN_INFO[4663].publicRpc,
40
+ };
9
41
  /**
10
42
  * A `fetch` that waits out HTTP 429 instead of failing the tool. Measured 2026-09-14: a free-tier
11
43
  * keyed Base RPC answered an `earn_quote` read with 429 and the tool failed outright, because viem's
@@ -82,10 +114,12 @@ export function makePublicClient(chainId, rpcUrl) {
82
114
  /**
83
115
  * An env value counts as an RPC URL only if it parses as one with an http(s) scheme. Anything else —
84
116
  * empty, whitespace, a non-URL, and in particular an UNEXPANDED placeholder like `${TREASURY_RPC_BASE}` —
85
- * is treated as unset. Measured 2026-09-12: Claude Code forwards the plugin's `.mcp.json` value
86
- * `${TREASURY_RPC_BASE}` verbatim when the host variable is unset, and with the old `if (v)` test every
87
- * RPC-touching tool died on "Failed to parse URL from ${TREASURY_RPC_BASE}". `.mcp.json` now also uses
88
- * `${VAR:-}`, but this guard is what makes the server independent of any host's expansion rules.
117
+ * is treated as unset. Measured 2026-09-12, when the plugin still declared an MCP server: Claude Code
118
+ * forwarded the server declaration's value `${TREASURY_RPC_BASE}` verbatim when the host variable was
119
+ * unset, and with the old `if (v)` test every RPC-touching tool died on "Failed to parse URL from
120
+ * ${TREASURY_RPC_BASE}". The plugin now runs the CLI through the shell and declares nothing, but any
121
+ * host or wrapper can still pass a placeholder through, and this guard is what makes the client
122
+ * independent of anyone's expansion rules.
89
123
  */
90
124
  export function rpcUrlFromEnvValue(v) {
91
125
  if (!v)
@@ -103,16 +137,21 @@ export function rpcUrlFromEnvValue(v) {
103
137
  }
104
138
  /**
105
139
  * Resolves the RPC URL for a chain from the environment. ⚠️ A keyed provider URL IS a secret: it must
106
- * never appear in tool output — every error crossing the tool boundary goes through `describeError`
107
- * (`src/redact.ts`), which strips endpoints. Fallback names after `TREASURY_RPC_BASE`:
108
- * `BASE_RPC_URL`; the plugin's `.mcp.json` passes only the `TREASURY_*` pair through, so under the
109
- * packaged path the fallback is unreachable.
110
- * `TREASURY_LOGS_RPC_BASE`, if set, is preferred for log scans (providers cap eth_getLogs ranges very
111
- * differently: Alchemy free 10 blocks, Base public 2,000) — see `position.ts`.
140
+ * never appear in tool output — every error crossing the tool boundary goes through `redactEndpoints`
141
+ * (`src/redact.ts`), which strips endpoints. The names come from `CHAIN_INFO`: on Base,
142
+ * `TREASURY_RPC_BASE` then `BASE_RPC_URL`; on Arbitrum One, `TREASURY_RPC_ARBITRUM` then
143
+ * `ARBITRUM_RPC_URL`; on Robinhood Chain, `TREASURY_RPC_ROBINHOOD` then `ROBINHOOD_RPC_URL`. The CLI inherits its shell's whole environment, so on every path, the plugin's
144
+ * included, the second name of each pair is used when the first is unset.
145
+ * The chain's logs variable (`TREASURY_LOGS_RPC_BASE`, `TREASURY_LOGS_RPC_ARBITRUM`, `TREASURY_LOGS_RPC_ROBINHOOD`), if set, is
146
+ * preferred for log scans (providers cap eth_getLogs ranges very differently: Alchemy free 10 blocks,
147
+ * Base public 2,000, Infura 10,000 on Arbitrum) — see `position.ts`.
148
+ *
149
+ * 🔴 A chain reads ONLY its own variables. An Arbitrum call never falls back to a Base endpoint: a
150
+ * vault's address has no contract on the other chain, so reads fail with "returned no data" — which
151
+ * reads as a broken vault rather than as a misconfiguration.
112
152
  */
113
153
  export function rpcUrlFromEnv(chainId) {
114
- const candidates = chainId === 8453 ? ["TREASURY_RPC_BASE", "BASE_RPC_URL"] : [];
115
- for (const k of candidates) {
154
+ for (const k of CHAIN_INFO[chainId].rpcEnv) {
116
155
  const v = rpcUrlFromEnvValue(process.env[k]);
117
156
  if (v)
118
157
  return v;
@@ -121,17 +160,23 @@ export function rpcUrlFromEnv(chainId) {
121
160
  }
122
161
  /**
123
162
  * The endpoint an event scan falls back to when the configured logs RPC cannot cover the range — and
124
- * the operator's opt-out from it. `TREASURY_LOGS_FALLBACK` unset ⇒ Base's public endpoint; an http(s)
125
- * URL ⇒ that endpoint; ANY other value — `off`, `none`, `disabled`, a typo — ⇒ no fallback at all, and
126
- * the scan degrades to a cut-short window as it did before the fallback existed. It exists because the fallback
163
+ * the operator's opt-out from it. `TREASURY_LOGS_FALLBACK` unset ⇒ the chain's public endpoint; an
164
+ * http(s) URL ⇒ that endpoint, ON BASE ONLY; ANY other value — `off`, `none`, `disabled`, a typo — ⇒ no
165
+ * fallback at all, and the scan degrades to a cut-short window as it did before the fallback existed. It exists because the fallback
127
166
  * otherwise sends a query to a third party the operator never named, which some
128
167
  * deployments cannot accept — and it fails CLOSED for the same reason.
168
+ *
169
+ * 🔴 The variable names ONE endpoint, and that endpoint is on Base. On any other chain a URL there
170
+ * cannot serve the scan — it would answer for the wrong chain — so a SET variable means no fallback
171
+ * on that chain, whatever it holds: either the operator opted out, or they named a Base endpoint and
172
+ * so constrained where this process talks. An operator who wants history on another chain points that
173
+ * chain's logs variable (`TREASURY_LOGS_RPC_ARBITRUM`, `TREASURY_LOGS_RPC_ROBINHOOD`) at a provider with a wide eth_getLogs range.
129
174
  */
130
175
  export function logsFallbackUrlFromEnv(chainId, logsUrl) {
131
176
  const raw = (process.env["TREASURY_LOGS_FALLBACK"] ?? "").trim();
132
177
  // Unset, empty, or an unexpanded `${VAR}` placeholder: the default fallback.
133
178
  // ⚠️ The placeholder is THE ONE DELIBERATE EXCEPTION to fail-closed below.
134
- // An MCP host forwards `${TREASURY_LOGS_FALLBACK}` verbatim when the host variable is unset, so a
179
+ // A host can forward `${TREASURY_LOGS_FALLBACK}` verbatim when the variable is unset, so a
135
180
  // placeholder means the operator never set it — and unset must behave exactly as absent, or every
136
181
  // plugin install without the variable silently loses its fallback. The function cannot tell "the
137
182
  // host did not expand it" from "someone typed it"; the second reading is treated as implausible on
@@ -141,6 +186,8 @@ export function logsFallbackUrlFromEnv(chainId, logsUrl) {
141
186
  // 🔴 An operator who set this variable at all was constraining where this process talks. Reading an
142
187
  // unrecognised value as "use the default third party" is the one outcome they cannot have meant
143
188
  // (measured in review: `disabled` silently kept the public fallback until this failed closed).
189
+ if (chainId !== 8453)
190
+ return undefined; // set, and this chain is not the one the variable names an endpoint for
144
191
  const url = rpcUrlFromEnvValue(raw);
145
192
  return url === undefined ? undefined : sameOrUndefined(url, logsUrl);
146
193
  }
@@ -150,7 +197,7 @@ function sameOrUndefined(url, logsUrl) {
150
197
  }
151
198
  /** RPC to use for eth_getLogs scans: a dedicated one if configured, else the general one. */
152
199
  export function logsRpcUrlFromEnv(chainId) {
153
- return rpcUrlFromEnvValue(process.env["TREASURY_LOGS_RPC_BASE"]) ?? rpcUrlFromEnv(chainId);
200
+ return rpcUrlFromEnvValue(process.env[CHAIN_INFO[chainId].logsRpcEnv]) ?? rpcUrlFromEnv(chainId);
154
201
  }
155
202
  /**
156
203
  * Which environment variable supplied the RPC URL — the NAME only, never the value. A keyed provider
@@ -158,8 +205,7 @@ export function logsRpcUrlFromEnv(chainId) {
158
205
  * no variable resolved and the public endpoint is in use (rate-limited, never a failure).
159
206
  */
160
207
  export function rpcSourceForEnv(chainId) {
161
- const candidates = chainId === 8453 ? ["TREASURY_RPC_BASE", "BASE_RPC_URL"] : [];
162
- for (const k of candidates) {
208
+ for (const k of CHAIN_INFO[chainId].rpcEnv) {
163
209
  if (rpcUrlFromEnvValue(process.env[k]))
164
210
  return { source: k, configured: true };
165
211
  }
@@ -180,9 +226,17 @@ export function resolvedRpcSecrets() {
180
226
  // `sk-Live_a%2Bb%2Fc%3Dd9f8e7`, only that was registered, and the plain key leaked. The earlier
181
227
  // test missed it because `SECRETKEY123` percent-encodes to ITSELF — the transformation was the
182
228
  // identity function, so the test could not tell the two forms apart.
229
+ // 🔴 A chain's own key is NOT a secret, and it is long enough to be taken for one. Providers put
230
+ // the chain in the URL — `rpc.example/arbitrum/<key>`, `arbitrum.example.org` — and a path segment
231
+ // or first host label of 8+ characters is registered below. "arbitrum" is exactly 8, so with such a
232
+ // URL configured every refusal that names the chain read `chains with a vault: base, <redacted>`
233
+ // (measured in review). "base" is 4 characters, which is why one chain never showed it.
234
+ const chainWords = new Set(supportedChainIds.map((id) => CHAIN_INFO[id].key));
183
235
  const add = (v) => {
184
236
  if (!v || v.length < 8)
185
237
  return;
238
+ if (chainWords.has(v.toLowerCase()))
239
+ return;
186
240
  out.add(v);
187
241
  try {
188
242
  const decoded = decodeURIComponent(v);
@@ -197,7 +251,9 @@ export function resolvedRpcSecrets() {
197
251
  // Every variable that can name a URL the package will CALL — the logs fallback included: it builds a
198
252
  // real client, and a provider's error body can echo its key exactly as the primary's (measured in
199
253
  // review; dormant until describeError began reporting the body).
200
- for (const k of ["TREASURY_RPC_BASE", "TREASURY_LOGS_RPC_BASE", "BASE_RPC_URL", "TREASURY_LOGS_FALLBACK"]) {
254
+ // Derived from the chain table, so a chain added there cannot be left out of the redactor.
255
+ const names = [...supportedChainIds.flatMap((id) => [...CHAIN_INFO[id].rpcEnv, CHAIN_INFO[id].logsRpcEnv]), "TREASURY_LOGS_FALLBACK"];
256
+ for (const k of names) {
201
257
  const v = rpcUrlFromEnvValue(process.env[k]);
202
258
  if (v)
203
259
  urls.add(v);
@@ -239,10 +295,76 @@ export function resolvedRpcSecrets() {
239
295
  export function publicRpcHint(chainId) {
240
296
  if (rpcSourceForEnv(chainId).configured)
241
297
  return undefined;
242
- return ("No RPC was configured, so this used the public endpoint (mainnet.base.org), which rate-limits " +
298
+ const info = CHAIN_INFO[chainId];
299
+ return (`No RPC was configured for ${info.name}, so this used the public endpoint (${new URL(info.publicRpc).hostname}), which rate-limits ` +
243
300
  "after a handful of calls — that is the most likely cause of the failure above, not the vault. " +
244
- "Set TREASURY_RPC_BASE to a keyed Base RPC URL (Alchemy, Infura, QuickNode or your own node) and " +
301
+ `Set ${info.rpcEnv[0]} to a keyed ${info.name} RPC URL (Alchemy, Infura, QuickNode or your own node) and ` +
245
302
  "retry. Reads like the vault list and the disclosures work without one; quotes, pre-flight and " +
246
303
  "position history generally do not.");
247
304
  }
305
+ /** How long a chain-identity probe may take before the endpoint counts as "did not say". */
306
+ export const CHAIN_PROBE_MS = 3_000;
307
+ /** Endpoints that have already said which chain they are. An endpoint does not change chain. */
308
+ const reportedChain = new Map();
309
+ /**
310
+ * Which chain does this endpoint say it is? `undefined` when it did not say within
311
+ * `CHAIN_PROBE_MS` — an error, a rate limit, a hang — which is NOT a statement about the chain: the
312
+ * caller reports that as "not verified", never as a match and never as a mismatch.
313
+ *
314
+ * It exists because two chains mean two RPC variables, and the likeliest mistake is one pointed at
315
+ * the other chain. Nothing then errors usefully: a vault's address has no code there, so reads fail
316
+ * with "returned no data" and the failure reads as a broken vault.
317
+ *
318
+ * Bounded on purpose. The transport's own deadline is 10 s and a rate-limited `eth_chainId` is waited
319
+ * out for all of it, which would make a health check that already has its answer wait ten seconds
320
+ * for a second one (measured in review). An answer is remembered per endpoint URL, so a process asks
321
+ * each endpoint once.
322
+ */
323
+ export async function endpointChainId(client, rpcUrl, timeoutMs = CHAIN_PROBE_MS) {
324
+ const known = reportedChain.get(rpcUrl);
325
+ if (known !== undefined)
326
+ return known;
327
+ let timer;
328
+ const timedOut = new Promise((r) => {
329
+ timer = setTimeout(() => r(undefined), timeoutMs);
330
+ timer.unref?.();
331
+ });
332
+ try {
333
+ const got = await Promise.race([client.getChainId().catch(() => undefined), timedOut]);
334
+ if (got !== undefined)
335
+ reportedChain.set(rpcUrl, got);
336
+ return got;
337
+ }
338
+ finally {
339
+ if (timer !== undefined)
340
+ clearTimeout(timer);
341
+ }
342
+ }
343
+ /**
344
+ * The first of these endpoints that answers for a chain other than `chainId`, or `undefined`.
345
+ * A chain's public endpoint is never asked: it is this client's own constant, so the question
346
+ * would be a request to a third party with a known answer. An endpoint that does not say is not a
347
+ * mismatch.
348
+ */
349
+ export async function firstEndpointOnWrongChain(chainId, endpoints) {
350
+ const asked = endpoints.filter((e) => e.url !== PUBLIC_RPC[chainId]);
351
+ const said = await Promise.all(asked.map((e) => endpointChainId(e.client, e.url)));
352
+ for (const [i, id] of said.entries()) {
353
+ if (id !== undefined && id !== chainId)
354
+ return { source: asked[i].source, answersFor: id };
355
+ }
356
+ return undefined;
357
+ }
358
+ /** TEST SEAM — forgets what every endpoint said, so one test's mock port cannot answer for the next. NOT re-exported from index.ts. */
359
+ export function __forgetEndpointChainsForTests() {
360
+ reportedChain.clear();
361
+ }
362
+ /**
363
+ * Which variable supplied the endpoint `earn_balance` scans events through — the chain's logs
364
+ * variable when it resolves, otherwise whatever supplied the general RPC. The NAME only.
365
+ */
366
+ export function logsRpcSourceForEnv(chainId) {
367
+ const k = CHAIN_INFO[chainId].logsRpcEnv;
368
+ return rpcUrlFromEnvValue(process.env[k]) ? { source: k, configured: true } : rpcSourceForEnv(chainId);
369
+ }
248
370
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -3,13 +3,15 @@
3
3
  * as a literal; `scripts/roundtrip.ts` and the tiers read the default and the round-trip target
4
4
  * from here (the fork and live tiers also name the gated sibling directly, for the access pair).
5
5
  *
6
- * Two knobs, deliberately separate, because they can legitimately differ:
6
+ * Three knobs, deliberately separate, because they can legitimately differ:
7
7
  *
8
- * `defaultVault` what the tools use when the caller names none. The registry row must also be
9
- * `isDefault` — `defaultVault()` refuses a config/registry disagreement — and the
10
- * schema allows a WHITELIST_GATED default, because the pre-flight re-measures
11
- * access live on every call and refuses a non-member before anything is built.
12
- * `roundTripVault` what the deposit → redeem tiers exercise. The same vault today.
8
+ * `defaultChain` the chain the tools use when the caller names neither a chain nor a vault.
9
+ * `defaultVaultByChain` what the tools use on each chain when the caller names no vault. Each
10
+ * registry row must also be `isDefault` — `defaultVault()` refuses a
11
+ * config/registry disagreement — and the schema allows a WHITELIST_GATED
12
+ * default, because the pre-flight re-measures access live on every call and
13
+ * refuses a non-member before anything is built.
14
+ * `roundTripVault` what the deposit → redeem tiers exercise. The Base default today.
13
15
  *
14
16
  * Addresses live in the registry (`registry/vaults.json`, schema-validated, block-stamped) — a
15
17
  * ticker here resolves through it.
@@ -23,15 +25,32 @@
23
25
  /** A vault's ERC-20 ticker — resolved via `getVault`, so a typo fails at load, not at a call site. */
24
26
  export type VaultSymbol = string;
25
27
  export declare const EARN: {
28
+ /** The chain used when a caller names neither a chain nor a vault. */
29
+ readonly defaultChain: "base";
26
30
  /**
27
- * Tempora Labs Cash Plus USDC (Test 2), Base — a Morpho Vault V2, the Tempora vault this client
28
- * offers by default. Deposits are OPEN to any account (measured by a simulated stranger deposit;
29
- * `earn_vaults` reports `defaultAccess: "open"`). The whitelist-gated sibling, Cash Plus USDC
30
- * (Test 2A), stays listed as `tlCashPlusUSDC2A` and is refused per account by the pre-flight.
31
+ * The default vault on each chain, by chain key.
32
+ *
33
+ * `base`: Tempora Labs Cash Plus USDC (Test 2B) — a Morpho Vault V2, the Tempora Labs vault this client
34
+ * offers when nothing is named. Tempora Labs Cash Plus USDC (Test 2), also on Base, is the DEMO
35
+ * vault: listed and open, selected by naming it. Deposits are OPEN to any account (measured by a simulated stranger
36
+ * deposit; `earn_vaults` reports `defaultAccess: "open"`). The whitelist-gated sibling, Cash Plus
37
+ * USDC (Test 2A), stays listed as `tlCashPlusUSDC2A` and is refused per account by the pre-flight.
38
+ *
39
+ * `arbitrum`: Tempora Labs Cash Plus USDC (Test 2C) — a Morpho Vault V2 on Arbitrum One, open to
40
+ * any account by the same measurement.
41
+ *
42
+ * `robinhood`: Tempora Labs Cash Plus USDG (Test 2D) — a Morpho Vault V2 on Robinhood Chain over
43
+ * USDG, the first vault whose asset is not USDC. Open to any account by the same measurement.
44
+ *
45
+ * `Record<ChainKey, …>`: a chain added to `CHAIN_INFO` without a default here does not compile.
31
46
  */
32
- readonly defaultVault: "tlCashPlusUSDC2";
47
+ readonly defaultVaultByChain: {
48
+ base: string;
49
+ arbitrum: string;
50
+ robinhood: string;
51
+ };
33
52
  /** The round-trip target. The same vault as the default; open, so the fork tier deposits from the whale directly. */
34
- readonly roundTripVault: "tlCashPlusUSDC2";
53
+ readonly roundTripVault: "tlCashPlusUSDC2B";
35
54
  /** USDC, as a decimal string — the amount `scripts/roundtrip.ts` prepares by default. Never a float. */
36
55
  readonly roundTripAmountUsdc: "0.05";
37
56
  /** Fixtures the fork and live tiers share. */
@@ -40,6 +59,8 @@ export declare const EARN: {
40
59
  readonly stranger: "0x000000000000000000000000000000000000dEaD";
41
60
  /** Morpho Blue on Base — held ~2.1e14 USDC base units when probed 2026-09-11. Impersonated on the fork, never keyed. */
42
61
  readonly usdcWhale: "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb";
62
+ /** Aave V3's aArbUSDCn token on Arbitrum One — held ~1.7e13 native-USDC base units when probed 2026-10-02. Impersonated on the fork, never keyed. */
63
+ readonly usdcWhaleArbitrum: "0x724dc807b04555b71ed48a6896b6F41593b8C637";
43
64
  /** USDC the fork round trip deposits, and what it seeds a discovered depositor with beforehand. */
44
65
  readonly forkDepositUsdc: "100";
45
66
  readonly forkSeedUsdc: "1000";
@@ -3,13 +3,15 @@
3
3
  * as a literal; `scripts/roundtrip.ts` and the tiers read the default and the round-trip target
4
4
  * from here (the fork and live tiers also name the gated sibling directly, for the access pair).
5
5
  *
6
- * Two knobs, deliberately separate, because they can legitimately differ:
6
+ * Three knobs, deliberately separate, because they can legitimately differ:
7
7
  *
8
- * `defaultVault` what the tools use when the caller names none. The registry row must also be
9
- * `isDefault` — `defaultVault()` refuses a config/registry disagreement — and the
10
- * schema allows a WHITELIST_GATED default, because the pre-flight re-measures
11
- * access live on every call and refuses a non-member before anything is built.
12
- * `roundTripVault` what the deposit → redeem tiers exercise. The same vault today.
8
+ * `defaultChain` the chain the tools use when the caller names neither a chain nor a vault.
9
+ * `defaultVaultByChain` what the tools use on each chain when the caller names no vault. Each
10
+ * registry row must also be `isDefault` — `defaultVault()` refuses a
11
+ * config/registry disagreement — and the schema allows a WHITELIST_GATED
12
+ * default, because the pre-flight re-measures access live on every call and
13
+ * refuses a non-member before anything is built.
14
+ * `roundTripVault` what the deposit → redeem tiers exercise. The Base default today.
13
15
  *
14
16
  * Addresses live in the registry (`registry/vaults.json`, schema-validated, block-stamped) — a
15
17
  * ticker here resolves through it.
@@ -21,15 +23,32 @@
21
23
  * stale the moment the whitelist changes. An address is never a key either way (CONTRIBUTING.md, the first rule).
22
24
  */
23
25
  export const EARN = {
26
+ /** The chain used when a caller names neither a chain nor a vault. */
27
+ defaultChain: "base",
24
28
  /**
25
- * Tempora Labs Cash Plus USDC (Test 2), Base — a Morpho Vault V2, the Tempora vault this client
26
- * offers by default. Deposits are OPEN to any account (measured by a simulated stranger deposit;
27
- * `earn_vaults` reports `defaultAccess: "open"`). The whitelist-gated sibling, Cash Plus USDC
28
- * (Test 2A), stays listed as `tlCashPlusUSDC2A` and is refused per account by the pre-flight.
29
+ * The default vault on each chain, by chain key.
30
+ *
31
+ * `base`: Tempora Labs Cash Plus USDC (Test 2B) — a Morpho Vault V2, the Tempora Labs vault this client
32
+ * offers when nothing is named. Tempora Labs Cash Plus USDC (Test 2), also on Base, is the DEMO
33
+ * vault: listed and open, selected by naming it. Deposits are OPEN to any account (measured by a simulated stranger
34
+ * deposit; `earn_vaults` reports `defaultAccess: "open"`). The whitelist-gated sibling, Cash Plus
35
+ * USDC (Test 2A), stays listed as `tlCashPlusUSDC2A` and is refused per account by the pre-flight.
36
+ *
37
+ * `arbitrum`: Tempora Labs Cash Plus USDC (Test 2C) — a Morpho Vault V2 on Arbitrum One, open to
38
+ * any account by the same measurement.
39
+ *
40
+ * `robinhood`: Tempora Labs Cash Plus USDG (Test 2D) — a Morpho Vault V2 on Robinhood Chain over
41
+ * USDG, the first vault whose asset is not USDC. Open to any account by the same measurement.
42
+ *
43
+ * `Record<ChainKey, …>`: a chain added to `CHAIN_INFO` without a default here does not compile.
29
44
  */
30
- defaultVault: "tlCashPlusUSDC2",
45
+ defaultVaultByChain: {
46
+ base: "tlCashPlusUSDC2B",
47
+ arbitrum: "tlCashPlusUSDC2C",
48
+ robinhood: "tlCashPlusUSDG2D",
49
+ },
31
50
  /** The round-trip target. The same vault as the default; open, so the fork tier deposits from the whale directly. */
32
- roundTripVault: "tlCashPlusUSDC2",
51
+ roundTripVault: "tlCashPlusUSDC2B",
33
52
  /** USDC, as a decimal string — the amount `scripts/roundtrip.ts` prepares by default. Never a float. */
34
53
  roundTripAmountUsdc: "0.05",
35
54
  /** Fixtures the fork and live tiers share. */
@@ -38,6 +57,8 @@ export const EARN = {
38
57
  stranger: "0x000000000000000000000000000000000000dEaD",
39
58
  /** Morpho Blue on Base — held ~2.1e14 USDC base units when probed 2026-09-11. Impersonated on the fork, never keyed. */
40
59
  usdcWhale: "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb",
60
+ /** Aave V3's aArbUSDCn token on Arbitrum One — held ~1.7e13 native-USDC base units when probed 2026-10-02. Impersonated on the fork, never keyed. */
61
+ usdcWhaleArbitrum: "0x724dc807b04555b71ed48a6896b6F41593b8C637",
41
62
  /** USDC the fork round trip deposits, and what it seeds a discovered depositor with beforehand. */
42
63
  forkDepositUsdc: "100",
43
64
  forkSeedUsdc: "1000",
@@ -1 +1 @@
1
- {"version":3,"file":"earn.js","sourceRoot":"","sources":["../../src/config/earn.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAKH,MAAM,CAAC,MAAM,IAAI,GAAG;IAClB;;;;;OAKG;IACH,YAAY,EAAE,iBAAuC;IAErD,qHAAqH;IACrH,cAAc,EAAE,iBAAuC;IAEvD,wGAAwG;IACxG,mBAAmB,EAAE,MAAM;IAE3B,8CAA8C;IAC9C,QAAQ,EAAE;QACR,4FAA4F;QAC5F,QAAQ,EAAE,4CAAqD;QAC/D,wHAAwH;QACxH,SAAS,EAAE,4CAAqD;QAChE,mGAAmG;QACnG,eAAe,EAAE,KAAK;QACtB,YAAY,EAAE,MAAM;KACrB;CACO,CAAC"}
1
+ {"version":3,"file":"earn.js","sourceRoot":"","sources":["../../src/config/earn.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAOH,MAAM,CAAC,MAAM,IAAI,GAAG;IAClB,sEAAsE;IACtE,YAAY,EAAE,MAAyB;IAEvC;;;;;;;;;;;;;;;;OAgBG;IACH,mBAAmB,EAAE;QACnB,IAAI,EAAE,kBAAkB;QACxB,QAAQ,EAAE,kBAAkB;QAC5B,SAAS,EAAE,kBAAkB;KACU;IAEzC,qHAAqH;IACrH,cAAc,EAAE,kBAAwC;IAExD,wGAAwG;IACxG,mBAAmB,EAAE,MAAM;IAE3B,8CAA8C;IAC9C,QAAQ,EAAE;QACR,4FAA4F;QAC5F,QAAQ,EAAE,4CAAqD;QAC/D,wHAAwH;QACxH,SAAS,EAAE,4CAAqD;QAChE,qJAAqJ;QACrJ,iBAAiB,EAAE,4CAAqD;QACxE,mGAAmG;QACnG,eAAe,EAAE,KAAK;QACtB,YAAY,EAAE,MAAM;KACrB;CACO,CAAC"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * The operator's acknowledgement, which `connect deposit` and `connect withdraw` require before the
3
+ * signing page opens.
4
+ *
5
+ * Run without `--ack`, either command builds and gate-checks its calls, records them as pending, and
6
+ * returns `acknowledgement`: one fixed text, written here and not by the agent, naming the action,
7
+ * amount, chain, vault, its explorer link, the receiver, the vault's warning and the disclosures in
8
+ * plain words (`DISCLOSURES.plain`; the full text stays in `earn terms`). The agent posts it to the
9
+ * operator and waits for an explicit yes. Run again
10
+ * with `--ack <code>`, the page opens only if the code names the pending acknowledgement, it has not
11
+ * expired, and the calls are exactly the ones it described. The code is then spent, so every page
12
+ * open is preceded by its own acknowledgement.
13
+ *
14
+ * The code is not a secret and does not need to be: it ties the second run to the text the operator
15
+ * read. An amount, vault, chain, receiver or account that changes in between gives different calls,
16
+ * and the code no longer matches them.
17
+ */
18
+ import { type Address } from "viem";
19
+ import type { UnsignedCall } from "../build.js";
20
+ import type { Admitted } from "./gate.js";
21
+ /** How long an acknowledgement stays usable: long enough to read it and answer, not long enough to forget it. */
22
+ export declare const ACK_TTL_MS: number;
23
+ export interface PendingAck {
24
+ code: string;
25
+ digest: string;
26
+ issuedAtIso: string;
27
+ expiresAtIso: string;
28
+ }
29
+ /** What the calls ARE: the connected account and each call's chain, destination, calldata and value. */
30
+ export declare function callsDigest(calls: UnsignedCall[], account: Address): string;
31
+ export declare function issueAck(calls: UnsignedCall[], account: Address, now: Date): PendingAck;
32
+ /** Throws unless `code` names `pending`, it is unexpired, and it was issued for exactly these calls. */
33
+ export declare function checkAck(code: string, pending: PendingAck | undefined, calls: UnsignedCall[], account: Address, now: Date): void;
34
+ export interface AckSummary {
35
+ action: "deposit" | "withdraw";
36
+ amount: string;
37
+ /** The vault's asset (USDC; USDG on Robinhood Chain): what a withdrawal pays out. */
38
+ asset: string;
39
+ chain: string;
40
+ chainId: number;
41
+ vault: {
42
+ symbol: string;
43
+ name: string;
44
+ address: string;
45
+ explorer: string;
46
+ };
47
+ receiver: string;
48
+ warning: string;
49
+ disclosures: string[];
50
+ }
51
+ /**
52
+ * The registry's `warning` is written for both audiences, so it ends with an instruction to the agent
53
+ * ("Show this warning before preparing any deposit."). The operator is reading the warning itself, so
54
+ * that sentence is dropped here. The registry text is unchanged: `earn` output and the registry check use it.
55
+ */
56
+ export declare function operatorWarning(w: string, action?: "deposit" | "withdraw"): string;
57
+ export declare function summarize(action: "deposit" | "withdraw", calls: UnsignedCall[], admitted: Admitted[], receiver: Address): AckSummary;
58
+ /** The text the operator reads. Generated, never paraphrased: the same calls always produce the same words. */
59
+ export declare function acknowledgementText(s: AckSummary): string;
@@ -0,0 +1,111 @@
1
+ /**
2
+ * The operator's acknowledgement, which `connect deposit` and `connect withdraw` require before the
3
+ * signing page opens.
4
+ *
5
+ * Run without `--ack`, either command builds and gate-checks its calls, records them as pending, and
6
+ * returns `acknowledgement`: one fixed text, written here and not by the agent, naming the action,
7
+ * amount, chain, vault, its explorer link, the receiver, the vault's warning and the disclosures in
8
+ * plain words (`DISCLOSURES.plain`; the full text stays in `earn terms`). The agent posts it to the
9
+ * operator and waits for an explicit yes. Run again
10
+ * with `--ack <code>`, the page opens only if the code names the pending acknowledgement, it has not
11
+ * expired, and the calls are exactly the ones it described. The code is then spent, so every page
12
+ * open is preceded by its own acknowledgement.
13
+ *
14
+ * The code is not a secret and does not need to be: it ties the second run to the text the operator
15
+ * read. An amount, vault, chain, receiver or account that changes in between gives different calls,
16
+ * and the code no longer matches them.
17
+ */
18
+ import { formatUnits, keccak256, stringToHex } from "viem";
19
+ import { CHAIN_INFO } from "../client.js";
20
+ import { DISCLOSURES } from "../disclosures.js";
21
+ import { linksFor } from "../links.js";
22
+ /** How long an acknowledgement stays usable: long enough to read it and answer, not long enough to forget it. */
23
+ export const ACK_TTL_MS = 15 * 60_000;
24
+ /** What the calls ARE: the connected account and each call's chain, destination, calldata and value. */
25
+ export function callsDigest(calls, account) {
26
+ return keccak256(stringToHex(JSON.stringify([account, calls.map((c) => [c.chainId, c.to, c.data, c.value])])));
27
+ }
28
+ export function issueAck(calls, account, now) {
29
+ const digest = callsDigest(calls, account);
30
+ const issuedAtIso = now.toISOString();
31
+ return {
32
+ code: keccak256(stringToHex(`${digest}|${issuedAtIso}`)).slice(2, 10),
33
+ digest,
34
+ issuedAtIso,
35
+ expiresAtIso: new Date(now.getTime() + ACK_TTL_MS).toISOString(),
36
+ };
37
+ }
38
+ /** Throws unless `code` names `pending`, it is unexpired, and it was issued for exactly these calls. */
39
+ export function checkAck(code, pending, calls, account, now) {
40
+ const again = "run the same command without --ack, post its `acknowledgement` to the operator, and wait for their yes";
41
+ if (!pending)
42
+ throw new Error(`refused: no acknowledgement is pending; ${again}`);
43
+ if (code.trim().toLowerCase() !== pending.code)
44
+ throw new Error(`refused: --ack ${code} is not the pending acknowledgement's code; ${again}`);
45
+ const expires = Date.parse(pending.expiresAtIso);
46
+ // A missing or unreadable expiry counts as expired, never as no expiry.
47
+ if (!Number.isFinite(expires) || now.getTime() > expires)
48
+ throw new Error(`refused: the acknowledgement expired at ${pending.expiresAtIso}; ${again}`);
49
+ if (callsDigest(calls, account) !== pending.digest) {
50
+ throw new Error(`refused: these calls are not the ones the operator acknowledged (the amount, vault, chain, receiver or connected account changed); ${again}`);
51
+ }
52
+ }
53
+ /**
54
+ * The registry's `warning` is written for both audiences, so it ends with an instruction to the agent
55
+ * ("Show this warning before preparing any deposit."). The operator is reading the warning itself, so
56
+ * that sentence is dropped here. The registry text is unchanged: `earn` output and the registry check use it.
57
+ */
58
+ export function operatorWarning(w, action = "deposit") {
59
+ const s = w.replace(/\s*Show this warning before preparing any deposit\.\s*$/, "").trim();
60
+ // Before a withdrawal, advice on how much to deposit does not apply.
61
+ return action === "withdraw" ? s.replace(/\s*Deposit only .*?\.(?=\s|$)/g, "").trim() : s;
62
+ }
63
+ export function summarize(action, calls, admitted, receiver) {
64
+ const main = admitted.find((a) => a.kind !== "approve");
65
+ const v = main.vault;
66
+ const chainId = calls[0].chainId;
67
+ const amount = main.kind === "redeem"
68
+ ? `${formatUnits(main.amount, v.shareDecimals)} ${v.symbol} shares (the amount given; it is the whole position only if it equals the account's share balance, which is not checked here)`
69
+ : `${formatUnits(main.amount, v.asset.decimals)} ${v.asset.symbol}`;
70
+ return {
71
+ action,
72
+ amount,
73
+ asset: v.asset.symbol,
74
+ chain: CHAIN_INFO[chainId].name,
75
+ chainId,
76
+ vault: { symbol: v.symbol, name: v.name, address: v.address, explorer: linksFor(v).explorer },
77
+ receiver,
78
+ warning: operatorWarning(v.warning, action),
79
+ // The disclosures in plain words (`DISCLOSURES.plain`): the operator reads this before every page,
80
+ // so it is the short form. Before a withdrawal, only what holds for every action.
81
+ disclosures: action === "deposit"
82
+ ? [...DISCLOSURES.plain.deposit, ...(v.depositOpen.open ? [] : [DISCLOSURES.plain.gatedDeposit]), ...DISCLOSURES.plain.always]
83
+ : [...DISCLOSURES.plain.always],
84
+ };
85
+ }
86
+ /** The text the operator reads. Generated, never paraphrased: the same calls always produce the same words. */
87
+ export function acknowledgementText(s) {
88
+ const lands = s.action === "deposit" ? "Shares go to" : `${s.asset} goes to`;
89
+ const prompts = s.action === "deposit"
90
+ ? `Your wallet will ask you twice: first to approve ${s.amount} to the vault, then to make the deposit.`
91
+ : `Your wallet will ask you once, to make the withdrawal.`;
92
+ return [
93
+ `Confirm before the signing page opens. Nothing has been sent.`,
94
+ ``,
95
+ ` ${s.action === "deposit" ? "Deposit" : "Withdraw"}: ${s.amount}`,
96
+ ` Chain: ${s.chain} (chainId ${s.chainId})`,
97
+ ` Vault: ${s.vault.name} (${s.vault.symbol})`,
98
+ ` ${s.vault.explorer}`,
99
+ ` ${lands}: ${s.receiver} (the connected wallet)`,
100
+ ` ${prompts}`,
101
+ ``,
102
+ `WARNING: ${s.warning}`,
103
+ ``,
104
+ `Before you agree:`,
105
+ ...s.disclosures.map((d) => ` - ${d}`),
106
+ ` ${DISCLOSURES.plain.fullTerms}`,
107
+ ``,
108
+ `Do you acknowledge and want the signing page opened for exactly this ${s.action}? Reply yes or no.`,
109
+ ].join("\n");
110
+ }
111
+ //# sourceMappingURL=ack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ack.js","sourceRoot":"","sources":["../../src/connect/ack.ts"],"names":[],"mappings":"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"}