@cogcoin/client 1.1.9 → 1.1.10
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 +1 -1
- package/dist/bitcoind/managed-bitcoind-service-config.d.ts +13 -0
- package/dist/bitcoind/managed-bitcoind-service-config.js +165 -0
- package/dist/bitcoind/managed-bitcoind-service-lifecycle.d.ts +28 -0
- package/dist/bitcoind/managed-bitcoind-service-lifecycle.js +290 -0
- package/dist/bitcoind/managed-bitcoind-service-process.d.ts +8 -0
- package/dist/bitcoind/managed-bitcoind-service-process.js +48 -0
- package/dist/bitcoind/managed-bitcoind-service-replica.d.ts +8 -0
- package/dist/bitcoind/managed-bitcoind-service-replica.js +142 -0
- package/dist/bitcoind/managed-bitcoind-service-status.d.ts +42 -0
- package/dist/bitcoind/managed-bitcoind-service-status.js +178 -0
- package/dist/bitcoind/managed-bitcoind-service-types.d.ts +36 -0
- package/dist/bitcoind/managed-bitcoind-service-types.js +1 -0
- package/dist/bitcoind/service.d.ts +7 -63
- package/dist/bitcoind/service.js +7 -797
- package/dist/wallet/mining/engine-types.d.ts +1 -0
- package/dist/wallet/mining/engine-types.js +9 -1
- package/dist/wallet/mining/publish.js +3 -6
- package/dist/wallet/mining/runner.js +30 -18
- package/dist/wallet/mining/visualizer.js +7 -6
- package/dist/wallet/read/context.d.ts +4 -10
- package/dist/wallet/read/context.js +4 -227
- package/dist/wallet/read/local-state.d.ts +28 -0
- package/dist/wallet/read/local-state.js +233 -0
- package/dist/wallet/read/managed-bitcoind.d.ts +30 -0
- package/dist/wallet/read/managed-bitcoind.js +138 -0
- package/dist/wallet/read/managed-indexer.d.ts +23 -0
- package/dist/wallet/read/managed-indexer.js +87 -0
- package/dist/wallet/read/managed-services.d.ts +6 -21
- package/dist/wallet/read/managed-services.js +23 -196
- package/package.json +1 -1
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { access, constants } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
export function getManagedBitcoindWalletReplicaName(walletRootId) {
|
|
5
|
+
return `cogcoin-${walletRootId}`.replace(/[^a-zA-Z0-9._-]+/g, "-").slice(0, 63);
|
|
6
|
+
}
|
|
7
|
+
export function createMissingManagedWalletReplicaStatus(walletRootId, message) {
|
|
8
|
+
return {
|
|
9
|
+
walletRootId,
|
|
10
|
+
walletName: getManagedBitcoindWalletReplicaName(walletRootId),
|
|
11
|
+
loaded: false,
|
|
12
|
+
descriptors: false,
|
|
13
|
+
privateKeysEnabled: false,
|
|
14
|
+
created: false,
|
|
15
|
+
proofStatus: "missing",
|
|
16
|
+
descriptorChecksum: null,
|
|
17
|
+
fundingAddress0: null,
|
|
18
|
+
fundingScriptPubKeyHex0: null,
|
|
19
|
+
message,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function isMissingWalletError(message) {
|
|
23
|
+
return message.includes("bitcoind_rpc_loadwallet_-18_")
|
|
24
|
+
|| message.includes("Path does not exist")
|
|
25
|
+
|| message.includes("not found");
|
|
26
|
+
}
|
|
27
|
+
export async function loadManagedWalletReplicaIfPresent(rpc, walletRootId, dataDir) {
|
|
28
|
+
const walletName = getManagedBitcoindWalletReplicaName(walletRootId);
|
|
29
|
+
const loadedWallets = await rpc.listWallets();
|
|
30
|
+
let loaded = loadedWallets.includes(walletName);
|
|
31
|
+
if (!loaded) {
|
|
32
|
+
try {
|
|
33
|
+
await rpc.loadWallet(walletName, false);
|
|
34
|
+
loaded = true;
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
38
|
+
if (!isMissingWalletError(message)) {
|
|
39
|
+
return {
|
|
40
|
+
walletRootId,
|
|
41
|
+
walletName,
|
|
42
|
+
loaded: false,
|
|
43
|
+
descriptors: false,
|
|
44
|
+
privateKeysEnabled: false,
|
|
45
|
+
created: false,
|
|
46
|
+
proofStatus: "mismatch",
|
|
47
|
+
descriptorChecksum: null,
|
|
48
|
+
fundingAddress0: null,
|
|
49
|
+
fundingScriptPubKeyHex0: null,
|
|
50
|
+
message,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
const walletDir = join(dataDir, "wallets", walletName);
|
|
54
|
+
const walletDirExists = await access(walletDir, constants.F_OK).then(() => true).catch(() => false);
|
|
55
|
+
return createMissingManagedWalletReplicaStatus(walletRootId, walletDirExists
|
|
56
|
+
? "Managed Core wallet replica exists on disk but is not loaded."
|
|
57
|
+
: "Managed Core wallet replica is missing.");
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const info = await rpc.getWalletInfo(walletName);
|
|
61
|
+
if (!info.descriptors || !info.private_keys_enabled) {
|
|
62
|
+
return {
|
|
63
|
+
walletRootId,
|
|
64
|
+
walletName,
|
|
65
|
+
loaded: true,
|
|
66
|
+
descriptors: info.descriptors,
|
|
67
|
+
privateKeysEnabled: info.private_keys_enabled,
|
|
68
|
+
created: false,
|
|
69
|
+
proofStatus: "mismatch",
|
|
70
|
+
descriptorChecksum: null,
|
|
71
|
+
fundingAddress0: null,
|
|
72
|
+
fundingScriptPubKeyHex0: null,
|
|
73
|
+
message: "Managed Core wallet replica is not an encrypted descriptor wallet with private keys enabled.",
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
await rpc.walletLock(walletName);
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// A freshly created encrypted wallet may already be locked.
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
walletRootId,
|
|
84
|
+
walletName,
|
|
85
|
+
loaded: true,
|
|
86
|
+
descriptors: info.descriptors,
|
|
87
|
+
privateKeysEnabled: info.private_keys_enabled,
|
|
88
|
+
created: false,
|
|
89
|
+
proofStatus: "not-proven",
|
|
90
|
+
descriptorChecksum: null,
|
|
91
|
+
fundingAddress0: null,
|
|
92
|
+
fundingScriptPubKeyHex0: null,
|
|
93
|
+
message: null,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
export async function createManagedWalletReplica(rpc, walletRootId, options = {}) {
|
|
97
|
+
const walletName = getManagedBitcoindWalletReplicaName(walletRootId);
|
|
98
|
+
const loadedWallets = await rpc.listWallets();
|
|
99
|
+
let created = false;
|
|
100
|
+
if (!loadedWallets.includes(walletName)) {
|
|
101
|
+
try {
|
|
102
|
+
await rpc.loadWallet(walletName, false);
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
106
|
+
if (!isMissingWalletError(message)) {
|
|
107
|
+
throw error;
|
|
108
|
+
}
|
|
109
|
+
await rpc.createWallet(walletName, {
|
|
110
|
+
blank: true,
|
|
111
|
+
descriptors: true,
|
|
112
|
+
disablePrivateKeys: false,
|
|
113
|
+
loadOnStartup: false,
|
|
114
|
+
passphrase: options.managedWalletPassphrase ?? randomBytes(32).toString("hex"),
|
|
115
|
+
});
|
|
116
|
+
created = true;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
const info = await rpc.getWalletInfo(walletName);
|
|
120
|
+
if (!info.descriptors || !info.private_keys_enabled) {
|
|
121
|
+
throw new Error("managed_bitcoind_wallet_replica_invalid");
|
|
122
|
+
}
|
|
123
|
+
try {
|
|
124
|
+
await rpc.walletLock(walletName);
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
// A freshly created encrypted wallet may already be locked.
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
walletRootId,
|
|
131
|
+
walletName,
|
|
132
|
+
loaded: true,
|
|
133
|
+
descriptors: info.descriptors,
|
|
134
|
+
privateKeysEnabled: info.private_keys_enabled,
|
|
135
|
+
created,
|
|
136
|
+
proofStatus: "not-proven",
|
|
137
|
+
descriptorChecksum: null,
|
|
138
|
+
fundingAddress0: null,
|
|
139
|
+
fundingScriptPubKeyHex0: null,
|
|
140
|
+
message: null,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { createRpcClient } from "./node.js";
|
|
2
|
+
import { resolveManagedServicePaths } from "./service-paths.js";
|
|
3
|
+
import { type ManagedBitcoindObservedStatus, type ManagedBitcoindNodeHandle, type ManagedBitcoindServiceStatus, type ManagedCoreWalletReplicaStatus } from "./types.js";
|
|
4
|
+
import type { ManagedBitcoindServiceOwnership, ManagedBitcoindServiceOptions, ManagedBitcoindServiceStopResult } from "./managed-bitcoind-service-types.js";
|
|
5
|
+
import { type BitcoindRpcConfig, type BitcoindZmqConfig } from "./managed-bitcoind-service-config.js";
|
|
6
|
+
import type { ManagedBitcoindServiceProbeResult } from "./managed-runtime/types.js";
|
|
7
|
+
export declare function waitForManagedBitcoindRpcReady(rpc: ReturnType<typeof createRpcClient>, cookieFile: string, expectedChain: "main" | "regtest", timeoutMs: number): Promise<void>;
|
|
8
|
+
export declare function createBitcoindServiceStatus(options: {
|
|
9
|
+
binaryVersion: string;
|
|
10
|
+
serviceInstanceId: string;
|
|
11
|
+
state: ManagedBitcoindServiceStatus["state"];
|
|
12
|
+
processId: number | null;
|
|
13
|
+
walletRootId: string;
|
|
14
|
+
chain: "main" | "regtest";
|
|
15
|
+
dataDir: string;
|
|
16
|
+
runtimeRoot: string;
|
|
17
|
+
startHeight: number;
|
|
18
|
+
rpc: BitcoindRpcConfig;
|
|
19
|
+
zmq: BitcoindZmqConfig;
|
|
20
|
+
p2pPort: number;
|
|
21
|
+
getblockArchiveEndHeight: number | null;
|
|
22
|
+
getblockArchiveSha256: string | null;
|
|
23
|
+
walletReplica: ManagedCoreWalletReplicaStatus | null;
|
|
24
|
+
startedAtUnixMs: number;
|
|
25
|
+
heartbeatAtUnixMs: number;
|
|
26
|
+
lastError: string | null;
|
|
27
|
+
}): ManagedBitcoindServiceStatus;
|
|
28
|
+
export declare function probeManagedBitcoindStatusCandidate(status: ManagedBitcoindObservedStatus, options: ManagedBitcoindServiceOptions, runtimeRoot: string): Promise<ManagedBitcoindServiceProbeResult>;
|
|
29
|
+
export declare function writeManagedBitcoindStatus(paths: ReturnType<typeof resolveManagedServicePaths>, status: ManagedBitcoindServiceStatus): Promise<void>;
|
|
30
|
+
export declare function clearManagedBitcoindRuntimeArtifacts(paths: ReturnType<typeof resolveManagedServicePaths>): Promise<void>;
|
|
31
|
+
export declare function refreshManagedBitcoindStatus(status: ManagedBitcoindServiceStatus, paths: ReturnType<typeof resolveManagedServicePaths>, options: ManagedBitcoindServiceOptions): Promise<ManagedBitcoindServiceStatus>;
|
|
32
|
+
export declare function createManagedBitcoindNodeHandle(options: {
|
|
33
|
+
status: ManagedBitcoindServiceStatus;
|
|
34
|
+
paths: ReturnType<typeof resolveManagedServicePaths>;
|
|
35
|
+
serviceOptions: ManagedBitcoindServiceOptions;
|
|
36
|
+
ownership: ManagedBitcoindServiceOwnership;
|
|
37
|
+
stopService(options: {
|
|
38
|
+
dataDir: string;
|
|
39
|
+
walletRootId?: string;
|
|
40
|
+
shutdownTimeoutMs?: number;
|
|
41
|
+
}): Promise<ManagedBitcoindServiceStopResult>;
|
|
42
|
+
}): ManagedBitcoindNodeHandle;
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { mkdir, rm } from "node:fs/promises";
|
|
2
|
+
import { writeFileAtomic } from "../wallet/fs/atomic.js";
|
|
3
|
+
import { writeRuntimeStatusFile } from "../wallet/fs/status-file.js";
|
|
4
|
+
import { mapManagedBitcoindRuntimeProbeFailure, mapManagedBitcoindValidationError, validateManagedBitcoindObservedStatus, } from "./managed-runtime/bitcoind-policy.js";
|
|
5
|
+
import { createRpcClient, validateNodeConfigForTesting } from "./node.js";
|
|
6
|
+
import { resolveManagedServicePaths } from "./service-paths.js";
|
|
7
|
+
import { MANAGED_BITCOIND_SERVICE_API_VERSION, } from "./types.js";
|
|
8
|
+
import { createMissingManagedWalletReplicaStatus, loadManagedWalletReplicaIfPresent, } from "./managed-bitcoind-service-replica.js";
|
|
9
|
+
import { DEFAULT_MANAGED_BITCOIND_STARTUP_TIMEOUT_MS, isManagedBitcoindProcessAlive, sleep, } from "./managed-bitcoind-service-process.js";
|
|
10
|
+
import { waitForManagedBitcoindCookie, } from "./managed-bitcoind-service-config.js";
|
|
11
|
+
export async function waitForManagedBitcoindRpcReady(rpc, cookieFile, expectedChain, timeoutMs) {
|
|
12
|
+
await waitForManagedBitcoindCookie(cookieFile, timeoutMs, sleep);
|
|
13
|
+
const deadline = Date.now() + timeoutMs;
|
|
14
|
+
let lastError = null;
|
|
15
|
+
while (Date.now() < deadline) {
|
|
16
|
+
try {
|
|
17
|
+
const info = await rpc.getBlockchainInfo();
|
|
18
|
+
if (info.chain !== expectedChain) {
|
|
19
|
+
throw new Error(`bitcoind_chain_expected_${expectedChain}_got_${info.chain}`);
|
|
20
|
+
}
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
lastError = error;
|
|
25
|
+
await sleep(250);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
throw lastError instanceof Error ? lastError : new Error("bitcoind_rpc_timeout");
|
|
29
|
+
}
|
|
30
|
+
export function createBitcoindServiceStatus(options) {
|
|
31
|
+
return {
|
|
32
|
+
serviceApiVersion: MANAGED_BITCOIND_SERVICE_API_VERSION,
|
|
33
|
+
binaryVersion: options.binaryVersion,
|
|
34
|
+
buildId: null,
|
|
35
|
+
serviceInstanceId: options.serviceInstanceId,
|
|
36
|
+
state: options.state,
|
|
37
|
+
processId: options.processId,
|
|
38
|
+
walletRootId: options.walletRootId,
|
|
39
|
+
chain: options.chain,
|
|
40
|
+
dataDir: options.dataDir,
|
|
41
|
+
runtimeRoot: options.runtimeRoot,
|
|
42
|
+
startHeight: options.startHeight,
|
|
43
|
+
rpc: options.rpc,
|
|
44
|
+
zmq: options.zmq,
|
|
45
|
+
p2pPort: options.p2pPort,
|
|
46
|
+
getblockArchiveEndHeight: options.getblockArchiveEndHeight,
|
|
47
|
+
getblockArchiveSha256: options.getblockArchiveSha256,
|
|
48
|
+
walletReplica: options.walletReplica,
|
|
49
|
+
startedAtUnixMs: options.startedAtUnixMs,
|
|
50
|
+
heartbeatAtUnixMs: options.heartbeatAtUnixMs,
|
|
51
|
+
updatedAtUnixMs: options.heartbeatAtUnixMs,
|
|
52
|
+
lastError: options.lastError,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
export async function probeManagedBitcoindStatusCandidate(status, options, runtimeRoot) {
|
|
56
|
+
try {
|
|
57
|
+
validateManagedBitcoindObservedStatus(status, {
|
|
58
|
+
chain: options.chain,
|
|
59
|
+
dataDir: options.dataDir ?? "",
|
|
60
|
+
runtimeRoot,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
return mapManagedBitcoindValidationError(error, status);
|
|
65
|
+
}
|
|
66
|
+
const rpc = createRpcClient(status.rpc);
|
|
67
|
+
try {
|
|
68
|
+
await waitForManagedBitcoindRpcReady(rpc, status.rpc.cookieFile, status.chain, options.startupTimeoutMs ?? DEFAULT_MANAGED_BITCOIND_STARTUP_TIMEOUT_MS);
|
|
69
|
+
await validateNodeConfigForTesting(rpc, status.chain, status.zmq.endpoint);
|
|
70
|
+
return {
|
|
71
|
+
compatibility: "compatible",
|
|
72
|
+
status,
|
|
73
|
+
error: null,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
return mapManagedBitcoindRuntimeProbeFailure(error, status);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
export async function writeManagedBitcoindStatus(paths, status) {
|
|
81
|
+
await mkdir(paths.walletRuntimeRoot, { recursive: true });
|
|
82
|
+
await writeRuntimeStatusFile(paths.bitcoindStatusPath, status);
|
|
83
|
+
await writeFileAtomic(paths.bitcoindPidPath, `${status.processId ?? ""}\n`, { mode: 0o600 });
|
|
84
|
+
await writeFileAtomic(paths.bitcoindReadyPath, `${status.updatedAtUnixMs}\n`, { mode: 0o600 });
|
|
85
|
+
await writeRuntimeStatusFile(paths.bitcoindWalletStatusPath, status.walletReplica ?? createMissingManagedWalletReplicaStatus(status.walletRootId, "Managed Core wallet replica is missing."));
|
|
86
|
+
await writeRuntimeStatusFile(paths.bitcoindRuntimeConfigPath, {
|
|
87
|
+
chain: status.chain,
|
|
88
|
+
rpc: status.rpc,
|
|
89
|
+
zmqPort: status.zmq.port,
|
|
90
|
+
p2pPort: status.p2pPort,
|
|
91
|
+
getblockArchiveEndHeight: status.getblockArchiveEndHeight,
|
|
92
|
+
getblockArchiveSha256: status.getblockArchiveSha256,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
export async function clearManagedBitcoindRuntimeArtifacts(paths) {
|
|
96
|
+
await rm(paths.bitcoindStatusPath, { force: true }).catch(() => undefined);
|
|
97
|
+
await rm(paths.bitcoindPidPath, { force: true }).catch(() => undefined);
|
|
98
|
+
await rm(paths.bitcoindReadyPath, { force: true }).catch(() => undefined);
|
|
99
|
+
await rm(paths.bitcoindWalletStatusPath, { force: true }).catch(() => undefined);
|
|
100
|
+
}
|
|
101
|
+
export async function refreshManagedBitcoindStatus(status, paths, options) {
|
|
102
|
+
const nowUnixMs = Date.now();
|
|
103
|
+
const rpc = createRpcClient(status.rpc);
|
|
104
|
+
const targetWalletRootId = options.walletRootId ?? status.walletRootId;
|
|
105
|
+
try {
|
|
106
|
+
await waitForManagedBitcoindRpcReady(rpc, status.rpc.cookieFile, status.chain, options.startupTimeoutMs ?? DEFAULT_MANAGED_BITCOIND_STARTUP_TIMEOUT_MS);
|
|
107
|
+
await validateNodeConfigForTesting(rpc, status.chain, status.zmq.endpoint);
|
|
108
|
+
const walletReplica = await loadManagedWalletReplicaIfPresent(rpc, targetWalletRootId, status.dataDir);
|
|
109
|
+
const nextStatus = {
|
|
110
|
+
...status,
|
|
111
|
+
walletRootId: targetWalletRootId,
|
|
112
|
+
runtimeRoot: paths.walletRuntimeRoot,
|
|
113
|
+
state: "ready",
|
|
114
|
+
processId: await isManagedBitcoindProcessAlive(status.processId) ? status.processId : null,
|
|
115
|
+
walletReplica,
|
|
116
|
+
heartbeatAtUnixMs: nowUnixMs,
|
|
117
|
+
updatedAtUnixMs: nowUnixMs,
|
|
118
|
+
lastError: walletReplica.message ?? null,
|
|
119
|
+
};
|
|
120
|
+
await writeManagedBitcoindStatus(paths, nextStatus);
|
|
121
|
+
return nextStatus;
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
const nextStatus = {
|
|
125
|
+
...status,
|
|
126
|
+
walletRootId: targetWalletRootId,
|
|
127
|
+
runtimeRoot: paths.walletRuntimeRoot,
|
|
128
|
+
state: "failed",
|
|
129
|
+
processId: await isManagedBitcoindProcessAlive(status.processId) ? status.processId : null,
|
|
130
|
+
heartbeatAtUnixMs: nowUnixMs,
|
|
131
|
+
updatedAtUnixMs: nowUnixMs,
|
|
132
|
+
lastError: error instanceof Error ? error.message : String(error),
|
|
133
|
+
};
|
|
134
|
+
await writeManagedBitcoindStatus(paths, nextStatus);
|
|
135
|
+
return nextStatus;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
export function createManagedBitcoindNodeHandle(options) {
|
|
139
|
+
let currentStatus = options.status;
|
|
140
|
+
const rpc = createRpcClient(currentStatus.rpc);
|
|
141
|
+
let stopped = false;
|
|
142
|
+
return {
|
|
143
|
+
rpc: currentStatus.rpc,
|
|
144
|
+
zmq: currentStatus.zmq,
|
|
145
|
+
pid: currentStatus.processId,
|
|
146
|
+
expectedChain: currentStatus.chain,
|
|
147
|
+
startHeight: currentStatus.startHeight,
|
|
148
|
+
dataDir: currentStatus.dataDir,
|
|
149
|
+
getblockArchiveEndHeight: currentStatus.getblockArchiveEndHeight ?? null,
|
|
150
|
+
getblockArchiveSha256: currentStatus.getblockArchiveSha256 ?? null,
|
|
151
|
+
walletRootId: currentStatus.walletRootId,
|
|
152
|
+
runtimeRoot: options.paths.walletRuntimeRoot,
|
|
153
|
+
async validate() {
|
|
154
|
+
await validateNodeConfigForTesting(rpc, currentStatus.chain, currentStatus.zmq.endpoint);
|
|
155
|
+
},
|
|
156
|
+
async refreshServiceStatus() {
|
|
157
|
+
currentStatus = await refreshManagedBitcoindStatus(currentStatus, options.paths, options.serviceOptions);
|
|
158
|
+
this.getblockArchiveEndHeight = currentStatus.getblockArchiveEndHeight ?? null;
|
|
159
|
+
this.getblockArchiveSha256 = currentStatus.getblockArchiveSha256 ?? null;
|
|
160
|
+
this.walletRootId = currentStatus.walletRootId;
|
|
161
|
+
return currentStatus;
|
|
162
|
+
},
|
|
163
|
+
async stop() {
|
|
164
|
+
if (stopped) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
stopped = true;
|
|
168
|
+
if (options.serviceOptions.serviceLifetime !== "ephemeral" || options.ownership === "attached") {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
await options.stopService({
|
|
172
|
+
dataDir: currentStatus.dataDir,
|
|
173
|
+
walletRootId: currentStatus.walletRootId,
|
|
174
|
+
shutdownTimeoutMs: options.serviceOptions.shutdownTimeoutMs,
|
|
175
|
+
});
|
|
176
|
+
},
|
|
177
|
+
};
|
|
178
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { InternalManagedBitcoindOptions } from "./types.js";
|
|
2
|
+
export interface ManagedWalletReplicaRpc {
|
|
3
|
+
listWallets(): Promise<string[]>;
|
|
4
|
+
loadWallet(walletName: string, loadOnStartup?: boolean): Promise<{
|
|
5
|
+
name: string;
|
|
6
|
+
warning: string;
|
|
7
|
+
}>;
|
|
8
|
+
createWallet(walletName: string, options: {
|
|
9
|
+
blank: boolean;
|
|
10
|
+
descriptors: boolean;
|
|
11
|
+
disablePrivateKeys: boolean;
|
|
12
|
+
loadOnStartup: boolean;
|
|
13
|
+
passphrase: string;
|
|
14
|
+
}): Promise<unknown>;
|
|
15
|
+
getWalletInfo(walletName: string): Promise<{
|
|
16
|
+
descriptors: boolean;
|
|
17
|
+
private_keys_enabled: boolean;
|
|
18
|
+
}>;
|
|
19
|
+
walletLock(walletName: string): Promise<null>;
|
|
20
|
+
}
|
|
21
|
+
export type ManagedBitcoindServiceOptions = Pick<InternalManagedBitcoindOptions, "dataDir" | "chain" | "startHeight" | "walletRootId" | "rpcPort" | "zmqPort" | "p2pPort" | "pollIntervalMs" | "startupTimeoutMs" | "shutdownTimeoutMs" | "managedWalletPassphrase"> & {
|
|
22
|
+
getblockArchivePath?: string | null;
|
|
23
|
+
getblockArchiveEndHeight?: number | null;
|
|
24
|
+
getblockArchiveSha256?: string | null;
|
|
25
|
+
serviceLifetime?: "persistent" | "ephemeral";
|
|
26
|
+
};
|
|
27
|
+
export type ResolvedManagedBitcoindServiceOptions = ManagedBitcoindServiceOptions & {
|
|
28
|
+
dataDir: string;
|
|
29
|
+
walletRootId: string;
|
|
30
|
+
startupTimeoutMs: number;
|
|
31
|
+
};
|
|
32
|
+
export type ManagedBitcoindServiceOwnership = "attached" | "started";
|
|
33
|
+
export interface ManagedBitcoindServiceStopResult {
|
|
34
|
+
status: "stopped" | "not-running";
|
|
35
|
+
walletRootId: string;
|
|
36
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,64 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
1
|
+
import { buildManagedServiceArgsForTesting, resolveManagedBitcoindDbcacheMiB, writeBitcoinConfForTesting } from "./managed-bitcoind-service-config.js";
|
|
2
|
+
import { attachOrStartManagedBitcoindService, probeManagedBitcoindService, shutdownManagedBitcoindServiceForTesting, stopManagedBitcoindService, stopManagedBitcoindServiceWithLockHeld, withClaimedUninitializedManagedRuntime } from "./managed-bitcoind-service-lifecycle.js";
|
|
3
|
+
import { createManagedWalletReplica } from "./managed-bitcoind-service-replica.js";
|
|
4
4
|
export type { ManagedBitcoindServiceCompatibility, ManagedBitcoindServiceProbeResult, } from "./managed-runtime/types.js";
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
name: string;
|
|
10
|
-
warning: string;
|
|
11
|
-
}>;
|
|
12
|
-
createWallet(walletName: string, options: {
|
|
13
|
-
blank: boolean;
|
|
14
|
-
descriptors: boolean;
|
|
15
|
-
disablePrivateKeys: boolean;
|
|
16
|
-
loadOnStartup: boolean;
|
|
17
|
-
passphrase: string;
|
|
18
|
-
}): Promise<unknown>;
|
|
19
|
-
getWalletInfo(walletName: string): Promise<{
|
|
20
|
-
descriptors: boolean;
|
|
21
|
-
private_keys_enabled: boolean;
|
|
22
|
-
}>;
|
|
23
|
-
walletLock(walletName: string): Promise<null>;
|
|
24
|
-
}
|
|
25
|
-
type ManagedBitcoindServiceOptions = Pick<InternalManagedBitcoindOptions, "dataDir" | "chain" | "startHeight" | "walletRootId" | "rpcPort" | "zmqPort" | "p2pPort" | "pollIntervalMs" | "startupTimeoutMs" | "shutdownTimeoutMs" | "managedWalletPassphrase"> & {
|
|
26
|
-
getblockArchivePath?: string | null;
|
|
27
|
-
getblockArchiveEndHeight?: number | null;
|
|
28
|
-
getblockArchiveSha256?: string | null;
|
|
29
|
-
serviceLifetime?: "persistent" | "ephemeral";
|
|
30
|
-
};
|
|
31
|
-
export interface ManagedBitcoindServiceStopResult {
|
|
32
|
-
status: "stopped" | "not-running";
|
|
33
|
-
walletRootId: string;
|
|
34
|
-
}
|
|
35
|
-
export declare function writeBitcoinConfForTesting(filePath: string, options: ManagedBitcoindServiceOptions, runtimeConfig: ManagedBitcoindRuntimeConfig): Promise<void>;
|
|
36
|
-
export declare function buildManagedServiceArgsForTesting(options: ManagedBitcoindServiceOptions, runtimeConfig: ManagedBitcoindRuntimeConfig): string[];
|
|
37
|
-
export declare function createManagedWalletReplica(rpc: ManagedWalletReplicaRpc, walletRootId: string, options?: {
|
|
38
|
-
managedWalletPassphrase?: string;
|
|
39
|
-
}): Promise<ManagedCoreWalletReplicaStatus>;
|
|
40
|
-
export declare function stopManagedBitcoindServiceWithLockHeld(options: {
|
|
41
|
-
dataDir: string;
|
|
42
|
-
walletRootId?: string;
|
|
43
|
-
shutdownTimeoutMs?: number;
|
|
44
|
-
paths?: ReturnType<typeof resolveManagedServicePaths>;
|
|
45
|
-
}): Promise<ManagedBitcoindServiceStopResult>;
|
|
46
|
-
export declare function withClaimedUninitializedManagedRuntime<T>(options: {
|
|
47
|
-
dataDir: string;
|
|
48
|
-
walletRootId?: string;
|
|
49
|
-
shutdownTimeoutMs?: number;
|
|
50
|
-
}, callback: () => Promise<T>): Promise<T>;
|
|
51
|
-
export declare function probeManagedBitcoindService(options: ManagedBitcoindServiceOptions): Promise<ManagedBitcoindServiceProbeResult>;
|
|
52
|
-
export declare function attachOrStartManagedBitcoindService(options: ManagedBitcoindServiceOptions): Promise<ManagedBitcoindNodeHandle>;
|
|
53
|
-
export declare function stopManagedBitcoindService(options: {
|
|
54
|
-
dataDir: string;
|
|
55
|
-
walletRootId?: string;
|
|
56
|
-
shutdownTimeoutMs?: number;
|
|
57
|
-
}): Promise<ManagedBitcoindServiceStopResult>;
|
|
58
|
-
export declare function readManagedBitcoindServiceStatusForTesting(dataDir: string, walletRootId?: string): Promise<ManagedBitcoindObservedStatus | null>;
|
|
59
|
-
export declare function shutdownManagedBitcoindServiceForTesting(options: {
|
|
60
|
-
dataDir: string;
|
|
61
|
-
chain?: "main" | "regtest";
|
|
62
|
-
walletRootId?: string;
|
|
63
|
-
shutdownTimeoutMs?: number;
|
|
64
|
-
}): Promise<void>;
|
|
5
|
+
export type { ManagedBitcoindServiceStopResult } from "./managed-bitcoind-service-types.js";
|
|
6
|
+
export { attachOrStartManagedBitcoindService, createManagedWalletReplica, probeManagedBitcoindService, resolveManagedBitcoindDbcacheMiB, stopManagedBitcoindService, stopManagedBitcoindServiceWithLockHeld, withClaimedUninitializedManagedRuntime, writeBitcoinConfForTesting, buildManagedServiceArgsForTesting, };
|
|
7
|
+
export declare function readManagedBitcoindServiceStatusForTesting(dataDir: string, walletRootId?: string): Promise<import("./types.js").ManagedBitcoindObservedStatus | null>;
|
|
8
|
+
export { shutdownManagedBitcoindServiceForTesting, };
|