@temporalabs/treasury 0.1.2 → 0.1.4

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 (83) hide show
  1. package/README.md +45 -13
  2. package/THIRD_PARTY_NOTICES.connect-page.md +494 -24
  3. package/THIRD_PARTY_NOTICES.md +579 -6
  4. package/dist/cli.js +28 -5
  5. package/dist/cli.js.map +1 -1
  6. package/dist/client.d.ts +50 -209
  7. package/dist/client.js +66 -11
  8. package/dist/client.js.map +1 -1
  9. package/dist/config/earn.d.ts +16 -1
  10. package/dist/config/earn.js +16 -1
  11. package/dist/config/earn.js.map +1 -1
  12. package/dist/connect/ack.d.ts +88 -1
  13. package/dist/connect/ack.js +177 -6
  14. package/dist/connect/ack.js.map +1 -1
  15. package/dist/connect/commands.d.ts +30 -0
  16. package/dist/connect/commands.js +846 -88
  17. package/dist/connect/commands.js.map +1 -1
  18. package/dist/connect/config.d.ts +7 -5
  19. package/dist/connect/config.js +8 -6
  20. package/dist/connect/config.js.map +1 -1
  21. package/dist/connect/gate-solana.d.ts +8 -0
  22. package/dist/connect/gate-solana.js +147 -0
  23. package/dist/connect/gate-solana.js.map +1 -0
  24. package/dist/connect/http.d.ts +17 -2
  25. package/dist/connect/http.js +45 -13
  26. package/dist/connect/http.js.map +1 -1
  27. package/dist/connect/page.d.ts +1 -1
  28. package/dist/connect/page.js +2 -2
  29. package/dist/connect/page.js.map +1 -1
  30. package/dist/connect/session.d.ts +40 -1
  31. package/dist/connect/session.js +243 -2
  32. package/dist/connect/session.js.map +1 -1
  33. package/dist/connect/solana.d.ts +112 -0
  34. package/dist/connect/solana.js +370 -0
  35. package/dist/connect/solana.js.map +1 -0
  36. package/dist/connect-page.js +835 -671
  37. package/dist/disclosures.d.ts +7 -4
  38. package/dist/disclosures.js +7 -4
  39. package/dist/disclosures.js.map +1 -1
  40. package/dist/earn/commands.js +127 -54
  41. package/dist/earn/commands.js.map +1 -1
  42. package/dist/earn/solana.d.ts +278 -0
  43. package/dist/earn/solana.js +316 -0
  44. package/dist/earn/solana.js.map +1 -0
  45. package/dist/guide.d.ts +15 -0
  46. package/dist/guide.js +50 -0
  47. package/dist/guide.js.map +1 -0
  48. package/dist/links.js +2 -0
  49. package/dist/links.js.map +1 -1
  50. package/dist/position.d.ts +3 -2
  51. package/dist/position.js +6 -3
  52. package/dist/position.js.map +1 -1
  53. package/dist/quote.js +2 -2
  54. package/dist/quote.js.map +1 -1
  55. package/dist/redact.js +7 -1
  56. package/dist/redact.js.map +1 -1
  57. package/dist/registry-schema.d.ts +79 -2
  58. package/dist/registry-schema.js +77 -1
  59. package/dist/registry-schema.js.map +1 -1
  60. package/dist/registry.d.ts +21 -1
  61. package/dist/registry.js +48 -10
  62. package/dist/registry.js.map +1 -1
  63. package/dist/solana/constants.d.ts +49 -0
  64. package/dist/solana/constants.js +50 -0
  65. package/dist/solana/constants.js.map +1 -0
  66. package/dist/solana/kvault.d.ts +99 -0
  67. package/dist/solana/kvault.js +192 -0
  68. package/dist/solana/kvault.js.map +1 -0
  69. package/dist/solana/layout.d.ts +143 -0
  70. package/dist/solana/layout.js +209 -0
  71. package/dist/solana/layout.js.map +1 -0
  72. package/dist/solana/rpc.d.ts +24 -0
  73. package/dist/solana/rpc.js +66 -0
  74. package/dist/solana/rpc.js.map +1 -0
  75. package/dist/solana/vault.d.ts +153 -0
  76. package/dist/solana/vault.js +322 -0
  77. package/dist/solana/vault.js.map +1 -0
  78. package/dist/treasury.mjs +37410 -27965
  79. package/dist/version.js +5 -10
  80. package/dist/version.js.map +1 -1
  81. package/llms.txt +637 -0
  82. package/package.json +14 -8
  83. package/registry/vaults.json +113 -0
