@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.
Files changed (103) hide show
  1. package/NOTICE +4 -2
  2. package/README.md +100 -44
  3. package/THIRD_PARTY_NOTICES.connect-page.md +7836 -0
  4. package/THIRD_PARTY_NOTICES.md +543 -162
  5. package/dist/cli.d.ts +6 -0
  6. package/dist/cli.js +243 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/client.d.ts +366 -239
  9. package/dist/client.js +202 -25
  10. package/dist/client.js.map +1 -1
  11. package/dist/config/earn.d.ts +48 -12
  12. package/dist/config/earn.js +48 -12
  13. package/dist/config/earn.js.map +1 -1
  14. package/dist/connect/ack.d.ts +76 -0
  15. package/dist/connect/ack.js +147 -0
  16. package/dist/connect/ack.js.map +1 -0
  17. package/dist/connect/commands.d.ts +81 -0
  18. package/dist/connect/commands.js +555 -0
  19. package/dist/connect/commands.js.map +1 -0
  20. package/dist/connect/config.d.ts +24 -0
  21. package/dist/connect/config.js +35 -0
  22. package/dist/connect/config.js.map +1 -0
  23. package/dist/connect/gate-solana.d.ts +8 -0
  24. package/dist/connect/gate-solana.js +147 -0
  25. package/dist/connect/gate-solana.js.map +1 -0
  26. package/dist/connect/gate.d.ts +37 -0
  27. package/dist/connect/gate.js +115 -0
  28. package/dist/connect/gate.js.map +1 -0
  29. package/dist/connect/http.d.ts +60 -0
  30. package/dist/connect/http.js +235 -0
  31. package/dist/connect/http.js.map +1 -0
  32. package/dist/connect/open.d.ts +2 -0
  33. package/dist/connect/open.js +35 -0
  34. package/dist/connect/open.js.map +1 -0
  35. package/dist/connect/page.d.ts +5 -0
  36. package/dist/connect/page.js +69 -0
  37. package/dist/connect/page.js.map +1 -0
  38. package/dist/connect/session.d.ts +39 -0
  39. package/dist/connect/session.js +198 -0
  40. package/dist/connect/session.js.map +1 -0
  41. package/dist/connect/solana.d.ts +73 -0
  42. package/dist/connect/solana.js +267 -0
  43. package/dist/connect/solana.js.map +1 -0
  44. package/dist/connect/verify.d.ts +37 -0
  45. package/dist/connect/verify.js +89 -0
  46. package/dist/connect/verify.js.map +1 -0
  47. package/dist/connect-page.js +5143 -0
  48. package/dist/disclosures.d.ts +22 -6
  49. package/dist/disclosures.js +34 -8
  50. package/dist/disclosures.js.map +1 -1
  51. package/dist/earn/commands.d.ts +46 -0
  52. package/dist/earn/commands.js +556 -0
  53. package/dist/earn/commands.js.map +1 -0
  54. package/dist/earn/solana.d.ts +278 -0
  55. package/dist/earn/solana.js +302 -0
  56. package/dist/earn/solana.js.map +1 -0
  57. package/dist/guide.d.ts +15 -0
  58. package/dist/guide.js +50 -0
  59. package/dist/guide.js.map +1 -0
  60. package/dist/links.d.ts +2 -0
  61. package/dist/links.js +40 -14
  62. package/dist/links.js.map +1 -1
  63. package/dist/position.d.ts +9 -6
  64. package/dist/position.js +39 -19
  65. package/dist/position.js.map +1 -1
  66. package/dist/preflight.d.ts +9 -0
  67. package/dist/preflight.js +14 -3
  68. package/dist/preflight.js.map +1 -1
  69. package/dist/quote.js +24 -7
  70. package/dist/quote.js.map +1 -1
  71. package/dist/redact.d.ts +3 -3
  72. package/dist/redact.js +3 -3
  73. package/dist/redact.js.map +1 -1
  74. package/dist/registry-schema.d.ts +82 -5
  75. package/dist/registry-schema.js +105 -15
  76. package/dist/registry-schema.js.map +1 -1
  77. package/dist/registry.d.ts +50 -7
  78. package/dist/registry.js +122 -21
  79. package/dist/registry.js.map +1 -1
  80. package/dist/solana/constants.d.ts +49 -0
  81. package/dist/solana/constants.js +50 -0
  82. package/dist/solana/constants.js.map +1 -0
  83. package/dist/solana/kvault.d.ts +99 -0
  84. package/dist/solana/kvault.js +192 -0
  85. package/dist/solana/kvault.js.map +1 -0
  86. package/dist/solana/layout.d.ts +143 -0
  87. package/dist/solana/layout.js +209 -0
  88. package/dist/solana/layout.js.map +1 -0
  89. package/dist/solana/rpc.d.ts +24 -0
  90. package/dist/solana/rpc.js +66 -0
  91. package/dist/solana/rpc.js.map +1 -0
  92. package/dist/solana/vault.d.ts +153 -0
  93. package/dist/solana/vault.js +324 -0
  94. package/dist/solana/vault.js.map +1 -0
  95. package/dist/{mcp-server.mjs → treasury.mjs} +41101 -49486
  96. package/dist/version.js +5 -10
  97. package/dist/version.js.map +1 -1
  98. package/llms.txt +621 -0
  99. package/package.json +12 -9
  100. package/registry/vaults.json +218 -4
  101. package/dist/mcp/server.d.ts +0 -8
  102. package/dist/mcp/server.js +0 -368
  103. package/dist/mcp/server.js.map +0 -1
