@cogcoin/client 0.5.14 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. package/README.md +80 -25
  2. package/dist/app-paths.d.ts +5 -6
  3. package/dist/app-paths.js +8 -16
  4. package/dist/art/balance.txt +10 -0
  5. package/dist/art/welcome.txt +16 -0
  6. package/dist/bitcoind/bootstrap/controller.d.ts +1 -0
  7. package/dist/bitcoind/bootstrap/controller.js +53 -1
  8. package/dist/bitcoind/client/follow-block-times.d.ts +1 -0
  9. package/dist/bitcoind/client/follow-block-times.js +1 -1
  10. package/dist/bitcoind/client/internal-types.d.ts +7 -3
  11. package/dist/bitcoind/client/managed-client.d.ts +4 -2
  12. package/dist/bitcoind/client/managed-client.js +14 -0
  13. package/dist/bitcoind/client/sync-engine.js +72 -11
  14. package/dist/bitcoind/hash-order.d.ts +4 -0
  15. package/dist/bitcoind/hash-order.js +13 -0
  16. package/dist/bitcoind/indexer-daemon-main.js +11 -3
  17. package/dist/bitcoind/normalize.js +3 -2
  18. package/dist/bitcoind/processing-start-height.d.ts +5 -0
  19. package/dist/bitcoind/processing-start-height.js +7 -0
  20. package/dist/bitcoind/progress/constants.d.ts +4 -0
  21. package/dist/bitcoind/progress/constants.js +4 -0
  22. package/dist/bitcoind/progress/controller.d.ts +2 -1
  23. package/dist/bitcoind/progress/controller.js +3 -3
  24. package/dist/bitcoind/progress/follow-scene.d.ts +6 -2
  25. package/dist/bitcoind/progress/follow-scene.js +29 -6
  26. package/dist/bitcoind/progress/formatting.d.ts +1 -0
  27. package/dist/bitcoind/progress/formatting.js +6 -0
  28. package/dist/bitcoind/progress/train-scene.js +37 -18
  29. package/dist/bitcoind/progress/tty-renderer.d.ts +6 -1
  30. package/dist/bitcoind/progress/tty-renderer.js +8 -4
  31. package/dist/bitcoind/rpc.d.ts +2 -1
  32. package/dist/bitcoind/rpc.js +3 -0
  33. package/dist/bitcoind/types.d.ts +16 -0
  34. package/dist/bytes.d.ts +1 -0
  35. package/dist/bytes.js +3 -0
  36. package/dist/cli/art.d.ts +2 -0
  37. package/dist/cli/art.js +37 -0
  38. package/dist/cli/commands/client-admin.d.ts +2 -0
  39. package/dist/cli/commands/client-admin.js +91 -0
  40. package/dist/cli/commands/follow.js +0 -2
  41. package/dist/cli/commands/mining-admin.js +6 -47
  42. package/dist/cli/commands/mining-read.js +11 -50
  43. package/dist/cli/commands/mining-runtime.js +38 -3
  44. package/dist/cli/commands/service-runtime.js +0 -2
  45. package/dist/cli/commands/status.js +8 -2
  46. package/dist/cli/commands/sync.js +51 -4
  47. package/dist/cli/commands/wallet-admin.js +142 -136
  48. package/dist/cli/commands/wallet-mutation.js +91 -79
  49. package/dist/cli/commands/wallet-read.js +15 -18
  50. package/dist/cli/context.js +4 -14
  51. package/dist/cli/mining-format.d.ts +0 -1
  52. package/dist/cli/mining-format.js +5 -37
  53. package/dist/cli/mining-json.d.ts +0 -18
  54. package/dist/cli/mining-json.js +0 -35
  55. package/dist/cli/mutation-command-groups.d.ts +1 -2
  56. package/dist/cli/mutation-command-groups.js +0 -5
  57. package/dist/cli/mutation-json.d.ts +24 -145
  58. package/dist/cli/mutation-json.js +30 -136
  59. package/dist/cli/mutation-resolved-json.d.ts +0 -7
  60. package/dist/cli/mutation-resolved-json.js +4 -10
  61. package/dist/cli/mutation-success.d.ts +2 -0
  62. package/dist/cli/mutation-success.js +11 -1
  63. package/dist/cli/mutation-text-format.js +1 -3
  64. package/dist/cli/output.d.ts +1 -1
  65. package/dist/cli/output.js +254 -231
  66. package/dist/cli/parse.d.ts +1 -1
  67. package/dist/cli/parse.js +93 -122
  68. package/dist/cli/preview-json.d.ts +17 -120
  69. package/dist/cli/preview-json.js +14 -97
  70. package/dist/cli/prompt.js +8 -13
  71. package/dist/cli/read-json.d.ts +15 -37
  72. package/dist/cli/read-json.js +44 -140
  73. package/dist/cli/runner.js +10 -13
  74. package/dist/cli/types.d.ts +8 -17
  75. package/dist/cli/types.js +0 -2
  76. package/dist/cli/wallet-format.d.ts +1 -0
  77. package/dist/cli/wallet-format.js +205 -144
  78. package/dist/cli/workflow-hints.d.ts +3 -3
  79. package/dist/cli/workflow-hints.js +11 -8
  80. package/dist/client/default-client.d.ts +3 -1
  81. package/dist/client/default-client.js +45 -2
  82. package/dist/client/factory.js +1 -1
  83. package/dist/client/initialization.js +23 -0
  84. package/dist/client/persistence.js +5 -5
  85. package/dist/client/store-adapter.js +1 -0
  86. package/dist/sqlite/checkpoints.d.ts +1 -0
  87. package/dist/sqlite/checkpoints.js +7 -0
  88. package/dist/sqlite/store.js +14 -1
  89. package/dist/types.d.ts +1 -0
  90. package/dist/wallet/coin-control.d.ts +41 -11
  91. package/dist/wallet/coin-control.js +100 -357
  92. package/dist/wallet/descriptor-normalization.d.ts +1 -3
  93. package/dist/wallet/descriptor-normalization.js +0 -16
  94. package/dist/wallet/lifecycle.d.ts +7 -99
  95. package/dist/wallet/lifecycle.js +513 -968
  96. package/dist/wallet/managed-core-wallet.d.ts +13 -0
  97. package/dist/wallet/managed-core-wallet.js +20 -0
  98. package/dist/wallet/mining/constants.d.ts +5 -12
  99. package/dist/wallet/mining/constants.js +5 -12
  100. package/dist/wallet/mining/control.d.ts +1 -13
  101. package/dist/wallet/mining/control.js +45 -349
  102. package/dist/wallet/mining/index.d.ts +3 -4
  103. package/dist/wallet/mining/index.js +1 -2
  104. package/dist/wallet/mining/runner.d.ts +179 -6
  105. package/dist/wallet/mining/runner.js +891 -501
  106. package/dist/wallet/mining/runtime-artifacts.js +23 -3
  107. package/dist/wallet/mining/sentence-protocol.d.ts +44 -0
  108. package/dist/wallet/mining/sentence-protocol.js +123 -0
  109. package/dist/wallet/mining/sentences.d.ts +4 -8
  110. package/dist/wallet/mining/sentences.js +3 -52
  111. package/dist/wallet/mining/state.d.ts +11 -6
  112. package/dist/wallet/mining/state.js +7 -6
  113. package/dist/wallet/mining/types.d.ts +2 -30
  114. package/dist/wallet/mining/visualizer.d.ts +31 -3
  115. package/dist/wallet/mining/visualizer.js +135 -13
  116. package/dist/wallet/read/context.d.ts +0 -2
  117. package/dist/wallet/read/context.js +119 -140
  118. package/dist/wallet/read/filter.js +2 -11
  119. package/dist/wallet/read/index.d.ts +1 -1
  120. package/dist/wallet/read/project.js +24 -77
  121. package/dist/wallet/read/types.d.ts +10 -25
  122. package/dist/wallet/reset.d.ts +0 -1
  123. package/dist/wallet/reset.js +60 -138
  124. package/dist/wallet/root-resolution.d.ts +1 -5
  125. package/dist/wallet/root-resolution.js +0 -18
  126. package/dist/wallet/runtime.d.ts +0 -6
  127. package/dist/wallet/runtime.js +0 -8
  128. package/dist/wallet/state/client-password-agent.js +208 -0
  129. package/dist/wallet/state/client-password.d.ts +65 -0
  130. package/dist/wallet/state/client-password.js +952 -0
  131. package/dist/wallet/state/crypto.d.ts +1 -20
  132. package/dist/wallet/state/crypto.js +0 -63
  133. package/dist/wallet/state/provider.d.ts +23 -11
  134. package/dist/wallet/state/provider.js +248 -290
  135. package/dist/wallet/state/storage.d.ts +2 -2
  136. package/dist/wallet/state/storage.js +48 -16
  137. package/dist/wallet/tx/anchor.d.ts +3 -28
  138. package/dist/wallet/tx/anchor.js +349 -1240
  139. package/dist/wallet/tx/bitcoin-transfer.d.ts +35 -0
  140. package/dist/wallet/tx/bitcoin-transfer.js +200 -0
  141. package/dist/wallet/tx/cog.d.ts +5 -1
  142. package/dist/wallet/tx/cog.js +149 -185
  143. package/dist/wallet/tx/common.d.ts +74 -10
  144. package/dist/wallet/tx/common.js +315 -138
  145. package/dist/wallet/tx/domain-admin.d.ts +3 -1
  146. package/dist/wallet/tx/domain-admin.js +61 -99
  147. package/dist/wallet/tx/domain-market.d.ts +5 -1
  148. package/dist/wallet/tx/domain-market.js +221 -228
  149. package/dist/wallet/tx/field.d.ts +4 -10
  150. package/dist/wallet/tx/field.js +84 -914
  151. package/dist/wallet/tx/identity-selector.d.ts +9 -3
  152. package/dist/wallet/tx/identity-selector.js +17 -35
  153. package/dist/wallet/tx/index.d.ts +3 -1
  154. package/dist/wallet/tx/index.js +2 -1
  155. package/dist/wallet/tx/register.d.ts +3 -1
  156. package/dist/wallet/tx/register.js +62 -220
  157. package/dist/wallet/tx/reputation.d.ts +3 -1
  158. package/dist/wallet/tx/reputation.js +58 -95
  159. package/dist/wallet/types.d.ts +8 -122
  160. package/package.json +5 -5
  161. package/dist/wallet/archive.d.ts +0 -4
  162. package/dist/wallet/archive.js +0 -41
  163. package/dist/wallet/mining/hook-protocol.d.ts +0 -47
  164. package/dist/wallet/mining/hook-protocol.js +0 -161
  165. package/dist/wallet/mining/hook-runner.js +0 -52
  166. package/dist/wallet/mining/hooks.d.ts +0 -38
  167. package/dist/wallet/mining/hooks.js +0 -520
  168. package/dist/wallet/state/explicit-lock.d.ts +0 -4
  169. package/dist/wallet/state/explicit-lock.js +0 -19
  170. package/dist/wallet/state/session.d.ts +0 -12
  171. package/dist/wallet/state/session.js +0 -23
  172. /package/dist/wallet/{mining/hook-runner.d.ts → state/client-password-agent.d.ts} +0 -0
