@temporalabs/treasury 0.1.0

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 (55) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +10 -0
  3. package/README.md +153 -0
  4. package/THIRD_PARTY_NOTICES.md +366 -0
  5. package/dist/abi/erc4626.d.ts +243 -0
  6. package/dist/abi/erc4626.js +146 -0
  7. package/dist/abi/erc4626.js.map +1 -0
  8. package/dist/build.d.ts +88 -0
  9. package/dist/build.js +124 -0
  10. package/dist/build.js.map +1 -0
  11. package/dist/client.d.ts +429 -0
  12. package/dist/client.js +248 -0
  13. package/dist/client.js.map +1 -0
  14. package/dist/config/earn.d.ts +47 -0
  15. package/dist/config/earn.js +46 -0
  16. package/dist/config/earn.js.map +1 -0
  17. package/dist/disclosures.d.ts +14 -0
  18. package/dist/disclosures.js +28 -0
  19. package/dist/disclosures.js.map +1 -0
  20. package/dist/index.d.ts +14 -0
  21. package/dist/index.js +10 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/links.d.ts +21 -0
  24. package/dist/links.js +32 -0
  25. package/dist/links.js.map +1 -0
  26. package/dist/mcp/server.d.ts +33 -0
  27. package/dist/mcp/server.js +346 -0
  28. package/dist/mcp/server.js.map +1 -0
  29. package/dist/mcp-server.mjs +56281 -0
  30. package/dist/position.d.ts +142 -0
  31. package/dist/position.js +354 -0
  32. package/dist/position.js.map +1 -0
  33. package/dist/preflight.d.ts +62 -0
  34. package/dist/preflight.js +165 -0
  35. package/dist/preflight.js.map +1 -0
  36. package/dist/quote.d.ts +55 -0
  37. package/dist/quote.js +83 -0
  38. package/dist/quote.js.map +1 -0
  39. package/dist/redact.d.ts +44 -0
  40. package/dist/redact.js +92 -0
  41. package/dist/redact.js.map +1 -0
  42. package/dist/registry-schema.d.ts +127 -0
  43. package/dist/registry-schema.js +124 -0
  44. package/dist/registry-schema.js.map +1 -0
  45. package/dist/registry.d.ts +26 -0
  46. package/dist/registry.js +62 -0
  47. package/dist/registry.js.map +1 -0
  48. package/dist/units.d.ts +8 -0
  49. package/dist/units.js +24 -0
  50. package/dist/units.js.map +1 -0
  51. package/dist/version.d.ts +1 -0
  52. package/dist/version.js +14 -0
  53. package/dist/version.js.map +1 -0
  54. package/package.json +58 -0
  55. package/registry/vaults.json +68 -0
