@cogcoin/client 1.1.3 → 1.1.5

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 (88) hide show
  1. package/README.md +4 -5
  2. package/dist/bitcoind/node.js +2 -1
  3. package/dist/bitcoind/progress/tty-renderer.js +3 -2
  4. package/dist/bitcoind/service.js +6 -24
  5. package/dist/bitcoind/types.d.ts +1 -0
  6. package/dist/bitcoind/types.js +1 -0
  7. package/dist/cli/command-registry.d.ts +39 -0
  8. package/dist/cli/command-registry.js +1132 -0
  9. package/dist/cli/commands/client-admin.js +6 -56
  10. package/dist/cli/commands/mining-admin.js +9 -32
  11. package/dist/cli/commands/mining-read.js +15 -56
  12. package/dist/cli/commands/mining-runtime.js +258 -57
  13. package/dist/cli/commands/service-runtime.js +1 -64
  14. package/dist/cli/commands/status.js +2 -15
  15. package/dist/cli/commands/update.js +6 -21
  16. package/dist/cli/commands/wallet-admin.js +18 -120
  17. package/dist/cli/commands/wallet-mutation.js +4 -7
  18. package/dist/cli/commands/wallet-read.js +31 -138
  19. package/dist/cli/context.js +2 -4
  20. package/dist/cli/mining-format.js +8 -2
  21. package/dist/cli/mutation-command-groups.d.ts +11 -11
  22. package/dist/cli/mutation-command-groups.js +9 -18
  23. package/dist/cli/mutation-json.d.ts +1 -17
  24. package/dist/cli/mutation-json.js +1 -28
  25. package/dist/cli/mutation-success.d.ts +0 -1
  26. package/dist/cli/mutation-success.js +0 -19
  27. package/dist/cli/output.d.ts +1 -10
  28. package/dist/cli/output.js +52 -481
  29. package/dist/cli/parse.d.ts +1 -1
  30. package/dist/cli/parse.js +38 -695
  31. package/dist/cli/runner.js +28 -113
  32. package/dist/cli/types.d.ts +7 -8
  33. package/dist/cli/update-notifier.js +1 -1
  34. package/dist/cli/wallet-format.js +1 -1
  35. package/dist/wallet/lifecycle/managed-core.d.ts +23 -0
  36. package/dist/wallet/lifecycle/managed-core.js +257 -0
  37. package/dist/wallet/lifecycle/repair-mining.d.ts +49 -0
  38. package/dist/wallet/lifecycle/repair-mining.js +304 -0
  39. package/dist/wallet/lifecycle/repair-runtime.d.ts +36 -0
  40. package/dist/wallet/lifecycle/repair-runtime.js +206 -0
  41. package/dist/wallet/lifecycle/repair.d.ts +11 -0
  42. package/dist/wallet/lifecycle/repair.js +368 -0
  43. package/dist/wallet/lifecycle/setup.d.ts +16 -0
  44. package/dist/wallet/lifecycle/setup.js +430 -0
  45. package/dist/wallet/lifecycle/types.d.ts +125 -0
  46. package/dist/wallet/lifecycle/types.js +1 -0
  47. package/dist/wallet/lifecycle.d.ts +4 -165
  48. package/dist/wallet/lifecycle.js +3 -1656
  49. package/dist/wallet/mining/candidate.d.ts +60 -0
  50. package/dist/wallet/mining/candidate.js +290 -0
  51. package/dist/wallet/mining/competitiveness.d.ts +22 -0
  52. package/dist/wallet/mining/competitiveness.js +640 -0
  53. package/dist/wallet/mining/control.js +7 -251
  54. package/dist/wallet/mining/cycle.d.ts +39 -0
  55. package/dist/wallet/mining/cycle.js +542 -0
  56. package/dist/wallet/mining/engine-state.d.ts +66 -0
  57. package/dist/wallet/mining/engine-state.js +211 -0
  58. package/dist/wallet/mining/engine-types.d.ts +173 -0
  59. package/dist/wallet/mining/engine-types.js +1 -0
  60. package/dist/wallet/mining/engine-utils.d.ts +7 -0
  61. package/dist/wallet/mining/engine-utils.js +75 -0
  62. package/dist/wallet/mining/events.d.ts +2 -0
  63. package/dist/wallet/mining/events.js +19 -0
  64. package/dist/wallet/mining/lifecycle.d.ts +71 -0
  65. package/dist/wallet/mining/lifecycle.js +355 -0
  66. package/dist/wallet/mining/projection.d.ts +61 -0
  67. package/dist/wallet/mining/projection.js +319 -0
  68. package/dist/wallet/mining/publish.d.ts +79 -0
  69. package/dist/wallet/mining/publish.js +614 -0
  70. package/dist/wallet/mining/runner.d.ts +12 -418
  71. package/dist/wallet/mining/runner.js +274 -3433
  72. package/dist/wallet/mining/supervisor.d.ts +134 -0
  73. package/dist/wallet/mining/supervisor.js +558 -0
  74. package/dist/wallet/mining/visualizer-sync.d.ts +42 -0
  75. package/dist/wallet/mining/visualizer-sync.js +166 -0
  76. package/dist/wallet/mining/visualizer.d.ts +1 -0
  77. package/dist/wallet/mining/visualizer.js +33 -18
  78. package/dist/wallet/read/context.d.ts +5 -1
  79. package/dist/wallet/read/context.js +19 -4
  80. package/dist/wallet/reset.d.ts +1 -1
  81. package/dist/wallet/reset.js +35 -11
  82. package/dist/wallet/runtime.d.ts +0 -6
  83. package/dist/wallet/runtime.js +2 -38
  84. package/dist/wallet/tx/common.d.ts +18 -0
  85. package/dist/wallet/tx/common.js +40 -26
  86. package/package.json +1 -1
  87. package/dist/wallet/state/seed-index.d.ts +0 -43
  88. package/dist/wallet/state/seed-index.js +0 -151
