@candledottv/cli 0.13.21 → 0.13.23
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/README.md +43 -4
- package/dist/index.js +464 -223
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -84,6 +84,127 @@ var __callDispose = (stack, error, hasError) => {
|
|
|
84
84
|
return next();
|
|
85
85
|
};
|
|
86
86
|
|
|
87
|
+
// ../mcp/src/api-key-file.ts
|
|
88
|
+
import { closeSync, constants, fstatSync, openSync, readSync } from "node:fs";
|
|
89
|
+
import { resolve } from "node:path";
|
|
90
|
+
function hasApiKeyFile(env) {
|
|
91
|
+
return Boolean(env.CANDLE_API_KEY_FILE?.trim());
|
|
92
|
+
}
|
|
93
|
+
function assertApiKeySources(env) {
|
|
94
|
+
if (hasApiKeyFile(env) && (env.CANDLE_API_KEY?.trim() || env.CANDLE_AGENT_API_KEY?.trim())) {
|
|
95
|
+
throw new ApiKeyFileError("API_KEY_SOURCE_CONFLICT", "CANDLE_API_KEY_FILE conflicts with CANDLE_API_KEY or CANDLE_AGENT_API_KEY. Unset the raw sources or unset CANDLE_API_KEY_FILE.");
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function requireDescriptorMetadata(stat) {
|
|
99
|
+
if ([stat.uid, stat.mode, stat.size, stat.mtimeNs, stat.ctimeNs].some((value) => typeof value !== "bigint")) {
|
|
100
|
+
throw new ApiKeyFileError("API_KEY_FILE_UNSUPPORTED", "CANDLE_API_KEY_FILE requires POSIX descriptor metadata. Use an existing credential source or a supported host.");
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function invalid(rule) {
|
|
104
|
+
throw new ApiKeyFileError("API_KEY_FILE_INVALID", `CANDLE_API_KEY_FILE ${rule}. Fix the file locally.`);
|
|
105
|
+
}
|
|
106
|
+
function readApiKeyFile(path, io = apiKeyFileIo) {
|
|
107
|
+
let fd;
|
|
108
|
+
let key = "";
|
|
109
|
+
let failure;
|
|
110
|
+
try {
|
|
111
|
+
const uid = io.effectiveUid();
|
|
112
|
+
if (!["linux", "darwin"].includes(io.platform) || uid === undefined || !io.constants.O_NOFOLLOW || !io.constants.O_NONBLOCK || !io.open || !io.stat || !io.read || !io.close) {
|
|
113
|
+
throw new ApiKeyFileError("API_KEY_FILE_UNSUPPORTED", "CANDLE_API_KEY_FILE requires Linux or macOS with POSIX descriptor checks. Use an existing credential source or a supported host.");
|
|
114
|
+
}
|
|
115
|
+
fd = io.open(path, io.constants.O_RDONLY | io.constants.O_NOFOLLOW | io.constants.O_NONBLOCK);
|
|
116
|
+
const before = io.stat(fd);
|
|
117
|
+
requireDescriptorMetadata(before);
|
|
118
|
+
const mode = Number(before.mode & 0o7777n);
|
|
119
|
+
if (!before.isFile() || before.uid !== BigInt(uid) || mode !== 256 && mode !== 384) {
|
|
120
|
+
invalid("must be a regular file owned by the effective user with mode 0400 or 0600");
|
|
121
|
+
}
|
|
122
|
+
if (before.size > 4096n)
|
|
123
|
+
invalid("must be at most 4096 bytes");
|
|
124
|
+
const bytes = Buffer.alloc(4097);
|
|
125
|
+
let count = 0;
|
|
126
|
+
while (count < bytes.length) {
|
|
127
|
+
const read = io.read(fd, bytes, count, bytes.length - count);
|
|
128
|
+
if (read === 0)
|
|
129
|
+
break;
|
|
130
|
+
count += read;
|
|
131
|
+
}
|
|
132
|
+
const after = io.stat(fd);
|
|
133
|
+
requireDescriptorMetadata(after);
|
|
134
|
+
if (!after.isFile() || count > 4096 || BigInt(count) !== before.size || before.uid !== after.uid || before.mode !== after.mode || before.size !== after.size || before.mtimeNs !== after.mtimeNs || before.ctimeNs !== after.ctimeNs)
|
|
135
|
+
invalid("must remain unchanged while being read");
|
|
136
|
+
let end = count;
|
|
137
|
+
if (bytes[end - 1] === 10) {
|
|
138
|
+
end--;
|
|
139
|
+
if (bytes[end - 1] === 13)
|
|
140
|
+
end--;
|
|
141
|
+
}
|
|
142
|
+
if (end === 0)
|
|
143
|
+
invalid("must contain one nonempty printable ASCII token, optionally followed by LF or CRLF");
|
|
144
|
+
for (let i = 0;i < end; i++) {
|
|
145
|
+
const byte = bytes[i] ?? 0;
|
|
146
|
+
if (byte < 33 || byte > 126)
|
|
147
|
+
invalid("must contain one nonempty printable ASCII token, optionally followed by LF or CRLF");
|
|
148
|
+
}
|
|
149
|
+
key = bytes.subarray(0, end).toString("ascii");
|
|
150
|
+
} catch (error) {
|
|
151
|
+
const code = error?.code;
|
|
152
|
+
failure = error instanceof ApiKeyFileError ? error : code === "ELOOP" ? new ApiKeyFileError("API_KEY_FILE_INVALID", "CANDLE_API_KEY_FILE must not be a final-component symlink. Fix the file locally.") : ["ENOSYS", "ENOTSUP"].includes(String(code)) ? new ApiKeyFileError("API_KEY_FILE_UNSUPPORTED", "CANDLE_API_KEY_FILE requires POSIX descriptor checks. Use an existing credential source or a supported host.") : new ApiKeyFileError("API_KEY_FILE_UNREADABLE", "Cannot read CANDLE_API_KEY_FILE. Check the configured path and access.");
|
|
153
|
+
} finally {
|
|
154
|
+
if (fd !== undefined) {
|
|
155
|
+
try {
|
|
156
|
+
io.close(fd);
|
|
157
|
+
} catch {
|
|
158
|
+
failure ??= new ApiKeyFileError("API_KEY_FILE_UNREADABLE", "Cannot close CANDLE_API_KEY_FILE. Check local file access.");
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
if (failure)
|
|
163
|
+
throw failure;
|
|
164
|
+
return key;
|
|
165
|
+
}
|
|
166
|
+
function apiKeyFileSnapshot(env, load = readApiKeyFile, cwd = process.cwd()) {
|
|
167
|
+
env = { ...env };
|
|
168
|
+
const selected = hasApiKeyFile(env);
|
|
169
|
+
const path = selected ? resolve(cwd, env.CANDLE_API_KEY_FILE ?? "") : undefined;
|
|
170
|
+
let result;
|
|
171
|
+
return () => {
|
|
172
|
+
result ??= Promise.resolve().then(async () => {
|
|
173
|
+
assertApiKeySources(env);
|
|
174
|
+
if (path === undefined)
|
|
175
|
+
return;
|
|
176
|
+
try {
|
|
177
|
+
return await load(path);
|
|
178
|
+
} catch (error) {
|
|
179
|
+
if (error instanceof ApiKeyFileError)
|
|
180
|
+
throw error;
|
|
181
|
+
throw new ApiKeyFileError("API_KEY_FILE_UNREADABLE", "Cannot read CANDLE_API_KEY_FILE. Check the configured path and access.");
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
return result;
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
var ApiKeyFileError, apiKeyFileIo;
|
|
188
|
+
var init_api_key_file = __esm(() => {
|
|
189
|
+
ApiKeyFileError = class ApiKeyFileError extends Error {
|
|
190
|
+
code;
|
|
191
|
+
constructor(code, message) {
|
|
192
|
+
super(message);
|
|
193
|
+
this.code = code;
|
|
194
|
+
this.name = "ApiKeyFileError";
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
apiKeyFileIo = {
|
|
198
|
+
platform: process.platform,
|
|
199
|
+
effectiveUid: () => process.geteuid?.(),
|
|
200
|
+
constants,
|
|
201
|
+
open: openSync,
|
|
202
|
+
stat: (fd) => fstatSync(fd, { bigint: true }),
|
|
203
|
+
read: (fd, buffer, offset, length) => readSync(fd, buffer, offset, length, null),
|
|
204
|
+
close: closeSync
|
|
205
|
+
};
|
|
206
|
+
});
|
|
207
|
+
|
|
87
208
|
// src/client.ts
|
|
88
209
|
function setOwnerConfirmHooks(hooks) {
|
|
89
210
|
const previous = installedOwnerConfirmHooks;
|
|
@@ -634,7 +755,7 @@ var init_terminal_theme = __esm(() => {
|
|
|
634
755
|
});
|
|
635
756
|
|
|
636
757
|
// src/version.ts
|
|
637
|
-
var CLI_VERSION = "0.13.
|
|
758
|
+
var CLI_VERSION = "0.13.23";
|
|
638
759
|
|
|
639
760
|
// src/presentation.ts
|
|
640
761
|
function terminalStyle(deps, stream, machine = false) {
|
|
@@ -5697,13 +5818,16 @@ function keyedRedirectGuard(doFetch) {
|
|
|
5697
5818
|
};
|
|
5698
5819
|
}
|
|
5699
5820
|
function resolveConfig(env = process.env) {
|
|
5821
|
+
assertApiKeySources(env);
|
|
5822
|
+
const fileKey = hasApiKeyFile(env) ? readApiKeyFile(env.CANDLE_API_KEY_FILE ?? "") : undefined;
|
|
5700
5823
|
const apiUrl = env.CANDLE_API_URL?.trim() || DEFAULT_API_URL2;
|
|
5701
5824
|
assertTransportSecurity(apiUrl, env);
|
|
5702
|
-
const apiKey = env.CANDLE_AGENT_API_KEY?.trim() || env.CANDLE_API_KEY?.trim();
|
|
5825
|
+
const apiKey = fileKey ?? (env.CANDLE_AGENT_API_KEY?.trim() || env.CANDLE_API_KEY?.trim());
|
|
5703
5826
|
return apiKey ? { apiUrl, apiKey } : { apiUrl };
|
|
5704
5827
|
}
|
|
5705
5828
|
var DEFAULT_API_URL2 = "https://api.alpha.candle.tv", REDIRECT_STATUSES2, MAX_REDIRECTS2 = 5, CrossOriginRedirectError2;
|
|
5706
5829
|
var init_client2 = __esm(() => {
|
|
5830
|
+
init_api_key_file();
|
|
5707
5831
|
REDIRECT_STATUSES2 = new Set([301, 302, 303, 307, 308]);
|
|
5708
5832
|
CrossOriginRedirectError2 = class CrossOriginRedirectError2 extends Error {
|
|
5709
5833
|
from;
|
|
@@ -5909,7 +6033,7 @@ var init_convert = __esm(() => {
|
|
|
5909
6033
|
});
|
|
5910
6034
|
|
|
5911
6035
|
// ../mcp/src/image.ts
|
|
5912
|
-
import { constants } from "node:fs";
|
|
6036
|
+
import { constants as constants2 } from "node:fs";
|
|
5913
6037
|
import { lstat, open, realpath } from "node:fs/promises";
|
|
5914
6038
|
import { dirname, isAbsolute, relative, sep } from "node:path";
|
|
5915
6039
|
function configuredImageDir(env) {
|
|
@@ -5935,16 +6059,16 @@ function errno(error) {
|
|
|
5935
6059
|
return error?.code;
|
|
5936
6060
|
}
|
|
5937
6061
|
async function realImageDir(imageDir, fs) {
|
|
5938
|
-
const
|
|
6062
|
+
const invalid2 = () => new ImageRefusal("IMAGE_DIR_INVALID", `CANDLE_IMAGE_DIR must be an absolute path to an existing directory, and not the filesystem root. ${NOTHING_UPLOADED}`);
|
|
5939
6063
|
if (!isAbsolute(imageDir))
|
|
5940
|
-
throw
|
|
6064
|
+
throw invalid2();
|
|
5941
6065
|
try {
|
|
5942
6066
|
const real = await fs.realpath(imageDir);
|
|
5943
6067
|
if (dirname(real) === real || !(await fs.lstat(real, { bigint: true })).isDirectory())
|
|
5944
|
-
throw
|
|
6068
|
+
throw invalid2();
|
|
5945
6069
|
return real;
|
|
5946
6070
|
} catch {
|
|
5947
|
-
throw
|
|
6071
|
+
throw invalid2();
|
|
5948
6072
|
}
|
|
5949
6073
|
}
|
|
5950
6074
|
async function missingInside(dirReal, path, fs) {
|
|
@@ -5987,7 +6111,7 @@ async function readImageInDir(imageDir, imagePath, fs = nodeFs, field = "imagePa
|
|
|
5987
6111
|
throw outside();
|
|
5988
6112
|
let handle;
|
|
5989
6113
|
try {
|
|
5990
|
-
handle = await fs.open(fileReal,
|
|
6114
|
+
handle = await fs.open(fileReal, constants2.O_RDONLY | (constants2.O_NOFOLLOW ?? 0) | (constants2.O_NONBLOCK ?? 0));
|
|
5991
6115
|
} catch (error) {
|
|
5992
6116
|
throw errno(error) === "ELOOP" ? outside() : unreadable("it could not be opened");
|
|
5993
6117
|
}
|
|
@@ -6078,24 +6202,24 @@ async function resolveLaunchImage(args, imageDir, cfg, doFetch, fs = nodeFs) {
|
|
|
6078
6202
|
const hasUrl = typeof rest.imageUrl === "string" && rest.imageUrl.length > 0;
|
|
6079
6203
|
const hasBannerPath = typeof bannerPath === "string" && bannerPath.length > 0;
|
|
6080
6204
|
const hasBannerUrl = typeof rest.bannerUrl === "string" && rest.bannerUrl.length > 0;
|
|
6081
|
-
const
|
|
6205
|
+
const invalid2 = (message) => ({ refused: { code: "MCP_VALIDATION", message } });
|
|
6082
6206
|
if (imageDir === undefined) {
|
|
6083
6207
|
if (imagePath !== undefined)
|
|
6084
|
-
return
|
|
6208
|
+
return invalid2(`imagePath is not available on this server: no CANDLE_IMAGE_DIR is configured. Pass imageUrl, an https URL. ${NOTHING_UPLOADED}`);
|
|
6085
6209
|
if (bannerPath !== undefined)
|
|
6086
|
-
return
|
|
6210
|
+
return invalid2(`bannerPath is not available on this server: no CANDLE_IMAGE_DIR is configured. Pass bannerUrl, an https URL. ${NOTHING_UPLOADED}`);
|
|
6087
6211
|
return { args: rest };
|
|
6088
6212
|
}
|
|
6089
6213
|
if (hasPath && hasUrl)
|
|
6090
|
-
return
|
|
6214
|
+
return invalid2(`Pass exactly one of imageUrl or imagePath, not both. ${NOTHING_UPLOADED}`);
|
|
6091
6215
|
if (hasBannerPath && hasBannerUrl)
|
|
6092
|
-
return
|
|
6216
|
+
return invalid2(`Pass at most one of bannerUrl or bannerPath, not both. ${NOTHING_UPLOADED}`);
|
|
6093
6217
|
if (!hasPath && !hasUrl)
|
|
6094
|
-
return
|
|
6218
|
+
return invalid2("Pass imageUrl (an https URL) or imagePath (an absolute path to an image file inside CANDLE_IMAGE_DIR).");
|
|
6095
6219
|
if (!hasPath && !hasBannerPath)
|
|
6096
6220
|
return { args: rest };
|
|
6097
6221
|
if (!cfg.apiKey)
|
|
6098
|
-
return
|
|
6222
|
+
return invalid2(`CANDLE_AGENT_API_KEY is required to upload an image; the key needs the launch:write scope. ${NOTHING_UPLOADED}`);
|
|
6099
6223
|
const read = async (path, field) => {
|
|
6100
6224
|
try {
|
|
6101
6225
|
return await readImageInDir(imageDir, path, fs, field);
|
|
@@ -6135,7 +6259,7 @@ async function resolveLaunchImage(args, imageDir, cfg, doFetch, fs = nodeFs) {
|
|
|
6135
6259
|
if (uploaded === undefined)
|
|
6136
6260
|
return result2;
|
|
6137
6261
|
const why = "refused" in result2 ? result2.refused.message : result2.uploadFailed;
|
|
6138
|
-
return
|
|
6262
|
+
return invalid2(`The banner upload failed: ${why} The image was already uploaded to ${uploaded}; pass that as imageUrl on the retry. No launch was attempted.`);
|
|
6139
6263
|
}
|
|
6140
6264
|
uploadedBanner = result2.url;
|
|
6141
6265
|
launchArgs.bannerUrl = uploadedBanner;
|
|
@@ -6189,7 +6313,7 @@ function createLabClient(options) {
|
|
|
6189
6313
|
const doFetch = options.fetch ?? globalThis.fetch;
|
|
6190
6314
|
const callMs = options.callTimeoutMs ?? LAB_CALL_TIMEOUT_MS;
|
|
6191
6315
|
const now = options.now ?? Date.now;
|
|
6192
|
-
const sleep = options.sleep ?? ((ms) => new Promise((
|
|
6316
|
+
const sleep = options.sleep ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms)));
|
|
6193
6317
|
async function call(method, path, valid = () => true, body, timeoutMs = callMs) {
|
|
6194
6318
|
const controller = new AbortController;
|
|
6195
6319
|
let timedOut = false;
|
|
@@ -10077,7 +10201,7 @@ function perpsMarketGate(meta, ctx, minOpenInterestUsd) {
|
|
|
10077
10201
|
return { tradeable: false, reason: "minOpenInterest" };
|
|
10078
10202
|
return { tradeable: true, reason: null };
|
|
10079
10203
|
}
|
|
10080
|
-
function
|
|
10204
|
+
function resolve2(snapshot, coin) {
|
|
10081
10205
|
if (/^[A-Za-z0-9]{1,20}$/.test(coin)) {
|
|
10082
10206
|
const exact = snapshot.universe.findIndex((row) => row.name === coin);
|
|
10083
10207
|
if (exact !== -1)
|
|
@@ -10321,7 +10445,7 @@ class PerpsMarketReader {
|
|
|
10321
10445
|
async market(coin) {
|
|
10322
10446
|
this.key();
|
|
10323
10447
|
const [config, core, extras] = await Promise.all([this.config(), this.core(), this.extras()]);
|
|
10324
|
-
const asset =
|
|
10448
|
+
const asset = resolve2(core, coin);
|
|
10325
10449
|
const meta = at(core.universe, asset);
|
|
10326
10450
|
const ctx = at(core.ctxs, asset);
|
|
10327
10451
|
return {
|
|
@@ -10347,7 +10471,7 @@ class PerpsMarketReader {
|
|
|
10347
10471
|
if (opts.sigFigs !== undefined)
|
|
10348
10472
|
bounded(opts.sigFigs, 5, 2, 5, "sigFigs");
|
|
10349
10473
|
const [config, core] = await Promise.all([this.config(), this.core()]);
|
|
10350
|
-
const canonical2 = at(core.universe,
|
|
10474
|
+
const canonical2 = at(core.universe, resolve2(core, coin)).name;
|
|
10351
10475
|
const value = await info(this.opts.fetcher, this.opts.network, {
|
|
10352
10476
|
type: "l2Book",
|
|
10353
10477
|
coin: canonical2,
|
|
@@ -10388,7 +10512,7 @@ class PerpsMarketReader {
|
|
|
10388
10512
|
this.key();
|
|
10389
10513
|
const window = perpsCandleWindow(opts, this.now());
|
|
10390
10514
|
const [config, core] = await Promise.all([this.config(), this.core()]);
|
|
10391
|
-
const canonical2 = at(core.universe,
|
|
10515
|
+
const canonical2 = at(core.universe, resolve2(core, coin)).name;
|
|
10392
10516
|
const value = await info(this.opts.fetcher, this.opts.network, {
|
|
10393
10517
|
type: "candleSnapshot",
|
|
10394
10518
|
req: { coin: canonical2, interval: window.interval, startTime: window.startTime, endTime: window.endTime }
|
|
@@ -10423,7 +10547,7 @@ class PerpsMarketReader {
|
|
|
10423
10547
|
this.key();
|
|
10424
10548
|
const window = perpsFundingWindow(opts, this.now());
|
|
10425
10549
|
const [config, core] = await Promise.all([this.config(), this.core()]);
|
|
10426
|
-
const canonical2 = at(core.universe,
|
|
10550
|
+
const canonical2 = at(core.universe, resolve2(core, coin)).name;
|
|
10427
10551
|
const value = await info(this.opts.fetcher, this.opts.network, {
|
|
10428
10552
|
type: "fundingHistory",
|
|
10429
10553
|
coin: canonical2,
|
|
@@ -10515,7 +10639,7 @@ var init_hyperliquid_markets = __esm(() => {
|
|
|
10515
10639
|
function isTime(value) {
|
|
10516
10640
|
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
10517
10641
|
}
|
|
10518
|
-
function
|
|
10642
|
+
function invalid2(field, message) {
|
|
10519
10643
|
return new PerpsHistoryError("VALIDATION_FAILED", message, { field });
|
|
10520
10644
|
}
|
|
10521
10645
|
function unavailable2(message, retryAfterMs) {
|
|
@@ -10546,16 +10670,16 @@ function encodeCursor(state) {
|
|
|
10546
10670
|
}
|
|
10547
10671
|
function decodeCursor(cursor) {
|
|
10548
10672
|
if (cursor.length > PERPS_HISTORY_MAX_CURSOR_LENGTH || !cursor.startsWith("ph1."))
|
|
10549
|
-
throw
|
|
10673
|
+
throw invalid2("cursor", "cursor is not one this client issued");
|
|
10550
10674
|
let state;
|
|
10551
10675
|
try {
|
|
10552
10676
|
state = JSON.parse(base64UrlDecode(cursor.slice(4)));
|
|
10553
10677
|
} catch {
|
|
10554
|
-
throw
|
|
10678
|
+
throw invalid2("cursor", "cursor is not one this client issued");
|
|
10555
10679
|
}
|
|
10556
10680
|
const ok = state !== null && typeof state === "object" && state.v === 1 && (state.k === "fills" || state.k === "funding") && (state.n === "mainnet" || state.n === "testnet") && typeof state.w === "string" && EVM_ADDRESS_RE2.test(state.w) && isTime(state.s) && isTime(state.e) && state.s <= state.e && Number.isSafeInteger(state.l) && state.l >= 1 && state.l <= PERPS_HISTORY_MAX_LIMIT[state.k] && isTime(state.t) && state.t >= state.s && state.t <= state.e && Array.isArray(state.b) && state.b.every((id) => typeof id === "string" && id.length <= 512) && Number.isSafeInteger(state.c) && state.c >= 0;
|
|
10557
10681
|
if (!ok)
|
|
10558
|
-
throw
|
|
10682
|
+
throw invalid2("cursor", "cursor is not one this client issued");
|
|
10559
10683
|
return state;
|
|
10560
10684
|
}
|
|
10561
10685
|
function canonical2(value) {
|
|
@@ -10641,35 +10765,35 @@ function resolveWindow(req) {
|
|
|
10641
10765
|
const kind = req.kind;
|
|
10642
10766
|
const address = req.address.toLowerCase();
|
|
10643
10767
|
if (!EVM_ADDRESS_RE2.test(address))
|
|
10644
|
-
throw
|
|
10768
|
+
throw invalid2("wallet", "The wallet's Hyperliquid account is not an EVM address");
|
|
10645
10769
|
for (const field of ["startTime", "endTime"]) {
|
|
10646
10770
|
const value = options[field];
|
|
10647
10771
|
if (value !== undefined && !isTime(value))
|
|
10648
|
-
throw
|
|
10772
|
+
throw invalid2(field, `${field} must be a whole, non-negative number of epoch milliseconds`);
|
|
10649
10773
|
}
|
|
10650
10774
|
const max = PERPS_HISTORY_MAX_LIMIT[kind];
|
|
10651
10775
|
if (options.limit !== undefined && (!Number.isSafeInteger(options.limit) || options.limit < 1 || options.limit > max))
|
|
10652
|
-
throw
|
|
10776
|
+
throw invalid2("limit", `limit must be a whole number from 1 to ${max} for ${kind}`);
|
|
10653
10777
|
if (options.cursor !== undefined) {
|
|
10654
10778
|
if (typeof options.cursor !== "string" || options.cursor.length === 0)
|
|
10655
|
-
throw
|
|
10779
|
+
throw invalid2("cursor", "cursor is not one this client issued");
|
|
10656
10780
|
const state = decodeCursor(options.cursor);
|
|
10657
10781
|
if (state.k !== kind)
|
|
10658
|
-
throw
|
|
10782
|
+
throw invalid2("cursor", `This cursor pages ${state.k}, not ${kind}`);
|
|
10659
10783
|
if (state.n !== req.network)
|
|
10660
|
-
throw
|
|
10784
|
+
throw invalid2("cursor", `This cursor pages ${state.n}, not ${req.network}`);
|
|
10661
10785
|
if (state.w !== address)
|
|
10662
|
-
throw
|
|
10786
|
+
throw invalid2("cursor", "This cursor pages another wallet");
|
|
10663
10787
|
if (options.startTime !== undefined && options.startTime !== state.s || options.endTime !== undefined && options.endTime !== state.e || options.limit !== undefined && options.limit !== state.l)
|
|
10664
|
-
throw
|
|
10788
|
+
throw invalid2("cursor", "The window or page size changed; start again without a cursor");
|
|
10665
10789
|
return { state };
|
|
10666
10790
|
}
|
|
10667
10791
|
const endTime = options.endTime ?? req.now();
|
|
10668
10792
|
const startTime = options.startTime ?? Math.max(0, endTime - PERPS_HISTORY_DEFAULT_WINDOW_MS);
|
|
10669
10793
|
if (!isTime(endTime))
|
|
10670
|
-
throw
|
|
10794
|
+
throw invalid2("endTime", "endTime must be epoch milliseconds");
|
|
10671
10795
|
if (startTime > endTime)
|
|
10672
|
-
throw
|
|
10796
|
+
throw invalid2("startTime", "startTime must not be after endTime");
|
|
10673
10797
|
return {
|
|
10674
10798
|
state: {
|
|
10675
10799
|
v: 1,
|
|
@@ -10840,7 +10964,7 @@ function pickSettings(raw) {
|
|
|
10840
10964
|
return out;
|
|
10841
10965
|
}
|
|
10842
10966
|
async function hyperliquidInfo(fetcher, network, body, opts = {}) {
|
|
10843
|
-
const sleep = opts.sleep ?? ((ms) => new Promise((
|
|
10967
|
+
const sleep = opts.sleep ?? ((ms) => new Promise((resolve3) => setTimeout(resolve3, ms)));
|
|
10844
10968
|
for (let attempt = 0;; attempt++) {
|
|
10845
10969
|
const controller = new AbortController;
|
|
10846
10970
|
const timer = setTimeout(() => controller.abort(), opts.timeoutMs ?? INFO_TIMEOUT_MS);
|
|
@@ -10876,7 +11000,7 @@ async function hyperliquidInfo(fetcher, network, body, opts = {}) {
|
|
|
10876
11000
|
}
|
|
10877
11001
|
}
|
|
10878
11002
|
async function readHyperliquidMarketSnapshot(fetcher, network, opts = {}) {
|
|
10879
|
-
const sleep = opts.sleep ?? ((ms) => new Promise((
|
|
11003
|
+
const sleep = opts.sleep ?? ((ms) => new Promise((resolve3) => setTimeout(resolve3, ms)));
|
|
10880
11004
|
let limited = false;
|
|
10881
11005
|
const watched = async (url, init) => {
|
|
10882
11006
|
const res = await fetcher(url, init);
|
|
@@ -13202,8 +13326,13 @@ async function swap(args, cfg, doFetch) {
|
|
|
13202
13326
|
...ok ? {} : { isError: true }
|
|
13203
13327
|
};
|
|
13204
13328
|
}
|
|
13205
|
-
function
|
|
13206
|
-
const cfg = resolveConfig(env);
|
|
13329
|
+
function serverConfig(server, env, resolved) {
|
|
13330
|
+
const cfg = localServerConfigs.get(server) ?? resolved ?? resolveConfig(env);
|
|
13331
|
+
localServerConfigs.set(server, cfg);
|
|
13332
|
+
return cfg;
|
|
13333
|
+
}
|
|
13334
|
+
function registerTools(server, env = process.env, resolved) {
|
|
13335
|
+
const cfg = serverConfig(server, env, resolved);
|
|
13207
13336
|
const allowed = resolveToolAllowlist(env);
|
|
13208
13337
|
registerToolSubset(server, {
|
|
13209
13338
|
tools: [...allowed].filter((name) => !isProfileEditTool(name)),
|
|
@@ -13353,7 +13482,7 @@ function registerToolSubset(server, options) {
|
|
|
13353
13482
|
});
|
|
13354
13483
|
register("candle_get_market", {
|
|
13355
13484
|
title: "Get market state",
|
|
13356
|
-
description: "Read Candle and indexed external markets, including indexed-but-not-routable tokens. No key needed. " + EXTERNAL_MARKET_DISCLOSURE + " " + "Read candleLaunched, launchpad, venue and trade.routable; jupiterOk and discovery flags are distinct. " + "Routability is stored eligibility, not a quote or permission. General quotes use POST /api/v1/trade/agent/quote. " + "Curve quotes and lifecycle describe Candle launches. MARKET_NOT_FOUND is a legacy code: read " + "error.routing.reason, error.discovery and sibling error.retryable. A curve-only 404 does not mean untradeable.",
|
|
13485
|
+
description: "Read Candle and indexed external markets, including indexed-but-not-routable tokens. No key needed. quoteAsset names the pool pair; quoteAssets lists accepted settlement ids, with quoteAssets[0] the default (not a liquidity promise). " + EXTERNAL_MARKET_DISCLOSURE + " " + "Read candleLaunched, launchpad, venue and trade.routable; jupiterOk and discovery flags are distinct. " + "Routability is stored eligibility, not a quote or permission. General quotes use POST /api/v1/trade/agent/quote. " + "Curve quotes and lifecycle describe Candle launches. MARKET_NOT_FOUND is a legacy code: read " + "error.routing.reason, error.discovery and sibling error.retryable. A curve-only 404 does not mean untradeable.",
|
|
13357
13486
|
inputSchema: getMarketShape
|
|
13358
13487
|
}, async (args) => callAndRelay("candle_get_market", args, getConfig(), doFetch));
|
|
13359
13488
|
register("candle_quote", {
|
|
@@ -13877,8 +14006,8 @@ function registerToolSubset(server, options) {
|
|
|
13877
14006
|
annotations: labRead
|
|
13878
14007
|
}, labTool("candle_lab_edges"));
|
|
13879
14008
|
}
|
|
13880
|
-
async function registerEligibleProfileTool(server, env = process.env, doFetch = fetch) {
|
|
13881
|
-
const cfg =
|
|
14009
|
+
async function registerEligibleProfileTool(server, env = process.env, doFetch = fetch, resolved) {
|
|
14010
|
+
const cfg = serverConfig(server, env, resolved);
|
|
13882
14011
|
const allowlist = resolveToolAllowlist(env);
|
|
13883
14012
|
const wanted = PROFILE_EDIT_TOOL_NAMES.filter((name) => allowlist.has(name));
|
|
13884
14013
|
let eligible = false;
|
|
@@ -13906,7 +14035,7 @@ async function registerEligibleProfileTool(server, env = process.env, doFetch =
|
|
|
13906
14035
|
}
|
|
13907
14036
|
return eligible;
|
|
13908
14037
|
}
|
|
13909
|
-
var VAMP_CANDIDATES_DESCRIPTION, localProfileTools, STAKING_DISCLOSURE = "No instant unstake. Read pool.withdrawalTimelockSeconds for the wait. Solana rewards accrue to the holding wallet. sCNDL in any eligible account wallet counts toward Pro and earns the account's Hood staking reward, except a wallet another account also claims, wallets past the 200-wallet cap, and an account with no EVM wallet. CNDL in a pending withdrawal counts toward nothing for Pro.", stakingWriteShape, TOOL_NAMES, LAB_TOOL_NAMES, PROFILE_EDIT_TOOL_NAMES, isProfileEditTool = (name) => PROFILE_EDIT_TOOL_NAMES.includes(name), OPERATION_NOT_FOUND_RULE, SWAP_RECEIPT_DESCRIPTION, SWAP_SETTLEMENT_REREAD, getMarketShape, quoteShape, priceHistoryShape, TOKEN_EVENTS_LIMIT_MESSAGE = "limit must be a whole number from 1 to 1000", tokenEventsLimit, TOKEN_EVENTS_KIND_NOTE = "kept back from the request and applied to the returned page by this server, so a filtered page can be shorter than limit while older events of other kinds remain: page with nextCursor as before until it is null", tokenCardShape, tokenEventsShape, tokenForensicsShape, FEED_LIMIT_MESSAGE = "limit must be a whole number from 1 to 200", feedLimit, getFeedShape, reportActivityShape, getAgentProfileShape, listAgentsShape, createPostShape, deletePostShape, listAgentPostsShape, getAgentPositionsShape, getOperationShape, getSwapReceiptShape, vampCandidatesShape, getFeesShape, atomicPayerShape, atomicLaunchDryRunShape, claimFeesShape, resolveTokenShape, tradingWalletsShape, spendableBalancesShape, profileWalletsShape, profilePnlShape, profileTradesShape, noArgsShape, setProfileWalletsShape, swapShape, tradeShape, tradeExecuteShape, tokenImageUrl, tokenBannerUrl, localImageShape, localLaunchTokenShape, localLaunchAndSeedShape, IMAGE_PATH_DISCLOSURE, transferShape, sweepShape, PROFILE_PNL_HYPERLIQUID;
|
|
14038
|
+
var VAMP_CANDIDATES_DESCRIPTION, localProfileTools, STAKING_DISCLOSURE = "No instant unstake. Read pool.withdrawalTimelockSeconds for the wait. Solana rewards accrue to the holding wallet. sCNDL in any eligible account wallet counts toward Pro and earns the account's Hood staking reward, except a wallet another account also claims, wallets past the 200-wallet cap, and an account with no EVM wallet. CNDL in a pending withdrawal counts toward nothing for Pro.", stakingWriteShape, TOOL_NAMES, LAB_TOOL_NAMES, PROFILE_EDIT_TOOL_NAMES, isProfileEditTool = (name) => PROFILE_EDIT_TOOL_NAMES.includes(name), OPERATION_NOT_FOUND_RULE, SWAP_RECEIPT_DESCRIPTION, SWAP_SETTLEMENT_REREAD, getMarketShape, quoteShape, priceHistoryShape, TOKEN_EVENTS_LIMIT_MESSAGE = "limit must be a whole number from 1 to 1000", tokenEventsLimit, TOKEN_EVENTS_KIND_NOTE = "kept back from the request and applied to the returned page by this server, so a filtered page can be shorter than limit while older events of other kinds remain: page with nextCursor as before until it is null", tokenCardShape, tokenEventsShape, tokenForensicsShape, FEED_LIMIT_MESSAGE = "limit must be a whole number from 1 to 200", feedLimit, getFeedShape, reportActivityShape, getAgentProfileShape, listAgentsShape, createPostShape, deletePostShape, listAgentPostsShape, getAgentPositionsShape, getOperationShape, getSwapReceiptShape, vampCandidatesShape, getFeesShape, atomicPayerShape, atomicLaunchDryRunShape, claimFeesShape, resolveTokenShape, tradingWalletsShape, spendableBalancesShape, profileWalletsShape, profilePnlShape, profileTradesShape, noArgsShape, setProfileWalletsShape, swapShape, tradeShape, tradeExecuteShape, tokenImageUrl, tokenBannerUrl, localImageShape, localLaunchTokenShape, localLaunchAndSeedShape, IMAGE_PATH_DISCLOSURE, transferShape, sweepShape, PROFILE_PNL_HYPERLIQUID, localServerConfigs;
|
|
13910
14039
|
var init_tools = __esm(() => {
|
|
13911
14040
|
init_zod();
|
|
13912
14041
|
init_chain_registry();
|
|
@@ -14254,6 +14383,7 @@ var init_tools = __esm(() => {
|
|
|
14254
14383
|
mints: exports_external.array(exports_external.string()).optional().describe("Extra token mints/contracts to sweep besides the chain's base assets (own-wallet destinations only).")
|
|
14255
14384
|
};
|
|
14256
14385
|
PROFILE_PNL_HYPERLIQUID = "While Hyperliquid is enabled, `hyperliquid` reports the profile's main perps over every EVM TEE wallet bound " + "to it, per binding period (`coverage: 'profile'`): realized gross, funding (positive received, negative paid), " + "fees (builder fees included), realizedNetUsd = gross + funding - fees, `unrealizedUsd` at each wallet's " + "cutoff, and `netUsd` = realized net + unrealized, with `markedAt` (the oldest wallet cutoff) and open " + "`positions` (each `fundingNetUsd` positive when earned). Facts and unrealized stop at the same cutoff; each " + "`byWallet` period is `live` (reconciled on this read, not yet settled) or `settled` (a stored snapshot). " + "When `read` is true, `pnl.totalUsd` includes `netUsd` and `perpsInTotal` is true. When `read` is false, " + "`pnl.totalUsd` is spot only, `perpsInTotal` is false and `reason` says why; that is never a zero. Check " + "`historyPartial` and `partialReasons`.";
|
|
14386
|
+
localServerConfigs = new WeakMap;
|
|
14257
14387
|
});
|
|
14258
14388
|
|
|
14259
14389
|
// ../../node_modules/@noble/hashes/esm/_md.js
|
|
@@ -20076,7 +20206,7 @@ function apiKeyPrefix(key) {
|
|
|
20076
20206
|
return;
|
|
20077
20207
|
}
|
|
20078
20208
|
function credentialEnvOverrides(env) {
|
|
20079
|
-
return ["CANDLE_API_KEY", "CANDLE_DEVICE_TOKEN"].filter((name) => env[name]?.trim());
|
|
20209
|
+
return ["CANDLE_API_KEY_FILE", "CANDLE_API_KEY", "CANDLE_DEVICE_TOKEN"].filter((name) => env[name]?.trim());
|
|
20080
20210
|
}
|
|
20081
20211
|
function identityLine(profile, account, apiUrl, overrides, username, options = {}) {
|
|
20082
20212
|
const address = account === undefined ? undefined : shortId(account, options.full);
|
|
@@ -20097,7 +20227,7 @@ async function printIdentity(ctx) {
|
|
|
20097
20227
|
if (overrides.length > 0) {
|
|
20098
20228
|
account = undefined;
|
|
20099
20229
|
username = undefined;
|
|
20100
|
-
const key = ctx.deps.env.CANDLE_API_KEY?.trim();
|
|
20230
|
+
const key = ctx.deps.env.CANDLE_API_KEY_FILE?.trim() || ctx.deps.env.CANDLE_API_KEY?.trim() ? (await resolveApiCredential(ctx.deps, ctx.profile)).key : undefined;
|
|
20101
20231
|
if (key) {
|
|
20102
20232
|
const lookup = await fetchAccount(ctx.deps, ctx.apiUrl, key);
|
|
20103
20233
|
if (lookup.account)
|
|
@@ -20149,6 +20279,7 @@ function profileTable(config, now) {
|
|
|
20149
20279
|
var ProfileFleetOnlyError, PRE_PROFILE_FIELDS, API_KEY_PREFIXES, API_KEY_RANDOM_LENGTH = 43, INVALID_RPC_HOST = "invalid (fix with profile set)";
|
|
20150
20280
|
var init_profiles = __esm(() => {
|
|
20151
20281
|
init_account();
|
|
20282
|
+
init_deps();
|
|
20152
20283
|
init_presentation();
|
|
20153
20284
|
init_render();
|
|
20154
20285
|
ProfileFleetOnlyError = class ProfileFleetOnlyError extends Error {
|
|
@@ -22706,7 +22837,7 @@ __export(exports_store, {
|
|
|
22706
22837
|
candleConfigDir: () => candleConfigDir,
|
|
22707
22838
|
CONFIG_DIR_ENV: () => CONFIG_DIR_ENV
|
|
22708
22839
|
});
|
|
22709
|
-
import { access, chmod as chmod3, constants as
|
|
22840
|
+
import { access, chmod as chmod3, constants as constants3, mkdir as mkdir3, readFile as readFile5, stat as stat2 } from "node:fs/promises";
|
|
22710
22841
|
import { dirname as dirname4, join as join3 } from "node:path";
|
|
22711
22842
|
function candleConfigDir(env, home) {
|
|
22712
22843
|
const configured = env.CANDLE_CONFIG_DIR?.trim();
|
|
@@ -22746,7 +22877,7 @@ function errnoOf(error) {
|
|
|
22746
22877
|
}
|
|
22747
22878
|
async function writableDir(path) {
|
|
22748
22879
|
try {
|
|
22749
|
-
await access(path,
|
|
22880
|
+
await access(path, constants3.W_OK | constants3.X_OK);
|
|
22750
22881
|
return;
|
|
22751
22882
|
} catch (error) {
|
|
22752
22883
|
return errnoOf(error);
|
|
@@ -23215,7 +23346,7 @@ async function withFileLock(target, fn) {
|
|
|
23215
23346
|
if (Date.now() > deadline) {
|
|
23216
23347
|
throw new Error(`Timed out waiting for ${lockPath}. Another candle process is writing; if none is running, delete that file.`);
|
|
23217
23348
|
}
|
|
23218
|
-
await new Promise((
|
|
23349
|
+
await new Promise((resolve3) => setTimeout(resolve3, RETRY_MS));
|
|
23219
23350
|
}
|
|
23220
23351
|
}
|
|
23221
23352
|
try {
|
|
@@ -23388,18 +23519,18 @@ async function promptVisibleLine(promptText) {
|
|
|
23388
23519
|
}
|
|
23389
23520
|
async function readVisibleLine(promptText, io) {
|
|
23390
23521
|
const readline = await import("node:readline");
|
|
23391
|
-
return new Promise((
|
|
23522
|
+
return new Promise((resolve3, reject) => {
|
|
23392
23523
|
const rl = readline.createInterface({ input: io.input, output: io.output, terminal: true });
|
|
23393
23524
|
rl.question(promptText, (answer) => {
|
|
23394
23525
|
rl.close();
|
|
23395
|
-
|
|
23526
|
+
resolve3(answer);
|
|
23396
23527
|
});
|
|
23397
23528
|
onInterrupted(rl, io, reject);
|
|
23398
23529
|
});
|
|
23399
23530
|
}
|
|
23400
23531
|
async function readHiddenLine(promptText, io) {
|
|
23401
23532
|
const readline = await import("node:readline");
|
|
23402
|
-
return new Promise((
|
|
23533
|
+
return new Promise((resolve3, reject) => {
|
|
23403
23534
|
const rl = readline.createInterface({ input: io.input, output: io.output, terminal: true });
|
|
23404
23535
|
const rlInternals = rl;
|
|
23405
23536
|
rlInternals._writeToOutput = (text) => {
|
|
@@ -23410,7 +23541,7 @@ async function readHiddenLine(promptText, io) {
|
|
|
23410
23541
|
rl.close();
|
|
23411
23542
|
io.output.write(`
|
|
23412
23543
|
`);
|
|
23413
|
-
|
|
23544
|
+
resolve3(answer);
|
|
23414
23545
|
});
|
|
23415
23546
|
onInterrupted(rl, io, reject);
|
|
23416
23547
|
});
|
|
@@ -23440,6 +23571,8 @@ var init_secret_store = __esm(() => {
|
|
|
23440
23571
|
|
|
23441
23572
|
// src/deps.ts
|
|
23442
23573
|
async function resolveDeviceToken(deps, profile) {
|
|
23574
|
+
if (hasApiKeyFile(deps.env))
|
|
23575
|
+
await resolveApiCredential(deps, profile);
|
|
23443
23576
|
if (profile !== undefined)
|
|
23444
23577
|
assertOrdinaryProfile(await deps.readConfig(), profile);
|
|
23445
23578
|
const fromEnv = deps.env.CANDLE_DEVICE_TOKEN?.trim();
|
|
@@ -23452,20 +23585,53 @@ async function resolveDeviceToken(deps, profile) {
|
|
|
23452
23585
|
const stored = await deps.store.get(ref);
|
|
23453
23586
|
return stored ?? undefined;
|
|
23454
23587
|
}
|
|
23455
|
-
|
|
23588
|
+
function beginCredentialInvocation(deps) {
|
|
23589
|
+
const scoped = { ...deps, env: { ...deps.env } };
|
|
23590
|
+
return { ...scoped, resolvedApiKeyFile: apiKeyFileSnapshot(scoped.env, scoped.loadApiKeyFile) };
|
|
23591
|
+
}
|
|
23592
|
+
async function resolveApiCredential(deps, profile) {
|
|
23593
|
+
if (hasApiKeyFile(deps.env)) {
|
|
23594
|
+
let load = deps.resolvedApiKeyFile ?? fileSnapshots.get(deps);
|
|
23595
|
+
if (!load) {
|
|
23596
|
+
load = apiKeyFileSnapshot(deps.env, deps.loadApiKeyFile);
|
|
23597
|
+
fileSnapshots.set(deps, load);
|
|
23598
|
+
}
|
|
23599
|
+
const key2 = await load();
|
|
23600
|
+
if (profile !== undefined)
|
|
23601
|
+
assertOrdinaryProfile(await deps.readConfig(), profile);
|
|
23602
|
+
return { key: key2, source: "file" };
|
|
23603
|
+
}
|
|
23456
23604
|
if (profile !== undefined)
|
|
23457
23605
|
assertOrdinaryProfile(await deps.readConfig(), profile);
|
|
23458
23606
|
const fromEnv = deps.env.CANDLE_API_KEY?.trim();
|
|
23459
23607
|
if (fromEnv)
|
|
23460
|
-
return fromEnv;
|
|
23608
|
+
return { key: fromEnv, source: "env" };
|
|
23461
23609
|
const ref = profile ? profileSecretRef(profile, "apiKey") : SECRET_REFS.apiKey;
|
|
23462
|
-
const
|
|
23463
|
-
return
|
|
23610
|
+
const key = await deps.store.get(ref) ?? undefined;
|
|
23611
|
+
return { key, source: key ? profile ? "profile" : "legacy" : "none" };
|
|
23464
23612
|
}
|
|
23613
|
+
async function resolveExternalApiCredential(deps) {
|
|
23614
|
+
if (hasApiKeyFile(deps.env)) {
|
|
23615
|
+
let load = deps.resolvedApiKeyFile ?? fileSnapshots.get(deps);
|
|
23616
|
+
if (!load) {
|
|
23617
|
+
load = apiKeyFileSnapshot(deps.env, deps.loadApiKeyFile);
|
|
23618
|
+
fileSnapshots.set(deps, load);
|
|
23619
|
+
}
|
|
23620
|
+
return { key: await load(), source: "file" };
|
|
23621
|
+
}
|
|
23622
|
+
const fromEnv = deps.env.CANDLE_API_KEY?.trim();
|
|
23623
|
+
return fromEnv ? { key: fromEnv, source: "env" } : undefined;
|
|
23624
|
+
}
|
|
23625
|
+
async function resolveApiKey(deps, profile) {
|
|
23626
|
+
return (await resolveApiCredential(deps, profile)).key;
|
|
23627
|
+
}
|
|
23628
|
+
var fileSnapshots;
|
|
23465
23629
|
var init_deps = __esm(() => {
|
|
23630
|
+
init_api_key_file();
|
|
23466
23631
|
init_ownership();
|
|
23467
23632
|
init_profiles();
|
|
23468
23633
|
init_secret_store();
|
|
23634
|
+
fileSnapshots = new WeakMap;
|
|
23469
23635
|
});
|
|
23470
23636
|
|
|
23471
23637
|
// src/key-signers.ts
|
|
@@ -26181,6 +26347,10 @@ var init_trading_checks = __esm(() => {
|
|
|
26181
26347
|
// src/commands/swap.ts
|
|
26182
26348
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
26183
26349
|
function tradingFailure(ctx, error, id) {
|
|
26350
|
+
if (error instanceof ApiKeyFileError) {
|
|
26351
|
+
writeLocalFailure(ctx.deps, { code: error.code, message: error.message }, ctx.json);
|
|
26352
|
+
return 1;
|
|
26353
|
+
}
|
|
26184
26354
|
if (error instanceof TradingUsage) {
|
|
26185
26355
|
writeUsageFailure(ctx.deps, error.message, ctx.json);
|
|
26186
26356
|
return 2;
|
|
@@ -27212,6 +27382,7 @@ async function swapRecover(args, ctx) {
|
|
|
27212
27382
|
var isText = (value) => typeof value === "string" && value.length > 0, textsOf = (value) => Array.isArray(value) ? value.filter(isText) : [], AGENT_MAX_SLIPPAGE_BPS = 5000, SLIPPAGE_RANGE_MESSAGE, settlementSchema, SWAP_RECEIPT_USAGE = "Usage: candle swap receipt <hash> | candle swap receipt --client-swap-id <id>", BRIDGE_STATUS_WORDS, bridgeFactsSchema, HOOD_TRADE_LEGS, bridgeBuildSchema;
|
|
27213
27383
|
var init_swap = __esm(() => {
|
|
27214
27384
|
init_zod();
|
|
27385
|
+
init_api_key_file();
|
|
27215
27386
|
init_swap_receipt();
|
|
27216
27387
|
init_tools();
|
|
27217
27388
|
init_args();
|
|
@@ -27540,7 +27711,7 @@ async function readSignerRoles(rpc, addresses, opts) {
|
|
|
27540
27711
|
} catch {}
|
|
27541
27712
|
return { ...base2, target: programData, unresolvedProgram: true };
|
|
27542
27713
|
};
|
|
27543
|
-
await new Promise((
|
|
27714
|
+
await new Promise((resolve3) => {
|
|
27544
27715
|
const pump = () => {
|
|
27545
27716
|
let skippedAny = false;
|
|
27546
27717
|
while (active < cap && next < tasks.length) {
|
|
@@ -27575,7 +27746,7 @@ async function readSignerRoles(rpc, addresses, opts) {
|
|
|
27575
27746
|
if (skippedAny)
|
|
27576
27747
|
progress();
|
|
27577
27748
|
if (active === 0 && next >= tasks.length)
|
|
27578
|
-
|
|
27749
|
+
resolve3();
|
|
27579
27750
|
};
|
|
27580
27751
|
pump();
|
|
27581
27752
|
});
|
|
@@ -28050,7 +28221,8 @@ function accountUnresolved(reason) {
|
|
|
28050
28221
|
}
|
|
28051
28222
|
async function readControlledBy(ctx) {
|
|
28052
28223
|
const { deps } = ctx;
|
|
28053
|
-
const
|
|
28224
|
+
const credential = await resolveApiCredential(deps, ctx.profile);
|
|
28225
|
+
const apiKey = credential.key;
|
|
28054
28226
|
if (!apiKey)
|
|
28055
28227
|
throw accountUnresolved("no API key is available");
|
|
28056
28228
|
const keyPrefix = apiKeyPrefix(apiKey);
|
|
@@ -28071,7 +28243,7 @@ async function readControlledBy(ctx) {
|
|
|
28071
28243
|
throw accountUnresolved("the response carried no account");
|
|
28072
28244
|
}
|
|
28073
28245
|
const username = typeof body.username === "string" && body.username.length > 0 ? body.username : null;
|
|
28074
|
-
const keySource =
|
|
28246
|
+
const keySource = credential.source === "legacy" || credential.source === "none" ? "default" : credential.source;
|
|
28075
28247
|
const apiUrlFrom = ctx.apiUrlFlag !== undefined ? "--api-url" : deps.env.CANDLE_API_URL?.trim() ? "CANDLE_API_URL" : undefined;
|
|
28076
28248
|
return {
|
|
28077
28249
|
account: body.account,
|
|
@@ -28111,7 +28283,7 @@ async function readKeyLabel(ctx, keyPrefix) {
|
|
|
28111
28283
|
}
|
|
28112
28284
|
function renderControlledBy(controlledBy, n) {
|
|
28113
28285
|
const subject = n === 1 ? "This key" : `These ${n} keys`;
|
|
28114
|
-
const source = controlledBy.keySource === "env" ? "CANDLE_API_KEY" : controlledBy.keySource === "profile" ? `profile ${controlledBy.profileName ?? ""}`.trimEnd() : "default credentials";
|
|
28286
|
+
const source = controlledBy.keySource === "file" ? "CANDLE_API_KEY_FILE" : controlledBy.keySource === "env" ? "CANDLE_API_KEY" : controlledBy.keySource === "profile" ? `profile ${controlledBy.profileName ?? ""}`.trimEnd() : "default credentials";
|
|
28115
28287
|
const cleaned = controlledBy.keyLabel !== null ? labelCell(controlledBy.keyLabel) : "";
|
|
28116
28288
|
const label = cleaned.length > 0 ? `(${cleaned}) ` : "";
|
|
28117
28289
|
const environment = controlledBy.environment ?? "not a Candle host";
|
|
@@ -29250,7 +29422,7 @@ var init_ecies = __esm(() => {
|
|
|
29250
29422
|
});
|
|
29251
29423
|
|
|
29252
29424
|
// src/vault/enclave.ts
|
|
29253
|
-
import { access as access2, constants as
|
|
29425
|
+
import { access as access2, constants as constants4 } from "node:fs/promises";
|
|
29254
29426
|
import { dirname as dirname7, join as join7 } from "node:path";
|
|
29255
29427
|
function parseReleasePolicy(value) {
|
|
29256
29428
|
const bad = (detail) => {
|
|
@@ -29278,7 +29450,7 @@ function parseReleasePolicy(value) {
|
|
|
29278
29450
|
}
|
|
29279
29451
|
async function isExecutable(path) {
|
|
29280
29452
|
try {
|
|
29281
|
-
await access2(path,
|
|
29453
|
+
await access2(path, constants4.X_OK);
|
|
29282
29454
|
return true;
|
|
29283
29455
|
} catch {
|
|
29284
29456
|
return false;
|
|
@@ -29835,11 +30007,11 @@ var init_platform = __esm(() => {
|
|
|
29835
30007
|
});
|
|
29836
30008
|
|
|
29837
30009
|
// src/vault/fido2.ts
|
|
29838
|
-
import { access as access3, constants as
|
|
30010
|
+
import { access as access3, constants as constants5 } from "node:fs/promises";
|
|
29839
30011
|
import { dirname as dirname8, join as join8 } from "node:path";
|
|
29840
30012
|
async function isExecutable2(path) {
|
|
29841
30013
|
try {
|
|
29842
|
-
await access3(path,
|
|
30014
|
+
await access3(path, constants5.X_OK);
|
|
29843
30015
|
return true;
|
|
29844
30016
|
} catch {
|
|
29845
30017
|
return false;
|
|
@@ -38977,6 +39149,10 @@ async function typedConfirm(io, label, address, action) {
|
|
|
38977
39149
|
return typed.trim().toLowerCase() === "confirm";
|
|
38978
39150
|
}
|
|
38979
39151
|
function writeVaultFailure(ctx, error) {
|
|
39152
|
+
if (error instanceof ApiKeyFileError) {
|
|
39153
|
+
writeLocalFailure(ctx.deps, { code: error.code, message: error.message }, ctx.json);
|
|
39154
|
+
return 1;
|
|
39155
|
+
}
|
|
38980
39156
|
if (isUsageError(error))
|
|
38981
39157
|
return usage2(ctx, error.message);
|
|
38982
39158
|
if (isVaultError(error)) {
|
|
@@ -39071,6 +39247,7 @@ function takeRepeatedFlag(args, flag) {
|
|
|
39071
39247
|
}
|
|
39072
39248
|
var noTerminalRefusals, PASSPHRASE_ONLY_PREFIX = "Passphrase only: ";
|
|
39073
39249
|
var init_vault_support = __esm(() => {
|
|
39250
|
+
init_api_key_file();
|
|
39074
39251
|
init_args();
|
|
39075
39252
|
init_presentation();
|
|
39076
39253
|
init_render();
|
|
@@ -41564,15 +41741,15 @@ class Chacha20Poly1305Context {
|
|
|
41564
41741
|
return await this._open(iv, data, aad);
|
|
41565
41742
|
}
|
|
41566
41743
|
_seal(iv, data, aad) {
|
|
41567
|
-
return new Promise((
|
|
41744
|
+
return new Promise((resolve3) => {
|
|
41568
41745
|
const ret = chacha20poly1305(this._key, new Uint8Array(iv), new Uint8Array(aad)).encrypt(new Uint8Array(data));
|
|
41569
|
-
|
|
41746
|
+
resolve3(ret.buffer);
|
|
41570
41747
|
});
|
|
41571
41748
|
}
|
|
41572
41749
|
_open(iv, data, aad) {
|
|
41573
|
-
return new Promise((
|
|
41750
|
+
return new Promise((resolve3) => {
|
|
41574
41751
|
const ret = chacha20poly1305(this._key, new Uint8Array(iv), new Uint8Array(aad)).decrypt(new Uint8Array(data));
|
|
41575
|
-
|
|
41752
|
+
resolve3(ret.buffer);
|
|
41576
41753
|
});
|
|
41577
41754
|
}
|
|
41578
41755
|
}
|
|
@@ -41765,8 +41942,8 @@ class Mutex {
|
|
|
41765
41942
|
}
|
|
41766
41943
|
async lock() {
|
|
41767
41944
|
let releaseLock;
|
|
41768
|
-
const nextLock = new Promise((
|
|
41769
|
-
releaseLock =
|
|
41945
|
+
const nextLock = new Promise((resolve3) => {
|
|
41946
|
+
releaseLock = resolve3;
|
|
41770
41947
|
});
|
|
41771
41948
|
const previousLock = __classPrivateFieldGet(this, _Mutex_locked, "f");
|
|
41772
41949
|
__classPrivateFieldSet(this, _Mutex_locked, nextLock, "f");
|
|
@@ -48595,7 +48772,7 @@ class Protocol {
|
|
|
48595
48772
|
}
|
|
48596
48773
|
request(request2, resultSchema, options) {
|
|
48597
48774
|
const { relatedRequestId, resumptionToken, onresumptiontoken } = options !== null && options !== undefined ? options : {};
|
|
48598
|
-
return new Promise((
|
|
48775
|
+
return new Promise((resolve3, reject) => {
|
|
48599
48776
|
var _a, _b, _c, _d, _e, _f;
|
|
48600
48777
|
if (!this._transport) {
|
|
48601
48778
|
reject(new Error("Not connected"));
|
|
@@ -48646,7 +48823,7 @@ class Protocol {
|
|
|
48646
48823
|
}
|
|
48647
48824
|
try {
|
|
48648
48825
|
const result2 = resultSchema.parse(response.result);
|
|
48649
|
-
|
|
48826
|
+
resolve3(result2);
|
|
48650
48827
|
} catch (error) {
|
|
48651
48828
|
reject(error);
|
|
48652
48829
|
}
|
|
@@ -49121,11 +49298,11 @@ var require_codegen = __commonJS((exports) => {
|
|
|
49121
49298
|
const rhs = this.rhs === undefined ? "" : ` = ${this.rhs}`;
|
|
49122
49299
|
return `${varKind} ${this.name}${rhs};` + _n;
|
|
49123
49300
|
}
|
|
49124
|
-
optimizeNames(names,
|
|
49301
|
+
optimizeNames(names, constants6) {
|
|
49125
49302
|
if (!names[this.name.str])
|
|
49126
49303
|
return;
|
|
49127
49304
|
if (this.rhs)
|
|
49128
|
-
this.rhs = optimizeExpr(this.rhs, names,
|
|
49305
|
+
this.rhs = optimizeExpr(this.rhs, names, constants6);
|
|
49129
49306
|
return this;
|
|
49130
49307
|
}
|
|
49131
49308
|
get names() {
|
|
@@ -49143,10 +49320,10 @@ var require_codegen = __commonJS((exports) => {
|
|
|
49143
49320
|
render({ _n }) {
|
|
49144
49321
|
return `${this.lhs} = ${this.rhs};` + _n;
|
|
49145
49322
|
}
|
|
49146
|
-
optimizeNames(names,
|
|
49323
|
+
optimizeNames(names, constants6) {
|
|
49147
49324
|
if (this.lhs instanceof code_1.Name && !names[this.lhs.str] && !this.sideEffects)
|
|
49148
49325
|
return;
|
|
49149
|
-
this.rhs = optimizeExpr(this.rhs, names,
|
|
49326
|
+
this.rhs = optimizeExpr(this.rhs, names, constants6);
|
|
49150
49327
|
return this;
|
|
49151
49328
|
}
|
|
49152
49329
|
get names() {
|
|
@@ -49212,8 +49389,8 @@ var require_codegen = __commonJS((exports) => {
|
|
|
49212
49389
|
optimizeNodes() {
|
|
49213
49390
|
return `${this.code}` ? this : undefined;
|
|
49214
49391
|
}
|
|
49215
|
-
optimizeNames(names,
|
|
49216
|
-
this.code = optimizeExpr(this.code, names,
|
|
49392
|
+
optimizeNames(names, constants6) {
|
|
49393
|
+
this.code = optimizeExpr(this.code, names, constants6);
|
|
49217
49394
|
return this;
|
|
49218
49395
|
}
|
|
49219
49396
|
get names() {
|
|
@@ -49243,12 +49420,12 @@ var require_codegen = __commonJS((exports) => {
|
|
|
49243
49420
|
}
|
|
49244
49421
|
return nodes.length > 0 ? this : undefined;
|
|
49245
49422
|
}
|
|
49246
|
-
optimizeNames(names,
|
|
49423
|
+
optimizeNames(names, constants6) {
|
|
49247
49424
|
const { nodes } = this;
|
|
49248
49425
|
let i = nodes.length;
|
|
49249
49426
|
while (i--) {
|
|
49250
49427
|
const n = nodes[i];
|
|
49251
|
-
if (n.optimizeNames(names,
|
|
49428
|
+
if (n.optimizeNames(names, constants6))
|
|
49252
49429
|
continue;
|
|
49253
49430
|
subtractNames(names, n.names);
|
|
49254
49431
|
nodes.splice(i, 1);
|
|
@@ -49305,12 +49482,12 @@ var require_codegen = __commonJS((exports) => {
|
|
|
49305
49482
|
return;
|
|
49306
49483
|
return this;
|
|
49307
49484
|
}
|
|
49308
|
-
optimizeNames(names,
|
|
49485
|
+
optimizeNames(names, constants6) {
|
|
49309
49486
|
var _a;
|
|
49310
|
-
this.else = (_a = this.else) === null || _a === undefined ? undefined : _a.optimizeNames(names,
|
|
49311
|
-
if (!(super.optimizeNames(names,
|
|
49487
|
+
this.else = (_a = this.else) === null || _a === undefined ? undefined : _a.optimizeNames(names, constants6);
|
|
49488
|
+
if (!(super.optimizeNames(names, constants6) || this.else))
|
|
49312
49489
|
return;
|
|
49313
|
-
this.condition = optimizeExpr(this.condition, names,
|
|
49490
|
+
this.condition = optimizeExpr(this.condition, names, constants6);
|
|
49314
49491
|
return this;
|
|
49315
49492
|
}
|
|
49316
49493
|
get names() {
|
|
@@ -49335,10 +49512,10 @@ var require_codegen = __commonJS((exports) => {
|
|
|
49335
49512
|
render(opts) {
|
|
49336
49513
|
return `for(${this.iteration})` + super.render(opts);
|
|
49337
49514
|
}
|
|
49338
|
-
optimizeNames(names,
|
|
49339
|
-
if (!super.optimizeNames(names,
|
|
49515
|
+
optimizeNames(names, constants6) {
|
|
49516
|
+
if (!super.optimizeNames(names, constants6))
|
|
49340
49517
|
return;
|
|
49341
|
-
this.iteration = optimizeExpr(this.iteration, names,
|
|
49518
|
+
this.iteration = optimizeExpr(this.iteration, names, constants6);
|
|
49342
49519
|
return this;
|
|
49343
49520
|
}
|
|
49344
49521
|
get names() {
|
|
@@ -49376,10 +49553,10 @@ var require_codegen = __commonJS((exports) => {
|
|
|
49376
49553
|
render(opts) {
|
|
49377
49554
|
return `for(${this.varKind} ${this.name} ${this.loop} ${this.iterable})` + super.render(opts);
|
|
49378
49555
|
}
|
|
49379
|
-
optimizeNames(names,
|
|
49380
|
-
if (!super.optimizeNames(names,
|
|
49556
|
+
optimizeNames(names, constants6) {
|
|
49557
|
+
if (!super.optimizeNames(names, constants6))
|
|
49381
49558
|
return;
|
|
49382
|
-
this.iterable = optimizeExpr(this.iterable, names,
|
|
49559
|
+
this.iterable = optimizeExpr(this.iterable, names, constants6);
|
|
49383
49560
|
return this;
|
|
49384
49561
|
}
|
|
49385
49562
|
get names() {
|
|
@@ -49424,11 +49601,11 @@ var require_codegen = __commonJS((exports) => {
|
|
|
49424
49601
|
(_b = this.finally) === null || _b === undefined || _b.optimizeNodes();
|
|
49425
49602
|
return this;
|
|
49426
49603
|
}
|
|
49427
|
-
optimizeNames(names,
|
|
49604
|
+
optimizeNames(names, constants6) {
|
|
49428
49605
|
var _a, _b;
|
|
49429
|
-
super.optimizeNames(names,
|
|
49430
|
-
(_a = this.catch) === null || _a === undefined || _a.optimizeNames(names,
|
|
49431
|
-
(_b = this.finally) === null || _b === undefined || _b.optimizeNames(names,
|
|
49606
|
+
super.optimizeNames(names, constants6);
|
|
49607
|
+
(_a = this.catch) === null || _a === undefined || _a.optimizeNames(names, constants6);
|
|
49608
|
+
(_b = this.finally) === null || _b === undefined || _b.optimizeNames(names, constants6);
|
|
49432
49609
|
return this;
|
|
49433
49610
|
}
|
|
49434
49611
|
get names() {
|
|
@@ -49702,7 +49879,7 @@ var require_codegen = __commonJS((exports) => {
|
|
|
49702
49879
|
function addExprNames(names, from) {
|
|
49703
49880
|
return from instanceof code_1._CodeOrName ? addNames(names, from.names) : names;
|
|
49704
49881
|
}
|
|
49705
|
-
function optimizeExpr(expr, names,
|
|
49882
|
+
function optimizeExpr(expr, names, constants6) {
|
|
49706
49883
|
if (expr instanceof code_1.Name)
|
|
49707
49884
|
return replaceName(expr);
|
|
49708
49885
|
if (!canOptimize(expr))
|
|
@@ -49717,14 +49894,14 @@ var require_codegen = __commonJS((exports) => {
|
|
|
49717
49894
|
return items;
|
|
49718
49895
|
}, []));
|
|
49719
49896
|
function replaceName(n) {
|
|
49720
|
-
const c =
|
|
49897
|
+
const c = constants6[n.str];
|
|
49721
49898
|
if (c === undefined || names[n.str] !== 1)
|
|
49722
49899
|
return n;
|
|
49723
49900
|
delete names[n.str];
|
|
49724
49901
|
return c;
|
|
49725
49902
|
}
|
|
49726
49903
|
function canOptimize(e) {
|
|
49727
|
-
return e instanceof code_1._Code && e._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 &&
|
|
49904
|
+
return e instanceof code_1._Code && e._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 && constants6[c.str] !== undefined);
|
|
49728
49905
|
}
|
|
49729
49906
|
}
|
|
49730
49907
|
function subtractNames(names, from) {
|
|
@@ -51629,7 +51806,7 @@ var require_compile = __commonJS((exports) => {
|
|
|
51629
51806
|
const schOrFunc = root.refs[ref];
|
|
51630
51807
|
if (schOrFunc)
|
|
51631
51808
|
return schOrFunc;
|
|
51632
|
-
let _sch =
|
|
51809
|
+
let _sch = resolve3.call(this, root, ref);
|
|
51633
51810
|
if (_sch === undefined) {
|
|
51634
51811
|
const schema = (_a = root.localRefs) === null || _a === undefined ? undefined : _a[ref];
|
|
51635
51812
|
const { schemaId } = this.opts;
|
|
@@ -51656,7 +51833,7 @@ var require_compile = __commonJS((exports) => {
|
|
|
51656
51833
|
function sameSchemaEnv(s1, s2) {
|
|
51657
51834
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
51658
51835
|
}
|
|
51659
|
-
function
|
|
51836
|
+
function resolve3(root, ref) {
|
|
51660
51837
|
let sch;
|
|
51661
51838
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
51662
51839
|
ref = sch;
|
|
@@ -52242,7 +52419,7 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
52242
52419
|
}
|
|
52243
52420
|
return uri;
|
|
52244
52421
|
}
|
|
52245
|
-
function
|
|
52422
|
+
function resolve3(baseURI, relativeURI, options) {
|
|
52246
52423
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
52247
52424
|
const { parsed: baseParsed, malformedAuthorityOrPort: baseMalformed } = parseWithStatus(baseURI, schemelessOptions);
|
|
52248
52425
|
const { parsed: relativeParsed, malformedAuthorityOrPort: relativeMalformed } = parseWithStatus(relativeURI, schemelessOptions);
|
|
@@ -52527,7 +52704,7 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
52527
52704
|
var fastUri = {
|
|
52528
52705
|
SCHEMES,
|
|
52529
52706
|
normalize: normalize3,
|
|
52530
|
-
resolve:
|
|
52707
|
+
resolve: resolve3,
|
|
52531
52708
|
resolveComponent,
|
|
52532
52709
|
equal,
|
|
52533
52710
|
serialize,
|
|
@@ -53335,8 +53512,8 @@ var require_multipleOf = __commonJS((exports) => {
|
|
|
53335
53512
|
const { gen: gen2, data, schemaCode, it } = cxt;
|
|
53336
53513
|
const prec = it.opts.multipleOfPrecision;
|
|
53337
53514
|
const res = gen2.let("res");
|
|
53338
|
-
const
|
|
53339
|
-
cxt.fail$data((0, codegen_1._)`(${schemaCode} === 0 || (${res} = ${data}/${schemaCode}, ${
|
|
53515
|
+
const invalid3 = prec ? (0, codegen_1._)`Math.abs(Math.round(${res}) - ${res}) > 1e-${prec}` : (0, codegen_1._)`${res} !== parseInt(${res})`;
|
|
53516
|
+
cxt.fail$data((0, codegen_1._)`(${schemaCode} === 0 || (${res} = ${data}/${schemaCode}, ${invalid3}))`);
|
|
53340
53517
|
}
|
|
53341
53518
|
};
|
|
53342
53519
|
exports.default = def;
|
|
@@ -58007,12 +58184,12 @@ class StdioServerTransport {
|
|
|
58007
58184
|
(_a = this.onclose) === null || _a === undefined || _a.call(this);
|
|
58008
58185
|
}
|
|
58009
58186
|
send(message) {
|
|
58010
|
-
return new Promise((
|
|
58187
|
+
return new Promise((resolve3) => {
|
|
58011
58188
|
const json = serializeMessage(message);
|
|
58012
58189
|
if (this._stdout.write(json)) {
|
|
58013
|
-
|
|
58190
|
+
resolve3();
|
|
58014
58191
|
} else {
|
|
58015
|
-
this._stdout.once("drain",
|
|
58192
|
+
this._stdout.once("drain", resolve3);
|
|
58016
58193
|
}
|
|
58017
58194
|
});
|
|
58018
58195
|
}
|
|
@@ -73259,7 +73436,7 @@ class Protocol2 {
|
|
|
73259
73436
|
return;
|
|
73260
73437
|
}
|
|
73261
73438
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1000;
|
|
73262
|
-
await new Promise((
|
|
73439
|
+
await new Promise((resolve7) => setTimeout(resolve7, pollInterval));
|
|
73263
73440
|
options?.signal?.throwIfAborted();
|
|
73264
73441
|
}
|
|
73265
73442
|
} catch (error2) {
|
|
@@ -73271,7 +73448,7 @@ class Protocol2 {
|
|
|
73271
73448
|
}
|
|
73272
73449
|
request(request2, resultSchema, options) {
|
|
73273
73450
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
73274
|
-
return new Promise((
|
|
73451
|
+
return new Promise((resolve7, reject) => {
|
|
73275
73452
|
const earlyReject = (error2) => {
|
|
73276
73453
|
reject(error2);
|
|
73277
73454
|
};
|
|
@@ -73349,7 +73526,7 @@ class Protocol2 {
|
|
|
73349
73526
|
if (!parseResult.success) {
|
|
73350
73527
|
reject(parseResult.error);
|
|
73351
73528
|
} else {
|
|
73352
|
-
|
|
73529
|
+
resolve7(parseResult.data);
|
|
73353
73530
|
}
|
|
73354
73531
|
} catch (error2) {
|
|
73355
73532
|
reject(error2);
|
|
@@ -73540,12 +73717,12 @@ class Protocol2 {
|
|
|
73540
73717
|
interval = task.pollInterval;
|
|
73541
73718
|
}
|
|
73542
73719
|
} catch {}
|
|
73543
|
-
return new Promise((
|
|
73720
|
+
return new Promise((resolve7, reject) => {
|
|
73544
73721
|
if (signal.aborted) {
|
|
73545
73722
|
reject(new McpError2(ErrorCode2.InvalidRequest, "Request cancelled"));
|
|
73546
73723
|
return;
|
|
73547
73724
|
}
|
|
73548
|
-
const timeoutId = setTimeout(
|
|
73725
|
+
const timeoutId = setTimeout(resolve7, interval);
|
|
73549
73726
|
signal.addEventListener("abort", () => {
|
|
73550
73727
|
clearTimeout(timeoutId);
|
|
73551
73728
|
reject(new McpError2(ErrorCode2.InvalidRequest, "Request cancelled"));
|
|
@@ -74368,7 +74545,7 @@ class McpServer2 {
|
|
|
74368
74545
|
let task = createTaskResult.task;
|
|
74369
74546
|
const pollInterval = task.pollInterval ?? 5000;
|
|
74370
74547
|
while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
|
|
74371
|
-
await new Promise((
|
|
74548
|
+
await new Promise((resolve7) => setTimeout(resolve7, pollInterval));
|
|
74372
74549
|
const updatedTask = await extra.taskStore.getTask(taskId);
|
|
74373
74550
|
if (!updatedTask) {
|
|
74374
74551
|
throw new McpError2(ErrorCode2.InternalError, `Task ${taskId} not found during polling`);
|
|
@@ -74992,12 +75169,12 @@ class StdioServerTransport2 {
|
|
|
74992
75169
|
this.onclose?.();
|
|
74993
75170
|
}
|
|
74994
75171
|
send(message) {
|
|
74995
|
-
return new Promise((
|
|
75172
|
+
return new Promise((resolve7) => {
|
|
74996
75173
|
const json = serializeMessage2(message);
|
|
74997
75174
|
if (this._stdout.write(json)) {
|
|
74998
|
-
|
|
75175
|
+
resolve7();
|
|
74999
75176
|
} else {
|
|
75000
|
-
this._stdout.once("drain",
|
|
75177
|
+
this._stdout.once("drain", resolve7);
|
|
75001
75178
|
}
|
|
75002
75179
|
});
|
|
75003
75180
|
}
|
|
@@ -75012,27 +75189,29 @@ __export(exports_server, {
|
|
|
75012
75189
|
runStdioServer: () => runStdioServer,
|
|
75013
75190
|
createCandleMcpServer: () => createCandleMcpServer
|
|
75014
75191
|
});
|
|
75015
|
-
function createCandleMcpServer(env = process.env) {
|
|
75192
|
+
function createCandleMcpServer(env = process.env, resolved) {
|
|
75016
75193
|
const server = new McpServer2({ name: "candle-mcp", version: SERVER_VERSION }, { instructions: INSTRUCTIONS });
|
|
75017
|
-
registerTools(server, env);
|
|
75194
|
+
registerTools(server, env, resolved ?? resolveConfig(env));
|
|
75018
75195
|
return server;
|
|
75019
75196
|
}
|
|
75020
75197
|
async function runStdioServer(env = process.env, transport = new StdioServerTransport2) {
|
|
75021
|
-
|
|
75022
|
-
|
|
75198
|
+
env = { ...env };
|
|
75199
|
+
const cfg = resolveConfig(env);
|
|
75200
|
+
const server = createCandleMcpServer(env, cfg);
|
|
75201
|
+
await registerEligibleProfileTool(server, env, undefined, cfg);
|
|
75023
75202
|
await server.connect(transport);
|
|
75024
75203
|
const dispatch = transport.onmessage;
|
|
75025
75204
|
transport.onmessage = (message, extra) => {
|
|
75026
75205
|
if ("method" in message && message.method === "tools/list") {
|
|
75027
|
-
registerEligibleProfileTool(server, env).then(() => dispatch?.(message, extra));
|
|
75206
|
+
registerEligibleProfileTool(server, env, undefined, cfg).then(() => dispatch?.(message, extra));
|
|
75028
75207
|
} else
|
|
75029
75208
|
dispatch?.(message, extra);
|
|
75030
75209
|
};
|
|
75031
|
-
await new Promise((
|
|
75210
|
+
await new Promise((resolve7) => {
|
|
75032
75211
|
const sdkOnClose = transport.onclose;
|
|
75033
75212
|
transport.onclose = () => {
|
|
75034
75213
|
sdkOnClose?.();
|
|
75035
|
-
|
|
75214
|
+
resolve7();
|
|
75036
75215
|
};
|
|
75037
75216
|
});
|
|
75038
75217
|
}
|
|
@@ -75040,6 +75219,7 @@ var INSTRUCTIONS;
|
|
|
75040
75219
|
var init_server3 = __esm(() => {
|
|
75041
75220
|
init_mcp2();
|
|
75042
75221
|
init_stdio4();
|
|
75222
|
+
init_client2();
|
|
75043
75223
|
init_market_disclosure();
|
|
75044
75224
|
init_tools();
|
|
75045
75225
|
INSTRUCTIONS = `Candle is a trading and token-launch rail for agents. You hold a scoped API key, never a private key; signing and funding stay with the key owner's wallet.
|
|
@@ -75114,6 +75294,7 @@ Full reference, error catalogue and end-to-end recipes: https://docs.candle.tv
|
|
|
75114
75294
|
});
|
|
75115
75295
|
|
|
75116
75296
|
// src/index.ts
|
|
75297
|
+
init_api_key_file();
|
|
75117
75298
|
init_client();
|
|
75118
75299
|
import { spawn as spawn3 } from "node:child_process";
|
|
75119
75300
|
import { realpathSync } from "node:fs";
|
|
@@ -76396,6 +76577,8 @@ async function authStatus(args, ctx) {
|
|
|
76396
76577
|
return 2;
|
|
76397
76578
|
}
|
|
76398
76579
|
const config = await deps.readConfig();
|
|
76580
|
+
const credential = await resolveApiCredential(deps, ctx.profile);
|
|
76581
|
+
const apiKey = credential.key;
|
|
76399
76582
|
let coreOwned = false;
|
|
76400
76583
|
const deviceToken = await resolveDeviceToken(deps, ctx.profile).catch((error) => {
|
|
76401
76584
|
if (!(error instanceof ProfileCoreOwnedError))
|
|
@@ -76403,7 +76586,6 @@ async function authStatus(args, ctx) {
|
|
|
76403
76586
|
coreOwned = true;
|
|
76404
76587
|
return;
|
|
76405
76588
|
});
|
|
76406
|
-
const apiKey = await resolveApiKey(deps, ctx.profile);
|
|
76407
76589
|
const rows = [];
|
|
76408
76590
|
if (coreOwned) {
|
|
76409
76591
|
rows.push({
|
|
@@ -76448,15 +76630,18 @@ async function authStatus(args, ctx) {
|
|
|
76448
76630
|
const configPath = configFilePathForDisplay(deps.env);
|
|
76449
76631
|
const profileFields = effectiveProfileFields(config, ctx.profile);
|
|
76450
76632
|
const cachedAccount = ctx.profile !== undefined ? profileFields.account : undefined;
|
|
76633
|
+
const shownKeyPrefix = credential.source === "file" ? apiKey ? apiKeyPrefix(apiKey) : undefined : profileFields.keyPrefix;
|
|
76451
76634
|
const mismatch = ctx.profile !== undefined && account !== undefined && cachedAccount !== undefined && account !== cachedAccount && credentialEnvOverrides(deps.env).length === 0;
|
|
76452
76635
|
if (json) {
|
|
76453
76636
|
deps.stdout.write(`${JSON.stringify({
|
|
76454
76637
|
backend: deps.backend,
|
|
76455
76638
|
profile: ctx.profile,
|
|
76456
76639
|
deviceTokenPrefix: profileFields.deviceTokenPrefix,
|
|
76457
|
-
keyPrefix:
|
|
76640
|
+
keyPrefix: shownKeyPrefix,
|
|
76641
|
+
apiKeySource: credential.source,
|
|
76458
76642
|
account,
|
|
76459
76643
|
cachedAccount,
|
|
76644
|
+
envOverrides: credentialEnvOverrides(deps.env),
|
|
76460
76645
|
apiUrl,
|
|
76461
76646
|
configPath,
|
|
76462
76647
|
rows
|
|
@@ -76464,9 +76649,10 @@ async function authStatus(args, ctx) {
|
|
|
76464
76649
|
`);
|
|
76465
76650
|
return exitCode;
|
|
76466
76651
|
}
|
|
76467
|
-
const
|
|
76468
|
-
const
|
|
76469
|
-
|
|
76652
|
+
const overrides = deps.env.CANDLE_API_KEY_FILE?.trim() ? credentialEnvOverrides(deps.env) : [];
|
|
76653
|
+
const shownAccount = overrides.length ? account : account ?? profileFields.account;
|
|
76654
|
+
const shownUsername = overrides.length ? undefined : account !== undefined ? username : profileFields.username;
|
|
76655
|
+
deps.stdout.write(`${identityLine(ctx.profile, shownAccount, apiUrl, overrides.length ? overrides : undefined, shownUsername, identityStyle(deps, "stdout"))}
|
|
76470
76656
|
`);
|
|
76471
76657
|
const style = terminalStyle(deps, "stdout");
|
|
76472
76658
|
if (mismatch) {
|
|
@@ -76479,7 +76665,7 @@ ${heading("Credentials", style)}
|
|
|
76479
76665
|
${fields([
|
|
76480
76666
|
["Backend", deps.backend],
|
|
76481
76667
|
["Device token prefix", profileFields.deviceTokenPrefix],
|
|
76482
|
-
["API key prefix",
|
|
76668
|
+
["API key prefix", shownKeyPrefix],
|
|
76483
76669
|
["Config file", configPath]
|
|
76484
76670
|
], style).join(`
|
|
76485
76671
|
`)}
|
|
@@ -77745,6 +77931,10 @@ var ENVIRONMENT = [
|
|
|
77745
77931
|
name: "CANDLE_X402_PAY_TO",
|
|
77746
77932
|
description: "Devnet tests only: the address devnet x402 payments go to (mainnet pays its pinned address)"
|
|
77747
77933
|
},
|
|
77934
|
+
{
|
|
77935
|
+
name: "CANDLE_API_KEY_FILE",
|
|
77936
|
+
description: "Owner-only API-key file (Linux/macOS 0400/0600); exclusive, conflicts with raw key variables; restart MCP after replacement"
|
|
77937
|
+
},
|
|
77748
77938
|
{ name: "CANDLE_API_KEY", description: "An agent API key; beats the stored one" },
|
|
77749
77939
|
{ name: "CANDLE_DEVICE_TOKEN", description: "A device token, for key-management commands" },
|
|
77750
77940
|
{
|
|
@@ -77790,6 +77980,7 @@ var ENV_API = [
|
|
|
77790
77980
|
"CANDLE_PROFILE",
|
|
77791
77981
|
"CANDLE_API_URL",
|
|
77792
77982
|
"CANDLE_API_KEY",
|
|
77983
|
+
"CANDLE_API_KEY_FILE",
|
|
77793
77984
|
"CANDLE_DEVICE_TOKEN",
|
|
77794
77985
|
"CANDLE_KEYRING_PASSPHRASE"
|
|
77795
77986
|
];
|
|
@@ -78741,7 +78932,7 @@ var HELP = {
|
|
|
78741
78932
|
{ invocation: "resume <prefix>", description: "Resume a stopped key with the device token" },
|
|
78742
78933
|
{
|
|
78743
78934
|
invocation: "rotate <prefix|label> ([--grace <duration> | --now] [--force] [--yes] | --finish)",
|
|
78744
|
-
description: "Give a key a new secret, keeping its prefix, label, access, limits, wallets and history. The old secret works through --grace (default 1h, at most 24h) or stops at once with --now; --finish ends an open window early. The profile's own key is replaced in the keychain; update CANDLE_API_KEY and
|
|
78935
|
+
description: "Give a key a new secret, keeping its prefix, label, access, limits, wallets and history. The old secret works through --grace (default 1h, at most 24h) or stops at once with --now; --finish ends an open window early. The profile's own key is replaced in the keychain; update CANDLE_API_KEY or CANDLE_API_KEY_FILE yourself and restart MCP. --force rotates again while a window is open"
|
|
78745
78936
|
},
|
|
78746
78937
|
{ invocation: "revoke <prefix>", description: "Revoke an API key permanently" },
|
|
78747
78938
|
{
|
|
@@ -79579,7 +79770,7 @@ async function completion(args, ctx) {
|
|
|
79579
79770
|
init_agent_key_access();
|
|
79580
79771
|
init_args();
|
|
79581
79772
|
init_client();
|
|
79582
|
-
import { closeSync, writeSync } from "node:fs";
|
|
79773
|
+
import { closeSync as closeSync2, writeSync } from "node:fs";
|
|
79583
79774
|
import { join as join11 } from "node:path";
|
|
79584
79775
|
|
|
79585
79776
|
// src/core/agent-profiles.ts
|
|
@@ -81842,8 +82033,8 @@ class SignalService {
|
|
|
81842
82033
|
this.armIdle();
|
|
81843
82034
|
}
|
|
81844
82035
|
if (!this.snapshotSeen) {
|
|
81845
|
-
const ready = new Promise((
|
|
81846
|
-
const wait = this.deps.waitForSnapshot ?? ((ms, until) => Promise.race([until, new Promise((
|
|
82036
|
+
const ready = new Promise((resolve3) => this.waiters.push(resolve3));
|
|
82037
|
+
const wait = this.deps.waitForSnapshot ?? ((ms, until) => Promise.race([until, new Promise((resolve3) => this.schedule(resolve3, ms))]));
|
|
81847
82038
|
await wait(SIGNAL_QUERY_WAIT_MS, ready);
|
|
81848
82039
|
}
|
|
81849
82040
|
const rows = this.rowsCache.filter((row2) => query2.chain === undefined || row2.chain === query2.chain).filter((row2) => query2.mint === undefined || sameWallet(row2.chain, row2.mint, query2.mint)).filter((row2) => query2.pattern === undefined || row2.pattern === query2.pattern).slice(0, query2.limit);
|
|
@@ -81941,8 +82132,8 @@ class SignalService {
|
|
|
81941
82132
|
const parsed = frame.signals.map(parseStreamRow).filter((row2) => row2 !== undefined);
|
|
81942
82133
|
this.rowsCache = replaceTape(parsed);
|
|
81943
82134
|
this.snapshotSeen = true;
|
|
81944
|
-
for (const
|
|
81945
|
-
|
|
82135
|
+
for (const resolve3 of this.waiters.splice(0))
|
|
82136
|
+
resolve3();
|
|
81946
82137
|
this.deps.events.publish("signals", this.snapshotAll());
|
|
81947
82138
|
this.deps.events.publish("signals:mine", this.snapshotMine());
|
|
81948
82139
|
return;
|
|
@@ -82699,8 +82890,8 @@ var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
|
82699
82890
|
var TURN_ID = /^[A-Za-z0-9_-]{1,64}$/;
|
|
82700
82891
|
var MESSAGE_ID = /^[A-Za-z0-9_-]{1,64}$/;
|
|
82701
82892
|
var MAX_SEND_BYTES = 64 * 1024;
|
|
82702
|
-
var defaultSleep = (ms) => new Promise((
|
|
82703
|
-
const timer = setTimeout(
|
|
82893
|
+
var defaultSleep = (ms) => new Promise((resolve3) => {
|
|
82894
|
+
const timer = setTimeout(resolve3, ms);
|
|
82704
82895
|
timer.unref?.();
|
|
82705
82896
|
});
|
|
82706
82897
|
function refusalError(refusal2) {
|
|
@@ -83376,11 +83567,11 @@ class CoreServer {
|
|
|
83376
83567
|
}
|
|
83377
83568
|
await rm4(path, { force: true });
|
|
83378
83569
|
const server = createServer((socket) => this.accept(socket));
|
|
83379
|
-
await new Promise((
|
|
83570
|
+
await new Promise((resolve3, reject) => {
|
|
83380
83571
|
server.once("error", reject);
|
|
83381
83572
|
server.listen(path, () => {
|
|
83382
83573
|
server.off("error", reject);
|
|
83383
|
-
|
|
83574
|
+
resolve3();
|
|
83384
83575
|
});
|
|
83385
83576
|
});
|
|
83386
83577
|
await chmod9(path, 384);
|
|
@@ -83393,7 +83584,7 @@ class CoreServer {
|
|
|
83393
83584
|
const server = this.server;
|
|
83394
83585
|
this.server = undefined;
|
|
83395
83586
|
if (server)
|
|
83396
|
-
await new Promise((
|
|
83587
|
+
await new Promise((resolve3) => server.close(() => resolve3()));
|
|
83397
83588
|
await rm4(this.options.socketPath, { force: true });
|
|
83398
83589
|
}
|
|
83399
83590
|
async disconnect(clientId2, reason) {
|
|
@@ -85623,7 +85814,7 @@ ${USAGE5}`, json);
|
|
|
85623
85814
|
try {
|
|
85624
85815
|
writeSync(viewTokenFd, `${tokens.viewToken}
|
|
85625
85816
|
`);
|
|
85626
|
-
|
|
85817
|
+
closeSync2(viewTokenFd);
|
|
85627
85818
|
} catch {
|
|
85628
85819
|
writeLocalFailure(deps, { code: "CORE_VIEW_TOKEN_FD", message: `Could not write the view token to descriptor ${viewTokenFd}.` }, json);
|
|
85629
85820
|
return 1;
|
|
@@ -85648,7 +85839,7 @@ Socket: ${paths.socket}
|
|
|
85648
85839
|
`);
|
|
85649
85840
|
}
|
|
85650
85841
|
const running = server;
|
|
85651
|
-
await new Promise((
|
|
85842
|
+
await new Promise((resolve3) => {
|
|
85652
85843
|
let unsubscribe;
|
|
85653
85844
|
let done = false;
|
|
85654
85845
|
const finish = (reason) => {
|
|
@@ -85657,7 +85848,7 @@ Socket: ${paths.socket}
|
|
|
85657
85848
|
done = true;
|
|
85658
85849
|
stopReason = reason;
|
|
85659
85850
|
unsubscribe?.();
|
|
85660
|
-
|
|
85851
|
+
resolve3();
|
|
85661
85852
|
};
|
|
85662
85853
|
running.onViewCount((count2) => {
|
|
85663
85854
|
if (count2 !== 0 || !running.hadView())
|
|
@@ -85895,9 +86086,9 @@ class CoreClientError extends Error {
|
|
|
85895
86086
|
}
|
|
85896
86087
|
}
|
|
85897
86088
|
async function connectCore(input) {
|
|
85898
|
-
const socket = await new Promise((
|
|
86089
|
+
const socket = await new Promise((resolve3, reject) => {
|
|
85899
86090
|
const s = createConnection(input.socketPath);
|
|
85900
|
-
s.once("connect", () =>
|
|
86091
|
+
s.once("connect", () => resolve3(s));
|
|
85901
86092
|
s.once("error", (error) => {
|
|
85902
86093
|
reject(error.code === "ENOENT" || error.code === "ECONNREFUSED" ? new CoreClientError("CORE_NOT_RUNNING", `No Candle core is listening at ${input.socketPath}. Start it with candle tui.`) : error);
|
|
85903
86094
|
});
|
|
@@ -85946,8 +86137,8 @@ async function connectCore(input) {
|
|
|
85946
86137
|
if (closed)
|
|
85947
86138
|
return Promise.reject(new CoreClientError("CORE_DISCONNECTED", "The Candle core closed the connection."));
|
|
85948
86139
|
const id = nextId++;
|
|
85949
|
-
return new Promise((
|
|
85950
|
-
pending.set(id, { resolve:
|
|
86140
|
+
return new Promise((resolve3, reject) => {
|
|
86141
|
+
pending.set(id, { resolve: resolve3, reject });
|
|
85951
86142
|
socket.write(encodeLine({ jsonrpc: "2.0", id, method, params: params ?? {} }));
|
|
85952
86143
|
});
|
|
85953
86144
|
},
|
|
@@ -86083,6 +86274,7 @@ ${USAGE6}`, json);
|
|
|
86083
86274
|
}
|
|
86084
86275
|
|
|
86085
86276
|
// src/commands/doctor.ts
|
|
86277
|
+
init_api_key_file();
|
|
86086
86278
|
init_agent_key_access();
|
|
86087
86279
|
init_args();
|
|
86088
86280
|
init_client();
|
|
@@ -86104,7 +86296,7 @@ function assertSafeRef(ref) {
|
|
|
86104
86296
|
}
|
|
86105
86297
|
var RUN_TIMEOUT_MS = 1e4;
|
|
86106
86298
|
function run(bin, args, stdin) {
|
|
86107
|
-
return new Promise((
|
|
86299
|
+
return new Promise((resolve3, reject) => {
|
|
86108
86300
|
const child = spawn(bin, args, { stdio: ["pipe", "pipe", "pipe"], env: process.env });
|
|
86109
86301
|
let stdout = "";
|
|
86110
86302
|
let stderr = "";
|
|
@@ -86133,7 +86325,7 @@ function run(bin, args, stdin) {
|
|
|
86133
86325
|
return;
|
|
86134
86326
|
settled = true;
|
|
86135
86327
|
clearTimeout(timeout);
|
|
86136
|
-
|
|
86328
|
+
resolve3({ status: code ?? -1, stdout, stderr });
|
|
86137
86329
|
});
|
|
86138
86330
|
if (stdin !== undefined)
|
|
86139
86331
|
child.stdin.write(stdin);
|
|
@@ -87874,7 +88066,7 @@ var DOCTOR_ROW_IDS = {
|
|
|
87874
88066
|
};
|
|
87875
88067
|
var API_KEY_CHECK = "API key valid";
|
|
87876
88068
|
function keyRotationRow(until, source) {
|
|
87877
|
-
const fix = source === "CANDLE_API_KEY" ? "update CANDLE_API_KEY where this key is deployed to the new secret" : "store the new secret with candle auth login, or rotate from this profile with candle keys rotate";
|
|
88069
|
+
const fix = source === "CANDLE_API_KEY_FILE" ? "replace the old secret in CANDLE_API_KEY_FILE and restart MCP; the CLI did not update the file" : source === "CANDLE_API_KEY" ? "update CANDLE_API_KEY where this key is deployed to the new secret" : "store the new secret with candle auth login, or rotate from this profile with candle keys rotate";
|
|
87878
88070
|
return {
|
|
87879
88071
|
check: "Key rotation",
|
|
87880
88072
|
state: "WARN",
|
|
@@ -87991,6 +88183,20 @@ async function doctor(args, ctx) {
|
|
|
87991
88183
|
writeUsageFailure(deps, "--role must be owner, bot, or auto", json);
|
|
87992
88184
|
return 2;
|
|
87993
88185
|
}
|
|
88186
|
+
if (hasApiKeyFile(deps.env)) {
|
|
88187
|
+
try {
|
|
88188
|
+
await resolveApiKey(deps, ctx.profile);
|
|
88189
|
+
} catch (error) {
|
|
88190
|
+
if (!(error instanceof ApiKeyFileError))
|
|
88191
|
+
throw error;
|
|
88192
|
+
writeLocalFailure(deps, {
|
|
88193
|
+
code: error.code,
|
|
88194
|
+
message: error.message,
|
|
88195
|
+
details: { rows: [{ check: "API key", state: "FAIL", code: error.code, detail: error.message }] }
|
|
88196
|
+
}, json);
|
|
88197
|
+
return 1;
|
|
88198
|
+
}
|
|
88199
|
+
}
|
|
87994
88200
|
const rows = [];
|
|
87995
88201
|
const config = await deps.readConfig();
|
|
87996
88202
|
const fields2 = effectiveProfileFields(config, ctx.profile);
|
|
@@ -88041,7 +88247,11 @@ async function doctor(args, ctx) {
|
|
|
88041
88247
|
coreOwned = true;
|
|
88042
88248
|
return;
|
|
88043
88249
|
}));
|
|
88044
|
-
|
|
88250
|
+
let apiCredential;
|
|
88251
|
+
const apiKey = await readCredential(async () => {
|
|
88252
|
+
apiCredential = await resolveApiCredential(deps, ctx.profile);
|
|
88253
|
+
return apiCredential.key;
|
|
88254
|
+
});
|
|
88045
88255
|
const role = requestedRole === "auto" ? apiKey && !deviceToken ? "bot" : "owner" : requestedRole;
|
|
88046
88256
|
rows.push(deviceToken || apiKey ? {
|
|
88047
88257
|
check: "Credentials present",
|
|
@@ -88058,7 +88268,10 @@ async function doctor(args, ctx) {
|
|
|
88058
88268
|
value: apiUrl,
|
|
88059
88269
|
source: ctx.apiUrlFlag !== undefined ? "--api-url" : deps.env.CANDLE_API_URL?.trim() ? "CANDLE_API_URL" : ctx.profile && config.profiles?.[ctx.profile]?.apiUrl?.trim() ? `profile ${ctx.profile}` : config.apiUrl?.trim() ? "config" : "default"
|
|
88060
88270
|
},
|
|
88061
|
-
apiKey: {
|
|
88271
|
+
apiKey: {
|
|
88272
|
+
source: apiCredential?.source === "file" ? "CANDLE_API_KEY_FILE" : source(apiKey, "CANDLE_API_KEY"),
|
|
88273
|
+
prefix: apiKey ? apiKeyPrefix(apiKey) ?? null : null
|
|
88274
|
+
},
|
|
88062
88275
|
deviceToken: { source: source(deviceToken, "CANDLE_DEVICE_TOKEN") }
|
|
88063
88276
|
};
|
|
88064
88277
|
rows.push({ check: "API URL", state: "PASS", detail: `${apiUrl} (from ${provenance.apiUrl.source})` }, {
|
|
@@ -88329,7 +88542,7 @@ init_solana_endpoint();
|
|
|
88329
88542
|
// src/vault/domains.ts
|
|
88330
88543
|
init_errors2();
|
|
88331
88544
|
import { homedir as homedir4 } from "node:os";
|
|
88332
|
-
import { basename as basename2, dirname as dirname10, isAbsolute as isAbsolute2, join as join12, resolve as
|
|
88545
|
+
import { basename as basename2, dirname as dirname10, isAbsolute as isAbsolute2, join as join12, resolve as resolve3, sep as sep2 } from "node:path";
|
|
88333
88546
|
var ICLOUD_DRIVE_SEGMENTS = ["Library", "Mobile Documents", "com~apple~CloudDocs"];
|
|
88334
88547
|
var ICLOUD_SHORTHAND = "icloud";
|
|
88335
88548
|
var ICLOUD_BACKUP_FOLDER = "Candle";
|
|
@@ -88378,7 +88591,7 @@ function placeResolvedPath(absolute, home) {
|
|
|
88378
88591
|
return "unknown";
|
|
88379
88592
|
}
|
|
88380
88593
|
async function classifyDestination(path, opts) {
|
|
88381
|
-
const absolute = isAbsolute2(path) ? path :
|
|
88594
|
+
const absolute = isAbsolute2(path) ? path : resolve3(path);
|
|
88382
88595
|
const spelledHome = opts.home ?? homedir4();
|
|
88383
88596
|
let home;
|
|
88384
88597
|
try {
|
|
@@ -93308,15 +93521,23 @@ async function keysRotate(args, ctx) {
|
|
|
93308
93521
|
storeError = error instanceof Error ? error.message : String(error);
|
|
93309
93522
|
}
|
|
93310
93523
|
}
|
|
93311
|
-
|
|
93312
|
-
|
|
93524
|
+
let credential;
|
|
93525
|
+
try {
|
|
93526
|
+
credential = await resolveExternalApiCredential(deps);
|
|
93527
|
+
} catch {
|
|
93528
|
+
credential = undefined;
|
|
93529
|
+
}
|
|
93530
|
+
const namesKey = credential?.key !== undefined && apiKeyPrefix(credential.key) === keyPrefix;
|
|
93531
|
+
const envNamesKey = credential?.source === "env" && namesKey;
|
|
93532
|
+
const fileNamesKey = credential?.source === "file" && namesKey;
|
|
93313
93533
|
const until = body.previousValidUntil;
|
|
93314
93534
|
if (json) {
|
|
93315
93535
|
deps.stdout.write(`${JSON.stringify({
|
|
93316
93536
|
...body,
|
|
93317
93537
|
stored,
|
|
93318
93538
|
...storeError ? { storeError } : {},
|
|
93319
|
-
...envNamesKey ? { candleApiKeyStale: true } : {}
|
|
93539
|
+
...envNamesKey ? { candleApiKeyStale: true } : {},
|
|
93540
|
+
...fileNamesKey ? { candleApiKeyFileStale: true } : {}
|
|
93320
93541
|
})}
|
|
93321
93542
|
`);
|
|
93322
93543
|
return storeError ? 1 : 0;
|
|
@@ -93338,6 +93559,9 @@ async function keysRotate(args, ctx) {
|
|
|
93338
93559
|
`)}
|
|
93339
93560
|
`);
|
|
93340
93561
|
const deadline = until === null ? "now" : `before ${formatTime(until)}`;
|
|
93562
|
+
if (fileNamesKey) {
|
|
93563
|
+
notice(deps, "stderr", "warning", `CANDLE_API_KEY_FILE still holds the old secret. The file was not updated. Replace it ${deadline} and restart MCP.`);
|
|
93564
|
+
}
|
|
93341
93565
|
if (envNamesKey) {
|
|
93342
93566
|
notice(deps, "stderr", "warning", `CANDLE_API_KEY holds the old secret, and this CLI cannot change it. Update CANDLE_API_KEY where this key is deployed ${deadline}.`);
|
|
93343
93567
|
}
|
|
@@ -93637,7 +93861,7 @@ function createLabClient2(options) {
|
|
|
93637
93861
|
const doFetch = options.fetch ?? globalThis.fetch;
|
|
93638
93862
|
const callMs = options.callTimeoutMs ?? LAB_CALL_TIMEOUT_MS2;
|
|
93639
93863
|
const now = options.now ?? Date.now;
|
|
93640
|
-
const sleep = options.sleep ?? ((ms) => new Promise((
|
|
93864
|
+
const sleep = options.sleep ?? ((ms) => new Promise((resolve4) => setTimeout(resolve4, ms)));
|
|
93641
93865
|
async function call2(method, path, valid = () => true, body, timeoutMs = callMs) {
|
|
93642
93866
|
const controller = new AbortController;
|
|
93643
93867
|
let timedOut = false;
|
|
@@ -96064,6 +96288,7 @@ var READ_ONLY_TOOL_NAMES = [
|
|
|
96064
96288
|
"candle_get_plans"
|
|
96065
96289
|
];
|
|
96066
96290
|
var CREDENTIAL_ENV_NAMES = [
|
|
96291
|
+
"CANDLE_API_KEY_FILE",
|
|
96067
96292
|
"CANDLE_API_KEY",
|
|
96068
96293
|
"CANDLE_AGENT_API_KEY",
|
|
96069
96294
|
"CANDLE_DEVICE_TOKEN",
|
|
@@ -97274,7 +97499,7 @@ function perpsMarketGate2(meta, ctx, minOpenInterestUsd) {
|
|
|
97274
97499
|
return { tradeable: false, reason: "minOpenInterest" };
|
|
97275
97500
|
return { tradeable: true, reason: null };
|
|
97276
97501
|
}
|
|
97277
|
-
function
|
|
97502
|
+
function resolve4(snapshot, coin) {
|
|
97278
97503
|
if (/^[A-Za-z0-9]{1,20}$/.test(coin)) {
|
|
97279
97504
|
const exact = snapshot.universe.findIndex((row2) => row2.name === coin);
|
|
97280
97505
|
if (exact !== -1)
|
|
@@ -97552,7 +97777,7 @@ class PerpsMarketReader2 {
|
|
|
97552
97777
|
async market(coin) {
|
|
97553
97778
|
this.key();
|
|
97554
97779
|
const [config, core, extras] = await Promise.all([this.config(), this.core(), this.extras()]);
|
|
97555
|
-
const asset =
|
|
97780
|
+
const asset = resolve4(core, coin);
|
|
97556
97781
|
const meta = at2(core.universe, asset);
|
|
97557
97782
|
const ctx = at2(core.ctxs, asset);
|
|
97558
97783
|
return {
|
|
@@ -97578,7 +97803,7 @@ class PerpsMarketReader2 {
|
|
|
97578
97803
|
if (opts.sigFigs !== undefined)
|
|
97579
97804
|
bounded2(opts.sigFigs, 5, 2, 5, "sigFigs");
|
|
97580
97805
|
const [config, core] = await Promise.all([this.config(), this.core()]);
|
|
97581
|
-
const canonical4 = at2(core.universe,
|
|
97806
|
+
const canonical4 = at2(core.universe, resolve4(core, coin)).name;
|
|
97582
97807
|
const value = await info2(this.opts.fetcher, this.opts.network, {
|
|
97583
97808
|
type: "l2Book",
|
|
97584
97809
|
coin: canonical4,
|
|
@@ -97619,7 +97844,7 @@ class PerpsMarketReader2 {
|
|
|
97619
97844
|
this.key();
|
|
97620
97845
|
const window = perpsCandleWindow2(opts, this.now());
|
|
97621
97846
|
const [config, core] = await Promise.all([this.config(), this.core()]);
|
|
97622
|
-
const canonical4 = at2(core.universe,
|
|
97847
|
+
const canonical4 = at2(core.universe, resolve4(core, coin)).name;
|
|
97623
97848
|
const value = await info2(this.opts.fetcher, this.opts.network, {
|
|
97624
97849
|
type: "candleSnapshot",
|
|
97625
97850
|
req: { coin: canonical4, interval: window.interval, startTime: window.startTime, endTime: window.endTime }
|
|
@@ -97654,7 +97879,7 @@ class PerpsMarketReader2 {
|
|
|
97654
97879
|
this.key();
|
|
97655
97880
|
const window = perpsFundingWindow2(opts, this.now());
|
|
97656
97881
|
const [config, core] = await Promise.all([this.config(), this.core()]);
|
|
97657
|
-
const canonical4 = at2(core.universe,
|
|
97882
|
+
const canonical4 = at2(core.universe, resolve4(core, coin)).name;
|
|
97658
97883
|
const value = await info2(this.opts.fetcher, this.opts.network, {
|
|
97659
97884
|
type: "fundingHistory",
|
|
97660
97885
|
coin: canonical4,
|
|
@@ -97718,7 +97943,7 @@ var EVM_ADDRESS_RE4 = /^0x[0-9a-f]{40}$/;
|
|
|
97718
97943
|
function isTime2(value) {
|
|
97719
97944
|
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
97720
97945
|
}
|
|
97721
|
-
function
|
|
97946
|
+
function invalid3(field, message) {
|
|
97722
97947
|
return new PerpsHistoryError2("VALIDATION_FAILED", message, { field });
|
|
97723
97948
|
}
|
|
97724
97949
|
function unavailable5(message, retryAfterMs2) {
|
|
@@ -97749,16 +97974,16 @@ function encodeCursor2(state) {
|
|
|
97749
97974
|
}
|
|
97750
97975
|
function decodeCursor2(cursor) {
|
|
97751
97976
|
if (cursor.length > PERPS_HISTORY_MAX_CURSOR_LENGTH2 || !cursor.startsWith("ph1."))
|
|
97752
|
-
throw
|
|
97977
|
+
throw invalid3("cursor", "cursor is not one this client issued");
|
|
97753
97978
|
let state;
|
|
97754
97979
|
try {
|
|
97755
97980
|
state = JSON.parse(base64UrlDecode2(cursor.slice(4)));
|
|
97756
97981
|
} catch {
|
|
97757
|
-
throw
|
|
97982
|
+
throw invalid3("cursor", "cursor is not one this client issued");
|
|
97758
97983
|
}
|
|
97759
97984
|
const ok = state !== null && typeof state === "object" && state.v === 1 && (state.k === "fills" || state.k === "funding") && (state.n === "mainnet" || state.n === "testnet") && typeof state.w === "string" && EVM_ADDRESS_RE4.test(state.w) && isTime2(state.s) && isTime2(state.e) && state.s <= state.e && Number.isSafeInteger(state.l) && state.l >= 1 && state.l <= PERPS_HISTORY_MAX_LIMIT2[state.k] && isTime2(state.t) && state.t >= state.s && state.t <= state.e && Array.isArray(state.b) && state.b.every((id) => typeof id === "string" && id.length <= 512) && Number.isSafeInteger(state.c) && state.c >= 0;
|
|
97760
97985
|
if (!ok)
|
|
97761
|
-
throw
|
|
97986
|
+
throw invalid3("cursor", "cursor is not one this client issued");
|
|
97762
97987
|
return state;
|
|
97763
97988
|
}
|
|
97764
97989
|
function canonical4(value) {
|
|
@@ -97844,35 +98069,35 @@ function resolveWindow2(req) {
|
|
|
97844
98069
|
const kind = req.kind;
|
|
97845
98070
|
const address = req.address.toLowerCase();
|
|
97846
98071
|
if (!EVM_ADDRESS_RE4.test(address))
|
|
97847
|
-
throw
|
|
98072
|
+
throw invalid3("wallet", "The wallet's Hyperliquid account is not an EVM address");
|
|
97848
98073
|
for (const field of ["startTime", "endTime"]) {
|
|
97849
98074
|
const value = options[field];
|
|
97850
98075
|
if (value !== undefined && !isTime2(value))
|
|
97851
|
-
throw
|
|
98076
|
+
throw invalid3(field, `${field} must be a whole, non-negative number of epoch milliseconds`);
|
|
97852
98077
|
}
|
|
97853
98078
|
const max = PERPS_HISTORY_MAX_LIMIT2[kind];
|
|
97854
98079
|
if (options.limit !== undefined && (!Number.isSafeInteger(options.limit) || options.limit < 1 || options.limit > max))
|
|
97855
|
-
throw
|
|
98080
|
+
throw invalid3("limit", `limit must be a whole number from 1 to ${max} for ${kind}`);
|
|
97856
98081
|
if (options.cursor !== undefined) {
|
|
97857
98082
|
if (typeof options.cursor !== "string" || options.cursor.length === 0)
|
|
97858
|
-
throw
|
|
98083
|
+
throw invalid3("cursor", "cursor is not one this client issued");
|
|
97859
98084
|
const state = decodeCursor2(options.cursor);
|
|
97860
98085
|
if (state.k !== kind)
|
|
97861
|
-
throw
|
|
98086
|
+
throw invalid3("cursor", `This cursor pages ${state.k}, not ${kind}`);
|
|
97862
98087
|
if (state.n !== req.network)
|
|
97863
|
-
throw
|
|
98088
|
+
throw invalid3("cursor", `This cursor pages ${state.n}, not ${req.network}`);
|
|
97864
98089
|
if (state.w !== address)
|
|
97865
|
-
throw
|
|
98090
|
+
throw invalid3("cursor", "This cursor pages another wallet");
|
|
97866
98091
|
if (options.startTime !== undefined && options.startTime !== state.s || options.endTime !== undefined && options.endTime !== state.e || options.limit !== undefined && options.limit !== state.l)
|
|
97867
|
-
throw
|
|
98092
|
+
throw invalid3("cursor", "The window or page size changed; start again without a cursor");
|
|
97868
98093
|
return { state };
|
|
97869
98094
|
}
|
|
97870
98095
|
const endTime = options.endTime ?? req.now();
|
|
97871
98096
|
const startTime = options.startTime ?? Math.max(0, endTime - PERPS_HISTORY_DEFAULT_WINDOW_MS2);
|
|
97872
98097
|
if (!isTime2(endTime))
|
|
97873
|
-
throw
|
|
98098
|
+
throw invalid3("endTime", "endTime must be epoch milliseconds");
|
|
97874
98099
|
if (startTime > endTime)
|
|
97875
|
-
throw
|
|
98100
|
+
throw invalid3("startTime", "startTime must not be after endTime");
|
|
97876
98101
|
return {
|
|
97877
98102
|
state: {
|
|
97878
98103
|
v: 1,
|
|
@@ -98105,7 +98330,7 @@ class HyperliquidReadError2 extends Error {
|
|
|
98105
98330
|
var INFO_TIMEOUT_MS2 = 5000;
|
|
98106
98331
|
var RATE_LIMIT_RETRY_MS2 = 1000;
|
|
98107
98332
|
async function hyperliquidInfo2(fetcher, network2, body, opts = {}) {
|
|
98108
|
-
const sleep = opts.sleep ?? ((ms) => new Promise((
|
|
98333
|
+
const sleep = opts.sleep ?? ((ms) => new Promise((resolve5) => setTimeout(resolve5, ms)));
|
|
98109
98334
|
for (let attempt = 0;; attempt++) {
|
|
98110
98335
|
const controller = new AbortController;
|
|
98111
98336
|
const timer = setTimeout(() => controller.abort(), opts.timeoutMs ?? INFO_TIMEOUT_MS2);
|
|
@@ -98141,7 +98366,7 @@ async function hyperliquidInfo2(fetcher, network2, body, opts = {}) {
|
|
|
98141
98366
|
}
|
|
98142
98367
|
}
|
|
98143
98368
|
async function readHyperliquidMarketSnapshot2(fetcher, network2, opts = {}) {
|
|
98144
|
-
const sleep = opts.sleep ?? ((ms) => new Promise((
|
|
98369
|
+
const sleep = opts.sleep ?? ((ms) => new Promise((resolve5) => setTimeout(resolve5, ms)));
|
|
98145
98370
|
let limited = false;
|
|
98146
98371
|
const watched = async (url, init) => {
|
|
98147
98372
|
const res = await fetcher(url, init);
|
|
@@ -98655,10 +98880,10 @@ function abortableSleep(sleep, ms, signal) {
|
|
|
98655
98880
|
return sleep(ms);
|
|
98656
98881
|
if (signal.aborted)
|
|
98657
98882
|
return Promise.resolve();
|
|
98658
|
-
return new Promise((
|
|
98883
|
+
return new Promise((resolve5) => {
|
|
98659
98884
|
const done = () => {
|
|
98660
98885
|
signal.removeEventListener("abort", done);
|
|
98661
|
-
|
|
98886
|
+
resolve5();
|
|
98662
98887
|
};
|
|
98663
98888
|
signal.addEventListener("abort", done);
|
|
98664
98889
|
sleep(ms).then(done, done);
|
|
@@ -101077,6 +101302,7 @@ async function perpsReduceOnly(args, ctx) {
|
|
|
101077
101302
|
}
|
|
101078
101303
|
|
|
101079
101304
|
// src/commands/perps-markets.ts
|
|
101305
|
+
init_api_key_file();
|
|
101080
101306
|
init_args();
|
|
101081
101307
|
init_deps();
|
|
101082
101308
|
init_presentation();
|
|
@@ -101220,6 +101446,10 @@ async function read2(ctx, argv, command) {
|
|
|
101220
101446
|
}
|
|
101221
101447
|
return 0;
|
|
101222
101448
|
} catch (error) {
|
|
101449
|
+
if (error instanceof ApiKeyFileError) {
|
|
101450
|
+
writeLocalFailure(ctx.deps, { code: error.code, message: error.message }, ctx.json);
|
|
101451
|
+
return 1;
|
|
101452
|
+
}
|
|
101223
101453
|
if (error instanceof PerpsMarketError2) {
|
|
101224
101454
|
if (error.code === "PERPS_USAGE") {
|
|
101225
101455
|
writeUsageFailure(ctx.deps, error.message, ctx.json);
|
|
@@ -103623,7 +103853,7 @@ init_human_output();
|
|
|
103623
103853
|
|
|
103624
103854
|
// src/plugins.ts
|
|
103625
103855
|
import { spawn as spawn2 } from "node:child_process";
|
|
103626
|
-
import { accessSync, constants as
|
|
103856
|
+
import { accessSync, constants as constants6, readdirSync, statSync } from "node:fs";
|
|
103627
103857
|
import { delimiter, join as join14 } from "node:path";
|
|
103628
103858
|
var PLUGIN_PREFIX = "candle-";
|
|
103629
103859
|
var RESERVED_HELPER_NAMES = ["fido2", "enclave"];
|
|
@@ -103634,7 +103864,7 @@ function executableAt(path) {
|
|
|
103634
103864
|
try {
|
|
103635
103865
|
if (!statSync(path).isFile())
|
|
103636
103866
|
return false;
|
|
103637
|
-
accessSync(path,
|
|
103867
|
+
accessSync(path, constants6.X_OK);
|
|
103638
103868
|
return true;
|
|
103639
103869
|
} catch {
|
|
103640
103870
|
return false;
|
|
@@ -103743,16 +103973,16 @@ function pluginEnvironment(input) {
|
|
|
103743
103973
|
return env;
|
|
103744
103974
|
}
|
|
103745
103975
|
function realRunPlugin(path, args, env) {
|
|
103746
|
-
return new Promise((
|
|
103976
|
+
return new Promise((resolve5) => {
|
|
103747
103977
|
let child;
|
|
103748
103978
|
try {
|
|
103749
103979
|
child = spawn2(path, args, { stdio: "inherit", env });
|
|
103750
103980
|
} catch {
|
|
103751
|
-
|
|
103981
|
+
resolve5(1);
|
|
103752
103982
|
return;
|
|
103753
103983
|
}
|
|
103754
|
-
child.on("error", () =>
|
|
103755
|
-
child.on("close", (code) =>
|
|
103984
|
+
child.on("error", () => resolve5(1));
|
|
103985
|
+
child.on("close", (code) => resolve5(code ?? 1));
|
|
103756
103986
|
});
|
|
103757
103987
|
}
|
|
103758
103988
|
function pluginInvocation(argv, env, isBuiltIn) {
|
|
@@ -107513,9 +107743,9 @@ function parseRenamePairs(contents) {
|
|
|
107513
107743
|
continue;
|
|
107514
107744
|
}
|
|
107515
107745
|
rows.push({ line, from, to });
|
|
107516
|
-
const
|
|
107517
|
-
if (
|
|
107518
|
-
findings.push({ line, problem:
|
|
107746
|
+
const invalid4 = validateLabel(to);
|
|
107747
|
+
if (invalid4 !== undefined)
|
|
107748
|
+
findings.push({ line, problem: invalid4 });
|
|
107519
107749
|
}
|
|
107520
107750
|
for (const field of ["from", "to"]) {
|
|
107521
107751
|
const seen = new Map;
|
|
@@ -107596,9 +107826,9 @@ async function vaultRename(args, ctx) {
|
|
|
107596
107826
|
return usage2(ctx, RENAME_USAGE);
|
|
107597
107827
|
}
|
|
107598
107828
|
if (!batch && next !== undefined) {
|
|
107599
|
-
const
|
|
107600
|
-
if (
|
|
107601
|
-
return usage2(ctx,
|
|
107829
|
+
const invalid4 = validateLabel(next);
|
|
107830
|
+
if (invalid4 !== undefined)
|
|
107831
|
+
return usage2(ctx, invalid4);
|
|
107602
107832
|
if (old === next)
|
|
107603
107833
|
return usage2(ctx, SAME_STRING_LINE);
|
|
107604
107834
|
}
|
|
@@ -107856,9 +108086,9 @@ async function teeRename(args, ctx) {
|
|
|
107856
108086
|
return refusal3(ctx, parsedFile.findings, 2);
|
|
107857
108087
|
pairs = parsedFile.rows;
|
|
107858
108088
|
} else {
|
|
107859
|
-
const
|
|
107860
|
-
if (
|
|
107861
|
-
return usage2(ctx,
|
|
108089
|
+
const invalid4 = validateLabel(next);
|
|
108090
|
+
if (invalid4 !== undefined)
|
|
108091
|
+
return usage2(ctx, invalid4);
|
|
107862
108092
|
if (old === next)
|
|
107863
108093
|
return usage2(ctx, SAME_STRING_LINE);
|
|
107864
108094
|
pairs = [{ line: 0, from: old, to: next }];
|
|
@@ -109675,7 +109905,7 @@ init_args();
|
|
|
109675
109905
|
init_human_output();
|
|
109676
109906
|
init_presentation();
|
|
109677
109907
|
import { chmod as chmod13, copyFile, mkdir as mkdir11, stat as stat6 } from "node:fs/promises";
|
|
109678
|
-
import nodePath, { dirname as dirname11, resolve as
|
|
109908
|
+
import nodePath, { dirname as dirname11, resolve as resolve5 } from "node:path";
|
|
109679
109909
|
init_crypto();
|
|
109680
109910
|
init_errors2();
|
|
109681
109911
|
init_evm_record();
|
|
@@ -110008,7 +110238,7 @@ function fileModeOctal(mode) {
|
|
|
110008
110238
|
}
|
|
110009
110239
|
function resolveBackupDestination(to, deps) {
|
|
110010
110240
|
if (to.trim().toLowerCase() !== ICLOUD_SHORTHAND)
|
|
110011
|
-
return { path:
|
|
110241
|
+
return { path: resolve5(to) };
|
|
110012
110242
|
const home = homeDirOf(deps.env);
|
|
110013
110243
|
return { path: icloudBackupPath(home, deps.now()), requires: icloudDriveDir(home) };
|
|
110014
110244
|
}
|
|
@@ -110087,7 +110317,7 @@ async function vaultVerifyBackup(args, ctx) {
|
|
|
110087
110317
|
const path = resolvedVault.path;
|
|
110088
110318
|
return runVaultCommand(ctx, async ({ hold }) => {
|
|
110089
110319
|
const raw = await requireVaultRaw(ctx, resolvedVault);
|
|
110090
|
-
const target =
|
|
110320
|
+
const target = resolve5(copyPath);
|
|
110091
110321
|
const copyRaw = await readVaultRaw(target);
|
|
110092
110322
|
if (copyRaw === null)
|
|
110093
110323
|
throw new VaultError("VAULT_MISSING", `No file at ${target}.`, {
|
|
@@ -110788,8 +111018,8 @@ init_errors2();
|
|
|
110788
111018
|
init_promote_support();
|
|
110789
111019
|
init_store();
|
|
110790
111020
|
init_vault_support();
|
|
110791
|
-
import { access as access4, chmod as chmod14, constants as
|
|
110792
|
-
import { dirname as dirname12, resolve as
|
|
111021
|
+
import { access as access4, chmod as chmod14, constants as constants7, lstat as lstat2, writeFile as writeFile13 } from "node:fs/promises";
|
|
111022
|
+
import { dirname as dirname12, resolve as resolve6 } from "node:path";
|
|
110793
111023
|
async function vaultExportKey(args, ctx) {
|
|
110794
111024
|
const parsed = parseArgs(args, {
|
|
110795
111025
|
valueFlags: ["--keystore", "--to"],
|
|
@@ -110809,7 +111039,7 @@ async function vaultExportKey(args, ctx) {
|
|
|
110809
111039
|
return 1;
|
|
110810
111040
|
if (!requireTty(ctx, "vault export-key"))
|
|
110811
111041
|
return 1;
|
|
110812
|
-
const destination =
|
|
111042
|
+
const destination = resolve6(to);
|
|
110813
111043
|
const resolvedVault = vaultPathFor(ctx, parsed);
|
|
110814
111044
|
if ("error" in resolvedVault)
|
|
110815
111045
|
return usage2(ctx, resolvedVault.error);
|
|
@@ -110923,7 +111153,7 @@ async function assertExportTargetWritable(destination) {
|
|
|
110923
111153
|
throw error;
|
|
110924
111154
|
}
|
|
110925
111155
|
try {
|
|
110926
|
-
await access4(parent,
|
|
111156
|
+
await access4(parent, constants7.W_OK);
|
|
110927
111157
|
} catch {
|
|
110928
111158
|
throw new VaultError("VAULT_WRITE_FAILED", `${parent} is not writable.`, {
|
|
110929
111159
|
suggestion: "Choose a directory you can write to, or fix its permissions, then retry."
|
|
@@ -111688,7 +111918,7 @@ async function createVault(request2, clock) {
|
|
|
111688
111918
|
if (indexRequiresVersion4(seedIndex)) {
|
|
111689
111919
|
orphaned = await moveAsideOrphanRecord(request2.path, {
|
|
111690
111920
|
now: clock.now,
|
|
111691
|
-
sleep: clock.sleep ?? ((ms) => new Promise((
|
|
111921
|
+
sleep: clock.sleep ?? ((ms) => new Promise((resolve7) => setTimeout(resolve7, ms)))
|
|
111692
111922
|
});
|
|
111693
111923
|
}
|
|
111694
111924
|
const dek = freshDek();
|
|
@@ -115796,14 +116026,14 @@ function parseCounts(count3, teeCount, externalCount, rpcUrl, evmCount, evmTeeCo
|
|
|
115796
116026
|
return evmTeeParsed;
|
|
115797
116027
|
const allOmitted = vaultCount === undefined && teeParsed === undefined && externalParsed === undefined;
|
|
115798
116028
|
const scan2 = rpcUrl !== undefined;
|
|
115799
|
-
const
|
|
116029
|
+
const resolve7 = (value) => {
|
|
115800
116030
|
if (value !== undefined)
|
|
115801
116031
|
return value;
|
|
115802
116032
|
return scan2 ? undefined : 1;
|
|
115803
116033
|
};
|
|
115804
|
-
const solanaVault = allOmitted && !scan2 ? 1 :
|
|
115805
|
-
const solanaTee = allOmitted && !scan2 ? 1 :
|
|
115806
|
-
const solanaExternal = allOmitted && !scan2 ? 1 :
|
|
116034
|
+
const solanaVault = allOmitted && !scan2 ? 1 : resolve7(vaultCount);
|
|
116035
|
+
const solanaTee = allOmitted && !scan2 ? 1 : resolve7(teeParsed);
|
|
116036
|
+
const solanaExternal = allOmitted && !scan2 ? 1 : resolve7(externalParsed);
|
|
115807
116037
|
return {
|
|
115808
116038
|
solanaVault,
|
|
115809
116039
|
solanaTee,
|
|
@@ -117978,9 +118208,11 @@ async function clearConfig() {
|
|
|
117978
118208
|
|
|
117979
118209
|
// src/index.ts
|
|
117980
118210
|
init_ownership();
|
|
118211
|
+
init_deps();
|
|
117981
118212
|
init_file_lock();
|
|
117982
118213
|
|
|
117983
118214
|
// src/guard.ts
|
|
118215
|
+
init_api_key_file();
|
|
117984
118216
|
init_account();
|
|
117985
118217
|
init_profiles();
|
|
117986
118218
|
async function verifyProfileAccount(ctx, config) {
|
|
@@ -117989,6 +118221,8 @@ async function verifyProfileAccount(ctx, config) {
|
|
|
117989
118221
|
return { ok: true, skipped: "--no-verify-account" };
|
|
117990
118222
|
if (!profile)
|
|
117991
118223
|
return { ok: true, skipped: "no profile" };
|
|
118224
|
+
if (hasApiKeyFile(deps.env))
|
|
118225
|
+
return { ok: true, skipped: "CANDLE_API_KEY_FILE external override" };
|
|
117992
118226
|
if (credentialEnvOverrides(deps.env).length > 0)
|
|
117993
118227
|
return { ok: true, skipped: "env override" };
|
|
117994
118228
|
const cached = effectiveProfileFields(config, profile).account;
|
|
@@ -118081,9 +118315,9 @@ init_evm_tee();
|
|
|
118081
118315
|
// release-policy.json
|
|
118082
118316
|
var release_policy_default = {
|
|
118083
118317
|
macosHelper: {
|
|
118084
|
-
release: "
|
|
118318
|
+
release: "signed",
|
|
118085
118319
|
bundleId: "tv.candle.cli.enclave",
|
|
118086
|
-
teamId: ""
|
|
118320
|
+
teamId: "ZC2DLBZS4U"
|
|
118087
118321
|
}
|
|
118088
118322
|
};
|
|
118089
118323
|
|
|
@@ -118375,6 +118609,7 @@ function extractOwnerConfirmFlags(argv) {
|
|
|
118375
118609
|
return { argv: [...kept, ...tail], open: open8, noWait };
|
|
118376
118610
|
}
|
|
118377
118611
|
async function run2(argv, deps) {
|
|
118612
|
+
deps = beginCredentialInvocation(deps);
|
|
118378
118613
|
const confirmFlags = extractOwnerConfirmFlags(argv);
|
|
118379
118614
|
argv = confirmFlags.argv;
|
|
118380
118615
|
const confirmState = { pendingWithoutWait: false };
|
|
@@ -118406,6 +118641,11 @@ async function runWithConfirm(argv, deps) {
|
|
|
118406
118641
|
try {
|
|
118407
118642
|
code = await runCommand(argv, deps);
|
|
118408
118643
|
} catch (error2) {
|
|
118644
|
+
if (error2 instanceof ApiKeyFileError) {
|
|
118645
|
+
const parsed2 = extractGlobalFlags(argv);
|
|
118646
|
+
writeLocalFailure(deps, { code: error2.code, message: error2.message }, !("error" in parsed2) && parsed2.flags.json);
|
|
118647
|
+
return 1;
|
|
118648
|
+
}
|
|
118409
118649
|
if (error2 instanceof ProfileFleetOnlyError) {
|
|
118410
118650
|
const parsed2 = extractGlobalFlags(argv);
|
|
118411
118651
|
writeLocalFailure(deps, { code: error2.code, message: error2.message }, !("error" in parsed2) && parsed2.flags.json);
|
|
@@ -118506,7 +118746,8 @@ async function runCommand(argv, deps) {
|
|
|
118506
118746
|
vaultDevice: flags2.vaultDevice
|
|
118507
118747
|
});
|
|
118508
118748
|
}
|
|
118509
|
-
const
|
|
118749
|
+
const keylessMcp = cmd === "mcp" && tokens.includes("--read-only");
|
|
118750
|
+
const config2 = cmd === "doctor" || keylessMcp ? await deps.readConfig() : await migrateProfiles(deps);
|
|
118510
118751
|
const isAuthLogin = cmd === "auth" && sub === "login";
|
|
118511
118752
|
const isProfileCommand = cmd === "profile";
|
|
118512
118753
|
const resolution = isAuthLogin ? resolveProfileNameForLogin(config2, { flag: flags2.profile, env: deps.env }) : isProfileCommand ? { ok: true, name: undefined } : resolveProfileName(config2, { flag: flags2.profile, env: deps.env });
|
|
@@ -118599,7 +118840,7 @@ function unknownCommand(deps, token2, word3) {
|
|
|
118599
118840
|
}
|
|
118600
118841
|
async function migrateProfiles(deps) {
|
|
118601
118842
|
const before = await deps.readConfig();
|
|
118602
|
-
if (deps.env.CANDLE_API_KEY?.trim() || deps.env.CANDLE_DEVICE_TOKEN?.trim())
|
|
118843
|
+
if (hasApiKeyFile(deps.env) || deps.env.CANDLE_API_KEY?.trim() || deps.env.CANDLE_DEVICE_TOKEN?.trim())
|
|
118603
118844
|
return before;
|
|
118604
118845
|
const { config: config2, migrated } = migratedConfig(before);
|
|
118605
118846
|
if (!migrated)
|
|
@@ -118628,12 +118869,12 @@ function realOpenBrowser(serverUrl) {
|
|
|
118628
118869
|
}
|
|
118629
118870
|
var HELPER_WORKING_DIRECTORY = "/";
|
|
118630
118871
|
function realSpawnHelper(path, requestLine, opts) {
|
|
118631
|
-
return new Promise((
|
|
118872
|
+
return new Promise((resolve7) => {
|
|
118632
118873
|
let child;
|
|
118633
118874
|
try {
|
|
118634
118875
|
child = spawn3(path, opts.args ?? [], { stdio: ["pipe", "pipe", "pipe"], cwd: HELPER_WORKING_DIRECTORY });
|
|
118635
118876
|
} catch (error2) {
|
|
118636
|
-
|
|
118877
|
+
resolve7({ stdout: "", stderr: "", exitCode: null, signal: null, spawnError: messageOf4(error2) });
|
|
118637
118878
|
return;
|
|
118638
118879
|
}
|
|
118639
118880
|
const out = [];
|
|
@@ -118646,7 +118887,7 @@ function realSpawnHelper(path, requestLine, opts) {
|
|
|
118646
118887
|
return;
|
|
118647
118888
|
settled = true;
|
|
118648
118889
|
clearTimeout(timer);
|
|
118649
|
-
|
|
118890
|
+
resolve7({ stdout: Buffer.concat(out).toString("utf8"), stderr: Buffer.concat(err).toString("utf8"), ...result2 });
|
|
118650
118891
|
};
|
|
118651
118892
|
let exited;
|
|
118652
118893
|
const timer = setTimeout(() => {
|
|
@@ -118695,7 +118936,7 @@ async function buildRealDeps() {
|
|
|
118695
118936
|
}
|
|
118696
118937
|
},
|
|
118697
118938
|
now: () => Date.now(),
|
|
118698
|
-
sleep: (ms) => new Promise((
|
|
118939
|
+
sleep: (ms) => new Promise((resolve7) => setTimeout(resolve7, ms)),
|
|
118699
118940
|
openBrowser: realOpenBrowser,
|
|
118700
118941
|
env: process.env,
|
|
118701
118942
|
nodeVersion: process.versions.node,
|
|
@@ -118709,10 +118950,10 @@ async function buildRealDeps() {
|
|
|
118709
118950
|
},
|
|
118710
118951
|
readFile: (path) => readFile21(path, "utf8"),
|
|
118711
118952
|
readBytes: (path) => readFile21(path),
|
|
118712
|
-
readStdin: () => new Promise((
|
|
118953
|
+
readStdin: () => new Promise((resolve7, reject) => {
|
|
118713
118954
|
const chunks = [];
|
|
118714
118955
|
process.stdin.on("data", (chunk) => chunks.push(chunk));
|
|
118715
|
-
process.stdin.on("end", () =>
|
|
118956
|
+
process.stdin.on("end", () => resolve7(new Uint8Array(Buffer.concat(chunks))));
|
|
118716
118957
|
process.stdin.on("error", reject);
|
|
118717
118958
|
process.stdin.resume();
|
|
118718
118959
|
}),
|
|
@@ -118752,13 +118993,13 @@ async function buildRealDeps() {
|
|
|
118752
118993
|
};
|
|
118753
118994
|
}
|
|
118754
118995
|
function realRunHook(command, stdin, env, timeoutMs) {
|
|
118755
|
-
return new Promise((
|
|
118996
|
+
return new Promise((resolve7) => {
|
|
118756
118997
|
let timedOut = false;
|
|
118757
118998
|
let child;
|
|
118758
118999
|
try {
|
|
118759
119000
|
child = spawn3(command, { shell: true, env: { ...process.env, ...env }, stdio: ["pipe", "pipe", "pipe"] });
|
|
118760
119001
|
} catch (err) {
|
|
118761
|
-
|
|
119002
|
+
resolve7({
|
|
118762
119003
|
exitCode: null,
|
|
118763
119004
|
signal: null,
|
|
118764
119005
|
timedOut: false,
|
|
@@ -118776,11 +119017,11 @@ function realRunHook(command, stdin, env, timeoutMs) {
|
|
|
118776
119017
|
child.stdin?.end(stdin);
|
|
118777
119018
|
child.on("error", (err) => {
|
|
118778
119019
|
clearTimeout(timer);
|
|
118779
|
-
|
|
119020
|
+
resolve7({ exitCode: null, signal: null, timedOut, error: err.message });
|
|
118780
119021
|
});
|
|
118781
119022
|
child.on("close", (exitCode, signal) => {
|
|
118782
119023
|
clearTimeout(timer);
|
|
118783
|
-
|
|
119024
|
+
resolve7({ exitCode, signal, timedOut });
|
|
118784
119025
|
});
|
|
118785
119026
|
});
|
|
118786
119027
|
}
|