@cogcoin/client 0.5.3 → 0.5.4

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 (40) hide show
  1. package/README.md +11 -3
  2. package/dist/art/wallet.txt +10 -0
  3. package/dist/bitcoind/indexer-daemon.d.ts +9 -0
  4. package/dist/bitcoind/indexer-daemon.js +51 -14
  5. package/dist/bitcoind/service.d.ts +9 -0
  6. package/dist/bitcoind/service.js +65 -24
  7. package/dist/bitcoind/testing.d.ts +2 -2
  8. package/dist/bitcoind/testing.js +2 -2
  9. package/dist/cli/commands/service-runtime.d.ts +2 -0
  10. package/dist/cli/commands/service-runtime.js +432 -0
  11. package/dist/cli/commands/wallet-admin.js +227 -132
  12. package/dist/cli/commands/wallet-mutation.js +597 -580
  13. package/dist/cli/context.js +23 -1
  14. package/dist/cli/mutation-json.d.ts +17 -1
  15. package/dist/cli/mutation-json.js +42 -0
  16. package/dist/cli/output.js +112 -1
  17. package/dist/cli/parse.d.ts +1 -1
  18. package/dist/cli/parse.js +65 -0
  19. package/dist/cli/preview-json.d.ts +19 -1
  20. package/dist/cli/preview-json.js +31 -0
  21. package/dist/cli/prompt.js +40 -12
  22. package/dist/cli/runner.js +12 -0
  23. package/dist/cli/signals.d.ts +1 -0
  24. package/dist/cli/signals.js +44 -0
  25. package/dist/cli/types.d.ts +24 -2
  26. package/dist/cli/types.js +6 -0
  27. package/dist/cli/wallet-format.js +3 -0
  28. package/dist/cli/workflow-hints.d.ts +1 -0
  29. package/dist/cli/workflow-hints.js +3 -0
  30. package/dist/wallet/fs/lock.d.ts +2 -0
  31. package/dist/wallet/fs/lock.js +32 -0
  32. package/dist/wallet/lifecycle.d.ts +19 -1
  33. package/dist/wallet/lifecycle.js +251 -3
  34. package/dist/wallet/material.d.ts +2 -0
  35. package/dist/wallet/material.js +8 -1
  36. package/dist/wallet/mnemonic-art.d.ts +2 -0
  37. package/dist/wallet/mnemonic-art.js +54 -0
  38. package/dist/wallet/reset.d.ts +61 -0
  39. package/dist/wallet/reset.js +781 -0
  40. package/package.json +3 -3
@@ -1,13 +1,14 @@
1
1
  import { createHash, randomBytes } from "node:crypto";
2
2
  import { bech32 } from "@scure/base";
3
3
  import { HDKey } from "@scure/bip32";
4
- import { generateMnemonic, mnemonicToSeedSync } from "@scure/bip39";
4
+ import { generateMnemonic, mnemonicToSeedSync, validateMnemonic } from "@scure/bip39";
5
5
  import { wordlist as englishWordlist } from "@scure/bip39/wordlists/english.js";
6
6
  import { secp256k1 } from "@noble/curves/secp256k1.js";
7
7
  import { keccak_256 } from "@noble/hashes/sha3.js";
8
8
  export const WALLET_ACCOUNT_PATH = "m/84'/0'/0'";
9
9
  export const DEFAULT_DESCRIPTOR_RANGE_END = 4095;
10
10
  export const DEFAULT_DESCRIPTOR_SAFETY_MARGIN = 128;
