@cogcoin/client 1.2.0 → 1.2.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # `@cogcoin/client`
2
2
 
3
- `@cogcoin/client@1.2.0` is the reference Cogcoin client package for applications that want a local wallet, durable SQLite-backed state, and a managed Bitcoin Core integration around `@cogcoin/indexer`. It publishes the reusable client APIs, the SQLite adapter, the managed `bitcoind` integration, and the first-party `cogcoin` CLI in one package.
3
+ `@cogcoin/client@1.2.1` is the reference Cogcoin client package for applications that want a local wallet, durable SQLite-backed state, and a managed Bitcoin Core integration around `@cogcoin/indexer`. It publishes the reusable client APIs, the SQLite adapter, the managed `bitcoind` integration, and the first-party `cogcoin` CLI in one package.
4
4
 
5
5
  Use Node 22 or newer.
6
6
 
@@ -8,6 +8,9 @@ function isRuntimeMismatchError(error) {
8
8
  return error.message.startsWith("bitcoind_chain_expected_")
9
9
  || error.message === "managed_bitcoind_runtime_mismatch";
10
10
  }
11
+ function isMissingRawTxZmqError(error) {
12
+ return error instanceof Error && error.message === "bitcoind_zmq_rawtx_missing";
13
+ }
11
14
  function isUnreachableManagedBitcoindError(error) {
12
15
  if (error instanceof Error) {
13
16
  if ("code" in error) {
@@ -47,6 +50,13 @@ export function mapManagedBitcoindValidationError(error, status) {
47
50
  };
48
51
  }
49
52
  export function mapManagedBitcoindRuntimeProbeFailure(error, status) {
53
+ if (isMissingRawTxZmqError(error)) {
54
+ return {
55
+ compatibility: "rawtx-zmq-missing",
56
+ status,
57
+ error: "bitcoind_zmq_rawtx_missing",
58
+ };
59
+ }
50
60
  if (isRuntimeMismatchError(error)) {
51
61
  return {
52
62
  compatibility: "runtime-mismatch",
@@ -2,7 +2,7 @@ import type { ClientTip } from "../../types.js";
2
2
  import type { ManagedServicePaths } from "../service-paths.js";
3
3
  import type { ManagedBitcoindObservedStatus, ManagedIndexerDaemonObservedStatus, ManagedIndexerTruthSource } from "../types.js";
4
4
  import type { WalletBitcoindStatus, WalletIndexerStatus, WalletNodeStatus, WalletServiceHealth, WalletSnapshotView } from "../../wallet/read/types.js";
5
- export type ManagedBitcoindServiceCompatibility = "compatible" | "service-version-mismatch" | "wallet-root-mismatch" | "runtime-mismatch" | "unreachable" | "protocol-error";
5
+ export type ManagedBitcoindServiceCompatibility = "compatible" | "service-version-mismatch" | "wallet-root-mismatch" | "runtime-mismatch" | "rawtx-zmq-missing" | "unreachable" | "protocol-error";
6
6
  export interface ManagedBitcoindServiceProbeResult {
7
7
  compatibility: ManagedBitcoindServiceCompatibility;
8
8
  status: ManagedBitcoindObservedStatus | null;
@@ -108,6 +108,13 @@ export const serviceErrorRules = [
108
108
  next: "Run `cogcoin repair` so the wallet can clear the conflicting runtime and restart a compatible managed bitcoind service.",
109
109
  };
110
110
  }
111
+ if (errorCode === "bitcoind_zmq_rawtx_missing" || errorCode.includes("rawtx_zmq_missing")) {
112
+ return {
113
+ what: "The live managed bitcoind service is missing raw transaction ZMQ.",
114
+ why: "This usually means an older managed bitcoind runtime is still running without the v1.2.0 `zmqpubrawtx` setting.",
115
+ next: "Run `cogcoin repair` so the wallet can stop the stale managed bitcoind service and restart it with the current ZMQ configuration.",
116
+ };
117
+ }
111
118
  if (errorCode.includes("bitcoind_replica_missing")) {
112
119
  return {
113
120
  what: "The managed Core wallet replica is missing.",
@@ -33,28 +33,38 @@ export async function repairManagedBitcoindStage(options) {
33
33
  bitcoindCompatibilityIssue = mapBitcoindCompatibilityToRepairIssue(initialBitcoindProbe.compatibility);
34
34
  if (initialBitcoindProbe.compatibility === "service-version-mismatch"
35
35
  || initialBitcoindProbe.compatibility === "wallet-root-mismatch"
36
- || initialBitcoindProbe.compatibility === "runtime-mismatch") {
36
+ || initialBitcoindProbe.compatibility === "runtime-mismatch"
37
+ || initialBitcoindProbe.compatibility === "rawtx-zmq-missing") {
37
38
  const processId = initialBitcoindProbe.status?.processId ?? null;
38
39
  if (processId === null) {
39
- throw new Error("managed_bitcoind_process_id_unavailable");
40
- }
41
- try {
42
- process.kill(processId, "SIGTERM");
40
+ if (initialBitcoindProbe.compatibility !== "rawtx-zmq-missing") {
41
+ throw new Error("managed_bitcoind_process_id_unavailable");
42
+ }
43
+ await clearManagedBitcoindArtifacts(options.servicePaths);
44
+ bitcoindServiceAction = "restarted-missing-rawtx-zmq";
43
45
  }
44
- catch (error) {
45
- if (!(error instanceof Error) || !("code" in error) || error.code !== "ESRCH") {
46
- throw error;
46
+ else {
47
+ try {
48
+ process.kill(processId, "SIGTERM");
47
49
  }
50
+ catch (error) {
51
+ if (!(error instanceof Error) || !("code" in error) || error.code !== "ESRCH") {
52
+ throw error;
53
+ }
54
+ }
55
+ await waitForProcessExit(processId, 15_000, "managed_bitcoind_stop_timeout");
56
+ await clearManagedBitcoindArtifacts(options.servicePaths);
57
+ bitcoindServiceAction = initialBitcoindProbe.compatibility === "rawtx-zmq-missing"
58
+ ? "restarted-missing-rawtx-zmq"
59
+ : "stopped-incompatible-service";
48
60
  }
49
- await waitForProcessExit(processId, 15_000, "managed_bitcoind_stop_timeout");
50
- await clearManagedBitcoindArtifacts(options.servicePaths);
51
- bitcoindServiceAction = "stopped-incompatible-service";
52
61
  }
53
62
  else if (initialBitcoindProbe.compatibility === "unreachable") {
54
63
  const hasStaleArtifacts = await Promise.all([
55
64
  options.servicePaths.bitcoindStatusPath,
56
65
  options.servicePaths.bitcoindPidPath,
57
66
  options.servicePaths.bitcoindReadyPath,
67
+ options.servicePaths.bitcoindRuntimeConfigPath,
58
68
  options.servicePaths.bitcoindWalletStatusPath,
59
69
  ].map(pathExists));
60
70
  if (hasStaleArtifacts.some(Boolean)) {
@@ -69,6 +69,8 @@ export function mapBitcoindCompatibilityToRepairIssue(compatibility) {
69
69
  return "wallet-root-mismatch";
70
70
  case "runtime-mismatch":
71
71
  return "runtime-mismatch";
72
+ case "rawtx-zmq-missing":
73
+ return "rawtx-zmq-missing";
72
74
  default:
73
75
  return "none";
74
76
  }
@@ -169,6 +171,7 @@ export async function clearManagedBitcoindArtifacts(servicePaths) {
169
171
  await rm(servicePaths.bitcoindStatusPath, { force: true }).catch(() => undefined);
170
172
  await rm(servicePaths.bitcoindPidPath, { force: true }).catch(() => undefined);
171
173
  await rm(servicePaths.bitcoindReadyPath, { force: true }).catch(() => undefined);
174
+ await rm(servicePaths.bitcoindRuntimeConfigPath, { force: true }).catch(() => undefined);
172
175
  await rm(servicePaths.bitcoindWalletStatusPath, { force: true }).catch(() => undefined);
173
176
  }
174
177
  export async function stopRecordedManagedProcess(pid, errorCode) {
@@ -36,8 +36,8 @@ export interface WalletRepairResult {
36
36
  recoveredFromBackup: boolean;
37
37
  recreatedManagedCoreWallet: boolean;
38
38
  resetIndexerDatabase: boolean;
39
- bitcoindServiceAction: "none" | "cleared-stale-artifacts" | "stopped-incompatible-service" | "restarted-compatible-service";
40
- bitcoindCompatibilityIssue: "none" | "service-version-mismatch" | "wallet-root-mismatch" | "runtime-mismatch";
39
+ bitcoindServiceAction: "none" | "cleared-stale-artifacts" | "stopped-incompatible-service" | "restarted-compatible-service" | "restarted-missing-rawtx-zmq";
40
+ bitcoindCompatibilityIssue: "none" | "service-version-mismatch" | "wallet-root-mismatch" | "runtime-mismatch" | "rawtx-zmq-missing";
41
41
  managedCoreReplicaAction: "none" | "recreated";
42
42
  bitcoindPostRepairHealth: "ready" | "catching-up" | "starting" | "failed" | "unavailable";
43
43
  indexerDaemonAction: "none" | "cleared-stale-artifacts" | "stopped-incompatible-daemon" | "restarted-compatible-daemon";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cogcoin/client",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
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",