package/dist/client.js CHANGED
@@ -1,11 +1,96 @@
1
1
  import { createPublicClient, http } from "viem";
2
- import { base } from "viem/chains";
3
- export const chains = { 8453: base };
2
+ import { arbitrum, base, mainnet, monad, robinhood } from "viem/chains";
3
+ export const chains = { 8453: base, 42161: arbitrum, 4663: robinhood, 1: mainnet, 143: monad };
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
+ 1: {
24
+ key: "ethereum",
25
+ name: "Ethereum",
26
+ rpcEnv: ["TREASURY_RPC_ETHEREUM", "ETHEREUM_RPC_URL"],
27
+ logsRpcEnv: "TREASURY_LOGS_RPC_ETHEREUM",
28
+ publicRpc: "https://ethereum.reth.rs/rpc",
29
+ },
30
+ 143: {
31
+ key: "monad",
32
+ name: "Monad",
33
+ rpcEnv: ["TREASURY_RPC_MONAD", "MONAD_RPC_URL"],
34
+ logsRpcEnv: "TREASURY_LOGS_RPC_MONAD",
35
+ publicRpc: "https://rpc.monad.xyz",
36
+ },
37
+ };
38
+ /**
39
+ * Solana — the one chain here that is not an EVM chain. It has no chain id, no `viem` chain and no
40
+ * `eth_getLogs`, so it is not a row of `CHAIN_INFO`; everything else about it follows the same rules:
41
+ * its own variables only, then its public endpoint. An endpoint is checked for the right cluster by its
42
+ * genesis hash (`src/solana/rpc.ts`), the counterpart of an EVM endpoint's chain id.
43
+ */
44
+ export const SOLANA_INFO = {
45
+ key: "solana",
46
+ name: "Solana",
47
+ rpcEnv: ["TREASURY_RPC_SOLANA", "SOLANA_RPC_URL"],
48
+ publicRpc: "https://api.mainnet-beta.solana.com",
49
+ };
50
+ /** The Solana RPC URL: `TREASURY_RPC_SOLANA`, then `SOLANA_RPC_URL`, then the public mainnet endpoint. */
51
+ export function solanaRpcUrlFromEnv() {
52
+ for (const k of SOLANA_INFO.rpcEnv) {
53
+ const v = rpcUrlFromEnvValue(process.env[k]);
54
+ if (v)
55
+ return v;
56
+ }
57
+ return SOLANA_INFO.publicRpc;
58
+ }
59
+ /** Which variable supplied the Solana RPC URL — the NAME only, never the value. */
60
+ export function solanaRpcSourceForEnv() {
61
+ for (const k of SOLANA_INFO.rpcEnv) {
62
+ if (rpcUrlFromEnvValue(process.env[k]))
63
+ return { source: k, configured: true };
64
+ }
65
+ return { source: "public default", configured: false };
66
+ }
67
+ /** `publicRpcHint` for Solana: the sentence for a failure on the unconfigured public endpoint. */
68
+ export function solanaPublicRpcHint() {
69
+ if (solanaRpcSourceForEnv().configured)
70
+ return undefined;
71
+ return (`No RPC was configured for Solana, so this used the public endpoint (${new URL(SOLANA_INFO.publicRpc).hostname}), which rate-limits ` +
72
+ "after a handful of calls — that is the most likely cause of the failure above, not the vault. " +
73
+ `Set ${SOLANA_INFO.rpcEnv[0]} to a keyed Solana RPC URL (Helius, QuickNode, Alchemy or your own node) and retry.`);
74
+ }
75
+ /**
76
+ * Every supported chain, in the order chains were added: Base first, then Arbitrum One, Robinhood
77
+ * Chain, Ethereum and Monad. Listed rather than read from `Object.keys(chains)`, whose integer keys
78
+ * enumerate in numeric order and would put Ethereum (1) ahead of Base everywhere a list of chains is shown.
79
+ * `client.unit.test.ts` holds this list equal to the keys of `chains`.
80
+ */
81
+ export const supportedChainIds = [8453, 42161, 4663, 1, 143];
82
+ /** `"arbitrum"` → 42161. `undefined` for a name this client does not know — the caller says so. */
83
+ export function chainIdForKey(key) {
84
+ return supportedChainIds.find((id) => CHAIN_INFO[id].key === key);
85
+ }
7
86
  /** The public endpoint used when nothing is configured, and the fallback for event scans. */
