@temporalabs/treasury 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE +4 -2
- package/README.md +100 -44
- package/THIRD_PARTY_NOTICES.connect-page.md +7836 -0
- package/THIRD_PARTY_NOTICES.md +543 -162
- package/dist/cli.d.ts +6 -0
- package/dist/cli.js +243 -0
- package/dist/cli.js.map +1 -0
- package/dist/client.d.ts +366 -239
- package/dist/client.js +202 -25
- package/dist/client.js.map +1 -1
- package/dist/config/earn.d.ts +48 -12
- package/dist/config/earn.js +48 -12
- package/dist/config/earn.js.map +1 -1
- package/dist/connect/ack.d.ts +76 -0
- package/dist/connect/ack.js +147 -0
- package/dist/connect/ack.js.map +1 -0
- package/dist/connect/commands.d.ts +81 -0
- package/dist/connect/commands.js +555 -0
- package/dist/connect/commands.js.map +1 -0
- package/dist/connect/config.d.ts +24 -0
- package/dist/connect/config.js +35 -0
- package/dist/connect/config.js.map +1 -0
- package/dist/connect/gate-solana.d.ts +8 -0
- package/dist/connect/gate-solana.js +147 -0
- package/dist/connect/gate-solana.js.map +1 -0
- package/dist/connect/gate.d.ts +37 -0
- package/dist/connect/gate.js +115 -0
- package/dist/connect/gate.js.map +1 -0
- package/dist/connect/http.d.ts +60 -0
- package/dist/connect/http.js +235 -0
- package/dist/connect/http.js.map +1 -0
- package/dist/connect/open.d.ts +2 -0
- package/dist/connect/open.js +35 -0
- package/dist/connect/open.js.map +1 -0
- package/dist/connect/page.d.ts +5 -0
- package/dist/connect/page.js +69 -0
- package/dist/connect/page.js.map +1 -0
- package/dist/connect/session.d.ts +39 -0
- package/dist/connect/session.js +198 -0
- package/dist/connect/session.js.map +1 -0
- package/dist/connect/solana.d.ts +73 -0
- package/dist/connect/solana.js +267 -0
- package/dist/connect/solana.js.map +1 -0
- package/dist/connect/verify.d.ts +37 -0
- package/dist/connect/verify.js +89 -0
- package/dist/connect/verify.js.map +1 -0
- package/dist/connect-page.js +5143 -0
- package/dist/disclosures.d.ts +22 -6
- package/dist/disclosures.js +34 -8
- package/dist/disclosures.js.map +1 -1
- package/dist/earn/commands.d.ts +46 -0
- package/dist/earn/commands.js +556 -0
- package/dist/earn/commands.js.map +1 -0
- package/dist/earn/solana.d.ts +278 -0
- package/dist/earn/solana.js +302 -0
- package/dist/earn/solana.js.map +1 -0
- package/dist/guide.d.ts +15 -0
- package/dist/guide.js +50 -0
- package/dist/guide.js.map +1 -0
- package/dist/links.d.ts +2 -0
- package/dist/links.js +40 -14
- package/dist/links.js.map +1 -1
- package/dist/position.d.ts +9 -6
- package/dist/position.js +39 -19
- package/dist/position.js.map +1 -1
- package/dist/preflight.d.ts +9 -0
- package/dist/preflight.js +14 -3
- package/dist/preflight.js.map +1 -1
- package/dist/quote.js +24 -7
- package/dist/quote.js.map +1 -1
- package/dist/redact.d.ts +3 -3
- package/dist/redact.js +3 -3
- package/dist/redact.js.map +1 -1
- package/dist/registry-schema.d.ts +82 -5
- package/dist/registry-schema.js +105 -15
- package/dist/registry-schema.js.map +1 -1
- package/dist/registry.d.ts +50 -7
- package/dist/registry.js +122 -21
- package/dist/registry.js.map +1 -1
- package/dist/solana/constants.d.ts +49 -0
- package/dist/solana/constants.js +50 -0
- package/dist/solana/constants.js.map +1 -0
- package/dist/solana/kvault.d.ts +99 -0
- package/dist/solana/kvault.js +192 -0
- package/dist/solana/kvault.js.map +1 -0
- package/dist/solana/layout.d.ts +143 -0
- package/dist/solana/layout.js +209 -0
- package/dist/solana/layout.js.map +1 -0
- package/dist/solana/rpc.d.ts +24 -0
- package/dist/solana/rpc.js +66 -0
- package/dist/solana/rpc.js.map +1 -0
- package/dist/solana/vault.d.ts +153 -0
- package/dist/solana/vault.js +324 -0
- package/dist/solana/vault.js.map +1 -0
- package/dist/{mcp-server.mjs → treasury.mjs} +41101 -49486
- package/dist/version.js +5 -10
- package/dist/version.js.map +1 -1
- package/llms.txt +621 -0
- package/package.json +12 -9
- package/registry/vaults.json +218 -4
- package/dist/mcp/server.d.ts +0 -8
- package/dist/mcp/server.js +0 -368
- package/dist/mcp/server.js.map +0 -1
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settings for `treasury connect`. Every value has a working default; each environment variable
|
|
3
|
+
* here is optional and documented in docs/configuration.md.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* The Privy app the sign-in page uses. A Privy app ID is a PUBLIC identifier — it ships inside the
|
|
7
|
+
* page every browser downloads — so it is committed here. A fork or self-host can point at its own
|
|
8
|
+
* Privy app with `PRIVY_APP_ID`. The app SECRET is never used anywhere in this package.
|
|
9
|
+
*/
|
|
10
|
+
export const DEFAULT_PRIVY_APP_ID = "cmubfegl2028d0ci3n0f2u6z5";
|
|
11
|
+
/**
|
|
12
|
+
* The local ports the page may be served on, tried in this order. Privy accepts sign-in only from
|
|
13
|
+
* origins listed in its dashboard, by exact string, so every one of them is listed there as
|
|
14
|
+
* `http://localhost:<port>`. The first stays 53682, the only port earlier versions used, so an
|
|
15
|
+
* operator who signed in before keeps the same origin. `TREASURY_CONNECT_PORT` replaces the list with
|
|
16
|
+
* one port, which must then be listed in the Privy app's allowed domains.
|
|
17
|
+
*/
|
|
18
|
+
export const DEFAULT_CONNECT_PORTS = [53682, 53683, 53684, 53685, 53686];
|
|
19
|
+
export const privyAppId = () => {
|
|
20
|
+
const v = (process.env["PRIVY_APP_ID"] ?? "").trim();
|
|
21
|
+
return v.length > 0 && !v.includes("${") ? v : DEFAULT_PRIVY_APP_ID;
|
|
22
|
+
};
|
|
23
|
+
export const connectPorts = () => {
|
|
24
|
+
const raw = (process.env["TREASURY_CONNECT_PORT"] ?? "").trim();
|
|
25
|
+
const n = Number(raw);
|
|
26
|
+
return raw.length > 0 && Number.isInteger(n) && n > 0 && n < 65536 ? [n] : DEFAULT_CONNECT_PORTS;
|
|
27
|
+
};
|
|
28
|
+
/** Where the session file lives; `TREASURY_CONNECT_HOME` moves it (tests use a temporary directory). */
|
|
29
|
+
export const connectHome = () => {
|
|
30
|
+
const v = (process.env["TREASURY_CONNECT_HOME"] ?? "").trim();
|
|
31
|
+
return v.length > 0 && !v.includes("${") ? v : undefined;
|
|
32
|
+
};
|
|
33
|
+
/** Set to anything to stop the CLI opening a browser itself (it prints the URL instead). */
|
|
34
|
+
export const noOpen = () => (process.env["TREASURY_CONNECT_NO_OPEN"] ?? "").trim().length > 0;
|
|
35
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/connect/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,2BAA2B,CAAC;AAEhE;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAsB,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AAE5F,MAAM,CAAC,MAAM,UAAU,GAAG,GAAW,EAAE;IACrC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACrD,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC;AACtE,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,GAAsB,EAAE;IAClD,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAChE,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACtB,OAAO,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,qBAAqB,CAAC;AACnG,CAAC,CAAC;AAEF,wGAAwG;AACxG,MAAM,CAAC,MAAM,WAAW,GAAG,GAAuB,EAAE;IAClD,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9D,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC3D,CAAC,CAAC;AAEF,4FAA4F;AAC5F,MAAM,CAAC,MAAM,MAAM,GAAG,GAAY,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { SolanaVaultEntry } from "../registry-schema.js";
|
|
2
|
+
export interface AdmittedSolana {
|
|
3
|
+
kind: "deposit" | "withdraw";
|
|
4
|
+
vault: SolanaVaultEntry;
|
|
5
|
+
/** A deposit's base units of the asset, or the shares a withdrawal burns (summed over its legs). */
|
|
6
|
+
amount: bigint;
|
|
7
|
+
}
|
|
8
|
+
export declare function admitSolana(wireBase64: string, account: string): Promise<AdmittedSolana>;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Solana gate: what the confirm page may hand a connected Solana wallet. The counterpart of `gate.ts`.
|
|
3
|
+
*
|
|
4
|
+
* It reads the transaction's own BYTES — the wire transaction the wallet will be given — and admits it only if
|
|
5
|
+
* every instruction in it is one of these, each for the connected account and a registry vault:
|
|
6
|
+
*
|
|
7
|
+
* ComputeBudget SetComputeUnitLimit nothing else from that program (no fee price, no heap)
|
|
8
|
+
* Associated Token Account CreateIdempotent payer and owner the connected account; mint the vault's
|
|
9
|
+
* share mint or its token mint
|
|
10
|
+
* Kamino vault `deposit` exactly one, signer the connected account, vault a registry vault,
|
|
11
|
+
* paying from and into the account's own token accounts
|
|
12
|
+
* Kamino vault `withdraw` one or more, the same checks
|
|
13
|
+
*
|
|
14
|
+
* Within a deposit or withdrawal, every account the registry determines is pinned: the vault state (both
|
|
15
|
+
* places a withdrawal names it), the vault's token vault and authority (PDAs of the vault), its token and
|
|
16
|
+
* share mints, and the connected account's own token and share accounts. The reserve, market and program
|
|
17
|
+
* accounts a withdrawal lists are NOT pinned here: they are left to the vault program's own account
|
|
18
|
+
* constraints, which refuse a reserve the vault does not allocate to.
|
|
19
|
+
*
|
|
20
|
+
* The fee payer and the only signer must be the connected account. Anything else — another program, a
|
|
21
|
+
* transfer, a second signer, a deposit and a withdrawal together, a vault not in the registry — is refused
|
|
22
|
+
* before any page opens. It checks the bytes, not the builder that made them: a builder bug, or a transaction
|
|
23
|
+
* from anywhere else, meets the same refusal.
|
|
24
|
+
*/
|
|
25
|
+
import { AccountRole, decompileTransactionMessage, getBase64Encoder, getCompiledTransactionMessageDecoder, getTransactionDecoder, } from "@solana/kit";
|
|
26
|
+
import { listSolanaVaults } from "../registry.js";
|
|
27
|
+
import { ASSOCIATED_TOKEN_PROGRAM_ID, COMPUTE_BUDGET_PROGRAM_ID, KVAULT_PROGRAM_ID, SPL_TOKEN_PROGRAM_ID, SYSTEM_PROGRAM_ID } from "../solana/constants.js";
|
|
28
|
+
import { associatedTokenAccount, DISCRIMINATORS, vaultPdas } from "../solana/kvault.js";
|
|
29
|
+
const same = (a, b) => a.length <= b.length && a.every((x, i) => b[i] === x);
|
|
30
|
+
const u64 = (d, o) => new DataView(d.buffer, d.byteOffset, d.byteLength).getBigUint64(o, true);
|
|
31
|
+
const isSigner = (role) => role === AccountRole.READONLY_SIGNER || role === AccountRole.WRITABLE_SIGNER;
|
|
32
|
+
export async function admitSolana(wireBase64, account) {
|
|
33
|
+
const refuse = (why) => {
|
|
34
|
+
throw new Error(`refused: ${why}`);
|
|
35
|
+
};
|
|
36
|
+
let ixs;
|
|
37
|
+
let feePayer;
|
|
38
|
+
let signers;
|
|
39
|
+
try {
|
|
40
|
+
const tx = getTransactionDecoder().decode(getBase64Encoder().encode(wireBase64));
|
|
41
|
+
const compiled = getCompiledTransactionMessageDecoder().decode(tx.messageBytes);
|
|
42
|
+
signers = compiled.header.numSignerAccounts;
|
|
43
|
+
if ("addressTableLookups" in compiled && (compiled.addressTableLookups?.length ?? 0) > 0)
|
|
44
|
+
refuse("the transaction loads accounts from a lookup table, which this gate cannot read");
|
|
45
|
+
const message = decompileTransactionMessage(compiled);
|
|
46
|
+
feePayer = message.feePayer.address;
|
|
47
|
+
ixs = message.instructions;
|
|
48
|
+
}
|
|
49
|
+
catch (e) {
|
|
50
|
+
if (e instanceof Error && e.message.startsWith("refused:"))
|
|
51
|
+
throw e;
|
|
52
|
+
return refuse(`the transaction does not decode (${e instanceof Error ? e.message : String(e)})`);
|
|
53
|
+
}
|
|
54
|
+
if (feePayer !== account)
|
|
55
|
+
refuse(`the fee payer is ${feePayer}, not the connected account ${account}`);
|
|
56
|
+
if (signers !== 1)
|
|
57
|
+
refuse(`the transaction needs ${signers} signers; only the connected account may sign`);
|
|
58
|
+
let kind;
|
|
59
|
+
let vault;
|
|
60
|
+
let amount = 0n;
|
|
61
|
+
const ataMints = new Set();
|
|
62
|
+
for (const [i, ix] of ixs.entries()) {
|
|
63
|
+
const at = `instruction ${i + 1}`;
|
|
64
|
+
const data = Uint8Array.from(ix.data ?? []);
|
|
65
|
+
const accts = ix.accounts ?? [];
|
|
66
|
+
for (const a of accts)
|
|
67
|
+
if (isSigner(a.role) && a.address !== account)
|
|
68
|
+
refuse(`${at} asks ${a.address} to sign, not the connected account`);
|
|
69
|
+
switch (ix.programAddress) {
|
|
70
|
+
case COMPUTE_BUDGET_PROGRAM_ID:
|
|
71
|
+
if (data.length !== 5 || data[0] !== 2)
|
|
72
|
+
refuse(`${at}: only a compute-unit limit is allowed from the Compute Budget program`);
|
|
73
|
+
break;
|
|
74
|
+
case ASSOCIATED_TOKEN_PROGRAM_ID: {
|
|
75
|
+
if (data.length !== 1 || data[0] !== 1)
|
|
76
|
+
refuse(`${at}: only an idempotent token-account creation is allowed`);
|
|
77
|
+
const [payer, ata, owner, mint, system, token] = accts.map((a) => a.address);
|
|
78
|
+
if (payer !== account || owner !== account)
|
|
79
|
+
refuse(`${at} creates a token account for ${owner}, paid by ${payer}; only the connected account's own`);
|
|
80
|
+
if (system !== SYSTEM_PROGRAM_ID || token !== SPL_TOKEN_PROGRAM_ID)
|
|
81
|
+
refuse(`${at} names an unexpected program`);
|
|
82
|
+
if (ata !== (await associatedTokenAccount(account, mint)))
|
|
83
|
+
refuse(`${at} names a token account that is not the connected account's for ${mint}`);
|
|
84
|
+
ataMints.add(mint);
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
case KVAULT_PROGRAM_ID: {
|
|
88
|
+
const isDeposit = same(DISCRIMINATORS.deposit, data);
|
|
89
|
+
const isWithdraw = same(DISCRIMINATORS.withdraw, data);
|
|
90
|
+
if (!isDeposit && !isWithdraw)
|
|
91
|
+
refuse(`${at} is a Kamino vault instruction other than deposit or withdraw`);
|
|
92
|
+
if (data.length !== 16)
|
|
93
|
+
refuse(`${at} carries ${data.length} bytes of data, not 16`);
|
|
94
|
+
const k = isDeposit ? "deposit" : "withdraw";
|
|
95
|
+
if (kind !== undefined && kind !== k)
|
|
96
|
+
refuse("a deposit and a withdrawal in one transaction");
|
|
97
|
+
if (k === "deposit" && kind === "deposit")
|
|
98
|
+
refuse("two deposits in one transaction");
|
|
99
|
+
kind = k;
|
|
100
|
+
const user = accts[0]?.address;
|
|
101
|
+
const state = accts[1]?.address;
|
|
102
|
+
if (user !== account)
|
|
103
|
+
refuse(`${at} acts for ${user}, not the connected account ${account}`);
|
|
104
|
+
const v = listSolanaVaults().find((x) => x.address === state);
|
|
105
|
+
if (!v)
|
|
106
|
+
refuse(`${at} names ${state}, which is not a vault in the registry`);
|
|
107
|
+
if (vault && vault.address !== v.address)
|
|
108
|
+
refuse("two different vaults in one transaction");
|
|
109
|
+
vault = v;
|
|
110
|
+
const [tokenAta, sharesAta, pdas] = await Promise.all([associatedTokenAccount(account, v.asset.address), associatedTokenAccount(account, v.sharesMint), vaultPdas(v.address)]);
|
|
111
|
+
// The vault's own token vault and authority are PDAs of the vault: pinned, not left to the program.
|
|
112
|
+
const tokenVault = accts[isDeposit ? 2 : 3]?.address;
|
|
113
|
+
const authority = accts[4]?.address;
|
|
114
|
+
if (tokenVault !== pdas.tokenVault || authority !== pdas.baseVaultAuthority)
|
|
115
|
+
refuse(`${at} names a token vault or vault authority that is not ${v.symbol}'s`);
|
|
116
|
+
// A withdrawal names the vault state twice (its reserve-accounts group repeats it): both must be the vault.
|
|
117
|
+
if (isWithdraw && accts[14]?.address !== state)
|
|
118
|
+
refuse(`${at} names a second vault state ${accts[14]?.address}, not ${state}`);
|
|
119
|
+
// The fixed account positions, as `src/solana/kvault.ts` builds them and Kamino's SDK does.
|
|
120
|
+
const userToken = accts[isDeposit ? 6 : 5]?.address;
|
|
121
|
+
const userShares = accts[7]?.address; // both instructions put the user's share account at index 7
|
|
122
|
+
const mint = accts[isDeposit ? 3 : 6]?.address;
|
|
123
|
+
const sharesMint = accts[isDeposit ? 5 : 8]?.address;
|
|
124
|
+
if (mint !== v.asset.address || sharesMint !== v.sharesMint)
|
|
125
|
+
refuse(`${at} names a token or share mint that is not the vault's`);
|
|
126
|
+
if (userToken !== tokenAta)
|
|
127
|
+
refuse(`${at} ${isDeposit ? "takes from" : "pays into"} ${userToken}, not the connected account's own ${v.asset.symbol} account`);
|
|
128
|
+
if (userShares !== sharesAta)
|
|
129
|
+
refuse(`${at} names ${userShares} as the share account, not the connected account's own`);
|
|
130
|
+
const n = u64(data, 8);
|
|
131
|
+
if (n === 0n)
|
|
132
|
+
refuse(`${at} moves 0`);
|
|
133
|
+
amount += n;
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
default:
|
|
137
|
+
refuse(`${at} calls ${ix.programAddress}, which is not one this page may send`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (!kind || !vault)
|
|
141
|
+
return refuse("the transaction contains no deposit or withdrawal");
|
|
142
|
+
for (const m of ataMints)
|
|
143
|
+
if (m !== vault.sharesMint && m !== vault.asset.address)
|
|
144
|
+
refuse(`a token account is created for ${m}, which is not this vault's`);
|
|
145
|
+
return { kind, vault, amount };
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=gate-solana.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gate-solana.js","sourceRoot":"","sources":["../../src/connect/gate-solana.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The hard gate every call passes before a page opens: what `treasury connect` will put in front of
|
|
3
|
+
* the operator's wallet at all. It re-derives everything from the calldata and the registry and
|
|
4
|
+
* trusts nothing the call's own fields say about themselves (`description`, `args`, `function`).
|
|
5
|
+
*
|
|
6
|
+
* Allowed, and nothing else:
|
|
7
|
+
* - `approve(vault, n)` on a registry vault's own asset, for exactly the amount the deposit after
|
|
8
|
+
* it pulls — never unlimited, never to anything but that vault;
|
|
9
|
+
* - `deposit(assets, receiver)` on a registry vault, receiver = the connected account;
|
|
10
|
+
* - `withdraw(assets, receiver, owner)` / `redeem(shares, receiver, owner)` on a registry vault,
|
|
11
|
+
* receiver = owner = the connected account.
|
|
12
|
+
* Every call carries no value and names a supported chain that matches its vault.
|
|
13
|
+
*
|
|
14
|
+
* And one batch is one operation on one vault, on one chain, in one of the shapes the builders
|
|
15
|
+
* emit: `[approve, deposit]`, `[withdraw]` or `[redeem]`. Calldata must be exactly the canonical
|
|
16
|
+
* encoding of what it decodes to: no trailing bytes, no stray bits in an address word.
|
|
17
|
+
*
|
|
18
|
+
* This is the rule of AGENTS.md / CONTRIBUTING.md that the relay refuses any destination outside
|
|
19
|
+
* the registry, made executable. Paying an address other than the
|
|
20
|
+
* connected account is refused here on purpose: that is what the prepare commands are for, with the
|
|
21
|
+
* operator's own signer.
|
|
22
|
+
*/
|
|
23
|
+
import { type Address, type Hex } from "viem";
|
|
24
|
+
import type { VaultEntry } from "../registry-schema.js";
|
|
25
|
+
export interface GateCall {
|
|
26
|
+
chainId: number;
|
|
27
|
+
to: Address;
|
|
28
|
+
data: Hex;
|
|
29
|
+
value: string;
|
|
30
|
+
}
|
|
31
|
+
export interface Admitted {
|
|
32
|
+
kind: "approve" | "deposit" | "withdraw" | "redeem";
|
|
33
|
+
vault: VaultEntry;
|
|
34
|
+
/** Raw units: the approved/deposited/withdrawn assets, or the redeemed shares. */
|
|
35
|
+
amount: bigint;
|
|
36
|
+
}
|
|
37
|
+
export declare function admit(calls: GateCall[], account: Address): Admitted[];
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The hard gate every call passes before a page opens: what `treasury connect` will put in front of
|
|
3
|
+
* the operator's wallet at all. It re-derives everything from the calldata and the registry and
|
|
4
|
+
* trusts nothing the call's own fields say about themselves (`description`, `args`, `function`).
|
|
5
|
+
*
|
|
6
|
+
* Allowed, and nothing else:
|
|
7
|
+
* - `approve(vault, n)` on a registry vault's own asset, for exactly the amount the deposit after
|
|
8
|
+
* it pulls — never unlimited, never to anything but that vault;
|
|
9
|
+
* - `deposit(assets, receiver)` on a registry vault, receiver = the connected account;
|
|
10
|
+
* - `withdraw(assets, receiver, owner)` / `redeem(shares, receiver, owner)` on a registry vault,
|
|
11
|
+
* receiver = owner = the connected account.
|
|
12
|
+
* Every call carries no value and names a supported chain that matches its vault.
|
|
13
|
+
*
|
|
14
|
+
* And one batch is one operation on one vault, on one chain, in one of the shapes the builders
|
|
15
|
+
* emit: `[approve, deposit]`, `[withdraw]` or `[redeem]`. Calldata must be exactly the canonical
|
|
16
|
+
* encoding of what it decodes to: no trailing bytes, no stray bits in an address word.
|
|
17
|
+
*
|
|
18
|
+
* This is the rule of AGENTS.md / CONTRIBUTING.md that the relay refuses any destination outside
|
|
19
|
+
* the registry, made executable. Paying an address other than the
|
|
20
|
+
* connected account is refused here on purpose: that is what the prepare commands are for, with the
|
|
21
|
+
* operator's own signer.
|
|
22
|
+
*/
|
|
23
|
+
import { decodeFunctionData, encodeFunctionData, getAddress } from "viem";
|
|
24
|
+
import { erc4626Abi } from "../abi/erc4626.js";
|
|
25
|
+
import { isSupportedChainId } from "../client.js";
|
|
26
|
+
import { listVaults } from "../registry.js";
|
|
27
|
+
/** Anything at or above this is an "unlimited" approval, which the gate never admits. */
|
|
28
|
+
const UNLIMITED = 2n ** 128n;
|
|
29
|
+
const same = (a, b) => getAddress(a) === getAddress(b);
|
|
30
|
+
/** The only batches the builders emit; anything else is refused whole. */
|
|
31
|
+
const SHAPES = new Set(["approve,deposit", "withdraw", "redeem"]);
|
|
32
|
+
export function admit(calls, account) {
|
|
33
|
+
if (calls.length === 0)
|
|
34
|
+
throw new Error("refused: there is nothing to confirm");
|
|
35
|
+
// The page switches the wallet to one chain for the whole batch, so a batch never spans two.
|
|
36
|
+
if (calls.some((c) => c.chainId !== calls[0].chainId))
|
|
37
|
+
throw new Error("refused: the calls are on more than one chain");
|
|
38
|
+
const vaults = listVaults();
|
|
39
|
+
const out = [];
|
|
40
|
+
calls.forEach((c, i) => {
|
|
41
|
+
const at = `call ${i + 1} of ${calls.length}`;
|
|
42
|
+
if (!isSupportedChainId(c.chainId))
|
|
43
|
+
throw new Error(`refused (${at}): chain ${c.chainId} is not supported`);
|
|
44
|
+
if (BigInt(c.value) !== 0n)
|
|
45
|
+
throw new Error(`refused (${at}): it attaches native value, which no vault call needs`);
|
|
46
|
+
let decoded;
|
|
47
|
+
try {
|
|
48
|
+
decoded = decodeFunctionData({ abi: erc4626Abi, data: c.data });
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
throw new Error(`refused (${at}): its calldata is not an approve, deposit, withdraw or redeem`);
|
|
52
|
+
}
|
|
53
|
+
const name = decoded.functionName;
|
|
54
|
+
const args = (decoded.args ?? []);
|
|
55
|
+
// Decoding forgives trailing bytes and keeps only the low 20 bytes of an address word; the
|
|
56
|
+
// wallet would sign the bytes as sent. Admit only calldata that is its own canonical encoding.
|
|
57
|
+
const canonical = encodeFunctionData({ abi: erc4626Abi, functionName: name, args });
|
|
58
|
+
if (canonical !== c.data)
|
|
59
|
+
throw new Error(`refused (${at}): its calldata is not the canonical encoding of ${name} (trailing bytes, stray bits in an address, or hex not in lowercase)`);
|
|
60
|
+
if (name === "approve") {
|
|
61
|
+
const vault = vaults.find((v) => v.chainId === c.chainId && same(v.asset.address, c.to));
|
|
62
|
+
if (!vault)
|
|
63
|
+
throw new Error(`refused (${at}): approve on ${c.to}, which is not the asset of a listed vault on chain ${c.chainId}`);
|
|
64
|
+
const [spender, value] = args;
|
|
65
|
+
const target = vaults.find((v) => v.chainId === c.chainId && same(v.address, spender) && same(v.asset.address, c.to));
|
|
66
|
+
if (!target)
|
|
67
|
+
throw new Error(`refused (${at}): the approval goes to ${spender}, not to a listed vault for this asset`);
|
|
68
|
+
if (value === 0n)
|
|
69
|
+
throw new Error(`refused (${at}): an approval of 0`);
|
|
70
|
+
if (value >= UNLIMITED)
|
|
71
|
+
throw new Error(`refused (${at}): an unlimited approval`);
|
|
72
|
+
out.push({ kind: "approve", vault: target, amount: value });
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const vault = vaults.find((v) => v.chainId === c.chainId && same(v.address, c.to));
|
|
76
|
+
if (!vault)
|
|
77
|
+
throw new Error(`refused (${at}): ${c.to} is not a listed vault on chain ${c.chainId}`);
|
|
78
|
+
if (name === "deposit") {
|
|
79
|
+
const [assets, receiver] = args;
|
|
80
|
+
if (assets === 0n)
|
|
81
|
+
throw new Error(`refused (${at}): a deposit of 0`);
|
|
82
|
+
if (!same(receiver, account))
|
|
83
|
+
throw new Error(`refused (${at}): the shares would go to ${receiver}, not the connected account ${account}`);
|
|
84
|
+
out.push({ kind: "deposit", vault, amount: assets });
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (name === "withdraw" || name === "redeem") {
|
|
88
|
+
const [amount, receiver, owner] = args;
|
|
89
|
+
if (amount === 0n)
|
|
90
|
+
throw new Error(`refused (${at}): a ${name} of 0`);
|
|
91
|
+
if (!same(receiver, account))
|
|
92
|
+
throw new Error(`refused (${at}): the funds would go to ${receiver}, not the connected account ${account}`);
|
|
93
|
+
if (!same(owner, account))
|
|
94
|
+
throw new Error(`refused (${at}): it burns the shares of ${owner}, not the connected account ${account}`);
|
|
95
|
+
out.push({ kind: name, vault, amount });
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
throw new Error(`refused (${at}): ${name} is not something this page hands to a wallet`);
|
|
99
|
+
});
|
|
100
|
+
// An approval only ever precedes the deposit it pays for: same vault, same amount, next call.
|
|
101
|
+
out.forEach((a, i) => {
|
|
102
|
+
if (a.kind !== "approve")
|
|
103
|
+
return;
|
|
104
|
+
const next = out[i + 1];
|
|
105
|
+
if (!next || next.kind !== "deposit" || next.vault.address !== a.vault.address || next.amount !== a.amount) {
|
|
106
|
+
throw new Error(`refused (call ${i + 1}): an approval must be followed by a deposit of exactly that amount into the same vault`);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
const shape = out.map((a) => a.kind).join(",");
|
|
110
|
+
// With the pairing above, these shapes also mean one vault per batch.
|
|
111
|
+
if (!SHAPES.has(shape))
|
|
112
|
+
throw new Error(`refused: ${shape} is not a batch this page confirms (only approve+deposit, withdraw, or redeem)`);
|
|
113
|
+
return out;
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=gate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gate.js","sourceRoot":"","sources":["../../src/connect/gate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export type Accepted<T> = {
|
|
2
|
+
ok: true;
|
|
3
|
+
final: true;
|
|
4
|
+
value: T;
|
|
5
|
+
reply?: Record<string, unknown>;
|
|
6
|
+
} | {
|
|
7
|
+
ok: true;
|
|
8
|
+
final: false;
|
|
9
|
+
reply?: Record<string, unknown>;
|
|
10
|
+
} | {
|
|
11
|
+
ok: false;
|
|
12
|
+
reason: string;
|
|
13
|
+
fatal?: boolean;
|
|
14
|
+
};
|
|
15
|
+
export type Settled<T> = {
|
|
16
|
+
ok: true;
|
|
17
|
+
value: T;
|
|
18
|
+
} | {
|
|
19
|
+
ok: false;
|
|
20
|
+
reason: string;
|
|
21
|
+
};
|
|
22
|
+
export interface Flow<T> {
|
|
23
|
+
mode: "connect" | "confirm";
|
|
24
|
+
ttlMs: number;
|
|
25
|
+
/** The page served at `/<mode>`, as a function of the flow's secret. */
|
|
26
|
+
html: (secret: string) => string;
|
|
27
|
+
csp: string;
|
|
28
|
+
/** Static assets served at their path. */
|
|
29
|
+
assets: Record<string, {
|
|
30
|
+
type: string;
|
|
31
|
+
body: string | Buffer;
|
|
32
|
+
}>;
|
|
33
|
+
info: () => Record<string, unknown>;
|
|
34
|
+
challenge?: (address: string, origin: string, nonce: string) => string;
|
|
35
|
+
/**
|
|
36
|
+
* Reads the address a sign-in challenge is for, or `undefined` for one that is not an address. An EVM
|
|
37
|
+
* address (checksummed) unless the flow says otherwise; the Solana sign-in takes a base58 one.
|
|
38
|
+
*/
|
|
39
|
+
challengeAddress?: (a: unknown) => string | undefined;
|
|
40
|
+
accept: (body: Record<string, unknown>, ctx: {
|
|
41
|
+
nonce: string;
|
|
42
|
+
origin: string;
|
|
43
|
+
message?: string;
|
|
44
|
+
challengedAddress?: string;
|
|
45
|
+
}) => Promise<Accepted<T>>;
|
|
46
|
+
/** Called with the page's body when it reports a rejection, before the flow ends. */
|
|
47
|
+
onReject?: (body: Record<string, unknown>) => void;
|
|
48
|
+
/** Why the flow ended when the time limit ran out; the default says nothing happened. */
|
|
49
|
+
timeoutReason?: () => string;
|
|
50
|
+
/** Overrides the cancel grace period (tests). */
|
|
51
|
+
cancelGraceMs?: number;
|
|
52
|
+
/** Tried in order; the page takes the first one free. Each must be an origin the Privy app allows. */
|
|
53
|
+
ports: readonly number[];
|
|
54
|
+
}
|
|
55
|
+
export interface Handle<T> {
|
|
56
|
+
url: string;
|
|
57
|
+
done: Promise<Settled<T>>;
|
|
58
|
+
close: () => void;
|
|
59
|
+
}
|
|
60
|
+
export declare function serveOnce<T>(flow: Flow<T>): Promise<Handle<T>>;
|