@@ -416,35 +416,16 @@ export async function pauseMiningForWalletMutation(options) {
416
416
  });
417
417
  }
418
418
  export async function buildWalletMutationTransaction(options) {
419
- const availableFundingMinConf = options.availableFundingMinConf ?? 1;
420
- const availableFundingUtxos = (await options.rpc.listUnspent(options.walletName, availableFundingMinConf))
421
- .filter((entry) => isSpendableFundingUtxo(entry, options.plan.allowedFundingScriptPubKeyHex, availableFundingMinConf));
422
- const availableFundingValueByKey = new Map(availableFundingUtxos.map((entry) => [
423
- outpointKey({ txid: entry.txid, vout: entry.vout }),
424
- btcNumberToSats(entry.amount),
425
- ]));
426
- const validationPlan = {
427
- ...options.plan,
428
- eligibleFundingOutpointKeys: new Set([
429
- ...options.plan.eligibleFundingOutpointKeys,
430
- ...availableFundingUtxos.map((entry) => outpointKey({ txid: entry.txid, vout: entry.vout })),
431
- ]),
432
- };
433
419
  const temporaryBuilderLockedOutpoints = [];
434
420
  try {
435
- const funded = await options.rpc.walletCreateFundedPsbt(options.walletName, options.plan.fixedInputs, options.plan.outputs, 0, {
436
- add_inputs: true,
437
- include_unsafe: false,
438
- minconf: availableFundingMinConf,
439
- changeAddress: options.plan.changeAddress,
440
- ...(options.plan.changePosition == null ? {} : { changePosition: options.plan.changePosition }),
441
- lockUnspents: false,
442
- fee_rate: options.feeRate ?? DEFAULT_WALLET_MUTATION_FEE_RATE_SAT_VB,
443
- replaceable: true,
444
- subtractFeeFromOutputs: [],
421
+ const { funded, decoded } = await fundAndValidateWalletMutationDraft({
422
+ rpc: options.rpc,
423
+ walletName: options.walletName,
424
+ plan: options.plan,
425
+ validateFundedDraft: options.validateFundedDraft,
426
+ feeRate: options.feeRate,
427
+ availableFundingMinConf: options.availableFundingMinConf,
445
428
  });
446
- const decoded = await options.rpc.decodePsbt(funded.psbt);
447
- options.validateFundedDraft(decoded, funded, validationPlan);
448
429
  let signed;
449
430
  let finalized;
450
431
  let rawHex;
@@ -490,6 +471,39 @@ export async function buildWalletMutationTransaction(options) {
490
471
  throw error;
491
472
  }
492
473
  }
474
+ export async function fundAndValidateWalletMutationDraft(options) {
475
+ const availableFundingMinConf = options.availableFundingMinConf ?? 1;
476
+ const availableFundingUtxos = (await options.rpc.listUnspent(options.walletName, availableFundingMinConf))
477
+ .filter((entry) => isSpendableFundingUtxo(entry, options.plan.allowedFundingScriptPubKeyHex, availableFundingMinConf));
478
+ const availableFundingValueByKey = new Map(availableFundingUtxos.map((entry) => [
479
+ outpointKey({ txid: entry.txid, vout: entry.vout }),
480
+ btcNumberToSats(entry.amount),
481
+ ]));
482
+ const validationPlan = {
483
+ ...options.plan,
484
+ eligibleFundingOutpointKeys: new Set([
485
+ ...options.plan.eligibleFundingOutpointKeys,
486
+ ...availableFundingUtxos.map((entry) => outpointKey({ txid: entry.txid, vout: entry.vout })),
487
+ ]),
488
+ };
489
+ const funded = await options.rpc.walletCreateFundedPsbt(options.walletName, options.plan.fixedInputs, options.plan.outputs, 0, {
490
+ add_inputs: true,
491
+ include_unsafe: false,
492
+ minconf: availableFundingMinConf,
493
+ changeAddress: options.plan.changeAddress,
494
+ ...(options.plan.changePosition == null ? {} : { changePosition: options.plan.changePosition }),
495
+ lockUnspents: false,
496
+ fee_rate: options.feeRate ?? DEFAULT_WALLET_MUTATION_FEE_RATE_SAT_VB,
497
+ replaceable: true,
498
+ subtractFeeFromOutputs: [],
499
+ });
500
+ const decoded = await options.rpc.decodePsbt(funded.psbt);
501
+ options.validateFundedDraft(decoded, funded, validationPlan);
502
+ return {
503
+ funded,
504
+ decoded,
505
+ };
506
+ }
493
507
  export async function buildWalletMutationTransactionWithReserveFallback(options) {
494
508
  return buildWalletMutationTransaction({
495
509
  rpc: options.rpc,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cogcoin/client",
3
- "version": "1.1.3",
3
+ "version": "1.1.5",
4
4
  "description": "Store-backed Cogcoin client with wallet flows, SQLite persistence, and managed Bitcoin Core integration.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,43 +0,0 @@
1
- import type { WalletSeedKind, WalletRuntimePaths } from "../runtime.js";
2
- import { type RawWalletStateEnvelope } from "./storage.js";
3
- export interface WalletSeedRecord {
4
- name: string;
5
- kind: WalletSeedKind;
6
- walletRootId: string;
7
- createdAtUnixMs: number;
8
- restoredAtUnixMs: number | null;
9
- }
10
- export interface WalletSeedIndexV1 {
11
- schemaVersion: 1;
12
- lastWrittenAtUnixMs: number;
13
- seeds: WalletSeedRecord[];
14
- }
15
- export declare function normalizeWalletSeedName(name: string): string;
16
- export declare function isValidWalletSeedName(name: string): boolean;
17
- export declare function assertValidImportedWalletSeedName(name: string): string;
18
- export declare function findWalletSeedRecord(index: WalletSeedIndexV1, seedName: string): WalletSeedRecord | null;
19
- export declare function loadWalletSeedIndex(options: {
20
- paths: Pick<WalletRuntimePaths, "seedRegistryPath" | "walletStatePath" | "walletStateBackupPath">;
21
- nowUnixMs?: number;
22
- loadRawWalletStateEnvelope?: (paths: {
23
- primaryPath: string;
24
- backupPath: string;
25
- }) => Promise<RawWalletStateEnvelope | null>;
26
- }): Promise<WalletSeedIndexV1>;
27
- export declare function saveWalletSeedIndex(paths: Pick<WalletRuntimePaths, "seedRegistryPath">, index: WalletSeedIndexV1): Promise<void>;
28
- export declare function ensureMainWalletSeedIndexRecord(options: {
29
- paths: Pick<WalletRuntimePaths, "seedRegistryPath" | "walletStatePath" | "walletStateBackupPath">;
30
- walletRootId: string;
31
- nowUnixMs?: number;
32
- }): Promise<WalletSeedIndexV1>;
33
- export declare function addImportedWalletSeedRecord(options: {
34
- paths: Pick<WalletRuntimePaths, "seedRegistryPath" | "walletStatePath" | "walletStateBackupPath">;
35
- seedName: string;
36
- walletRootId: string;
37
- nowUnixMs?: number;
38
- }): Promise<WalletSeedIndexV1>;
39
- export declare function removeWalletSeedRecord(options: {
40
- paths: Pick<WalletRuntimePaths, "seedRegistryPath" | "walletStatePath" | "walletStateBackupPath">;
41
- seedName: string;
42
- nowUnixMs?: number;
43
- }): Promise<WalletSeedIndexV1>;
@@ -1,151 +0,0 @@
1
- import { mkdir, readFile } from "node:fs/promises";
2
- import { dirname } from "node:path";
3
- import { writeFileAtomic } from "../fs/atomic.js";
4
- import { extractWalletRootIdHintFromWalletStateEnvelope, loadRawWalletStateEnvelope, } from "./storage.js";
5
- function createEmptySeedIndex(nowUnixMs) {
6
- return {
7
- schemaVersion: 1,
8
- lastWrittenAtUnixMs: nowUnixMs,
9
- seeds: [],
10
- };
11
- }
12
- function sortSeedRecords(seeds) {
13
- return [...seeds].sort((left, right) => left.name.localeCompare(right.name));
14
- }
15
- async function readSeedIndexFile(path) {
16
- try {
17
- const parsed = JSON.parse(await readFile(path, "utf8"));
18
- if (parsed?.schemaVersion !== 1 || !Array.isArray(parsed.seeds)) {
19
- throw new Error("wallet_seed_index_invalid");
20
- }
21
- return {
22
- schemaVersion: 1,
23
- lastWrittenAtUnixMs: typeof parsed.lastWrittenAtUnixMs === "number" ? parsed.lastWrittenAtUnixMs : 0,
24
- seeds: sortSeedRecords(parsed.seeds),
25
- };
26
- }
27
- catch (error) {
28
- if (error instanceof Error && "code" in error && error.code === "ENOENT") {
29
- return null;
30
- }
31
- throw new Error("wallet_seed_index_invalid");
32
- }
33
- }
34
- export function normalizeWalletSeedName(name) {
35
- return name.trim().toLowerCase();
36
- }
37
- export function isValidWalletSeedName(name) {
38
- return /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(name);
39
- }
40
- export function assertValidImportedWalletSeedName(name) {
41
- const normalized = normalizeWalletSeedName(name);
42
- if (!isValidWalletSeedName(normalized)) {
43
- throw new Error("wallet_seed_name_invalid");
44
- }
45
- if (normalized === "main") {
46
- throw new Error("wallet_seed_name_reserved");
47
- }
48
- return normalized;
49
- }
50
- export function findWalletSeedRecord(index, seedName) {
51
- const normalized = normalizeWalletSeedName(seedName);
52
- return index.seeds.find((seed) => seed.name === normalized) ?? null;
53
- }
54
- export async function loadWalletSeedIndex(options) {
55
- const nowUnixMs = options.nowUnixMs ?? Date.now();
56
- const stored = await readSeedIndexFile(options.paths.seedRegistryPath);
57
- if (stored !== null) {
58
- return stored;
59
- }
60
- const rawEnvelope = await (options.loadRawWalletStateEnvelope ?? loadRawWalletStateEnvelope)({
61
- primaryPath: options.paths.walletStatePath,
62
- backupPath: options.paths.walletStateBackupPath,
63
- }).catch(() => null);
64
- const mainWalletRootId = extractWalletRootIdHintFromWalletStateEnvelope(rawEnvelope?.envelope ?? null);
65
- if (mainWalletRootId === null) {
66
- return createEmptySeedIndex(nowUnixMs);
67
- }
68
- return {
69
- schemaVersion: 1,
70
- lastWrittenAtUnixMs: nowUnixMs,
71
- seeds: [{
72
- name: "main",
73
- kind: "main",
74
- walletRootId: mainWalletRootId,
75
- createdAtUnixMs: nowUnixMs,
76
- restoredAtUnixMs: null,
77
- }],
78
- };
79
- }
80
- export async function saveWalletSeedIndex(paths, index) {
81
- await mkdir(dirname(paths.seedRegistryPath), { recursive: true });
82
- await writeFileAtomic(paths.seedRegistryPath, `${JSON.stringify({
83
- ...index,
84
- seeds: sortSeedRecords(index.seeds),
85
- }, null, 2)}\n`, { mode: 0o600 });
86
- }
87
- export async function ensureMainWalletSeedIndexRecord(options) {
88
- const nowUnixMs = options.nowUnixMs ?? Date.now();
89
- const index = await loadWalletSeedIndex({
90
- paths: options.paths,
91
- nowUnixMs,
92
- });
93
- const existing = findWalletSeedRecord(index, "main");
94
- const seeds = index.seeds.filter((seed) => seed.name !== "main");
95
- seeds.push({
96
- name: "main",
97
- kind: "main",
98
- walletRootId: options.walletRootId,
99
- createdAtUnixMs: existing?.createdAtUnixMs ?? nowUnixMs,
100
- restoredAtUnixMs: existing?.restoredAtUnixMs ?? null,
101
- });
102
- const nextIndex = {
103
- schemaVersion: 1,
104
- lastWrittenAtUnixMs: nowUnixMs,
105
- seeds: sortSeedRecords(seeds),
106
- };
107
- await saveWalletSeedIndex(options.paths, nextIndex);
108
- return nextIndex;
109
- }
110
- export async function addImportedWalletSeedRecord(options) {
111
- const nowUnixMs = options.nowUnixMs ?? Date.now();
112
- const seedName = assertValidImportedWalletSeedName(options.seedName);
113
- const index = await loadWalletSeedIndex({
114
- paths: options.paths,
115
- nowUnixMs,
116
- });
117
- if (findWalletSeedRecord(index, seedName) !== null) {
118
- throw new Error("wallet_seed_name_exists");
119
- }
120
- const nextIndex = {
121
- schemaVersion: 1,
122
- lastWrittenAtUnixMs: nowUnixMs,
123
- seeds: sortSeedRecords([
124
- ...index.seeds,
125
- {
126
- name: seedName,
127
- kind: "imported",
128
- walletRootId: options.walletRootId,
129
- createdAtUnixMs: nowUnixMs,
130
- restoredAtUnixMs: nowUnixMs,
131
- },
132
- ]),
133
- };
134
- await saveWalletSeedIndex(options.paths, nextIndex);
135
- return nextIndex;
136
- }
137
- export async function removeWalletSeedRecord(options) {
138
- const nowUnixMs = options.nowUnixMs ?? Date.now();
139
- const seedName = normalizeWalletSeedName(options.seedName);
140
- const index = await loadWalletSeedIndex({
141
- paths: options.paths,
142
- nowUnixMs,
143
- });
144
- const nextIndex = {
145
- schemaVersion: 1,
146
- lastWrittenAtUnixMs: nowUnixMs,
147
- seeds: sortSeedRecords(index.seeds.filter((seed) => seed.name !== seedName)),
148
- };
149
- await saveWalletSeedIndex(options.paths, nextIndex);
150
- return nextIndex;
151
- }