11
+ const ENGLISH_WORDLIST_SET = new Set(englishWordlist);
11
12
  function hash160(value) {
12
13
  const sha256 = createHash("sha256").update(value).digest();
13
14
  return createHash("ripemd160").update(sha256).digest();
@@ -57,6 +58,12 @@ export function generateWalletMaterial() {
57
58
  const phrase = generateMnemonic(englishWordlist, 256);
58
59
  return deriveWalletMaterialFromMnemonic(phrase);
59
60
  }
61
+ export function isEnglishMnemonicWord(word) {
62
+ return ENGLISH_WORDLIST_SET.has(word);
63
+ }
64
+ export function validateEnglishMnemonic(phrase) {
65
+ return validateMnemonic(phrase, englishWordlist);
66
+ }
60
67
  export function deriveWalletMaterialFromMnemonic(phrase) {
61
68
  const words = phrase.trim().split(/\s+/);
62
69
  const seed = mnemonicToSeedSync(phrase);
@@ -0,0 +1,2 @@
1
+ export declare function renderWalletMnemonicRevealArt(words: readonly string[]): string[];
2
+ export declare function loadWalletArtTemplateForTesting(): string[];
@@ -0,0 +1,54 @@
1
+ import { readFileSync } from "node:fs";
2
+ const WALLET_ART_WIDTH = 80;
3
+ const WALLET_ART_SLOT_WIDTH = 8;
4
+ const WALLET_ART_PLACEHOLDER_WORD = "achieved";
5
+ const WALLET_ART_WORD_COUNT = 24;
6
+ let walletArtTemplateCache = null;
7
+ function normalizeWalletArtTemplate(raw) {
8
+ const lines = raw.replaceAll("\r\n", "\n").split("\n");
9
+ if (lines[lines.length - 1] === "") {
10
+ lines.pop();
11
+ }
12
+ for (const line of lines) {
13
+ if (line.length !== WALLET_ART_WIDTH) {
14
+ throw new Error(`wallet_art_template_width_invalid_${line.length}`);
15
+ }
16
+ }
17
+ const template = lines.join("\n");
18
+ for (let index = 1; index <= WALLET_ART_WORD_COUNT; index += 1) {
19
+ if (!template.includes(`${index}.${WALLET_ART_PLACEHOLDER_WORD}`)) {
20
+ throw new Error(`wallet_art_template_placeholder_missing_${index}`);
21
+ }
22
+ }
23
+ return lines;
24
+ }
25
+ function loadWalletArtTemplate() {
26
+ if (walletArtTemplateCache !== null) {
27
+ return walletArtTemplateCache;
28
+ }
29
+ walletArtTemplateCache = normalizeWalletArtTemplate(readFileSync(new URL("../art/wallet.txt", import.meta.url), "utf8"));
30
+ return walletArtTemplateCache;
31
+ }
32
+ function formatWalletArtWord(word) {
33
+ const normalized = word ?? "";
34
+ if (normalized.length > WALLET_ART_SLOT_WIDTH) {
35
+ throw new Error(`wallet_art_word_too_wide_${normalized.length}`);
36
+ }
37
+ return normalized.padEnd(WALLET_ART_SLOT_WIDTH, " ");
38
+ }
39
+ export function renderWalletMnemonicRevealArt(words) {
40
+ const rendered = loadWalletArtTemplate().map((line) => {
41
+ let next = line;
42
+ for (let index = 0; index < WALLET_ART_WORD_COUNT; index += 1) {
43
+ next = next.replace(`${index + 1}.${WALLET_ART_PLACEHOLDER_WORD}`, `${index + 1}.${formatWalletArtWord(words[index])}`);
44
+ }
45
+ return next;
46
+ });
47
+ if (rendered.some((line) => line.includes(`.${WALLET_ART_PLACEHOLDER_WORD}`))) {
48
+ throw new Error("wallet_art_render_placeholder_unreplaced");
49
+ }
50
+ return rendered;
51
+ }
52
+ export function loadWalletArtTemplateForTesting() {
53
+ return [...loadWalletArtTemplate()];
54
+ }
@@ -0,0 +1,61 @@
1
+ import { type WalletRuntimePaths } from "./runtime.js";
2
+ import { type WalletSecretProvider } from "./state/provider.js";
3
+ import type { WalletPrompter } from "./lifecycle.js";
4
+ export type WalletResetAction = "not-present" | "kept-unchanged" | "reset-base-entropy" | "deleted";
5
+ export type WalletResetSecretCleanupStatus = "deleted" | "not-found" | "failed" | "unknown";
6
+ export type WalletResetSnapshotResultStatus = "not-present" | "invalid-removed" | "deleted" | "preserved";
7
+ export interface WalletResetResult {
8
+ dataRoot: string;
9
+ factoryResetReady: true;
10
+ stoppedProcesses: {
11
+ managedBitcoind: number;
12
+ indexerDaemon: number;
13
+ backgroundMining: number;
14
+ survivors: number;
15
+ };
16
+ secretCleanupStatus: WalletResetSecretCleanupStatus;
17
+ deletedSecretRefs: string[];
18
+ failedSecretRefs: string[];
19
+ preservedSecretRefs: string[];
20
+ walletAction: WalletResetAction;
21
+ walletOldRootId: string | null;
22
+ walletNewRootId: string | null;
23
+ bootstrapSnapshot: {
24
+ status: WalletResetSnapshotResultStatus;
25
+ path: string;
26
+ };
27
+ removedPaths: string[];
28
+ }
29
+ export interface WalletResetPreview {
30
+ dataRoot: string;
31
+ confirmationPhrase: "permanently reset";
32
+ walletPrompt: null | {
33
+ defaultAction: "reset-base-entropy";
34
+ acceptedInputs: ["", "skip", "delete wallet"];
35
+ entropyRetainingResetAvailable: boolean;
36
+ requiresPassphrase: boolean;
37
+ envelopeSource: "primary" | "backup" | null;
38
+ };
39
+ bootstrapSnapshot: {
40
+ status: "not-present" | "invalid" | "valid";
41
+ path: string;
42
+ defaultAction: "preserve" | "delete";
43
+ };
44
+ trackedProcessKinds: Array<"managed-bitcoind" | "indexer-daemon" | "background-mining">;
45
+ willDeleteOsSecrets: boolean;
46
+ removedPaths: string[];
47
+ }
48
+ export declare function previewResetWallet(options: {
49
+ dataDir: string;
50
+ provider?: WalletSecretProvider;
51
+ paths?: WalletRuntimePaths;
52
+ validateSnapshotFile?: (path: string) => Promise<void>;
53
+ }): Promise<WalletResetPreview>;
54
+ export declare function resetWallet(options: {
55
+ dataDir: string;
56
+ provider?: WalletSecretProvider;
57
+ prompter: WalletPrompter;
58
+ nowUnixMs?: number;
59
+ paths?: WalletRuntimePaths;
60
+ validateSnapshotFile?: (path: string) => Promise<void>;
61
+ }): Promise<WalletResetResult>;