@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,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A one-shot localhost server: it exists for one sign-in or one confirmation, answers only requests
|
|
3
|
+
* that carry its random secret, its own Host and (for POSTs) its own Origin, and closes itself once
|
|
4
|
+
* the flow settles or times out.
|
|
5
|
+
*
|
|
6
|
+
* The page talks back by POSTing to `/challenge` (sign-in only) and `/result`. A `/result` handler
|
|
7
|
+
* may answer "not yet" (`final: false`) to keep the flow open — the confirm flow uses that to take
|
|
8
|
+
* one transaction at a time — and anything it refuses with `fatal` ends the flow at once.
|
|
9
|
+
*/
|
|
10
|
+
import http from "node:http";
|
|
11
|
+
import { randomBytes, timingSafeEqual } from "node:crypto";
|
|
12
|
+
import { getAddress, isAddress } from "viem";
|
|
13
|
+
import { claimPageLock } from "./session.js";
|
|
14
|
+
const MAX_BODY_BYTES = 16 * 1024;
|
|
15
|
+
/** How long past the page's own time limit the lock stays valid, covering the cancel grace and the close. */
|
|
16
|
+
const LOCK_MARGIN_MS = 60_000;
|
|
17
|
+
/** How long a cancel waits for a result already being checked, so it can carry that verdict. */
|
|
18
|
+
const CANCEL_GRACE_MS = 30_000;
|
|
19
|
+
const same = (a, b) => {
|
|
20
|
+
const x = Buffer.from(a);
|
|
21
|
+
const y = Buffer.from(b);
|
|
22
|
+
return x.length === y.length && timingSafeEqual(x, y);
|
|
23
|
+
};
|
|
24
|
+
export async function serveOnce(flow) {
|
|
25
|
+
const secret = randomBytes(24).toString("hex");
|
|
26
|
+
// Privy matches allowed origins by exact string, and `localhost` is the host it documents. Set to
|
|
27
|
+
// the port being tried; a request can only arrive on the port that was bound.
|
|
28
|
+
let origin = "";
|
|
29
|
+
let settled = false;
|
|
30
|
+
let busy = false;
|
|
31
|
+
/** A cancel or timeout that arrived while a result was being checked; applied once the check ends. */
|
|
32
|
+
let deferred;
|
|
33
|
+
const expiresAt = Date.now() + flow.ttlMs;
|
|
34
|
+
let resolveDone;
|
|
35
|
+
const done = new Promise((r) => (resolveDone = r));
|
|
36
|
+
let issued;
|
|
37
|
+
const json = (res, code, body) => {
|
|
38
|
+
res.writeHead(code, { "content-type": "application/json", "cache-control": "no-store", "x-content-type-options": "nosniff" });
|
|
39
|
+
res.end(JSON.stringify(body));
|
|
40
|
+
};
|
|
41
|
+
const readBody = (req) => new Promise((resolve, reject) => {
|
|
42
|
+
let size = 0;
|
|
43
|
+
const chunks = [];
|
|
44
|
+
req.on("data", (c) => {
|
|
45
|
+
size += c.length;
|
|
46
|
+
if (size > MAX_BODY_BYTES) {
|
|
47
|
+
reject(new Error("body too large"));
|
|
48
|
+
req.destroy();
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
chunks.push(c);
|
|
52
|
+
});
|
|
53
|
+
req.on("end", () => {
|
|
54
|
+
try {
|
|
55
|
+
const v = JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
56
|
+
if (v === null || typeof v !== "object" || Array.isArray(v))
|
|
57
|
+
throw new Error("not an object");
|
|
58
|
+
resolve(v);
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
reject(new Error("body is not a JSON object"));
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
req.on("error", reject);
|
|
65
|
+
});
|
|
66
|
+
const onRequest = (req, res) => {
|
|
67
|
+
void (async () => {
|
|
68
|
+
try {
|
|
69
|
+
if (String(req.headers.host ?? "") !== new URL(origin).host)
|
|
70
|
+
return json(res, 403, { ok: false, reason: "bad host" });
|
|
71
|
+
const url = new URL(req.url ?? "/", origin);
|
|
72
|
+
if (req.method === "GET") {
|
|
73
|
+
if (!same(url.searchParams.get("s") ?? "", secret))
|
|
74
|
+
return json(res, 404, { ok: false, reason: "not found" });
|
|
75
|
+
if (url.pathname === "/info") {
|
|
76
|
+
if (settled)
|
|
77
|
+
return json(res, 410, { ok: false, reason: "already finished" });
|
|
78
|
+
return json(res, 200, { ...flow.info(), msLeft: Math.max(0, expiresAt - Date.now()) });
|
|
79
|
+
}
|
|
80
|
+
if (url.pathname === `/${flow.mode}`) {
|
|
81
|
+
res.writeHead(200, {
|
|
82
|
+
"content-type": "text/html; charset=utf-8",
|
|
83
|
+
"cache-control": "no-store",
|
|
84
|
+
"referrer-policy": "no-referrer",
|
|
85
|
+
"content-security-policy": flow.csp,
|
|
86
|
+
"x-content-type-options": "nosniff",
|
|
87
|
+
});
|
|
88
|
+
return res.end(flow.html(secret));
|
|
89
|
+
}
|
|
90
|
+
const asset = flow.assets[url.pathname];
|
|
91
|
+
if (asset) {
|
|
92
|
+
res.writeHead(200, { "content-type": asset.type, "cache-control": "no-store", "x-content-type-options": "nosniff" });
|
|
93
|
+
return res.end(asset.body);
|
|
94
|
+
}
|
|
95
|
+
return json(res, 404, { ok: false, reason: "not found" });
|
|
96
|
+
}
|
|
97
|
+
if (req.method === "POST" && (url.pathname === "/challenge" || url.pathname === "/result")) {
|
|
98
|
+
if (req.headers.origin !== origin)
|
|
99
|
+
return json(res, 403, { ok: false, reason: "bad origin" });
|
|
100
|
+
if (!String(req.headers["content-type"] ?? "").startsWith("application/json"))
|
|
101
|
+
return json(res, 415, { ok: false, reason: "expected JSON" });
|
|
102
|
+
if (settled)
|
|
103
|
+
return json(res, 409, { ok: false, reason: "already finished" });
|
|
104
|
+
const body = await readBody(req);
|
|
105
|
+
if (typeof body["s"] !== "string" || !same(body["s"], secret))
|
|
106
|
+
return json(res, 404, { ok: false, reason: "not found" });
|
|
107
|
+
if (url.pathname === "/challenge") {
|
|
108
|
+
if (!flow.challenge)
|
|
109
|
+
return json(res, 404, { ok: false, reason: "not found" });
|
|
110
|
+
const a = body["address"];
|
|
111
|
+
const address = flow.challengeAddress ? flow.challengeAddress(a) : typeof a === "string" && isAddress(a) ? getAddress(a) : undefined;
|
|
112
|
+
if (address === undefined)
|
|
113
|
+
return json(res, 400, { ok: false, reason: "not an address" });
|
|
114
|
+
const message = flow.challenge(address, origin, secret);
|
|
115
|
+
issued = { address, message };
|
|
116
|
+
return json(res, 200, { ok: true, message });
|
|
117
|
+
}
|
|
118
|
+
if (body["rejected"] === true) {
|
|
119
|
+
const reason = typeof body["reason"] === "string" ? body["reason"].slice(0, 300) : "declined in the browser";
|
|
120
|
+
flow.onReject?.(body);
|
|
121
|
+
finishWhenIdle({ ok: false, reason });
|
|
122
|
+
return json(res, 200, { ok: true });
|
|
123
|
+
}
|
|
124
|
+
// One result at a time: a double click must never hand the same call over twice.
|
|
125
|
+
if (busy)
|
|
126
|
+
return json(res, 409, { ok: false, reason: "already in progress" });
|
|
127
|
+
busy = true;
|
|
128
|
+
try {
|
|
129
|
+
const r = await flow.accept(body, { nonce: secret, origin, ...(issued ? { message: issued.message, challengedAddress: issued.address } : {}) });
|
|
130
|
+
if (!r.ok) {
|
|
131
|
+
if (r.fatal)
|
|
132
|
+
finish({ ok: false, reason: r.reason });
|
|
133
|
+
return json(res, 400, { ok: false, reason: r.reason });
|
|
134
|
+
}
|
|
135
|
+
if (r.final)
|
|
136
|
+
finish({ ok: true, value: r.value });
|
|
137
|
+
return json(res, 200, { ok: true, ...r.reply });
|
|
138
|
+
}
|
|
139
|
+
finally {
|
|
140
|
+
busy = false;
|
|
141
|
+
if (deferred)
|
|
142
|
+
finish(deferred);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return json(res, 405, { ok: false, reason: "method not allowed" });
|
|
146
|
+
}
|
|
147
|
+
catch (e) {
|
|
148
|
+
return json(res, 400, { ok: false, reason: e instanceof Error ? e.message : "bad request" });
|
|
149
|
+
}
|
|
150
|
+
})();
|
|
151
|
+
};
|
|
152
|
+
// `localhost` can resolve to either loopback address, so both are held: a browser that tries
|
|
153
|
+
// `::1` first must reach this server, never another process waiting on that address.
|
|
154
|
+
let servers = [];
|
|
155
|
+
const closeAll = () => {
|
|
156
|
+
for (const s of servers) {
|
|
157
|
+
s.close();
|
|
158
|
+
s.closeAllConnections();
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
const finish = (r) => {
|
|
162
|
+
if (settled)
|
|
163
|
+
return;
|
|
164
|
+
settled = true;
|
|
165
|
+
lock.release();
|
|
166
|
+
resolveDone(r);
|
|
167
|
+
// A short grace period lets the page receive its last answer before the socket closes.
|
|
168
|
+
setTimeout(closeAll, 1500).unref();
|
|
169
|
+
};
|
|
170
|
+
/**
|
|
171
|
+
* A cancel that arrives while a result is being checked waits for that check, so the command can
|
|
172
|
+
* report its verdict — but never longer than the grace period. The time limit does not wait: the
|
|
173
|
+
* transaction is already on record (`unverified`), and the command must return inside it.
|
|
174
|
+
*/
|
|
175
|
+
const finishWhenIdle = (r) => {
|
|
176
|
+
if (!busy)
|
|
177
|
+
return finish(r);
|
|
178
|
+
if (deferred)
|
|
179
|
+
return;
|
|
180
|
+
deferred = r;
|
|
181
|
+
setTimeout(() => finish(r), flow.cancelGraceMs ?? CANCEL_GRACE_MS).unref();
|
|
182
|
+
};
|
|
183
|
+
const listen = (server, port, host, optional) => new Promise((resolve, reject) => {
|
|
184
|
+
server.once("error", (e) => {
|
|
185
|
+
if (e.code === "EADDRINUSE") {
|
|
186
|
+
return reject(Object.assign(new Error(`port ${port} is in use on ${host} by another program; close it, then retry`), { inUse: true }));
|
|
187
|
+
}
|
|
188
|
+
// A machine with IPv6 switched off has no `::1` for anyone to wait on.
|
|
189
|
+
if (optional && (e.code === "EADDRNOTAVAIL" || e.code === "EAFNOSUPPORT"))
|
|
190
|
+
return resolve();
|
|
191
|
+
reject(e);
|
|
192
|
+
});
|
|
193
|
+
server.listen({ port, host, ipv6Only: host === "::1" }, () => resolve());
|
|
194
|
+
});
|
|
195
|
+
// Taken before any port is tried: a page this machine already has open is reported as that, and
|
|
196
|
+
// never answered by opening a second one on the next port.
|
|
197
|
+
const lock = claimPageLock(flow.ttlMs + LOCK_MARGIN_MS);
|
|
198
|
+
try {
|
|
199
|
+
let busy;
|
|
200
|
+
let bound = false;
|
|
201
|
+
for (const port of flow.ports) {
|
|
202
|
+
origin = `http://localhost:${port}`;
|
|
203
|
+
servers = [http.createServer(onRequest), http.createServer(onRequest)];
|
|
204
|
+
try {
|
|
205
|
+
await listen(servers[0], port, "127.0.0.1", false);
|
|
206
|
+
await listen(servers[1], port, "::1", true);
|
|
207
|
+
lock.setPort(port);
|
|
208
|
+
bound = true;
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
catch (e) {
|
|
212
|
+
closeAll();
|
|
213
|
+
if (!e.inUse)
|
|
214
|
+
throw e;
|
|
215
|
+
busy = e;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
if (!bound) {
|
|
219
|
+
if (flow.ports.length === 1 && busy)
|
|
220
|
+
throw busy;
|
|
221
|
+
throw new Error(`ports ${flow.ports.join(", ")} are all in use by other programs; close one of them, then retry`);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
catch (e) {
|
|
225
|
+
lock.release();
|
|
226
|
+
throw e;
|
|
227
|
+
}
|
|
228
|
+
const timer = setTimeout(
|
|
229
|
+
// A cancel still waiting on a check is the operator's reason; it wins over the clock.
|
|
230
|
+
() => finish(deferred ?? { ok: false, reason: flow.timeoutReason?.() ?? `nothing happened in the browser within ${Math.round(flow.ttlMs / 60_000)} minutes` }), flow.ttlMs);
|
|
231
|
+
timer.unref();
|
|
232
|
+
void done.then(() => clearTimeout(timer));
|
|
233
|
+
return { url: `${origin}/${flow.mode}?s=${secret}`, done, close: () => finish({ ok: false, reason: "cancelled" }) };
|
|
234
|
+
}
|
|
235
|
+
//# sourceMappingURL=http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/connect/http.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opens a URL in the operator's browser. Refuses — returning false, so the caller prints the URL
|
|
3
|
+
* instead — when there is evidently no browser to open: over SSH, on Linux with no display, or when
|
|
4
|
+
* `TREASURY_CONNECT_NO_OPEN` is set.
|
|
5
|
+
*/
|
|
6
|
+
import { spawn } from "node:child_process";
|
|
7
|
+
import { noOpen } from "./config.js";
|
|
8
|
+
export function canOpenBrowser() {
|
|
9
|
+
if (noOpen())
|
|
10
|
+
return false;
|
|
11
|
+
if (process.env["SSH_CONNECTION"] || process.env["SSH_TTY"])
|
|
12
|
+
return false;
|
|
13
|
+
if (process.platform === "linux" && !process.env["DISPLAY"] && !process.env["WAYLAND_DISPLAY"])
|
|
14
|
+
return false;
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
export function openBrowser(url) {
|
|
18
|
+
if (!canOpenBrowser())
|
|
19
|
+
return false;
|
|
20
|
+
try {
|
|
21
|
+
// One literal program per platform: the boundary test pins what this file may start.
|
|
22
|
+
const child = process.platform === "darwin"
|
|
23
|
+
? spawn("open", [url], { stdio: "ignore", detached: true })
|
|
24
|
+
: process.platform === "win32"
|
|
25
|
+
? spawn("cmd", ["/c", "start", "", url], { stdio: "ignore", detached: true })
|
|
26
|
+
: spawn("xdg-open", [url], { stdio: "ignore", detached: true });
|
|
27
|
+
child.on("error", () => { });
|
|
28
|
+
child.unref();
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=open.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"open.js","sourceRoot":"","sources":["../../src/connect/open.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,UAAU,cAAc;IAC5B,IAAI,MAAM,EAAE;QAAE,OAAO,KAAK,CAAC;IAC3B,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1E,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7G,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,IAAI,CAAC,cAAc,EAAE;QAAE,OAAO,KAAK,CAAC;IACpC,IAAI,CAAC;QACH,qFAAqF;QACrF,MAAM,KAAK,GACT,OAAO,CAAC,QAAQ,KAAK,QAAQ;YAC3B,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;YAC3D,CAAC,CAAC,OAAO,CAAC,QAAQ,KAAK,OAAO;gBAC5B,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;gBAC7E,CAAC,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QACtE,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC5B,KAAK,CAAC,KAAK,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Privy's own hosts: its auth and embedded-wallet iframe, its RPC (HTTPS, and WebSocket for Solana), and the Cloudflare check it uses. */
|
|
2
|
+
export declare const PAGE_CSP: string;
|
|
3
|
+
export declare function readPageBundle(): Buffer;
|
|
4
|
+
/** The HTML shell. `secret` authorises every request the page makes back to this process. */
|
|
5
|
+
export declare function shell(secret: string, title: string): string;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The page shell both flows serve, and the browser bundle it loads.
|
|
3
|
+
*
|
|
4
|
+
* The bundle (`dist/connect-page.js`) is the React + Privy page built from `connect-page/` — one
|
|
5
|
+
* Connect button, one Privy modal, and the confirm view. It sits beside the CLI bundle at runtime,
|
|
6
|
+
* so it is found next to this module once bundled, and at `../../dist/` when run from source.
|
|
7
|
+
*
|
|
8
|
+
* The shell carries the visual tokens (temporalabs.com's palette) so the page is styled before the
|
|
9
|
+
* bundle runs, and a CSP that admits what Privy's modal needs (scripts and connections by host; images from any HTTPS host).
|
|
10
|
+
*/
|
|
11
|
+
import { readFileSync, realpathSync } from "node:fs";
|
|
12
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
13
|
+
/** Privy's own hosts: its auth and embedded-wallet iframe, its RPC (HTTPS, and WebSocket for Solana), and the Cloudflare check it uses. */
|
|
14
|
+
export const PAGE_CSP = [
|
|
15
|
+
"default-src 'self'",
|
|
16
|
+
"script-src 'self' https://challenges.cloudflare.com",
|
|
17
|
+
"style-src 'self' 'unsafe-inline'",
|
|
18
|
+
"img-src 'self' data: blob: https:",
|
|
19
|
+
"font-src 'self' data:",
|
|
20
|
+
"object-src 'none'",
|
|
21
|
+
"base-uri 'self'",
|
|
22
|
+
"form-action 'none'",
|
|
23
|
+
"frame-ancestors 'none'",
|
|
24
|
+
"child-src https://auth.privy.io",
|
|
25
|
+
"frame-src https://auth.privy.io https://challenges.cloudflare.com",
|
|
26
|
+
"connect-src 'self' https://auth.privy.io https://*.rpc.privy.systems wss://*.rpc.privy.systems",
|
|
27
|
+
"worker-src 'self'",
|
|
28
|
+
"manifest-src 'self'",
|
|
29
|
+
].join("; ");
|
|
30
|
+
const here = pathToFileURL(realpathSync(fileURLToPath(import.meta.url)));
|
|
31
|
+
export function readPageBundle() {
|
|
32
|
+
for (const rel of ["./connect-page.js", "../../dist/connect-page.js"]) {
|
|
33
|
+
try {
|
|
34
|
+
return readFileSync(new URL(rel, here));
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
// try the next layout
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
throw new Error("the connect page is not built (dist/connect-page.js is missing) — run `npm ci && npm run build` in connect-page/");
|
|
41
|
+
}
|
|
42
|
+
/** The HTML shell. `secret` authorises every request the page makes back to this process. */
|
|
43
|
+
export function shell(secret, title) {
|
|
44
|
+
return `<!doctype html>
|
|
45
|
+
<html lang="en">
|
|
46
|
+
<head>
|
|
47
|
+
<meta charset="utf-8">
|
|
48
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
49
|
+
<title>${title}</title>
|
|
50
|
+
<style>
|
|
51
|
+
:root { --ink:#22303F; --navy:#1E3553; --navy-700:#2A456A; --steel:#465569; --slate:#5F6B7B; --paper:#FFFFFF; --ground:#F3F6F9;
|
|
52
|
+
--hair:rgba(34,48,63,.12); --blue:#76A6D5; --lavender:#B9A7D6; --grey:#B2B2B2; --ok:#2E8B57; --bad:#B4362A; --warn:#8A5A00; }
|
|
53
|
+
html,body { margin:0; min-height:100%; color:var(--ink); font:15px/1.55 Inter,ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,sans-serif; -webkit-font-smoothing:antialiased; }
|
|
54
|
+
body { background:
|
|
55
|
+
radial-gradient(ellipse 48% 60% at 72% 60%, rgba(255,255,255,.9), rgba(255,255,255,0) 72%),
|
|
56
|
+
radial-gradient(ellipse 60% 75% at 0% 0%, rgba(118,166,213,.16), rgba(118,166,213,0) 70%),
|
|
57
|
+
radial-gradient(ellipse 55% 65% at 100% 100%, rgba(185,167,214,.17), rgba(185,167,214,0) 70%),
|
|
58
|
+
linear-gradient(90deg, #e9f1f9 0%, #eff1f6 50%, #efecf6 100%); min-height:100vh; }
|
|
59
|
+
:focus-visible { outline:2px solid #266cad; outline-offset:2px; }
|
|
60
|
+
</style>
|
|
61
|
+
</head>
|
|
62
|
+
<body>
|
|
63
|
+
<div id="root"></div>
|
|
64
|
+
<script src="/app.js?s=${secret}"></script>
|
|
65
|
+
</body>
|
|
66
|
+
</html>
|
|
67
|
+
`;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=page.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page.js","sourceRoot":"","sources":["../../src/connect/page.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAExD,2IAA2I;AAC3I,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,oBAAoB;IACpB,qDAAqD;IACrD,kCAAkC;IAClC,mCAAmC;IACnC,uBAAuB;IACvB,mBAAmB;IACnB,iBAAiB;IACjB,oBAAoB;IACpB,wBAAwB;IACxB,iCAAiC;IACjC,mEAAmE;IACnE,gGAAgG;IAChG,mBAAmB;IACnB,qBAAqB;CACtB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,IAAI,GAAG,aAAa,CAAC,YAAY,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAEzE,MAAM,UAAU,cAAc;IAC5B,KAAK,MAAM,GAAG,IAAI,CAAC,mBAAmB,EAAE,4BAA4B,CAAC,EAAE,CAAC;QACtE,IAAI,CAAC;YACH,OAAO,YAAY,CAAC,IAAI,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;QAC1C,CAAC;QAAC,MAAM,CAAC;YACP,sBAAsB;QACxB,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,kHAAkH,CAAC,CAAC;AACtI,CAAC;AAED,6FAA6F;AAC7F,MAAM,UAAU,KAAK,CAAC,MAAc,EAAE,KAAa;IACjD,OAAO;;;;;SAKA,KAAK;;;;;;;;;;;;;;;yBAeW,MAAM;;;CAG9B,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { PendingAck } from "./ack.js";
|
|
2
|
+
export interface Session {
|
|
3
|
+
account: string;
|
|
4
|
+
/** `external`: a browser wallet the operator controls. `embedded`: a Privy wallet opened by email or a social login. */
|
|
5
|
+
walletType: "external" | "embedded";
|
|
6
|
+
connectedAtIso: string;
|
|
7
|
+
}
|
|
8
|
+
export declare const sessionPath: () => string;
|
|
9
|
+
export declare function readSession(): Session | undefined;
|
|
10
|
+
export declare function writeSession(s: Session): void;
|
|
11
|
+
export declare function clearSession(): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* The connected SOLANA account, kept apart from the EVM one: an operator can be connected on both at once,
|
|
14
|
+
* with different wallets, and a command for a vault on one chain family reads only that family's session.
|
|
15
|
+
*/
|
|
16
|
+
export declare const solanaSessionPath: () => string;
|
|
17
|
+
export declare function readSolanaSession(): Session | undefined;
|
|
18
|
+
export declare function writeSolanaSession(s: Session): void;
|
|
19
|
+
export declare function clearSolanaSession(): boolean;
|
|
20
|
+
/** The one acknowledgement waiting for `--ack` (`ack.ts`). Issuing another replaces it. */
|
|
21
|
+
export declare const pendingAckPath: () => string;
|
|
22
|
+
export declare function writePendingAck(a: PendingAck): void;
|
|
23
|
+
export declare function readPendingAck(): PendingAck | undefined;
|
|
24
|
+
export declare function clearPendingAck(): void;
|
|
25
|
+
/**
|
|
26
|
+
* One sign-in or confirmation page at a time. The page can fall back to another port when its first
|
|
27
|
+
* is taken, so the port no longer keeps a second page from opening; this file does. It names the
|
|
28
|
+
* process that holds it and when its page expires; a file whose process has gone, or whose page has
|
|
29
|
+
* expired, is left over from a run that never closed it, and is replaced.
|
|
30
|
+
*/
|
|
31
|
+
export declare const pageLockPath: () => string;
|
|
32
|
+
/**
|
|
33
|
+
* Claims the page lock until `ttlMs` from now. Returns `setPort` (records which port the page took)
|
|
34
|
+
* and `release` (removes the file, only while it is still this claim's). Throws when a live page holds it.
|
|
35
|
+
*/
|
|
36
|
+
export declare function claimPageLock(ttlMs: number): {
|
|
37
|
+
setPort: (port: number) => void;
|
|
38
|
+
release: () => void;
|
|
39
|
+
};
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The connected account, remembered between commands in a small file readable only by its owner
|
|
3
|
+
* (`~/.config/treasury/connect-session.json`, mode 0600; `TREASURY_CONNECT_HOME` moves it).
|
|
4
|
+
*
|
|
5
|
+
* It holds no credential: an address, how it signed in, and when. Being "connected" grants nothing
|
|
6
|
+
* by itself — every transaction is still confirmed by the operator in the browser and in their
|
|
7
|
+
* wallet — it only fixes WHICH account the confirm page will accept and pay.
|
|
8
|
+
*/
|
|
9
|
+
import { chmodSync, closeSync, mkdirSync, openSync, readFileSync, rmSync, statSync, writeFileSync, writeSync } from "node:fs";
|
|
10
|
+
import { homedir } from "node:os";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
import { getAddress, isAddress } from "viem";
|
|
13
|
+
import { isAddress as isSolanaAddress } from "@solana/kit";
|
|
14
|
+
import { connectHome } from "./config.js";
|
|
15
|
+
const dir = () => connectHome() ?? join(homedir(), ".config", "treasury");
|
|
16
|
+
export const sessionPath = () => join(dir(), "connect-session.json");
|
|
17
|
+
export function readSession() {
|
|
18
|
+
let raw;
|
|
19
|
+
try {
|
|
20
|
+
raw = readFileSync(sessionPath(), "utf8");
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
const v = JSON.parse(raw);
|
|
27
|
+
if (typeof v.account !== "string" || !isAddress(v.account))
|
|
28
|
+
return undefined;
|
|
29
|
+
if (v.walletType !== "external" && v.walletType !== "embedded")
|
|
30
|
+
return undefined;
|
|
31
|
+
return { account: getAddress(v.account), walletType: v.walletType, connectedAtIso: String(v.connectedAtIso ?? "") };
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// A file that does not parse is no session, never a guessed one.
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function writeOwnerOnly(path, value) {
|
|
39
|
+
mkdirSync(dir(), { recursive: true, mode: 0o700 });
|
|
40
|
+
writeFileSync(path, `${JSON.stringify(value, null, 2)}\n`, { mode: 0o600 });
|
|
41
|
+
// `mode` applies only when the file is created; an existing file keeps its own.
|
|
42
|
+
chmodSync(path, 0o600);
|
|
43
|
+
}
|
|
44
|
+
export function writeSession(s) {
|
|
45
|
+
writeOwnerOnly(sessionPath(), s);
|
|
46
|
+
// A new connection voids any acknowledgement given for the one before it.
|
|
47
|
+
clearPendingAck();
|
|
48
|
+
}
|
|
49
|
+
export function clearSession() {
|
|
50
|
+
const had = readSession() !== undefined;
|
|
51
|
+
rmSync(sessionPath(), { force: true });
|
|
52
|
+
clearPendingAck();
|
|
53
|
+
return had;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The connected SOLANA account, kept apart from the EVM one: an operator can be connected on both at once,
|
|
57
|
+
* with different wallets, and a command for a vault on one chain family reads only that family's session.
|
|
58
|
+
*/
|
|
59
|
+
export const solanaSessionPath = () => join(dir(), "connect-session-solana.json");
|
|
60
|
+
export function readSolanaSession() {
|
|
61
|
+
try {
|
|
62
|
+
const v = JSON.parse(readFileSync(solanaSessionPath(), "utf8"));
|
|
63
|
+
if (typeof v.account !== "string" || !isSolanaAddress(v.account))
|
|
64
|
+
return undefined;
|
|
65
|
+
if (v.walletType !== "external" && v.walletType !== "embedded")
|
|
66
|
+
return undefined;
|
|
67
|
+
return { account: v.account, walletType: v.walletType, connectedAtIso: String(v.connectedAtIso ?? "") };
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
export function writeSolanaSession(s) {
|
|
74
|
+
writeOwnerOnly(solanaSessionPath(), s);
|
|
75
|
+
clearPendingAck();
|
|
76
|
+
}
|
|
77
|
+
export function clearSolanaSession() {
|
|
78
|
+
const had = readSolanaSession() !== undefined;
|
|
79
|
+
rmSync(solanaSessionPath(), { force: true });
|
|
80
|
+
clearPendingAck();
|
|
81
|
+
return had;
|
|
82
|
+
}
|
|
83
|
+
/** The one acknowledgement waiting for `--ack` (`ack.ts`). Issuing another replaces it. */
|
|
84
|
+
export const pendingAckPath = () => join(dir(), "connect-ack.json");
|
|
85
|
+
export function writePendingAck(a) {
|
|
86
|
+
writeOwnerOnly(pendingAckPath(), a);
|
|
87
|
+
}
|
|
88
|
+
export function readPendingAck() {
|
|
89
|
+
try {
|
|
90
|
+
const v = JSON.parse(readFileSync(pendingAckPath(), "utf8"));
|
|
91
|
+
if (typeof v.code !== "string" || typeof v.digest !== "string" || typeof v.issuedAtIso !== "string" || typeof v.expiresAtIso !== "string")
|
|
92
|
+
return undefined;
|
|
93
|
+
return { code: v.code, digest: v.digest, issuedAtIso: v.issuedAtIso, expiresAtIso: v.expiresAtIso };
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
export function clearPendingAck() {
|
|
100
|
+
rmSync(pendingAckPath(), { force: true });
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* One sign-in or confirmation page at a time. The page can fall back to another port when its first
|
|
104
|
+
* is taken, so the port no longer keeps a second page from opening; this file does. It names the
|
|
105
|
+
* process that holds it and when its page expires; a file whose process has gone, or whose page has
|
|
106
|
+
* expired, is left over from a run that never closed it, and is replaced.
|
|
107
|
+
*/
|
|
108
|
+
export const pageLockPath = () => join(dir(), "connect-page.lock");
|
|
109
|
+
/** A lock file this young that does not parse yet is still being written by the process that made it. */
|
|
110
|
+
const LOCK_WRITE_GRACE_MS = 2_000;
|
|
111
|
+
const alive = (pid) => {
|
|
112
|
+
try {
|
|
113
|
+
process.kill(pid, 0);
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
catch (e) {
|
|
117
|
+
// EPERM: the process exists and belongs to someone else.
|
|
118
|
+
return e.code === "EPERM";
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
function heldBy(path) {
|
|
122
|
+
let raw;
|
|
123
|
+
try {
|
|
124
|
+
raw = readFileSync(path, "utf8");
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
return undefined;
|
|
128
|
+
}
|
|
129
|
+
try {
|
|
130
|
+
const v = JSON.parse(raw);
|
|
131
|
+
if (typeof v.pid !== "number" || typeof v.expiresAt !== "number")
|
|
132
|
+
return undefined;
|
|
133
|
+
if (v.expiresAt < Date.now() || !alive(v.pid))
|
|
134
|
+
return undefined;
|
|
135
|
+
return { pid: v.pid, ...(typeof v.port === "number" ? { port: v.port } : {}) };
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
try {
|
|
139
|
+
return Date.now() - statSync(path).mtimeMs < LOCK_WRITE_GRACE_MS ? { pid: 0 } : undefined;
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
return undefined;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Claims the page lock until `ttlMs` from now. Returns `setPort` (records which port the page took)
|
|
148
|
+
* and `release` (removes the file, only while it is still this claim's). Throws when a live page holds it.
|
|
149
|
+
*/
|
|
150
|
+
export function claimPageLock(ttlMs) {
|
|
151
|
+
mkdirSync(dir(), { recursive: true, mode: 0o700 });
|
|
152
|
+
const path = pageLockPath();
|
|
153
|
+
// Tells this claim from a later one in the same file; not a secret.
|
|
154
|
+
const token = `${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
155
|
+
const expiresAt = Date.now() + ttlMs;
|
|
156
|
+
const write = (port) => writeFileSync(path, JSON.stringify({ pid: process.pid, expiresAt, token, ...(port ? { port } : {}) }), { mode: 0o600 });
|
|
157
|
+
for (let attempt = 0;; attempt++) {
|
|
158
|
+
try {
|
|
159
|
+
const fd = openSync(path, "wx", 0o600);
|
|
160
|
+
try {
|
|
161
|
+
writeSync(fd, JSON.stringify({ pid: process.pid, expiresAt, token }));
|
|
162
|
+
}
|
|
163
|
+
finally {
|
|
164
|
+
closeSync(fd);
|
|
165
|
+
}
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
catch (e) {
|
|
169
|
+
if (e.code !== "EEXIST")
|
|
170
|
+
throw e;
|
|
171
|
+
const holder = heldBy(path);
|
|
172
|
+
if (holder || attempt > 0) {
|
|
173
|
+
const where = holder?.port ? ` on port ${holder.port}` : "";
|
|
174
|
+
throw new Error(`another sign-in or confirmation page is still open${where}; finish or close it, then retry`);
|
|
175
|
+
}
|
|
176
|
+
rmSync(path, { force: true });
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
const ours = () => {
|
|
180
|
+
try {
|
|
181
|
+
return JSON.parse(readFileSync(path, "utf8")).token === token;
|
|
182
|
+
}
|
|
183
|
+
catch {
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
return {
|
|
188
|
+
setPort: (port) => {
|
|
189
|
+
if (ours())
|
|
190
|
+
write(port);
|
|
191
|
+
},
|
|
192
|
+
release: () => {
|
|
193
|
+
if (ours())
|
|
194
|
+
rmSync(path, { force: true });
|
|
195
|
+
},
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/connect/session.ts"],"names":[],"mappings":"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"}
|