@@ -11,7 +11,8 @@
11
11
  * config/registry disagreement — and the schema allows a WHITELIST_GATED
12
12
  * default, because the pre-flight re-measures access live on every call and
13
13
  * refuses a non-member before anything is built.
14
- * `roundTripVault` what the deposit → redeem tiers exercise. The Base default today.
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.)
15
16
  *
16
17
  * Addresses live in the registry (`registry/vaults.json`, schema-validated, block-stamped) — a
17
18
  * ticker here resolves through it.
@@ -42,12 +43,20 @@ export declare const EARN: {
42
43
  * `robinhood`: Tempora Labs Cash Plus USDG (Test 2D) — a Morpho Vault V2 on Robinhood Chain over
43
44
  * USDG, the first vault whose asset is not USDC. Open to any account by the same measurement.
44
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
+ *
45
52
  * `Record<ChainKey, …>`: a chain added to `CHAIN_INFO` without a default here does not compile.
46
53
  */
47
54
  readonly defaultVaultByChain: {
48
55
  base: string;
49
56
  arbitrum: string;
50
57
  robinhood: string;
58
+ ethereum: string;
59
+ monad: string;
51
60
  };
52
61
  /** The round-trip target. The same vault as the default; open, so the fork tier deposits from the whale directly. */
53
62
  readonly roundTripVault: "tlCashPlusUSDC2B";
@@ -61,6 +70,12 @@ export declare const EARN: {
61
70
  readonly usdcWhale: "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb";
62
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. */
63
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";
64
79
  /** USDC the fork round trip deposits, and what it seeds a discovered depositor with beforehand. */
65
80
  readonly forkDepositUsdc: "100";
66
81
  readonly forkSeedUsdc: "1000";
@@ -11,7 +11,8 @@
11
11
  * config/registry disagreement — and the schema allows a WHITELIST_GATED
12
12
  * default, because the pre-flight re-measures access live on every call and
13
13
  * refuses a non-member before anything is built.
14
- * `roundTripVault` what the deposit → redeem tiers exercise. The Base default today.
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.)
15
16
  *
16
17
  * Addresses live in the registry (`registry/vaults.json`, schema-validated, block-stamped) — a
17
18
  * ticker here resolves through it.
@@ -40,12 +41,20 @@ export const EARN = {
40
41
  * `robinhood`: Tempora Labs Cash Plus USDG (Test 2D) — a Morpho Vault V2 on Robinhood Chain over
41
42
  * USDG, the first vault whose asset is not USDC. Open to any account by the same measurement.
42
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
+ *
43
50
  * `Record<ChainKey, …>`: a chain added to `CHAIN_INFO` without a default here does not compile.
44
51
  */
45
52
  defaultVaultByChain: {
46
53
  base: "tlCashPlusUSDC2B",
47
54
  arbitrum: "tlCashPlusUSDC2C",
48
55
  robinhood: "tlCashPlusUSDG2D",
56
+ ethereum: "tlCashPlusUSDC2E",
57
+ monad: "tlCashPlusUSDC2F",
49
58
  },
50
59
  /** The round-trip target. The same vault as the default; open, so the fork tier deposits from the whale directly. */
51
60
  roundTripVault: "tlCashPlusUSDC2B",
@@ -59,6 +68,12 @@ export const EARN = {
59
68
  usdcWhale: "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb",
60
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. */
61
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",
62
77
  /** USDC the fork round trip deposits, and what it seeds a discovered depositor with beforehand. */
63
78
  forkDepositUsdc: "100",
64
79
  forkSeedUsdc: "1000",
@@ -1 +1 @@
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"}
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"}
@@ -18,6 +18,7 @@
18
18
  import { type Address } from "viem";
19
19
  import type { UnsignedCall } from "../build.js";
20
20
  import type { Admitted } from "./gate.js";
21
+ import type { SolanaVaultEntry } from "../registry-schema.js";
21
22
  /** How long an acknowledgement stays usable: long enough to read it and answer, not long enough to forget it. */
22
23
  export declare const ACK_TTL_MS: number;
23
24
  export interface PendingAck {
@@ -29,21 +30,35 @@ export interface PendingAck {
29
30
  /** What the calls ARE: the connected account and each call's chain, destination, calldata and value. */
30
31
  export declare function callsDigest(calls: UnsignedCall[], account: Address): string;
31
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;
32
42
  /** Throws unless `code` names `pending`, it is unexpired, and it was issued for exactly these calls. */
33
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;
34
46
  export interface AckSummary {
35
47
  action: "deposit" | "withdraw";
36
48
  amount: string;
37
49
  /** The vault's asset (USDC; USDG on Robinhood Chain): what a withdrawal pays out. */
38
50
  asset: string;
39
51
  chain: string;
40
- chainId: number;
52
+ /** `null` on Solana, which has no chain id; the text then names the cluster. */
53
+ chainId: number | null;
41
54
  vault: {
42
55
  symbol: string;
43
56
  name: string;
44
57
  address: string;
45
58
  explorer: string;
46
59
  };
60
+ /** What the wallet will ask; the EVM default (approve then deposit, or one withdrawal) when absent. */
61
+ prompts?: string;
47
62
  receiver: string;
48
63
  warning: string;
49
64
  disclosures: string[];
@@ -55,5 +70,77 @@ export interface AckSummary {
55
70
  */
56
71
  export declare function operatorWarning(w: string, action?: "deposit" | "withdraw"): string;
57
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;
58
75
  /** The text the operator reads. Generated, never paraphrased: the same calls always produce the same words. */
59
76
  export declare function acknowledgementText(s: AckSummary): string;
77
+ /**
78
+ * A plan: one acknowledgement for several deposits and withdrawals, across vaults and chains (`connect plan`).
79
+ *
80
+ * Each leg is bound to the same digest its own `--ack` would be (`callsDigest`, `solanaIntentDigest`), so a
81
+ * leg run rebuilds its calls exactly as a single acknowledgement does and is held to them. The plan's code
82
+ * is spent leg by leg, in order: a leg that does not complete ends the plan, and the legs after it never run.
83
+ */
84
+ export declare const PLAN_TTL_MS: number;
85
+ /** Past this many legs, the operator is better served by more than one plan. */
86
+ export declare const PLAN_MAX_LEGS = 8;
87
+ export type PlanLegStatus = "pending" | "running" | "completed" | "stopped" | "not_reported";
88
+ export interface PlanLeg {
89
+ leg: number;
90
+ action: "deposit" | "withdraw";
91
+ vault: string;
92
+ chain: string;
93
+ amount: string;
94
+ digest: string;
95
+ /** The exact command that runs this leg once the plan is acknowledged. */
96
+ command: string;
97
+ /** What that command builds the leg's calls from: how `connect plan --run` rebuilds them for its one page. */
98
+ args?: PlanLegArgs;
99
+ status: PlanLegStatus;
100
+ txs?: PlanTx[];
101
+ reason?: string;
102
+ }
103
+ /** A leg's transaction as the plan keeps it: its hash, its verdict, and anything else the wallet moved with it. */
104
+ export interface PlanTx {
105
+ hash: string;
106
+ verified: string;
107
+ alsoMoved?: {
108
+ to: string;
109
+ amountRaw: string;
110
+ }[];
111
+ }
112
+ export interface PlanLegArgs {
113
+ vault: string;
114
+ receiver: string;
115
+ amount_usdc?: string;
116
+ all?: boolean;
117
+ shares_exact?: string;
118
+ }
119
+ export interface PendingPlan {
120
+ code: string;
121
+ issuedAtIso: string;
122
+ expiresAtIso: string;
123
+ acknowledged: boolean;
124
+ legs: PlanLeg[];
125
+ /**
126
+ * The one page `connect plan --run` serves for this plan: its secret and port, kept so a run that stops at the
127
+ * shell's time limit and the run after it serve the same page, and the operator's open tab carries on.
128
+ */
129
+ page?: {
130
+ secret: string;
131
+ port: number;
132
+ };
133
+ }
134
+ /** What a plan IS: its legs' digests, in order. Reordering, adding or dropping a leg changes it. */
135
+ export declare function planDigest(digests: string[]): string;
136
+ export declare function issuePlan(legs: Omit<PlanLeg, "status">[], now: Date): PendingPlan;
137
+ export declare const planExpired: (p: PendingPlan, now: Date) => boolean;
138
+ /** Throws unless `code` names the pending plan, it is unexpired and not yet acknowledged, and its legs are exactly `digests`. */
139
+ export declare function checkPlanAck(code: string, plan: PendingPlan | undefined, digests: string[], now: Date): void;
140
+ /**
141
+ * Throws unless leg `leg` of the acknowledged plan `code` may run now, for exactly `digest`: the plan is
142
+ * acknowledged and unexpired, every earlier leg completed, and this leg has not run. Returns its index.
143
+ */
144
+ export declare function checkPlanLeg(code: string, leg: number, plan: PendingPlan | undefined, digest: string, now: Date): number;
145
+ /** The text the operator reads for a plan: every leg, then each warning and the disclosures once. */
146
+ export declare function planAcknowledgementText(legs: AckSummary[], totals: string[]): string;
@@ -26,7 +26,19 @@ export function callsDigest(calls, account) {
26
26
  return keccak256(stringToHex(JSON.stringify([account, calls.map((c) => [c.chainId, c.to, c.data, c.value])])));
27
27
  }
28
28
  export function issueAck(calls, account, now) {
29
- const digest = callsDigest(calls, account);
29
+ return issueAckForDigest(callsDigest(calls, account), now);
30
+ }
31
+ /**
32
+ * What a Solana intent IS: the connected account, the vault, the action and its raw amount. Not the
33
+ * transaction's bytes — those name a blockhash that expires in about a minute, so the page builds a fresh
34
+ * transaction for the same intent, and the gate holds every one of them to it. A withdrawal by amount is
35
+ * `withdraw-assets` with the asset's raw amount: the shares worth it change as the vault earns, so they are
36
+ * worked out only once the acknowledgement is accepted.
37
+ */
38
+ export function solanaIntentDigest(account, vault, action, raw) {
39
+ return keccak256(stringToHex(JSON.stringify(["solana", account, vault, action, raw.toString()])));
40
+ }
41
+ export function issueAckForDigest(digest, now) {
30
42
  const issuedAtIso = now.toISOString();
31
43
  return {
32
44
  code: keccak256(stringToHex(`${digest}|${issuedAtIso}`)).slice(2, 10),
@@ -37,6 +49,10 @@ export function issueAck(calls, account, now) {
37
49
  }
38
50
  /** Throws unless `code` names `pending`, it is unexpired, and it was issued for exactly these calls. */
39
51
  export function checkAck(code, pending, calls, account, now) {
52
+ checkAckDigest(code, pending, callsDigest(calls, account), now);
53
+ }
54
+ /** `checkAck` against a digest computed by the caller (a Solana intent's). */
55
+ export function checkAckDigest(code, pending, digest, now) {
40
56
  const again = "run the same command without --ack, post its `acknowledgement` to the operator, and wait for their yes";
41
57
  if (!pending)
42
58
  throw new Error(`refused: no acknowledgement is pending; ${again}`);
@@ -46,7 +62,7 @@ export function checkAck(code, pending, calls, account, now) {
46
62
  // A missing or unreadable expiry counts as expired, never as no expiry.
47
63
  if (!Number.isFinite(expires) || now.getTime() > expires)
48
64
  throw new Error(`refused: the acknowledgement expired at ${pending.expiresAtIso}; ${again}`);
49
- if (callsDigest(calls, account) !== pending.digest) {
65
+ if (digest !== pending.digest) {
50
66
  throw new Error(`refused: these calls are not the ones the operator acknowledged (the amount, vault, chain, receiver or connected account changed); ${again}`);
51
67
  }
52
68
  }
@@ -83,17 +99,37 @@ export function summarize(action, calls, admitted, receiver) {
83
99
  : [...DISCLOSURES.plain.always],
84
100
  };
85
101
  }
102
+ /** The summary for a Solana intent: one transaction, no approve, and shares only ever to the account itself. */
103
+ export function summarizeSolana(action, v, amountText, account) {
104
+ return {
105
+ action,
106
+ amount: amountText,
107
+ asset: v.asset.symbol,
108
+ chain: "Solana",
109
+ chainId: null,
110
+ vault: { symbol: v.symbol, name: v.name, address: v.address, explorer: `https://solscan.io/account/${v.address}` },
111
+ receiver: account,
112
+ warning: operatorWarning(v.warning, action),
113
+ prompts: action === "deposit"
114
+ ? "Your wallet will ask you once, to make the deposit. A first deposit also opens your share account, which takes about 0.002 SOL of rent."
115
+ : "Your wallet will ask you once, to make the withdrawal. Kamino keeps up to 0.001 USDC of each withdraw instruction in the vault, a charge it sets and can change.",
116
+ disclosures: action === "deposit"
117
+ ? [...DISCLOSURES.plain.deposit, ...(v.depositOpen.open ? [] : [DISCLOSURES.plain.gatedDeposit]), ...DISCLOSURES.plain.always]
118
+ : [...DISCLOSURES.plain.always],
119
+ };
120
+ }
86
121
  /** The text the operator reads. Generated, never paraphrased: the same calls always produce the same words. */
87
122
  export function acknowledgementText(s) {
88
123
  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.`;
124
+ const prompts = s.prompts ??
125
+ (s.action === "deposit"
126
+ ? `Your wallet will ask you twice: first to approve ${s.amount} to the vault, then to make the deposit.`
127
+ : `Your wallet will ask you once, to make the withdrawal.`);
92
128
  return [
93
129
  `Confirm before the signing page opens. Nothing has been sent.`,
94
130
  ``,
95
131
  ` ${s.action === "deposit" ? "Deposit" : "Withdraw"}: ${s.amount}`,
96
- ` Chain: ${s.chain} (chainId ${s.chainId})`,
132
+ s.chainId === null ? ` Chain: ${s.chain} (mainnet-beta)` : ` Chain: ${s.chain} (chainId ${s.chainId})`,
97
133
  ` Vault: ${s.vault.name} (${s.vault.symbol})`,
98
134
  ` ${s.vault.explorer}`,
99
135
  ` ${lands}: ${s.receiver} (the connected wallet)`,
@@ -108,4 +144,139 @@ export function acknowledgementText(s) {
108
144
  `Do you acknowledge and want the signing page opened for exactly this ${s.action}? Reply yes or no.`,
109
145
  ].join("\n");
110
146
  }
147
+ /**
148
+ * A plan: one acknowledgement for several deposits and withdrawals, across vaults and chains (`connect plan`).
149
+ *
150
+ * Each leg is bound to the same digest its own `--ack` would be (`callsDigest`, `solanaIntentDigest`), so a
151
+ * leg run rebuilds its calls exactly as a single acknowledgement does and is held to them. The plan's code
152
+ * is spent leg by leg, in order: a leg that does not complete ends the plan, and the legs after it never run.
153
+ */
154
+ export const PLAN_TTL_MS = 60 * 60_000;
155
+ /** Past this many legs, the operator is better served by more than one plan. */
156
+ export const PLAN_MAX_LEGS = 8;
157
+ /** What a plan IS: its legs' digests, in order. Reordering, adding or dropping a leg changes it. */
158
+ export function planDigest(digests) {
159
+ return keccak256(stringToHex(JSON.stringify(["plan", digests])));
160
+ }
161
+ export function issuePlan(legs, now) {
162
+ const a = issueAckForDigest(planDigest(legs.map((l) => l.digest)), now);
163
+ return {
164
+ code: a.code,
165
+ issuedAtIso: a.issuedAtIso,
166
+ expiresAtIso: new Date(now.getTime() + PLAN_TTL_MS).toISOString(),
167
+ acknowledged: false,
168
+ legs: legs.map((l) => ({ ...l, status: "pending" })),
169
+ };
170
+ }
171
+ export const planExpired = (p, now) => {
172
+ const expires = Date.parse(p.expiresAtIso);
173
+ // A missing or unreadable expiry counts as expired, never as no expiry.
174
+ return !Number.isFinite(expires) || now.getTime() > expires;
175
+ };
176
+ /** Throws unless `code` names the pending plan, it is unexpired and not yet acknowledged, and its legs are exactly `digests`. */
177
+ export function checkPlanAck(code, plan, digests, now) {
178
+ const again = "run the same `connect plan` without --ack, post its `acknowledgement` to the operator, and wait for their yes";
179
+ if (!plan)
180
+ throw new Error(`refused: no plan is pending; ${again}`);
181
+ if (code.trim().toLowerCase() !== plan.code)
182
+ throw new Error(`refused: --ack ${code} is not the pending plan's code; ${again}`);
183
+ if (planExpired(plan, now))
184
+ throw new Error(`refused: the plan expired at ${plan.expiresAtIso}; ${again}`);
185
+ if (plan.acknowledged)
186
+ throw new Error(`refused: this plan was already acknowledged; run its legs (\`connect plan --status\` lists them)`);
187
+ if (planDigest(digests) !== planDigest(plan.legs.map((l) => l.digest))) {
188
+ throw new Error(`refused: these legs are not the ones the operator acknowledged (a leg, its order, amount, vault, or a share balance changed); ${again}`);
189
+ }
190
+ }
191
+ /**
192
+ * Throws unless leg `leg` of the acknowledged plan `code` may run now, for exactly `digest`: the plan is
193
+ * acknowledged and unexpired, every earlier leg completed, and this leg has not run. Returns its index.
194
+ */
195
+ export function checkPlanLeg(code, leg, plan, digest, now) {
196
+ const again = "acknowledge a new plan with `connect plan`";
197
+ if (!plan)
198
+ throw new Error(`refused: no plan is pending; ${again}`);
199
+ if (code.trim().toLowerCase() !== plan.code)
200
+ throw new Error(`refused: --plan ${code} is not the pending plan's code; ${again}`);
201
+ if (!plan.acknowledged)
202
+ throw new Error(`refused: plan ${plan.code} has not been acknowledged; post its acknowledgement and, on the operator's yes, run \`connect plan\` with --ack ${plan.code}`);
203
+ if (planExpired(plan, now))
204
+ throw new Error(`refused: the plan expired at ${plan.expiresAtIso}; legs that have not started do not run; ${again}`);
205
+ const i = plan.legs.findIndex((l) => l.leg === leg);
206
+ if (i < 0)
207
+ throw new Error(`refused: plan ${plan.code} has no leg ${leg}; it has legs 1 to ${plan.legs.length}`);
208
+ const ended = plan.legs.find((l) => l.status !== "pending" && l.status !== "completed");
209
+ if (ended && ended.leg !== leg) {
210
+ throw new Error(ended.status === "running"
211
+ ? `refused: leg ${ended.leg} is still running, or its run never finished; no later leg runs until it has completed`
212
+ : `refused: the plan ended at leg ${ended.leg} (${ended.status}), so no later leg runs; ${again}`);
213
+ }
214
+ if (plan.legs[i].status !== "pending")
215
+ throw new Error(`refused: leg ${leg} has already run (${plan.legs[i].status})`);
216
+ const before = plan.legs.slice(0, i).find((l) => l.status !== "completed");
217
+ if (before)
218
+ throw new Error(`refused: legs run in order, and leg ${before.leg} has not completed; run it first`);
219
+ if (digest !== plan.legs[i].digest) {
220
+ throw new Error(`refused: these calls are not leg ${leg} as the operator acknowledged it (the amount, vault, chain, receiver or connected account changed); ${again}`);
221
+ }
222
+ return i;
223
+ }
224
+ /** The text the operator reads for a plan: every leg, then each warning and the disclosures once. */
225
+ export function planAcknowledgementText(legs, totals) {
226
+ const n = legs.length;
227
+ // One warning per text, naming every vault it covers. A withdrawal's warning is the deposit's without its advice on
228
+ // how much to deposit (`operatorWarning`), so the two are one warning, with that advice named for the deposits only.
229
+ const advice = (w) => w.match(/Deposit only .*?\.(?=\s|$)/g)?.join(" ") ?? "";
230
+ const warnings = [];
231
+ for (const s of legs) {
232
+ const base = operatorWarning(s.warning, "withdraw");
233
+ const w = warnings.find((x) => x.text === base) ?? warnings[warnings.push({ text: base, vaults: [], advice: "", depositVaults: [] }) - 1];
234
+ if (!w.vaults.includes(s.vault.symbol))
235
+ w.vaults.push(s.vault.symbol);
236
+ if (s.action === "deposit" && advice(s.warning)) {
237
+ w.advice = advice(s.warning);
238
+ if (!w.depositVaults.includes(s.vault.symbol))
239
+ w.depositVaults.push(s.vault.symbol);
240
+ }
241
+ }
242
+ const several = new Set(legs.map((s) => s.vault.symbol)).size > 1;
243
+ const fees = DISCLOSURES.plain.deposit.find((d) => d.startsWith("Tempora Labs runs this vault"));
244
+ const disclosures = [...new Set(legs.flatMap((s) => s.disclosures))].map((d) => (several && d === fees ? DISCLOSURES.plain.feesSeveral : d));
245
+ const minutes = Math.round(PLAN_TTL_MS / 60_000);
246
+ const legLines = legs.flatMap((s, i) => {
247
+ const lands = s.action === "deposit" ? "Shares go to" : `${s.asset} goes to`;
248
+ const prompts = s.prompts ??
249
+ (s.action === "deposit"
250
+ ? `Your wallet will ask you twice: first to approve ${s.amount} to the vault, then to make the deposit.`
251
+ : `Your wallet will ask you once, to make the withdrawal.`);
252
+ return [
253
+ ` ${i + 1}. ${s.action === "deposit" ? "Deposit" : "Withdraw"}: ${s.amount}`,
254
+ s.chainId === null ? ` Chain: ${s.chain} (mainnet-beta)` : ` Chain: ${s.chain} (chainId ${s.chainId})`,
255
+ ` Vault: ${s.vault.name} (${s.vault.symbol})`,
256
+ ` ${s.vault.explorer}`,
257
+ ` ${lands}: ${s.receiver} (the connected wallet)`,
258
+ ` ${prompts}`,
259
+ ``,
260
+ ];
261
+ });
262
+ return [
263
+ `Confirm before any signing page opens. Nothing has been sent.`,
264
+ ``,
265
+ `This plan has ${n} ${n === 1 ? "leg" : "legs"}, run in this order on one signing page, where your wallet asks you to confirm each transaction. If a leg does not complete, the legs after it do not run.`,
266
+ `The plan lasts ${minutes} minutes: a leg not started by then does not run, and connecting a wallet again cancels it. To stop partway, reject a transaction in your wallet, or stop the plan on the signing page; the legs after it then do not run.`,
267
+ ``,
268
+ ...legLines,
269
+ ...(totals.length ? [`In total: ${totals.join("; ")}.`, ``] : []),
270
+ ...warnings.flatMap((w) => [
271
+ `WARNING (${w.vaults.join(", ")}): ${w.text}`,
272
+ ...(w.advice ? [` For the ${w.depositVaults.length === 1 ? "deposit" : "deposits"} (${w.depositVaults.join(", ")}): ${w.advice}`] : []),
273
+ ]),
274
+ ``,
275
+ `Before you agree:`,
276
+ ...disclosures.map((d) => ` - ${d}`),
277
+ ` ${DISCLOSURES.plain.fullTerms}`,
278
+ ``,
279
+ `Do you acknowledge and want the signing page opened for exactly these ${n} ${n === 1 ? "leg" : "legs"}, run one leg at a time? Reply yes or no.`,
280
+ ].join("\n");
281
+ }
111
282
  //# sourceMappingURL=ack.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ack.js","sourceRoot":"","sources":["../../src/connect/ack.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ack.js","sourceRoot":"","sources":["../../src/connect/ack.ts"],"names":[],"mappings":"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"}
@@ -19,6 +19,7 @@ import { type Address, type Hex } from "viem";
19
19
  import { type UnsignedCall } from "../build.js";
20
20
  import { makePublicClient } from "../client.js";
21
21
  import type { Command } from "../earn/commands.js";
22
+ import { type SolanaFlowDeps } from "./solana.js";
22
23
  import { type Settled } from "./http.js";
23
24
  import { type Session } from "./session.js";
24
25
  import { type Verdict } from "./verify.js";
@@ -48,6 +49,10 @@ export interface ConnectDeps {
48
49
  balanceTimeoutMs?: number;
49
50
  /** The clock acknowledgements are issued and checked against (tests). */
50
51
  now?: () => Date;
52
+ /** The Solana flows' chain reads (tests). */
53
+ solanaRpc?: SolanaFlowDeps["rpc"];
54
+ /** Overrides the page time `connect plan --run` keeps back before starting a leg (tests). */
55
+ legMinMs?: number;
51
56
  }
52
57
  export declare function runConnect(deps?: ConnectDeps): Promise<{
53
58
  result: Settled<Session>;
@@ -59,6 +64,31 @@ interface TxOutcome extends Verdict {
59
64
  description: string;
60
65
  hash: string;
61
66
  }
67
+ /** One leg's confirm core: the gate, the chain reads, and the step-by-step verdicts, without the page around it. */
68
+ export interface ConfirmCore {
69
+ chainId: number;
70
+ calls: UnsignedCall[];
71
+ done: TxOutcome[];
72
+ stopReason: () => string | undefined;
73
+ info: () => Record<string, unknown>;
74
+ /** Records the hash for step `index`, reads its receipt, and says whether the next step may go. */
75
+ accept: (index: unknown, hash: unknown) => Promise<{
76
+ ok: false;
77
+ reason: string;
78
+ } | {
79
+ ok: true;
80
+ kind: "next" | "finished" | "stop";
81
+ reply: Record<string, unknown>;
82
+ }>;
83
+ /** Puts a hash the page could not hand over on record, against the step it names. */
84
+ onReject: (body: Record<string, unknown>) => void;
85
+ }
86
+ /**
87
+ * The confirm flow without its page: the gate runs here, on exactly the calls the page will hand the
88
+ * wallet, so no caller can pass a check for one batch and the calls of another. It throws before any
89
+ * page opens. `deadline`: when the page closes, so every chain read stops waiting by then.
90
+ */
91
+ export declare function prepareConfirm(calls: UnsignedCall[], session: Session, deps: ConnectDeps, deadline: number): Promise<ConfirmCore>;
62
92
  export declare function runConfirm(calls: UnsignedCall[], session: Session, deps?: ConnectDeps): Promise<{
63
93
  result: Settled<TxOutcome[]>;
64
94
  url: string;