8
- export const PUBLIC_RPC = { 8453: "https://mainnet.base.org" };
87
+ export const PUBLIC_RPC = {
88
+ 8453: CHAIN_INFO[8453].publicRpc,
89
+ 42161: CHAIN_INFO[42161].publicRpc,
90
+ 4663: CHAIN_INFO[4663].publicRpc,
91
+ 1: CHAIN_INFO[1].publicRpc,
92
+ 143: CHAIN_INFO[143].publicRpc,
93
+ };
9
94
  /**
10
95
  * A `fetch` that waits out HTTP 429 instead of failing the tool. Measured 2026-09-14: a free-tier
11
96
  * keyed Base RPC answered an `earn_quote` read with 429 and the tool failed outright, because viem's
@@ -82,10 +167,12 @@ export function makePublicClient(chainId, rpcUrl) {
82
167
  /**
83
168
  * An env value counts as an RPC URL only if it parses as one with an http(s) scheme. Anything else —
84
169
  * 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.
170
+ * is treated as unset. Measured 2026-09-12, when the plugin still declared an MCP server: Claude Code
171
+ * forwarded the server declaration's value `${TREASURY_RPC_BASE}` verbatim when the host variable was
172
+ * unset, and with the old `if (v)` test every RPC-touching tool died on "Failed to parse URL from
173
+ * ${TREASURY_RPC_BASE}". The plugin now runs the CLI through the shell and declares nothing, but any
174
+ * host or wrapper can still pass a placeholder through, and this guard is what makes the client
175
+ * independent of anyone's expansion rules.
89
176
  */