@@ -0,0 +1,146 @@
1
+ /**
2
+ * The depositor-facing ERC-4626 + ERC-20 surface, and nothing else — no admin, allocator or
3
+ * operator entry points, because the client never calls any. This fragment is the whole interface
4
+ * a depositor needs on a standard 4626 chassis (Morpho Vault V2, IPOR Fusion).
5
+ * Enzyme is NOT 4626 (`buyShares` via the comptroller) and is not covered here.
6
+ */
7
+ export const erc4626Abi = [
8
+ // --- ERC-20 ---
9
+ { type: "function", name: "name", stateMutability: "view", inputs: [], outputs: [{ type: "string" }] },
10
+ { type: "function", name: "symbol", stateMutability: "view", inputs: [], outputs: [{ type: "string" }] },
11
+ { type: "function", name: "decimals", stateMutability: "view", inputs: [], outputs: [{ type: "uint8" }] },
12
+ { type: "function", name: "totalSupply", stateMutability: "view", inputs: [], outputs: [{ type: "uint256" }] },
13
+ {
14
+ type: "function",
15
+ name: "balanceOf",
16
+ stateMutability: "view",
17
+ inputs: [{ name: "account", type: "address" }],
18
+ outputs: [{ type: "uint256" }],
19
+ },
20
+ {
21
+ type: "function",
22
+ name: "allowance",
23
+ stateMutability: "view",
24
+ inputs: [
25
+ { name: "owner", type: "address" },
26
+ { name: "spender", type: "address" },
27
+ ],
28
+ outputs: [{ type: "uint256" }],
29
+ },
30
+ {
31
+ type: "function",
32
+ name: "approve",
33
+ stateMutability: "nonpayable",
34
+ inputs: [
35
+ { name: "spender", type: "address" },
36
+ // `value`, not `amount`: these names are now USER-VISIBLE as `UnsignedCall.args`, and an
37
+ // operator reads them next to a block explorer's own form, which is labelled from the
38
+ // verified contract's ABI. EIP-20 and OpenZeppelin's implementation both name this `value`.
39
+ // Encoding is unaffected — a parameter binds by position and type, never by name.
40
+ { name: "value", type: "uint256" },
41
+ ],
42
+ outputs: [{ type: "bool" }],
43
+ },
44
+ // --- ERC-4626 ---
45
+ { type: "function", name: "asset", stateMutability: "view", inputs: [], outputs: [{ type: "address" }] },
46
+ { type: "function", name: "totalAssets", stateMutability: "view", inputs: [], outputs: [{ type: "uint256" }] },
47
+ {
48
+ type: "function",
49
+ name: "convertToAssets",
50
+ stateMutability: "view",
51
+ inputs: [{ name: "shares", type: "uint256" }],
52
+ outputs: [{ type: "uint256" }],
53
+ },
54
+ {
55
+ type: "function",
56
+ name: "convertToShares",
57
+ stateMutability: "view",
58
+ inputs: [{ name: "assets", type: "uint256" }],
59
+ outputs: [{ type: "uint256" }],
60
+ },
61
+ {
62
+ type: "function",
63
+ name: "previewDeposit",
64
+ stateMutability: "view",
65
+ inputs: [{ name: "assets", type: "uint256" }],
66
+ outputs: [{ type: "uint256" }],
67
+ },
68
+ {
69
+ type: "function",
70
+ name: "previewRedeem",
71
+ stateMutability: "view",
72
+ inputs: [{ name: "shares", type: "uint256" }],
73
+ outputs: [{ type: "uint256" }],
74
+ },
75
+ {
76
+ type: "function",
77
+ name: "maxDeposit",
78
+ stateMutability: "view",
79
+ inputs: [{ name: "receiver", type: "address" }],
80
+ outputs: [{ type: "uint256" }],
81
+ },
82
+ {
83
+ type: "function",
84
+ name: "maxRedeem",
85
+ stateMutability: "view",
86
+ inputs: [{ name: "owner", type: "address" }],
87
+ outputs: [{ type: "uint256" }],
88
+ },
89
+ {
90
+ type: "function",
91
+ name: "deposit",
92
+ stateMutability: "nonpayable",
93
+ inputs: [
94
+ { name: "assets", type: "uint256" },
95
+ { name: "receiver", type: "address" },
96
+ ],
97
+ outputs: [{ name: "shares", type: "uint256" }],
98
+ },
99
+ {
100
+ type: "function",
101
+ name: "previewWithdraw",
102
+ stateMutability: "view",
103
+ inputs: [{ name: "assets", type: "uint256" }],
104
+ outputs: [{ type: "uint256" }],
105
+ },
106
+ {
107
+ type: "function",
108
+ name: "maxWithdraw",
109
+ stateMutability: "view",
110
+ inputs: [{ name: "owner", type: "address" }],
111
+ outputs: [{ type: "uint256" }],
112
+ },
113
+ {
114
+ type: "function",
115
+ name: "withdraw",
116
+ stateMutability: "nonpayable",
117
+ inputs: [
118
+ { name: "assets", type: "uint256" },
119
+ { name: "receiver", type: "address" },
120
+ { name: "owner", type: "address" },
121
+ ],
122
+ outputs: [{ name: "shares", type: "uint256" }],
123
+ },
124
+ {
125
+ type: "function",
126
+ name: "redeem",
127
+ stateMutability: "nonpayable",
128
+ inputs: [
129
+ { name: "shares", type: "uint256" },
130
+ { name: "receiver", type: "address" },
131
+ { name: "owner", type: "address" },
132
+ ],
133
+ outputs: [{ name: "assets", type: "uint256" }],
134
+ },
135
+ ];
136
+ /**
137
+ * Revert selectors a depositor pre-flight must be able to name. Each was observed
138
+ * live on Base (2026-09-11, blocks 51154060–51154242), not taken from documentation.
139
+ */
140
+ export const knownRevertSelectors = {
141
+ /** OpenZeppelin AccessManaged — IPOR Fusion PlasmaVault `deposit` restricted to a role (800 = WHITELIST). */
142
+ AccessManagedUnauthorized: "0x068ca9d8",
143
+ /** Morpho Vault V2 wrapper around the USDC pull failing on allowance — access is OPEN, the call reached the money. */
144
+ TransferFromReverted: "0xe65b7a77",
145
+ };
146
+ //# sourceMappingURL=erc4626.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"erc4626.js","sourceRoot":"","sources":["../../src/abi/erc4626.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ import { type Address, type Hex } from "viem";
2
+ import { type VaultEntry } from "./registry-schema.js";
3
+ /**
4
+ * An unsigned call. This is the only thing this package ever produces on the write side.
5
+ * Whoever holds the key decides whether to sign it — a wallet, an operator, a policy-engine
6
+ * signer, a token-bound account. The skill supplies intent; the consumer supplies verification.
7
+ */
8
+ export interface UnsignedCall {
9
+ chainId: number;
10
+ to: Address;
11
+ data: Hex;
12
+ /**
13
+ * The same call `data` encodes, in the form a block explorer's "Write Contract" tab asks for:
14
+ * a full signature with parameter names, e.g. `approve(address spender, uint256 value)`.
15
+ * See `encodeCall` for why this cannot drift from `data`.
16
+ */
17
+ function: string;
18
+ /**
19
+ * The arguments of `function`, by name, as strings — `{ spender: "0x…", value: "1000000" }`.
20
+ * Values are raw contract units (the same integers `data` carries), NOT human decimals, because
21
+ * that is what an explorer's form takes. `description` is the human-readable sentence.
22
+ */
23
+ args: Record<string, string>;
24
+ value: "0x0";
25
+ /** What a human should read before anyone signs this. */
26
+ description: string;
27
+ /** Which step this is in a multi-call intent (approve → deposit). */
28
+ step: number;
29
+ of: number;
30
+ /**
31
+ * How to set the gas limit. Measured on Morpho Vault V2: deposit/redeem gas depends on the time
32
+ * elapsed since the vault's last interest accrual, so an estimate taken now under-counts the
33
+ * storage writes the mined block will do — the tx dies out-of-gas while every simulation
34
+ * succeeds. Buffer the estimate; do not sign an unbuffered one.
35
+ */
36
+ gasAdvice: string;
37
+ /**
38
+ * A read the signer must see satisfied — THROUGH THE RPC IT WILL SEND THROUGH — before it
39
+ * estimates or sends this call. Present only where a step depends on an earlier step's state.
40
+ *
41
+ * Why this is a field and not a sentence: the provider answering `eth_estimateGas` can be
42
+ * a replica one block behind the one that served the previous step's receipt. Measured on both
43
+ * real Cash-Plus round trips (2026-09-13, blocks 51253xxx and 51266819→51266821): approve
44
+ * confirmed, deposit's estimate reverted "ERC20: transfer amount exceeds allowance", the
45
+ * allowance was on-chain. A signer that reads this precondition until it holds is
46
+ * deterministic; a signer that retries on a string match is guessing.
47
+ */
48
+ precondition?: Precondition;
49
+ }
50
+ /** `read(contract).call(args) >= minimum` (raw units) on the sending RPC before this call goes out. */
51
+ export interface Precondition {
52
+ read: "allowance";
53
+ contract: Address;
54
+ owner: Address;
55
+ spender: Address;
56
+ /** Raw token units, as a decimal string — compare as integers, never as floats. */
57
+ minimum: string;
58
+ why: string;
59
+ }
60
+ /**
61
+ * `approve(vault, assets)` on the asset token, then `deposit(assets, receiver)` on the vault.
62
+ * `account` is the depositor — the address that signs both calls and whose allowance step 2
63
+ * depends on; it is what the precondition names.
64
+ */
65
+ export declare function buildDeposit(vault: VaultEntry, args: {
66
+ assetsHuman: string;
67
+ receiver: Address;
68
+ account: Address;
69
+ }): UnsignedCall[];
70
+ /**
71
+ * USDC-denominated withdrawal — the caller never handles share amounts.
72
+ *
73
+ * - `{ assetsHuman }` → ERC-4626 `withdraw(assets, receiver, owner)`: the vault burns whatever
74
+ * shares that many assets cost at the time of inclusion.
75
+ * - `{ all: true, sharesExact }` → `redeem(shares, receiver, owner)` with the EXACT share balance
76
+ * the caller read from `earn_balance` (as a string, never through a float): the only way to
77
+ * empty an account without leaving dust or asking for more than is owned.
78
+ */
79
+ export declare function buildWithdraw(vault: VaultEntry, args: {
80
+ receiver: Address;
81
+ owner: Address;
82
+ } & ({
83
+ assetsHuman: string;
84
+ all?: false;
85
+ } | {
86
+ all: true;
87
+ sharesExact: string;
88
+ })): UnsignedCall[];
package/dist/build.js ADDED
@@ -0,0 +1,124 @@
1
+ import { encodeFunctionData, getAbiItem } from "viem";
2
+ import { erc4626Abi } from "./abi/erc4626.js";
3
+ import { erc4626Chassis } from "./registry-schema.js";
4
+ import { parseAmount, formatAmount } from "./units.js";
5
+ /**
6
+ * 🔴 ONE CALL SITE PRODUCES BOTH `data` AND ITS DECODING, FROM THE SAME ARGUMENT TUPLE.
7
+ *
8
+ * The obvious implementation of #11 is a second step that decodes the finished calldata back into
9
+ * names and values. That is two sources for one fact, and two sources drift: a decoder pointed at a
10
+ * stale ABI, or simply not re-run when an argument order changes, produces a signature and an
11
+ * argument list that disagree with the bytes an operator is about to sign — and the operator is
12
+ * using this field precisely BECAUSE they cannot read the bytes. Silent, and wrong in the one
13
+ * direction that matters.
14
+ *
15
+ * So there is no decode step. `data` is encoded from `args`, and the names are read off the same
16
+ * ABI entry `encodeFunctionData` resolves; the values ARE the tuple, stringified. The only way for
17
+ * the two to disagree is for viem to encode a different function than `getAbiItem` returns for the
18
+ * same name and ABI. (This is the same rule `linksFor` follows for a vault's links: derive from one
19
+ * row, never reconcile two sources that agree today.)
20
+ */
21
+ function encodeCall(abi, functionName, args) {
22
+ const item = getAbiItem({ abi, name: functionName, args });
23
+ if (item === undefined || item.type !== "function") {
24
+ throw new Error(`${functionName} is not a function on this ABI; this client cannot build a call for it`);
25
+ }
26
+ // A names/values length mismatch would silently drop or misalign an argument in the map an
27
+ // operator types into a form. `encodeFunctionData` rejects the same mismatch, but it must be
28
+ // impossible for THIS map to be built from one, whichever of the two runs first.
29
+ if (item.inputs.length !== args.length) {
30
+ throw new Error(`${functionName} takes ${item.inputs.length} argument(s), got ${args.length}`);
31
+ }
32
+ return {
33
+ data: encodeFunctionData({ abi, functionName, args }),
34
+ function: `${functionName}(${item.inputs.map((i, n) => `${i.type} ${i.name || `arg${n}`}`).join(", ")})`,
35
+ args: Object.fromEntries(item.inputs.map((i, n) => [i.name || `arg${n}`, String(args[n])])),
36
+ };
37
+ }
38
+ const GAS_ADVICE = "Set gas limit = eth_estimateGas × 1.5. Measured: an unbuffered estimate ran out of gas on a Morpho Vault V2 redeem (310,505 gas) while simulation and prior-block re-simulation both succeeded — accrual work grows with elapsed time between estimate and inclusion.";
39
+ function assert4626(vault) {
40
+ if (!erc4626Chassis.has(vault.chassis)) {
41
+ throw new Error(`${vault.symbol} is on ${vault.chassis}, which has no ERC-4626 deposit/redeem path; this client does not build calls for it`);
42
+ }
43
+ }
44
+ /**
45
+ * `approve(vault, assets)` on the asset token, then `deposit(assets, receiver)` on the vault.
46
+ * `account` is the depositor — the address that signs both calls and whose allowance step 2
47
+ * depends on; it is what the precondition names.
48
+ */
49
+ export function buildDeposit(vault, args) {
50
+ assert4626(vault);
51
+ const assets = parseAmount(args.assetsHuman, vault.asset.decimals, `deposit amount (${vault.asset.symbol})`);
52
+ const pretty = `${formatAmount(assets, vault.asset.decimals)} ${vault.asset.symbol}`;
53
+ return [
54
+ {
55
+ chainId: vault.chainId,
56
+ to: vault.asset.address,
57
+ ...encodeCall(erc4626Abi, "approve", [vault.address, assets]),
58
+ value: "0x0",
59
+ description: `Approve ${vault.symbol} vault (${vault.address}) to pull ${pretty}`,
60
+ step: 1,
61
+ of: 2,
62
+ gasAdvice: GAS_ADVICE,
63
+ },
64
+ {
65
+ chainId: vault.chainId,
66
+ to: vault.address,
67
+ ...encodeCall(erc4626Abi, "deposit", [assets, args.receiver]),
68
+ value: "0x0",
69
+ description: `Deposit ${pretty} into ${vault.name}; shares minted to ${args.receiver}`,
70
+ step: 2,
71
+ of: 2,
72
+ gasAdvice: GAS_ADVICE,
73
+ precondition: {
74
+ read: "allowance",
75
+ contract: vault.asset.address,
76
+ owner: args.account,
77
+ spender: vault.address,
78
+ minimum: assets.toString(),
79
+ why: "Do not estimate or send this until allowance(owner, spender) >= minimum reads back on the RPC you will send through. The receipt for step 1 can come from a node ahead of the one that simulates step 2 (measured twice on real funds).",
80
+ },
81
+ },
82
+ ];
83
+ }
84
+ /**
85
+ * USDC-denominated withdrawal — the caller never handles share amounts.
86
+ *
87
+ * - `{ assetsHuman }` → ERC-4626 `withdraw(assets, receiver, owner)`: the vault burns whatever
88
+ * shares that many assets cost at the time of inclusion.
89
+ * - `{ all: true, sharesExact }` → `redeem(shares, receiver, owner)` with the EXACT share balance
90
+ * the caller read from `earn_balance` (as a string, never through a float): the only way to
91
+ * empty an account without leaving dust or asking for more than is owned.
92
+ */
93
+ export function buildWithdraw(vault, args) {
94
+ assert4626(vault);
95
+ if (args.all) {
96
+ const shares = parseAmount(args.sharesExact, vault.shareDecimals, `share balance (${vault.symbol})`);
97
+ return [
98
+ {
99
+ chainId: vault.chainId,
100
+ to: vault.address,
101
+ ...encodeCall(erc4626Abi, "redeem", [shares, args.receiver, args.owner]),
102
+ value: "0x0",
103
+ description: `Withdraw EVERYTHING from ${vault.name}: redeem ${formatAmount(shares, vault.shareDecimals)} ${vault.symbol} (the exact balance) for ${vault.asset.symbol}, paid to ${args.receiver}`,
104
+ step: 1,
105
+ of: 1,
106
+ gasAdvice: GAS_ADVICE,
107
+ },
108
+ ];
109
+ }
110
+ const assets = parseAmount(args.assetsHuman, vault.asset.decimals, `withdraw amount (${vault.asset.symbol})`);
111
+ return [
112
+ {
113
+ chainId: vault.chainId,
114
+ to: vault.address,
115
+ ...encodeCall(erc4626Abi, "withdraw", [assets, args.receiver, args.owner]),
116
+ value: "0x0",
117
+ description: `Withdraw ${formatAmount(assets, vault.asset.decimals)} ${vault.asset.symbol} from ${vault.name}, paid to ${args.receiver}; the vault burns the shares that costs at inclusion`,
118
+ step: 1,
119
+ of: 1,
120
+ gasAdvice: GAS_ADVICE,
121
+ },
122
+ ];
123
+ }
124
+ //# sourceMappingURL=build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"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"}