@@ -1,520 +0,0 @@
1
- import { createHash } from "node:crypto";
2
- import { spawn } from "node:child_process";
3
- import { access, constants, lstat, mkdir, readFile, readdir, realpath, stat, writeFile, } from "node:fs/promises";
4
- import { dirname, isAbsolute, join, relative } from "node:path";
5
- import { fileURLToPath } from "node:url";
6
- import { MINING_HOOK_COOLDOWN_MS, MINING_HOOK_FAILURE_THRESHOLD, MINING_HOOK_STDERR_MAX_BYTES, MINING_HOOK_STDOUT_MAX_BYTES, MINING_HOOK_TERMINATE_GRACE_MS, MINING_HOOK_VALIDATION_TIMEOUT_MS, } from "./constants.js";
7
- import { MINING_HOOK_VALIDATION_FIXTURES, normalizeHookResponse, parseStrictJsonValue, } from "./hook-protocol.js";
8
- const DEFAULT_MINING_HOOK_TEMPLATE = `export async function generateSentences(request) {
9
- const domains = Array.isArray(request?.rootDomains) ? request.rootDomains : [];
10
- const candidates = domains.map((domain) => {
11
- const requiredWords = Array.isArray(domain?.requiredWords)
12
- ? domain.requiredWords.filter((word) => typeof word === "string" && word.length > 0).join(" ")
13
- : "abandon ability able about above";
14
- const domainName = typeof domain?.domainName === "string" && domain.domainName.length > 0
15
- ? domain.domainName
16
- : "domain";
17
-
18
- return {
19
- domainId: domain.domainId,
20
- sentence: \`\${domainName} sentence using \${requiredWords}.\`,
21
- };
22
- });
23
-
24
- return {
25
- schemaVersion: 1,
26
- requestId: typeof request?.requestId === "string" ? request.requestId : "",
27
- candidates,
28
- };
29
- }
30
- `;
31
- const DEFAULT_MINING_HOOK_PACKAGE_JSON = {
32
- name: "cogcoin-mining-hooks",
33
- private: true,
34
- type: "module",
35
- };
36
- const HOOK_ENV_ALLOWLIST = [
37
- "HOME",
38
- "USERPROFILE",
39
- "APPDATA",
40
- "LOCALAPPDATA",
41
- "TMPDIR",
42
- "TMP",
43
- "TEMP",
44
- "SystemRoot",
45
- "WINDIR",
46
- "ComSpec",
47
- "PATHEXT",
48
- "SSL_CERT_FILE",
49
- "SSL_CERT_DIR",
50
- "NODE_EXTRA_CA_CERTS",
51
- ];
52
- const RECOGNIZED_LOCKFILES = [
53
- "package-lock.json",
54
- "npm-shrinkwrap.json",
55
- "pnpm-lock.yaml",
56
- "yarn.lock",
57
- "bun.lockb",
58
- ];
59
- function mapStoredValidationState(raw) {
60
- switch (raw) {
61
- case "current":
62
- case "validated":
63
- return "current";
64
- case "stale":
65
- return "stale";
66
- case "failed":
67
- return "failed";
68
- default:
69
- return "never";
70
- }
71
- }
72
- function mapOperatorToLegacyValidationState(operatorState) {
73
- switch (operatorState) {
74
- case "current":
75
- return "validated";
76
- case "stale":
77
- return "stale";
78
- case "failed":
79
- return "failed";
80
- default:
81
- return "unknown";
82
- }
83
- }
84
- async function pathExists(path) {
85
- try {
86
- await access(path, constants.F_OK);
87
- return true;
88
- }
89
- catch {
90
- return false;
91
- }
92
- }
93
- async function hashFile(path) {
94
- const hash = createHash("sha256");
95
- hash.update(await readFile(path));
96
- return hash.digest("hex");
97
- }
98
- async function listFilesRecursively(root, options) {
99
- let entries;
100
- try {
101
- entries = await readdir(root, { withFileTypes: true });
102
- }
103
- catch (error) {
104
- if (error instanceof Error && "code" in error && error.code === "ENOENT") {
105
- return [];
106
- }
107
- throw error;
108
- }
109
- const files = [];
110
- for (const entry of entries) {
111
- const fullPath = join(root, entry.name);
112
- const relativePath = relative(root, fullPath);
113
- const isNodeModules = entry.name === "node_modules";
114
- const isExcludedRoot = entry.name === ".cache" || entry.name === "tmp" || entry.name === "logs";
115
- if (entry.isDirectory()) {
116
- if ((!options.includeNodeModules && isNodeModules) || isExcludedRoot) {
117
- continue;
118
- }
119
- if (options.includeNodeModules && relativePath === join("node_modules", ".cache")) {
120
- continue;
121
- }
122
- files.push(...await listFilesRecursively(fullPath, options));
123
- continue;
124
- }
125
- if (entry.isFile()) {
126
- files.push(fullPath);
127
- }
128
- }
129
- return files;
130
- }
131
- async function computeFingerprint(options) {
132
- const files = await listFilesRecursively(options.root, {
133
- includeNodeModules: options.includeNodeModules,
134
- });
135
- if (files.length === 0) {
136
- return null;
137
- }
138
- const descriptors = await Promise.all(files
139
- .sort()
140
- .map(async (filePath) => ({
141
- relativePath: relative(options.root, filePath),
142
- sha256Hex: await hashFile(filePath),
143
- })));
144
- const hash = createHash("sha256");
145
- hash.update(JSON.stringify({
146
- schemaVersion: 1,
147
- files: descriptors,
148
- }));
149
- return hash.digest("hex");
150
- }
151
- async function assessPackageJson(packagePath) {
152
- let parsed;
153
- try {
154
- parsed = JSON.parse(await readFile(packagePath, "utf8"));
155
- }
156
- catch (error) {
157
- if (error instanceof Error && "code" in error && error.code === "ENOENT") {
158
- return {
159
- status: "missing",
160
- message: "package.json is missing for the custom mining hook.",
161
- };
162
- }
163
- return {
164
- status: "invalid",
165
- message: "package.json is not valid JSON or could not be read.",
166
- };
167
- }
168
- if (parsed === null
169
- || typeof parsed !== "object"
170
- || parsed.type !== "module") {
171
- return {
172
- status: "invalid",
173
- message: "package.json must set \"type\": \"module\" for custom mining hooks.",
174
- };
175
- }
176
- return {
177
- status: "valid",
178
- message: null,
179
- };
180
- }
181
- async function collectTrustPaths(options) {
182
- const trustPaths = [
183
- dirname(options.hookRootPath),
184
- options.hookRootPath,
185
- options.entrypointPath,
186
- options.packagePath,
187
- ];
188
- for (const lockfile of RECOGNIZED_LOCKFILES) {
189
- const lockfilePath = `${options.hookRootPath}/${lockfile}`;
190
- if (await pathExists(lockfilePath)) {
191
- trustPaths.push(lockfilePath);
192
- }
193
- }
194
- const nodeModulesPath = `${options.hookRootPath}/node_modules`;
195
- if (await pathExists(nodeModulesPath)) {
196
- trustPaths.push(nodeModulesPath);
197
- }
198
- return [...new Set(trustPaths)];
199
- }
200
- function isPathInsideRoot(rootPath, candidatePath) {
201
- const relativePath = relative(rootPath, candidatePath);
202
- return relativePath === "" || (!relativePath.startsWith("..") && !isAbsolute(relativePath));
203
- }
204
- async function assessTrust(options) {
205
- const trustPaths = await collectTrustPaths(options);
206
- const hooksRootPath = dirname(options.hookRootPath);
207
- let hooksRootRealPath;
208
- try {
209
- hooksRootRealPath = await realpath(hooksRootPath);
210
- }
211
- catch (error) {
212
- if (error instanceof Error && "code" in error && error.code === "ENOENT") {
213
- return {
214
- status: "missing",
215
- message: `Hook path ${hooksRootPath} does not exist yet.`,
216
- };
217
- }
218
- throw error;
219
- }
220
- for (const path of trustPaths) {
221
- let metadata;
222
- try {
223
- metadata = await lstat(path);
224
- }
225
- catch (error) {
226
- if (error instanceof Error && "code" in error && error.code === "ENOENT") {
227
- return {
228
- status: "missing",
229
- message: `Hook path ${path} does not exist yet.`,
230
- };
231
- }
232
- throw error;
233
- }
234
- if (metadata.isSymbolicLink()) {
235
- return {
236
- status: "untrusted",
237
- message: `Hook path ${path} uses a symbolic link or reparse point.`,
238
- };
239
- }
240
- const canonicalPath = await realpath(path);
241
- if (!isPathInsideRoot(hooksRootRealPath, canonicalPath)) {
242
- return {
243
- status: "untrusted",
244
- message: `Hook path ${path} resolves outside the Cogcoin hooks root.`,
245
- };
246
- }
247
- if (process.platform === "win32") {
248
- continue;
249
- }
250
- const resolvedMetadata = await stat(path);
251
- if (typeof process.getuid === "function" && resolvedMetadata.uid !== process.getuid()) {
252
- return {
253
- status: "untrusted",
254
- message: `Hook path ${path} is not owned by the current user.`,
255
- };
256
- }
257
- if ((resolvedMetadata.mode & 0o022) !== 0) {
258
- return {
259
- status: "untrusted",
260
- message: `Hook path ${path} is writable by group or others.`,
261
- };
262
- }
263
- }
264
- return {
265
- status: "trusted",
266
- message: null,
267
- };
268
- }
269
- function buildHookChildEnvironment(parentEnv) {
270
- const environment = {
271
- COGCOIN_HOOK_KIND: "mining/generate-sentences",
272
- COGCOIN_HOOK_SCHEMA_VERSION: "1",
273
- NODE_ENV: "production",
274
- TZ: "UTC",
275
- };
276
- for (const key of HOOK_ENV_ALLOWLIST) {
277
- const value = parentEnv[key];
278
- if (typeof value === "string" && value.length > 0) {
279
- environment[key] = value;
280
- }
281
- }
282
- return environment;
283
- }
284
- async function terminateChildProcess(child) {
285
- if (child.exitCode !== null || child.killed) {
286
- return;
287
- }
288
- child.kill("SIGTERM");
289
- const exited = await new Promise((resolve) => {
290
- const timer = setTimeout(() => resolve(false), MINING_HOOK_TERMINATE_GRACE_MS);
291
- child.once("close", () => {
292
- clearTimeout(timer);
293
- resolve(true);
294
- });
295
- });
296
- if (!exited && child.exitCode === null) {
297
- child.kill("SIGKILL");
298
- if (child.exitCode === null) {
299
- await new Promise((resolve) => {
300
- child.once("close", () => resolve());
301
- });
302
- }
303
- }
304
- }
305
- async function runHookRunner(options) {
306
- const runnerPath = fileURLToPath(new URL("./hook-runner.js", import.meta.url));
307
- const child = spawn(process.execPath, [
308
- runnerPath,
309
- options.entrypointPath,
310
- ], {
311
- cwd: options.hookRootPath,
312
- env: buildHookChildEnvironment(process.env),
313
- stdio: ["pipe", "pipe", "pipe"],
314
- windowsHide: true,
315
- });
316
- let stdout = "";
317
- let stderr = "";
318
- let stdoutBytes = 0;
319
- let stderrBytes = 0;
320
- let timedOut = false;
321
- let aborted = false;
322
- let stdoutOverflow = false;
323
- let stderrOverflow = false;
324
- let terminated = null;
325
- const terminate = () => {
326
- terminated ??= terminateChildProcess(child);
327
- return terminated;
328
- };
329
- const timeout = setTimeout(() => {
330
- timedOut = true;
331
- void terminate();
332
- }, options.timeoutMs);
333
- const abortListener = () => {
334
- aborted = true;
335
- void terminate();
336
- };
337
- options.signal?.addEventListener("abort", abortListener, { once: true });
338
- child.stdin.on("error", () => undefined);
339
- child.stdin.end(`${JSON.stringify(options.request)}\n`, "utf8");
340
- child.stdout.on("data", (chunk) => {
341
- const text = Buffer.isBuffer(chunk) ? chunk.toString("utf8") : chunk;
342
- stdoutBytes += Buffer.byteLength(text);
343
- if (stdoutBytes > MINING_HOOK_STDOUT_MAX_BYTES) {
344
- stdoutOverflow = true;
345
- void terminate();
346
- return;
347
- }
348
- stdout += text;
349
- });
350
- child.stderr.on("data", (chunk) => {
351
- const text = Buffer.isBuffer(chunk) ? chunk.toString("utf8") : chunk;
352
- stderrBytes += Buffer.byteLength(text);
353
- if (stderrBytes > MINING_HOOK_STDERR_MAX_BYTES) {
354
- stderrOverflow = true;
355
- void terminate();
356
- return;
357
- }
358
- stderr += text;
359
- });
360
- const exit = await new Promise((resolve, reject) => {
361
- child.once("error", reject);
362
- child.once("close", (code, signal) => resolve({ code, signal }));
363
- });
364
- clearTimeout(timeout);
365
- options.signal?.removeEventListener("abort", abortListener);
366
- if (stdoutOverflow) {
367
- throw new Error(`Custom mining hook stdout exceeded ${MINING_HOOK_STDOUT_MAX_BYTES} bytes.`);
368
- }
369
- if (stderrOverflow) {
370
- throw new Error(`Custom mining hook stderr exceeded ${MINING_HOOK_STDERR_MAX_BYTES} bytes.`);
371
- }
372
- if (timedOut) {
373
- throw new Error("Custom mining hook request timed out.");
374
- }
375
- if (aborted) {
376
- throw new Error("Custom mining hook request aborted.");
377
- }
378
- if (exit.code !== 0 || exit.signal !== null) {
379
- const diagnostic = stderr.trim().length > 0
380
- ? stderr.trim()
381
- : stdout.trim().length > 0
382
- ? stdout.trim()
383
- : "Custom mining hook request failed.";
384
- throw new Error(diagnostic);
385
- }
386
- return { stdout, stderr };
387
- }
388
- export async function runGenerateSentencesHookRequest(options) {
389
- const { stdout } = await runHookRunner({
390
- hookRootPath: options.hookRootPath,
391
- entrypointPath: options.entrypointPath,
392
- request: options.request,
393
- signal: options.signal,
394
- timeoutMs: options.timeoutMs ?? MINING_HOOK_VALIDATION_TIMEOUT_MS,
395
- });
396
- const response = parseStrictJsonValue(stdout, "Custom mining hook stdout was not valid JSON.");
397
- return normalizeHookResponse({
398
- request: options.request,
399
- response,
400
- });
401
- }
402
- export async function ensureMiningHookTemplate(options) {
403
- const entrypointExists = await pathExists(options.entrypointPath);
404
- let created = false;
405
- if (!entrypointExists) {
406
- await mkdir(options.hookRootPath, { recursive: true });
407
- await writeFile(options.entrypointPath, DEFAULT_MINING_HOOK_TEMPLATE, {
408
- encoding: "utf8",
409
- mode: 0o600,
410
- });
411
- created = true;
412
- }
413
- if (!await pathExists(options.packagePath)) {
414
- await mkdir(options.hookRootPath, { recursive: true });
415
- await writeFile(options.packagePath, `${JSON.stringify(DEFAULT_MINING_HOOK_PACKAGE_JSON, null, 2)}\n`, {
416
- encoding: "utf8",
417
- mode: 0o600,
418
- });
419
- created = true;
420
- }
421
- return created;
422
- }
423
- export async function validateCustomMiningHook(options) {
424
- const entrypointExists = await pathExists(options.entrypointPath);
425
- if (!entrypointExists) {
426
- throw new Error("Custom mining hook entrypoint is missing.");
427
- }
428
- const packageAssessment = await assessPackageJson(options.packagePath);
429
- if (packageAssessment.status !== "valid") {
430
- throw new Error(packageAssessment.message ?? "Custom mining hook package.json is invalid.");
431
- }
432
- const trust = await assessTrust(options);
433
- if (trust.status !== "trusted") {
434
- throw new Error(trust.message ?? "Custom mining hook trust checks failed.");
435
- }
436
- const launchFingerprint = await computeFingerprint({
437
- root: options.hookRootPath,
438
- includeNodeModules: false,
439
- });
440
- const fullFingerprint = await computeFingerprint({
441
- root: options.hookRootPath,
442
- includeNodeModules: true,
443
- });
444
- if (launchFingerprint === null || fullFingerprint === null) {
445
- throw new Error("Custom mining hook files are incomplete.");
446
- }
447
- for (const request of MINING_HOOK_VALIDATION_FIXTURES) {
448
- await runGenerateSentencesHookRequest({
449
- hookRootPath: options.hookRootPath,
450
- entrypointPath: options.entrypointPath,
451
- request,
452
- timeoutMs: MINING_HOOK_VALIDATION_TIMEOUT_MS,
453
- });
454
- }
455
- return {
456
- launchFingerprint,
457
- fullFingerprint,
458
- };
459
- }
460
- export async function inspectMiningHookState(options) {
461
- const entrypointExists = await pathExists(options.entrypointPath);
462
- const packageAssessment = await assessPackageJson(options.packagePath);
463
- const trust = await assessTrust(options);
464
- const currentLaunchFingerprint = await computeFingerprint({
465
- root: options.hookRootPath,
466
- includeNodeModules: false,
467
- });
468
- const currentFullFingerprint = options.verify
469
- ? await computeFingerprint({
470
- root: options.hookRootPath,
471
- includeNodeModules: true,
472
- })
473
- : null;
474
- const storedState = options.localState;
475
- const nowUnixMs = options.nowUnixMs ?? Date.now();
476
- let operatorValidationState = mapStoredValidationState(storedState?.validationState);
477
- if (storedState !== null && operatorValidationState === "current") {
478
- const launchFingerprintMatches = storedState.validatedLaunchFingerprint !== null
479
- && currentLaunchFingerprint !== null
480
- && storedState.validatedLaunchFingerprint === currentLaunchFingerprint;
481
- const fullFingerprintMatches = !options.verify
482
- || storedState.validatedFullFingerprint === null
483
- || currentFullFingerprint === null
484
- || storedState.validatedFullFingerprint === currentFullFingerprint;
485
- if (trust.status !== "trusted" || !launchFingerprintMatches || !fullFingerprintMatches) {
486
- operatorValidationState = "stale";
487
- }
488
- }
489
- const cooldownUntilUnixMs = storedState?.cooldownUntilUnixMs ?? null;
490
- const cooldownActive = cooldownUntilUnixMs !== null && cooldownUntilUnixMs > nowUnixMs;
491
- return {
492
- mode: storedState?.mode ?? "unavailable",
493
- entrypointPath: options.entrypointPath,
494
- packagePath: options.packagePath,
495
- entrypointExists,
496
- packageStatus: packageAssessment.status,
497
- packageMessage: packageAssessment.message,
498
- trustStatus: trust.status,
499
- trustMessage: trust.message,
500
- validationState: storedState === null
501
- ? "unavailable"
502
- : mapOperatorToLegacyValidationState(operatorValidationState),
503
- operatorValidationState,
504
- validationError: storedState?.lastValidationError ?? null,
505
- validatedAtUnixMs: storedState?.lastValidationAtUnixMs ?? null,
506
- validatedLaunchFingerprint: storedState?.validatedLaunchFingerprint ?? null,
507
- validatedFullFingerprint: storedState?.validatedFullFingerprint ?? null,
508
- currentLaunchFingerprint,
509
- currentFullFingerprint,
510
- verifyUsed: options.verify,
511
- cooldownUntilUnixMs,
512
- cooldownActive,
513
- consecutiveFailureCount: storedState?.consecutiveFailureCount ?? 0,
514
- };
515
- }
516
- export function shouldEnterHookCooldown(options) {
517
- return options.consecutiveFailureCount >= MINING_HOOK_FAILURE_THRESHOLD
518
- ? options.nowUnixMs + MINING_HOOK_COOLDOWN_MS
519
- : null;
520
- }
@@ -1,4 +0,0 @@
1
- import type { WalletExplicitLockStateV1 } from "../types.js";
2
- export declare function loadWalletExplicitLock(lockPath: string): Promise<WalletExplicitLockStateV1 | null>;
3
- export declare function saveWalletExplicitLock(lockPath: string, state: WalletExplicitLockStateV1): Promise<void>;
4
- export declare function clearWalletExplicitLock(lockPath: string): Promise<void>;
@@ -1,19 +0,0 @@
1
- import { readFile, rm } from "node:fs/promises";
2
- import { writeJsonFileAtomic } from "../fs/atomic.js";
3
- export async function loadWalletExplicitLock(lockPath) {
4
- try {
5
- return JSON.parse(await readFile(lockPath, "utf8"));
6
- }
7
- catch (error) {
8
- if (error instanceof Error && "code" in error && error.code === "ENOENT") {
9
- return null;
10
- }
11
- throw error;
12
- }
13
- }
14
- export async function saveWalletExplicitLock(lockPath, state) {
15
- await writeJsonFileAtomic(lockPath, state, { mode: 0o600 });
16
- }
17
- export async function clearWalletExplicitLock(lockPath) {
18
- await rm(lockPath, { force: true });
19
- }
@@ -1,12 +0,0 @@
1
- import type { UnlockSessionStateV1 } from "../types.js";
2
- import type { WalletSecretProvider, WalletSecretReference } from "./provider.js";
3
- export type UnlockSessionSaveAccess = Uint8Array | string | {
4
- provider: WalletSecretProvider;
5
- secretReference: WalletSecretReference;
6
- };
7
- export type UnlockSessionLoadAccess = Uint8Array | string | {
8
- provider: WalletSecretProvider;
9
- };
10
- export declare function saveUnlockSession(sessionPath: string, session: UnlockSessionStateV1, access: UnlockSessionSaveAccess): Promise<void>;
11
- export declare function loadUnlockSession(sessionPath: string, access: UnlockSessionLoadAccess): Promise<UnlockSessionStateV1>;
12
- export declare function clearUnlockSession(sessionPath: string): Promise<void>;
@@ -1,23 +0,0 @@
1
- import { readFile, rm } from "node:fs/promises";
2
- import { writeJsonFileAtomic } from "../fs/atomic.js";
3
- import { decryptJsonWithPassphrase, decryptJsonWithSecretProvider, encryptJsonWithPassphrase, encryptJsonWithSecretProvider, } from "./crypto.js";
4
- export async function saveUnlockSession(sessionPath, session, access) {
5
- const envelope = typeof access === "string" || access instanceof Uint8Array
6
- ? await encryptJsonWithPassphrase(session, access, {
7
- format: "cogcoin-wallet-unlock-session",
8
- })
9
- : await encryptJsonWithSecretProvider(session, access.provider, access.secretReference, {
10
- format: "cogcoin-wallet-unlock-session",
11
- });
12
- await writeJsonFileAtomic(sessionPath, envelope, { mode: 0o600 });
13
- }
14
- export async function loadUnlockSession(sessionPath, access) {
15
- const raw = await readFile(sessionPath, "utf8");
16
- const envelope = JSON.parse(raw);
17
- return typeof access === "string" || access instanceof Uint8Array
18
- ? decryptJsonWithPassphrase(envelope, access)
19
- : decryptJsonWithSecretProvider(envelope, access.provider);
20
- }
21
- export async function clearUnlockSession(sessionPath) {
22
- await rm(sessionPath, { force: true });
23
- }