90
177
  export function rpcUrlFromEnvValue(v) {
91
178
  if (!v)
@@ -103,16 +190,23 @@ export function rpcUrlFromEnvValue(v) {
103
190
  }
104
191
  /**
105
192
  * 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`.
193
+ * never appear in tool output — every error crossing the tool boundary goes through `redactEndpoints`
194
+ * (`src/redact.ts`), which strips endpoints. The names come from `CHAIN_INFO`: on Base,
195
+ * `TREASURY_RPC_BASE` then `BASE_RPC_URL`; on Arbitrum One, `TREASURY_RPC_ARBITRUM` then
196
+ * `ARBITRUM_RPC_URL`; on Robinhood Chain, `TREASURY_RPC_ROBINHOOD` then `ROBINHOOD_RPC_URL`; on Ethereum,
197
+ * `TREASURY_RPC_ETHEREUM` then `ETHEREUM_RPC_URL`; on Monad, `TREASURY_RPC_MONAD` then `MONAD_RPC_URL`.
198
+ * The CLI inherits its shell's whole environment, so on every path, the plugin's
199
+ * included, the second name of each pair is used when the first is unset.
200
+ * The chain's logs variable (`TREASURY_LOGS_RPC_<CHAIN>`: BASE, ARBITRUM, ROBINHOOD, ETHEREUM, MONAD), if set, is
201
+ * preferred for log scans (providers cap eth_getLogs ranges very differently: Alchemy free 10 blocks,
202
+ * Base public 2,000, Infura 10,000 on Arbitrum) — see `position.ts`.
203
+ *
204
+ * 🔴 A chain reads ONLY its own variables. An Arbitrum call never falls back to a Base endpoint: a
205
+ * vault's address has no contract on the other chain, so reads fail with "returned no data" — which
206
+ * reads as a broken vault rather than as a misconfiguration.
112
207
  */
113
208
  export function rpcUrlFromEnv(chainId) {
114
- const candidates = chainId === 8453 ? ["TREASURY_RPC_BASE", "BASE_RPC_URL"] : [];
115
- for (const k of candidates) {
209
+ for (const k of CHAIN_INFO[chainId].rpcEnv) {
116
210
  const v = rpcUrlFromEnvValue(process.env[k]);
117
211
  if (v)
118
212
  return v;
@@ -121,17 +215,23 @@ export function rpcUrlFromEnv(chainId) {
121
215
  }
122
216
  /**
123
217
  * 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
218
+ * the operator's opt-out from it. `TREASURY_LOGS_FALLBACK` unset ⇒ the chain's public endpoint; an
219
+ * http(s) URL ⇒ that endpoint, ON BASE ONLY; ANY other value — `off`, `none`, `disabled`, a typo — ⇒ no
220
+ * 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
221
  * otherwise sends a query to a third party the operator never named, which some
128
222
  * deployments cannot accept — and it fails CLOSED for the same reason.
223
+ *
224
+ * 🔴 The variable names ONE endpoint, and that endpoint is on Base. On any other chain a URL there
225
+ * cannot serve the scan — it would answer for the wrong chain — so a SET variable means no fallback
226
+ * on that chain, whatever it holds: either the operator opted out, or they named a Base endpoint and
227
+ * so constrained where this process talks. An operator who wants history on another chain points that
228
+ * chain's logs variable (`TREASURY_LOGS_RPC_ARBITRUM`, `TREASURY_LOGS_RPC_MONAD`, …) at a provider with a wide eth_getLogs range.
129
229
  */
130
230
  export function logsFallbackUrlFromEnv(chainId, logsUrl) {
131
231
  const raw = (process.env["TREASURY_LOGS_FALLBACK"] ?? "").trim();
132
232
  // Unset, empty, or an unexpanded `${VAR}` placeholder: the default fallback.
133
233
  // ⚠️ 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
234
+ // A host can forward `${TREASURY_LOGS_FALLBACK}` verbatim when the variable is unset, so a
135
235
  // placeholder means the operator never set it — and unset must behave exactly as absent, or every
136
236
  // plugin install without the variable silently loses its fallback. The function cannot tell "the
137
237
  // host did not expand it" from "someone typed it"; the second reading is treated as implausible on
@@ -141,6 +241,8 @@ export function logsFallbackUrlFromEnv(chainId, logsUrl) {
141
241
  // 🔴 An operator who set this variable at all was constraining where this process talks. Reading an
142
242
  // unrecognised value as "use the default third party" is the one outcome they cannot have meant
143
243
  // (measured in review: `disabled` silently kept the public fallback until this failed closed).
244
+ if (chainId !== 8453)
245
+ return undefined; // set, and this chain is not the one the variable names an endpoint for
144
246
  const url = rpcUrlFromEnvValue(raw);
145
247
  return url === undefined ? undefined : sameOrUndefined(url, logsUrl);
146
248
  }
@@ -150,7 +252,7 @@ function sameOrUndefined(url, logsUrl) {
150
252
  }
151
253
  /** RPC to use for eth_getLogs scans: a dedicated one if configured, else the general one. */
152
254
  export function logsRpcUrlFromEnv(chainId) {
153
- return rpcUrlFromEnvValue(process.env["TREASURY_LOGS_RPC_BASE"]) ?? rpcUrlFromEnv(chainId);
255
+ return rpcUrlFromEnvValue(process.env[CHAIN_INFO[chainId].logsRpcEnv]) ?? rpcUrlFromEnv(chainId);
154
256
  }
155
257
  /**
156
258
  * Which environment variable supplied the RPC URL — the NAME only, never the value. A keyed provider
@@ -158,8 +260,7 @@ export function logsRpcUrlFromEnv(chainId) {
158
260
  * no variable resolved and the public endpoint is in use (rate-limited, never a failure).
159
261
  */
160
262
  export function rpcSourceForEnv(chainId) {
161
- const candidates = chainId === 8453 ? ["TREASURY_RPC_BASE", "BASE_RPC_URL"] : [];
162
- for (const k of candidates) {
263
+ for (const k of CHAIN_INFO[chainId].rpcEnv) {
163
264
  if (rpcUrlFromEnvValue(process.env[k]))
164
265
  return { source: k, configured: true };
165
266
  }
@@ -180,9 +281,17 @@ export function resolvedRpcSecrets() {
180
281
  // `sk-Live_a%2Bb%2Fc%3Dd9f8e7`, only that was registered, and the plain key leaked. The earlier
181
282
  // test missed it because `SECRETKEY123` percent-encodes to ITSELF — the transformation was the
182
283
  // identity function, so the test could not tell the two forms apart.
284
+ // 🔴 A chain's own key is NOT a secret, and it is long enough to be taken for one. Providers put
285
+ // the chain in the URL — `rpc.example/arbitrum/<key>`, `arbitrum.example.org` — and a path segment
286
+ // or first host label of 8+ characters is registered below. "arbitrum" is exactly 8, so with such a
287
+ // URL configured every refusal that names the chain read `chains with a vault: base, <redacted>`
288
+ // (measured in review). "base" is 4 characters, which is why one chain never showed it.
289
+ const chainWords = new Set([...supportedChainIds.map((id) => CHAIN_INFO[id].key), SOLANA_INFO.key]);
183
290
  const add = (v) => {
184
291
  if (!v || v.length < 8)
185
292
  return;
293
+ if (chainWords.has(v.toLowerCase()))
294
+ return;
186
295
  out.add(v);
187
296
  try {
188
297
  const decoded = decodeURIComponent(v);
@@ -197,7 +306,9 @@ export function resolvedRpcSecrets() {
197
306
  // Every variable that can name a URL the package will CALL — the logs fallback included: it builds a
198
307
  // real client, and a provider's error body can echo its key exactly as the primary's (measured in
199
308
  // 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"]) {
309
+ // Derived from the chain table, so a chain added there cannot be left out of the redactor.
310
+ const names = [...supportedChainIds.flatMap((id) => [...CHAIN_INFO[id].rpcEnv, CHAIN_INFO[id].logsRpcEnv]), ...SOLANA_INFO.rpcEnv, "TREASURY_LOGS_FALLBACK"];
311
+ for (const k of names) {
201
312
  const v = rpcUrlFromEnvValue(process.env[k]);
202
313
  if (v)
203
314
  urls.add(v);
@@ -239,10 +350,76 @@ export function resolvedRpcSecrets() {
239
350
  export function publicRpcHint(chainId) {
240
351
  if (rpcSourceForEnv(chainId).configured)
241
352
  return undefined;
242
- return ("No RPC was configured, so this used the public endpoint (mainnet.base.org), which rate-limits " +
353
+ const info = CHAIN_INFO[chainId];
354
+ return (`No RPC was configured for ${info.name}, so this used the public endpoint (${new URL(info.publicRpc).hostname}), which rate-limits ` +
243
355
  "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 " +
356
+ `Set ${info.rpcEnv[0]} to a keyed ${info.name} RPC URL (Alchemy, Infura, QuickNode or your own node) and ` +
245
357
  "retry. Reads like the vault list and the disclosures work without one; quotes, pre-flight and " +
246
358
  "position history generally do not.");
247
359
  }
360
+ /** How long a chain-identity probe may take before the endpoint counts as "did not say". */
361
+ export const CHAIN_PROBE_MS = 3_000;
362
+ /** Endpoints that have already said which chain they are. An endpoint does not change chain. */
363
+ const reportedChain = new Map();
364
+ /**
365
+ * Which chain does this endpoint say it is? `undefined` when it did not say within
366
+ * `CHAIN_PROBE_MS` — an error, a rate limit, a hang — which is NOT a statement about the chain: the
367
+ * caller reports that as "not verified", never as a match and never as a mismatch.
368
+ *
369
+ * It exists because two chains mean two RPC variables, and the likeliest mistake is one pointed at
370
+ * the other chain. Nothing then errors usefully: a vault's address has no code there, so reads fail
371
+ * with "returned no data" and the failure reads as a broken vault.
372
+ *
373
+ * Bounded on purpose. The transport's own deadline is 10 s and a rate-limited `eth_chainId` is waited
374
+ * out for all of it, which would make a health check that already has its answer wait ten seconds
375
+ * for a second one (measured in review). An answer is remembered per endpoint URL, so a process asks
376
+ * each endpoint once.
377
+ */
378
+ export async function endpointChainId(client, rpcUrl, timeoutMs = CHAIN_PROBE_MS) {
379
+ const known = reportedChain.get(rpcUrl);
380
+ if (known !== undefined)
381
+ return known;
382
+ let timer;
383
+ const timedOut = new Promise((r) => {
384
+ timer = setTimeout(() => r(undefined), timeoutMs);
385
+ timer.unref?.();
386
+ });
387
+ try {
388
+ const got = await Promise.race([client.getChainId().catch(() => undefined), timedOut]);
389
+ if (got !== undefined)
390
+ reportedChain.set(rpcUrl, got);
391
+ return got;
392
+ }
393
+ finally {
394
+ if (timer !== undefined)
395
+ clearTimeout(timer);
396
+ }
397
+ }
398
+ /**
399
+ * The first of these endpoints that answers for a chain other than `chainId`, or `undefined`.
400
+ * A chain's public endpoint is never asked: it is this client's own constant, so the question
401
+ * would be a request to a third party with a known answer. An endpoint that does not say is not a
402
+ * mismatch.
403
+ */
404
+ export async function firstEndpointOnWrongChain(chainId, endpoints) {
405
+ const asked = endpoints.filter((e) => e.url !== PUBLIC_RPC[chainId]);
406
+ const said = await Promise.all(asked.map((e) => endpointChainId(e.client, e.url)));
407
+ for (const [i, id] of said.entries()) {
408
+ if (id !== undefined && id !== chainId)
409
+ return { source: asked[i].source, answersFor: id };
410
+ }
411
+ return undefined;
412
+ }
413
+ /** TEST SEAM — forgets what every endpoint said, so one test's mock port cannot answer for the next. NOT re-exported from index.ts. */
414
+ export function __forgetEndpointChainsForTests() {
415
+ reportedChain.clear();
416
+ }
417
+ /**
418
+ * Which variable supplied the endpoint `earn_balance` scans events through — the chain's logs
419
+ * variable when it resolves, otherwise whatever supplied the general RPC. The NAME only.
420
+ */
421
+ export function logsRpcSourceForEnv(chainId) {
422
+ const k = CHAIN_INFO[chainId].logsRpcEnv;
423
+ return rpcUrlFromEnvValue(process.env[k]) ? { source: k, configured: true } : rpcSourceForEnv(chainId);
424
+ }
248
425
  //# 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,16 @@
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 `scripts/roundtrip.ts` exercises by default. The Base default today. (The fork
15
+ * tier round-trips every depositable vault on each chain, from the registry.)
13
16
  *
14
17
  * Addresses live in the registry (`registry/vaults.json`, schema-validated, block-stamped) — a
15
18
  * ticker here resolves through it.
@@ -23,15 +26,40 @@
23
26
  /** A vault's ERC-20 ticker — resolved via `getVault`, so a typo fails at load, not at a call site. */
24
27
  export type VaultSymbol = string;
25
28
  export declare const EARN: {
29
+ /** The chain used when a caller names neither a chain nor a vault. */
30
+ readonly defaultChain: "base";
26
31
  /**
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.
32
+ * The default vault on each chain, by chain key.
33
+ *
34
+ * `base`: Tempora Labs Cash Plus USDC (Test 2B) — a Morpho Vault V2, the Tempora Labs vault this client
35
+ * offers when nothing is named. Tempora Labs Cash Plus USDC (Test 2), also on Base, is the DEMO
36
+ * vault: listed and open, selected by naming it. Deposits are OPEN to any account (measured by a simulated stranger
37
+ * deposit; `earn_vaults` reports `defaultAccess: "open"`). The whitelist-gated sibling, Cash Plus
38
+ * USDC (Test 2A), stays listed as `tlCashPlusUSDC2A` and is refused per account by the pre-flight.
39
+ *
40
+ * `arbitrum`: Tempora Labs Cash Plus USDC (Test 2C) — a Morpho Vault V2 on Arbitrum One, open to
41
+ * any account by the same measurement.
42
+ *
43
+ * `robinhood`: Tempora Labs Cash Plus USDG (Test 2D) — a Morpho Vault V2 on Robinhood Chain over
44
+ * USDG, the first vault whose asset is not USDC. Open to any account by the same measurement.
45
+ *
46
+ * `ethereum`: Tempora Labs Cash Plus USDC (Test 2E) — a Morpho Vault V2 on Ethereum, open to any
47
+ * account by the same measurement. Gas there costs far more than on the other chains.
48
+ *
49
+ * `monad`: Tempora Labs Cash Plus USDC (Test 2F) — a Morpho Vault V2 on Monad, open to any account
50
+ * by the same measurement.
51
+ *
52
+ * `Record<ChainKey, …>`: a chain added to `CHAIN_INFO` without a default here does not compile.
31
53
  */
32
- readonly defaultVault: "tlCashPlusUSDC2";
54
+ readonly defaultVaultByChain: {
55
+ base: string;
56
+ arbitrum: string;
57
+ robinhood: string;
58
+ ethereum: string;
59
+ monad: string;
60
+ };
33
61
  /** The round-trip target. The same vault as the default; open, so the fork tier deposits from the whale directly. */
34
- readonly roundTripVault: "tlCashPlusUSDC2";
62
+ readonly roundTripVault: "tlCashPlusUSDC2B";
35
63
  /** USDC, as a decimal string — the amount `scripts/roundtrip.ts` prepares by default. Never a float. */
36
64
  readonly roundTripAmountUsdc: "0.05";
37
65
  /** Fixtures the fork and live tiers share. */
@@ -40,6 +68,14 @@ export declare const EARN: {
40
68
  readonly stranger: "0x000000000000000000000000000000000000dEaD";
41
69
  /** Morpho Blue on Base — held ~2.1e14 USDC base units when probed 2026-09-11. Impersonated on the fork, never keyed. */
42
70
  readonly usdcWhale: "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb";
71
+ /** 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. */
72
+ readonly usdcWhaleArbitrum: "0x724dc807b04555b71ed48a6896b6F41593b8C637";
73
+ /** Morpho Blue on Ethereum — held ~1.2e14 USDC base units when probed 2026-10-11. Impersonated on the fork, never keyed. */
74
+ readonly usdcWhaleEthereum: "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb";
75
+ /** The largest USDC holder among recent transfers on Monad — ~1.3e13 base units when probed 2026-10-11. Impersonated on the fork, never keyed. */
76
+ readonly usdcWhaleMonad: "0x188d586Ddcf52439676Ca21A244753fA19F9Ea8e";
77
+ /** The largest USDG holder among recent transfers on Robinhood Chain — ~1.0e14 base units when probed 2026-10-11. Impersonated on the fork, never keyed. */
78
+ readonly usdgWhaleRobinhood: "0x94bAB9693Ba2f6358507eFfcbd372b0660AFfF9d";
43
79
  /** USDC the fork round trip deposits, and what it seeds a discovered depositor with beforehand. */
44
80
  readonly forkDepositUsdc: "100";
45
81
  readonly forkSeedUsdc: "1000";
@@ -3,13 +3,16 @@
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 `scripts/roundtrip.ts` exercises by default. The Base default today. (The fork
15
+ * tier round-trips every depositable vault on each chain, from the registry.)
13
16
  *
14
17
  * Addresses live in the registry (`registry/vaults.json`, schema-validated, block-stamped) — a
15
18
  * ticker here resolves through it.
@@ -21,15 +24,40 @@
21
24
  * stale the moment the whitelist changes. An address is never a key either way (CONTRIBUTING.md, the first rule).
22
25
  */
23
26
  export const EARN = {
27
+ /** The chain used when a caller names neither a chain nor a vault. */
28
+ defaultChain: "base",
24
29
  /**
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.
30
+ * The default vault on each chain, by chain key.
31
+ *
32
+ * `base`: Tempora Labs Cash Plus USDC (Test 2B) — a Morpho Vault V2, the Tempora Labs vault this client
33
+ * offers when nothing is named. Tempora Labs Cash Plus USDC (Test 2), also on Base, is the DEMO
34
+ * vault: listed and open, selected by naming it. Deposits are OPEN to any account (measured by a simulated stranger
35
+ * deposit; `earn_vaults` reports `defaultAccess: "open"`). The whitelist-gated sibling, Cash Plus
36
+ * USDC (Test 2A), stays listed as `tlCashPlusUSDC2A` and is refused per account by the pre-flight.
37
+ *
38
+ * `arbitrum`: Tempora Labs Cash Plus USDC (Test 2C) — a Morpho Vault V2 on Arbitrum One, open to
39
+ * any account by the same measurement.
40
+ *
41
+ * `robinhood`: Tempora Labs Cash Plus USDG (Test 2D) — a Morpho Vault V2 on Robinhood Chain over
42
+ * USDG, the first vault whose asset is not USDC. Open to any account by the same measurement.
43
+ *
44
+ * `ethereum`: Tempora Labs Cash Plus USDC (Test 2E) — a Morpho Vault V2 on Ethereum, open to any
45
+ * account by the same measurement. Gas there costs far more than on the other chains.
46
+ *
47
+ * `monad`: Tempora Labs Cash Plus USDC (Test 2F) — a Morpho Vault V2 on Monad, open to any account
48
+ * by the same measurement.
49
+ *
50
+ * `Record<ChainKey, …>`: a chain added to `CHAIN_INFO` without a default here does not compile.
29
51
  */
30
- defaultVault: "tlCashPlusUSDC2",
52
+ defaultVaultByChain: {
53
+ base: "tlCashPlusUSDC2B",
54
+ arbitrum: "tlCashPlusUSDC2C",
55
+ robinhood: "tlCashPlusUSDG2D",
56
+ ethereum: "tlCashPlusUSDC2E",
57
+ monad: "tlCashPlusUSDC2F",
58
+ },
31
59
  /** The round-trip target. The same vault as the default; open, so the fork tier deposits from the whale directly. */
32
- roundTripVault: "tlCashPlusUSDC2",
60
+ roundTripVault: "tlCashPlusUSDC2B",
33
61
  /** USDC, as a decimal string — the amount `scripts/roundtrip.ts` prepares by default. Never a float. */
34
62
  roundTripAmountUsdc: "0.05",
35
63
  /** Fixtures the fork and live tiers share. */
@@ -38,6 +66,14 @@ export const EARN = {
38
66
  stranger: "0x000000000000000000000000000000000000dEaD",
39
67
  /** Morpho Blue on Base — held ~2.1e14 USDC base units when probed 2026-09-11. Impersonated on the fork, never keyed. */
40
68
  usdcWhale: "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb",
69
+ /** 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. */
70
+ usdcWhaleArbitrum: "0x724dc807b04555b71ed48a6896b6F41593b8C637",
71
+ /** Morpho Blue on Ethereum — held ~1.2e14 USDC base units when probed 2026-10-11. Impersonated on the fork, never keyed. */
72
+ usdcWhaleEthereum: "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb",
73
+ /** The largest USDC holder among recent transfers on Monad — ~1.3e13 base units when probed 2026-10-11. Impersonated on the fork, never keyed. */
74
+ usdcWhaleMonad: "0x188d586Ddcf52439676Ca21A244753fA19F9Ea8e",
75
+ /** The largest USDG holder among recent transfers on Robinhood Chain — ~1.0e14 base units when probed 2026-10-11. Impersonated on the fork, never keyed. */
76
+ usdgWhaleRobinhood: "0x94bAB9693Ba2f6358507eFfcbd372b0660AFfF9d",
41
77
  /** USDC the fork round trip deposits, and what it seeds a discovered depositor with beforehand. */
42
78
  forkDepositUsdc: "100",
43
79
  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;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAOH,MAAM,CAAC,MAAM,IAAI,GAAG;IAClB,sEAAsE;IACtE,YAAY,EAAE,MAAyB;IAEvC;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,mBAAmB,EAAE;QACnB,IAAI,EAAE,kBAAkB;QACxB,QAAQ,EAAE,kBAAkB;QAC5B,SAAS,EAAE,kBAAkB;QAC7B,QAAQ,EAAE,kBAAkB;QAC5B,KAAK,EAAE,kBAAkB;KACc;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,4HAA4H;QAC5H,iBAAiB,EAAE,4CAAqD;QACxE,kJAAkJ;QAClJ,cAAc,EAAE,4CAAqD;QACrE,4JAA4J;QAC5J,kBAAkB,EAAE,4CAAqD;QACzE,mGAAmG;QACnG,eAAe,EAAE,KAAK;QACtB,YAAY,EAAE,MAAM;KACrB;CACO,CAAC"}
@@ -0,0 +1,76 @@
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
+ import type { SolanaVaultEntry } from "../registry-schema.js";
22
+ /** How long an acknowledgement stays usable: long enough to read it and answer, not long enough to forget it. */
23
+ export declare const ACK_TTL_MS: number;
24
+ export interface PendingAck {
25
+ code: string;
26
+ digest: string;
27
+ issuedAtIso: string;
28
+ expiresAtIso: string;
29
+ }
30
+ /** What the calls ARE: the connected account and each call's chain, destination, calldata and value. */
31
+ export declare function callsDigest(calls: UnsignedCall[], account: Address): string;
32
+ export declare function issueAck(calls: UnsignedCall[], account: Address, now: Date): PendingAck;
33
+ /**
34
+ * What a Solana intent IS: the connected account, the vault, the action and its raw amount. Not the
35
+ * transaction's bytes — those name a blockhash that expires in about a minute, so the page builds a fresh
36
+ * transaction for the same intent, and the gate holds every one of them to it. A withdrawal by amount is
37
+ * `withdraw-assets` with the asset's raw amount: the shares worth it change as the vault earns, so they are
38
+ * worked out only once the acknowledgement is accepted.
39
+ */
40
+ export declare function solanaIntentDigest(account: string, vault: string, action: "deposit" | "withdraw" | "withdraw-assets", raw: bigint): string;
41
+ export declare function issueAckForDigest(digest: string, now: Date): PendingAck;
42
+ /** Throws unless `code` names `pending`, it is unexpired, and it was issued for exactly these calls. */
43
+ export declare function checkAck(code: string, pending: PendingAck | undefined, calls: UnsignedCall[], account: Address, now: Date): void;
44
+ /** `checkAck` against a digest computed by the caller (a Solana intent's). */
45
+ export declare function checkAckDigest(code: string, pending: PendingAck | undefined, digest: string, now: Date): void;
46
+ export interface AckSummary {
47
+ action: "deposit" | "withdraw";
48
+ amount: string;
49
+ /** The vault's asset (USDC; USDG on Robinhood Chain): what a withdrawal pays out. */
50
+ asset: string;
51
+ chain: string;
52
+ /** `null` on Solana, which has no chain id; the text then names the cluster. */
53
+ chainId: number | null;
54
+ vault: {
55
+ symbol: string;
56
+ name: string;
57
+ address: string;
58
+ explorer: string;
59
+ };
60
+ /** What the wallet will ask; the EVM default (approve then deposit, or one withdrawal) when absent. */
61
+ prompts?: string;
62
+ receiver: string;
63
+ warning: string;
64
+ disclosures: string[];
65
+ }
66
+ /**
67
+ * The registry's `warning` is written for both audiences, so it ends with an instruction to the agent
68
+ * ("Show this warning before preparing any deposit."). The operator is reading the warning itself, so
69
+ * that sentence is dropped here. The registry text is unchanged: `earn` output and the registry check use it.
70
+ */
71
+ export declare function operatorWarning(w: string, action?: "deposit" | "withdraw"): string;
72
+ export declare function summarize(action: "deposit" | "withdraw", calls: UnsignedCall[], admitted: Admitted[], receiver: Address): AckSummary;
73
+ /** The summary for a Solana intent: one transaction, no approve, and shares only ever to the account itself. */
74
+ export declare function summarizeSolana(action: "deposit" | "withdraw", v: SolanaVaultEntry, amountText: string, account: string): AckSummary;
75
+ /** The text the operator reads. Generated, never paraphrased: the same calls always produce the same words. */
76
+ export declare function acknowledgementText(s: AckSummary): string;