@cogcoin/client 1.1.6 → 1.1.8
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 +2 -2
- package/dist/bitcoind/indexer-daemon.js +29 -79
- package/dist/bitcoind/managed-runtime/bitcoind-runtime.d.ts +20 -0
- package/dist/bitcoind/managed-runtime/bitcoind-runtime.js +74 -0
- package/dist/bitcoind/managed-runtime/bitcoind-status.d.ts +11 -0
- package/dist/bitcoind/managed-runtime/bitcoind-status.js +44 -0
- package/dist/bitcoind/managed-runtime/indexer-runtime.d.ts +15 -0
- package/dist/bitcoind/managed-runtime/indexer-runtime.js +82 -0
- package/dist/bitcoind/managed-runtime/types.d.ts +40 -0
- package/dist/bitcoind/node.d.ts +2 -2
- package/dist/bitcoind/node.js +2 -2
- package/dist/bitcoind/rpc.d.ts +2 -1
- package/dist/bitcoind/rpc.js +53 -3
- package/dist/bitcoind/service.js +47 -127
- package/dist/cli/command-registry.d.ts +1 -1
- package/dist/cli/command-registry.js +2 -64
- package/dist/cli/commands/client-admin.js +3 -18
- package/dist/cli/commands/mining-runtime.js +4 -60
- package/dist/cli/commands/wallet-admin.js +6 -6
- package/dist/cli/context.js +1 -3
- package/dist/cli/mining-json.d.ts +1 -22
- package/dist/cli/mining-json.js +0 -23
- package/dist/cli/output.js +16 -2
- package/dist/cli/parse.js +0 -2
- package/dist/cli/preview-json.d.ts +1 -22
- package/dist/cli/preview-json.js +0 -19
- package/dist/cli/types.d.ts +1 -3
- package/dist/cli/wallet-format.js +1 -1
- package/dist/cli/workflow-hints.d.ts +1 -2
- package/dist/cli/workflow-hints.js +5 -8
- package/dist/wallet/lifecycle/context.js +0 -1
- package/dist/wallet/lifecycle/repair-mining.d.ts +1 -5
- package/dist/wallet/lifecycle/repair-mining.js +5 -39
- package/dist/wallet/lifecycle/repair.js +0 -3
- package/dist/wallet/lifecycle/setup.js +10 -8
- package/dist/wallet/lifecycle/types.d.ts +1 -4
- package/dist/wallet/managed-core-wallet.d.ts +2 -0
- package/dist/wallet/managed-core-wallet.js +27 -1
- package/dist/wallet/mining/candidate.d.ts +1 -0
- package/dist/wallet/mining/candidate.js +38 -6
- package/dist/wallet/mining/competitiveness.d.ts +1 -0
- package/dist/wallet/mining/competitiveness.js +6 -0
- package/dist/wallet/mining/cycle.d.ts +2 -0
- package/dist/wallet/mining/cycle.js +14 -4
- package/dist/wallet/mining/engine-state.js +10 -0
- package/dist/wallet/mining/engine-types.d.ts +1 -0
- package/dist/wallet/mining/index.d.ts +1 -1
- package/dist/wallet/mining/index.js +1 -1
- package/dist/wallet/mining/publish.d.ts +3 -0
- package/dist/wallet/mining/publish.js +78 -6
- package/dist/wallet/mining/runner.d.ts +0 -32
- package/dist/wallet/mining/runner.js +59 -104
- package/dist/wallet/mining/stop.d.ts +7 -0
- package/dist/wallet/mining/stop.js +23 -0
- package/dist/wallet/mining/supervisor.d.ts +2 -36
- package/dist/wallet/mining/supervisor.js +139 -246
- package/dist/wallet/mining/visualizer-sync.js +79 -15
- package/dist/wallet/read/context.d.ts +1 -5
- package/dist/wallet/read/context.js +21 -205
- package/dist/wallet/read/managed-services.d.ts +33 -0
- package/dist/wallet/read/managed-services.js +222 -0
- package/dist/wallet/reset/artifacts.d.ts +16 -0
- package/dist/wallet/reset/artifacts.js +141 -0
- package/dist/wallet/reset/execution.d.ts +38 -0
- package/dist/wallet/reset/execution.js +458 -0
- package/dist/wallet/reset/preflight.d.ts +7 -0
- package/dist/wallet/reset/preflight.js +116 -0
- package/dist/wallet/reset/preview.d.ts +2 -0
- package/dist/wallet/reset/preview.js +50 -0
- package/dist/wallet/reset/process-cleanup.d.ts +12 -0
- package/dist/wallet/reset/process-cleanup.js +179 -0
- package/dist/wallet/reset/types.d.ts +189 -0
- package/dist/wallet/reset/types.js +1 -0
- package/dist/wallet/reset.d.ts +4 -119
- package/dist/wallet/reset.js +4 -882
- package/dist/wallet/state/client-password/bootstrap.d.ts +2 -0
- package/dist/wallet/state/client-password/bootstrap.js +3 -0
- package/dist/wallet/state/client-password/context.d.ts +10 -0
- package/dist/wallet/state/client-password/context.js +46 -0
- package/dist/wallet/state/client-password/crypto.d.ts +34 -0
- package/dist/wallet/state/client-password/crypto.js +117 -0
- package/dist/wallet/state/client-password/files.d.ts +10 -0
- package/dist/wallet/state/client-password/files.js +109 -0
- package/dist/wallet/state/client-password/legacy-cleanup.d.ts +11 -0
- package/dist/wallet/state/client-password/legacy-cleanup.js +338 -0
- package/dist/wallet/state/client-password/messages.d.ts +3 -0
- package/dist/wallet/state/client-password/messages.js +9 -0
- package/dist/wallet/state/client-password/migration.d.ts +4 -0
- package/dist/wallet/state/client-password/migration.js +32 -0
- package/dist/wallet/state/client-password/prompts.d.ts +12 -0
- package/dist/wallet/state/client-password/prompts.js +79 -0
- package/dist/wallet/state/client-password/protected-secrets.d.ts +13 -0
- package/dist/wallet/state/client-password/protected-secrets.js +90 -0
- package/dist/wallet/state/client-password/readiness.d.ts +4 -0
- package/dist/wallet/state/client-password/readiness.js +48 -0
- package/dist/wallet/state/client-password/references.d.ts +1 -0
- package/dist/wallet/state/client-password/references.js +56 -0
- package/dist/wallet/state/client-password/rotation.d.ts +6 -0
- package/dist/wallet/state/client-password/rotation.js +98 -0
- package/dist/wallet/state/client-password/session-policy.d.ts +6 -0
- package/dist/wallet/state/client-password/session-policy.js +28 -0
- package/dist/wallet/state/client-password/session.d.ts +19 -0
- package/dist/wallet/state/client-password/session.js +170 -0
- package/dist/wallet/state/client-password/setup.d.ts +8 -0
- package/dist/wallet/state/client-password/setup.js +49 -0
- package/dist/wallet/state/client-password/types.d.ts +82 -0
- package/dist/wallet/state/client-password/types.js +5 -0
- package/dist/wallet/state/client-password.d.ts +7 -38
- package/dist/wallet/state/client-password.js +52 -937
- package/dist/wallet/tx/anchor.js +123 -216
- package/dist/wallet/tx/cog.js +294 -489
- package/dist/wallet/tx/common.d.ts +2 -0
- package/dist/wallet/tx/common.js +2 -0
- package/dist/wallet/tx/domain-admin.js +111 -220
- package/dist/wallet/tx/domain-market.js +401 -681
- package/dist/wallet/tx/executor.d.ts +176 -0
- package/dist/wallet/tx/executor.js +302 -0
- package/dist/wallet/tx/field.js +109 -215
- package/dist/wallet/tx/register.js +158 -269
- package/dist/wallet/tx/reputation.js +120 -227
- package/package.json +1 -1
- package/dist/wallet/mining/worker-main.d.ts +0 -1
- package/dist/wallet/mining/worker-main.js +0 -17
- package/dist/wallet/state/client-password-agent.d.ts +0 -1
- package/dist/wallet/state/client-password-agent.js +0 -211
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { readdir } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { DEFAULT_SNAPSHOT_METADATA } from "../../bitcoind/bootstrap/constants.js";
|
|
4
|
+
import { resolveBootstrapPathsForTesting } from "../../bitcoind/bootstrap/paths.js";
|
|
5
|
+
import { validateSnapshotFileForTesting } from "../../bitcoind/bootstrap/snapshot-file.js";
|
|
6
|
+
import { loadRawWalletStateEnvelope, } from "../state/storage.js";
|
|
7
|
+
import { resolveWalletRuntimePathsForTesting } from "../runtime.js";
|
|
8
|
+
import { isDeletedByRemovalPlan, pathExists, readJsonFileOrNull, resolveRemovedRoots, } from "./artifacts.js";
|
|
9
|
+
import { collectTrackedManagedProcesses } from "./process-cleanup.js";
|
|
10
|
+
function providerUsesExternalSecretStore(provider) {
|
|
11
|
+
return provider.kind === "macos-keychain";
|
|
12
|
+
}
|
|
13
|
+
export function resetDeletesOsSecrets(options) {
|
|
14
|
+
return providerUsesExternalSecretStore(options.provider)
|
|
15
|
+
&& (options.preflight.wallet.secretProviderKeyId !== null
|
|
16
|
+
|| options.preflight.wallet.importedSeedSecretProviderKeyIds.length > 0);
|
|
17
|
+
}
|
|
18
|
+
async function collectLegacyImportedSeedSecretProviderKeyIds(stateRoot, deps = {}) {
|
|
19
|
+
const seedsRoot = join(stateRoot, "seeds");
|
|
20
|
+
const entries = await readdir(seedsRoot, { withFileTypes: true }).catch((error) => {
|
|
21
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
throw error;
|
|
25
|
+
});
|
|
26
|
+
const keyIds = new Set();
|
|
27
|
+
for (const entry of entries) {
|
|
28
|
+
if (!entry.isDirectory()) {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
const seedRoot = join(seedsRoot, entry.name);
|
|
32
|
+
const candidatePaths = [
|
|
33
|
+
join(seedRoot, "wallet-state.enc"),
|
|
34
|
+
join(seedRoot, "wallet-state.enc.bak"),
|
|
35
|
+
join(seedRoot, "wallet-init-pending.enc"),
|
|
36
|
+
join(seedRoot, "wallet-init-pending.enc.bak"),
|
|
37
|
+
];
|
|
38
|
+
for (const candidatePath of candidatePaths) {
|
|
39
|
+
const envelope = await readJsonFileOrNull(candidatePath, deps);
|
|
40
|
+
const keyId = envelope?.secretProvider?.keyId?.trim() ?? "";
|
|
41
|
+
if (keyId.length > 0) {
|
|
42
|
+
keyIds.add(keyId);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return [...keyIds].sort((left, right) => left.localeCompare(right));
|
|
47
|
+
}
|
|
48
|
+
export async function preflightReset(options) {
|
|
49
|
+
const paths = options.paths ?? resolveWalletRuntimePathsForTesting();
|
|
50
|
+
const removedRoots = resolveRemovedRoots(paths);
|
|
51
|
+
const rawEnvelope = await loadRawWalletStateEnvelope({
|
|
52
|
+
primaryPath: paths.walletStatePath,
|
|
53
|
+
backupPath: paths.walletStateBackupPath,
|
|
54
|
+
});
|
|
55
|
+
const snapshotPaths = resolveBootstrapPathsForTesting(options.dataDir, DEFAULT_SNAPSHOT_METADATA);
|
|
56
|
+
const validateSnapshot = options.validateSnapshotFile
|
|
57
|
+
?? ((path) => validateSnapshotFileForTesting(path, DEFAULT_SNAPSHOT_METADATA));
|
|
58
|
+
const artifactDeps = options.artifactDeps ?? {};
|
|
59
|
+
const hasWalletState = await pathExists(paths.walletStatePath, artifactDeps)
|
|
60
|
+
|| await pathExists(paths.walletStateBackupPath, artifactDeps);
|
|
61
|
+
const hasBitcoinDataDir = await pathExists(options.dataDir, artifactDeps);
|
|
62
|
+
const bitcoinDataDirWithinResetScope = hasBitcoinDataDir
|
|
63
|
+
&& isDeletedByRemovalPlan(removedRoots, options.dataDir);
|
|
64
|
+
const hasSnapshot = await pathExists(snapshotPaths.snapshotPath, artifactDeps);
|
|
65
|
+
const hasPartialSnapshot = await pathExists(snapshotPaths.partialSnapshotPath, artifactDeps);
|
|
66
|
+
let snapshotStatus = "not-present";
|
|
67
|
+
if (hasSnapshot) {
|
|
68
|
+
try {
|
|
69
|
+
await validateSnapshot(snapshotPaths.snapshotPath);
|
|
70
|
+
snapshotStatus = "valid";
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
snapshotStatus = "invalid";
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else if (hasPartialSnapshot) {
|
|
77
|
+
snapshotStatus = "invalid";
|
|
78
|
+
}
|
|
79
|
+
const tracked = await collectTrackedManagedProcesses(paths, options.processCleanupDeps);
|
|
80
|
+
const secretProviderKeyId = rawEnvelope?.envelope.secretProvider?.keyId ?? null;
|
|
81
|
+
const importedSeedSecretProviderKeyIds = await collectLegacyImportedSeedSecretProviderKeyIds(paths.stateRoot, artifactDeps);
|
|
82
|
+
return {
|
|
83
|
+
dataRoot: paths.dataRoot,
|
|
84
|
+
removedRoots,
|
|
85
|
+
wallet: {
|
|
86
|
+
present: hasWalletState,
|
|
87
|
+
mode: rawEnvelope == null
|
|
88
|
+
? (hasWalletState ? "unknown" : "unknown")
|
|
89
|
+
: rawEnvelope.envelope.secretProvider != null
|
|
90
|
+
? "provider-backed"
|
|
91
|
+
: "unsupported-legacy",
|
|
92
|
+
envelopeSource: rawEnvelope?.source ?? null,
|
|
93
|
+
secretProviderKeyId,
|
|
94
|
+
importedSeedSecretProviderKeyIds,
|
|
95
|
+
rawEnvelope,
|
|
96
|
+
},
|
|
97
|
+
snapshot: {
|
|
98
|
+
status: snapshotStatus,
|
|
99
|
+
path: snapshotPaths.snapshotPath,
|
|
100
|
+
shouldPrompt: snapshotStatus === "valid",
|
|
101
|
+
withinResetScope: isDeletedByRemovalPlan(removedRoots, snapshotPaths.snapshotPath),
|
|
102
|
+
},
|
|
103
|
+
bitcoinDataDir: {
|
|
104
|
+
status: !hasBitcoinDataDir
|
|
105
|
+
? "not-present"
|
|
106
|
+
: bitcoinDataDirWithinResetScope
|
|
107
|
+
? "within-reset-scope"
|
|
108
|
+
: "outside-reset-scope",
|
|
109
|
+
path: options.dataDir,
|
|
110
|
+
shouldPrompt: bitcoinDataDirWithinResetScope,
|
|
111
|
+
},
|
|
112
|
+
trackedProcesses: tracked.trackedProcesses,
|
|
113
|
+
trackedProcessKinds: tracked.trackedProcessKinds,
|
|
114
|
+
serviceLockPaths: tracked.serviceLockPaths,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { createDefaultWalletSecretProvider } from "../state/provider.js";
|
|
2
|
+
import { resolveWalletRuntimePathsForTesting } from "../runtime.js";
|
|
3
|
+
import { resolveRemovedRoots } from "./artifacts.js";
|
|
4
|
+
import { preflightReset, resetDeletesOsSecrets } from "./preflight.js";
|
|
5
|
+
export async function previewResetWallet(options) {
|
|
6
|
+
const provider = options.provider ?? createDefaultWalletSecretProvider();
|
|
7
|
+
const paths = options.paths ?? resolveWalletRuntimePathsForTesting();
|
|
8
|
+
const preflight = await preflightReset({
|
|
9
|
+
...options,
|
|
10
|
+
provider,
|
|
11
|
+
paths,
|
|
12
|
+
});
|
|
13
|
+
const removedPaths = resolveRemovedRoots(paths, {
|
|
14
|
+
preserveBitcoinDataDir: preflight.snapshot.status === "valid" && preflight.bitcoinDataDir.shouldPrompt,
|
|
15
|
+
});
|
|
16
|
+
return {
|
|
17
|
+
dataRoot: preflight.dataRoot,
|
|
18
|
+
confirmationPhrase: "permanently reset",
|
|
19
|
+
walletPrompt: preflight.wallet.present
|
|
20
|
+
? {
|
|
21
|
+
defaultAction: "retain-mnemonic",
|
|
22
|
+
acceptedInputs: ["", "skip", "clear wallet entropy"],
|
|
23
|
+
entropyRetainingResetAvailable: preflight.wallet.mode === "provider-backed",
|
|
24
|
+
envelopeSource: preflight.wallet.envelopeSource,
|
|
25
|
+
}
|
|
26
|
+
: null,
|
|
27
|
+
bootstrapSnapshot: {
|
|
28
|
+
status: preflight.snapshot.status,
|
|
29
|
+
path: preflight.snapshot.path,
|
|
30
|
+
defaultAction: preflight.snapshot.status === "valid" ? "preserve" : "delete",
|
|
31
|
+
},
|
|
32
|
+
bitcoinDataDir: {
|
|
33
|
+
status: preflight.bitcoinDataDir.status,
|
|
34
|
+
path: preflight.bitcoinDataDir.path,
|
|
35
|
+
conditionalPrompt: preflight.bitcoinDataDir.shouldPrompt
|
|
36
|
+
? {
|
|
37
|
+
prompt: "Delete managed Bitcoin datadir too? [y/N]: ",
|
|
38
|
+
defaultAction: "preserve",
|
|
39
|
+
acceptedInputs: ["", "n", "no", "y", "yes"],
|
|
40
|
+
}
|
|
41
|
+
: null,
|
|
42
|
+
},
|
|
43
|
+
trackedProcessKinds: preflight.trackedProcessKinds,
|
|
44
|
+
willDeleteOsSecrets: resetDeletesOsSecrets({
|
|
45
|
+
provider,
|
|
46
|
+
preflight,
|
|
47
|
+
}),
|
|
48
|
+
removedPaths,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type FileLockHandle } from "../fs/lock.js";
|
|
2
|
+
import type { WalletRuntimePaths } from "../runtime.js";
|
|
3
|
+
import type { TrackedManagedProcess, WalletResetProcessCleanupDependencies, WalletResetResult } from "./types.js";
|
|
4
|
+
export declare function isProcessAlive(pid: number | null, deps?: WalletResetProcessCleanupDependencies): Promise<boolean>;
|
|
5
|
+
export declare function waitForProcessExit(pid: number, timeoutMs?: number, deps?: WalletResetProcessCleanupDependencies): Promise<boolean>;
|
|
6
|
+
export declare function terminateTrackedProcesses(trackedProcesses: readonly TrackedManagedProcess[], deps?: WalletResetProcessCleanupDependencies): Promise<WalletResetResult["stoppedProcesses"]>;
|
|
7
|
+
export declare function collectTrackedManagedProcesses(paths: WalletRuntimePaths, deps?: WalletResetProcessCleanupDependencies): Promise<{
|
|
8
|
+
trackedProcesses: TrackedManagedProcess[];
|
|
9
|
+
trackedProcessKinds: Array<TrackedManagedProcess["kind"]>;
|
|
10
|
+
serviceLockPaths: string[];
|
|
11
|
+
}>;
|
|
12
|
+
export declare function acquireResetLocks(paths: WalletRuntimePaths, serviceLockPaths: readonly string[], deps?: WalletResetProcessCleanupDependencies): Promise<FileLockHandle[]>;
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { loadMiningRuntimeStatus } from "../mining/runtime-artifacts.js";
|
|
2
|
+
import { acquireFileLock } from "../fs/lock.js";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { readdir } from "node:fs/promises";
|
|
5
|
+
import { readJsonFileOrNull } from "./artifacts.js";
|
|
6
|
+
function sleep(ms) {
|
|
7
|
+
return new Promise((resolve) => {
|
|
8
|
+
setTimeout(resolve, ms);
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
function resolveProcessCleanupDependencies(overrides = {}) {
|
|
12
|
+
return {
|
|
13
|
+
acquireLock: overrides.acquireLock ?? acquireFileLock,
|
|
14
|
+
processKill: overrides.processKill ?? process.kill.bind(process),
|
|
15
|
+
sleep: overrides.sleep ?? sleep,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export async function isProcessAlive(pid, deps = {}) {
|
|
19
|
+
const resolved = resolveProcessCleanupDependencies(deps);
|
|
20
|
+
if (pid === null) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
resolved.processKill(pid, 0);
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
if (error instanceof Error && "code" in error && error.code === "ESRCH") {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export async function waitForProcessExit(pid, timeoutMs = 15_000, deps = {}) {
|
|
35
|
+
const resolved = resolveProcessCleanupDependencies(deps);
|
|
36
|
+
const deadline = Date.now() + timeoutMs;
|
|
37
|
+
while (Date.now() < deadline) {
|
|
38
|
+
if (!await isProcessAlive(pid, resolved)) {
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
await resolved.sleep(100);
|
|
42
|
+
}
|
|
43
|
+
return !await isProcessAlive(pid, resolved);
|
|
44
|
+
}
|
|
45
|
+
export async function terminateTrackedProcesses(trackedProcesses, deps = {}) {
|
|
46
|
+
const resolved = resolveProcessCleanupDependencies(deps);
|
|
47
|
+
const survivors = new Set();
|
|
48
|
+
for (const processInfo of trackedProcesses) {
|
|
49
|
+
try {
|
|
50
|
+
resolved.processKill(processInfo.pid, "SIGTERM");
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
if (!(error instanceof Error) || !("code" in error) || error.code !== "ESRCH") {
|
|
54
|
+
throw error;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
for (const processInfo of trackedProcesses) {
|
|
59
|
+
if (!await waitForProcessExit(processInfo.pid, 5_000, resolved)) {
|
|
60
|
+
survivors.add(processInfo.pid);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
for (const pid of survivors) {
|
|
64
|
+
try {
|
|
65
|
+
resolved.processKill(pid, "SIGKILL");
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
if (!(error instanceof Error) || !("code" in error) || error.code !== "ESRCH") {
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const remaining = new Set();
|
|
74
|
+
for (const pid of survivors) {
|
|
75
|
+
if (!await waitForProcessExit(pid, 5_000, resolved)) {
|
|
76
|
+
remaining.add(pid);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (remaining.size > 0) {
|
|
80
|
+
throw new Error("reset_process_shutdown_failed");
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
managedBitcoind: trackedProcesses.filter((processInfo) => processInfo.kind === "managed-bitcoind").length,
|
|
84
|
+
indexerDaemon: trackedProcesses.filter((processInfo) => processInfo.kind === "indexer-daemon").length,
|
|
85
|
+
backgroundMining: trackedProcesses.filter((processInfo) => processInfo.kind === "background-mining").length,
|
|
86
|
+
survivors: 0,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
export async function collectTrackedManagedProcesses(paths, deps = {}) {
|
|
90
|
+
const trackedProcesses = [];
|
|
91
|
+
const trackedProcessKinds = new Set();
|
|
92
|
+
const serviceLockPaths = new Set();
|
|
93
|
+
const runtimeEntries = await readdir(paths.runtimeRoot, { withFileTypes: true }).catch((error) => {
|
|
94
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
95
|
+
return [];
|
|
96
|
+
}
|
|
97
|
+
throw error;
|
|
98
|
+
});
|
|
99
|
+
for (const entry of runtimeEntries) {
|
|
100
|
+
if (!entry.isDirectory()) {
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
const serviceRoot = join(paths.runtimeRoot, entry.name);
|
|
104
|
+
const bitcoindStatus = await readJsonFileOrNull(join(serviceRoot, "bitcoind-status.json"));
|
|
105
|
+
if (bitcoindStatus?.processId != null && await isProcessAlive(bitcoindStatus.processId, deps)) {
|
|
106
|
+
trackedProcesses.push({
|
|
107
|
+
kind: "managed-bitcoind",
|
|
108
|
+
pid: bitcoindStatus.processId,
|
|
109
|
+
});
|
|
110
|
+
trackedProcessKinds.add("managed-bitcoind");
|
|
111
|
+
serviceLockPaths.add(join(serviceRoot, "bitcoind.lock"));
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
const indexerEntries = await readdir(paths.indexerRoot, { withFileTypes: true }).catch((error) => {
|
|
115
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
116
|
+
return [];
|
|
117
|
+
}
|
|
118
|
+
throw error;
|
|
119
|
+
});
|
|
120
|
+
for (const entry of indexerEntries) {
|
|
121
|
+
if (!entry.isDirectory()) {
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
const status = await readJsonFileOrNull(join(paths.indexerRoot, entry.name, "status.json"));
|
|
125
|
+
if (status?.processId != null && await isProcessAlive(status.processId, deps)) {
|
|
126
|
+
trackedProcesses.push({
|
|
127
|
+
kind: "indexer-daemon",
|
|
128
|
+
pid: status.processId,
|
|
129
|
+
});
|
|
130
|
+
trackedProcessKinds.add("indexer-daemon");
|
|
131
|
+
serviceLockPaths.add(join(paths.runtimeRoot, entry.name, "indexer-daemon.lock"));
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
const miningRuntime = await loadMiningRuntimeStatus(paths.miningStatusPath).catch(() => null);
|
|
135
|
+
if (miningRuntime?.backgroundWorkerPid != null
|
|
136
|
+
&& await isProcessAlive(miningRuntime.backgroundWorkerPid, deps)) {
|
|
137
|
+
trackedProcesses.push({
|
|
138
|
+
kind: "background-mining",
|
|
139
|
+
pid: miningRuntime.backgroundWorkerPid,
|
|
140
|
+
});
|
|
141
|
+
trackedProcessKinds.add("background-mining");
|
|
142
|
+
}
|
|
143
|
+
const seen = new Set();
|
|
144
|
+
const deduped = trackedProcesses.filter((processInfo) => {
|
|
145
|
+
const key = `${processInfo.kind}:${processInfo.pid}`;
|
|
146
|
+
if (seen.has(key)) {
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
seen.add(key);
|
|
150
|
+
return true;
|
|
151
|
+
});
|
|
152
|
+
return {
|
|
153
|
+
trackedProcesses: deduped,
|
|
154
|
+
trackedProcessKinds: [...trackedProcessKinds],
|
|
155
|
+
serviceLockPaths: [...serviceLockPaths].sort(),
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
export async function acquireResetLocks(paths, serviceLockPaths, deps = {}) {
|
|
159
|
+
const resolved = resolveProcessCleanupDependencies(deps);
|
|
160
|
+
const lockPaths = [
|
|
161
|
+
paths.walletControlLockPath,
|
|
162
|
+
paths.miningControlLockPath,
|
|
163
|
+
...serviceLockPaths,
|
|
164
|
+
];
|
|
165
|
+
const handles = [];
|
|
166
|
+
try {
|
|
167
|
+
for (const lockPath of lockPaths) {
|
|
168
|
+
handles.push(await resolved.acquireLock(lockPath, {
|
|
169
|
+
purpose: "wallet-reset",
|
|
170
|
+
walletRootId: null,
|
|
171
|
+
}));
|
|
172
|
+
}
|
|
173
|
+
return handles;
|
|
174
|
+
}
|
|
175
|
+
catch (error) {
|
|
176
|
+
await Promise.all(handles.map(async (handle) => handle.release().catch(() => undefined)));
|
|
177
|
+
throw error;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { type FileLockHandle } from "../fs/lock.js";
|
|
2
|
+
import type { attachOrStartManagedBitcoindService } from "../../bitcoind/service.js";
|
|
3
|
+
import type { createRpcClient } from "../../bitcoind/node.js";
|
|
4
|
+
import type { WalletRuntimePaths } from "../runtime.js";
|
|
5
|
+
import type { WalletSecretProvider } from "../state/provider.js";
|
|
6
|
+
import type { RawWalletStateEnvelope } from "../state/storage.js";
|
|
7
|
+
import type { WalletStateV1 } from "../types.js";
|
|
8
|
+
import type { WalletPrompter } from "../lifecycle.js";
|
|
9
|
+
export type WalletResetAction = "not-present" | "kept-unchanged" | "retain-mnemonic" | "deleted";
|
|
10
|
+
export type WalletResetSecretCleanupStatus = "deleted" | "not-found" | "failed" | "unknown";
|
|
11
|
+
export type WalletResetSnapshotResultStatus = "not-present" | "invalid-removed" | "deleted" | "preserved";
|
|
12
|
+
export type WalletResetBitcoinDataDirResultStatus = "not-present" | "preserved" | "deleted" | "outside-reset-scope";
|
|
13
|
+
export interface WalletResetResult {
|
|
14
|
+
dataRoot: string;
|
|
15
|
+
factoryResetReady: true;
|
|
16
|
+
stoppedProcesses: {
|
|
17
|
+
managedBitcoind: number;
|
|
18
|
+
indexerDaemon: number;
|
|
19
|
+
backgroundMining: number;
|
|
20
|
+
survivors: number;
|
|
21
|
+
};
|
|
22
|
+
secretCleanupStatus: WalletResetSecretCleanupStatus;
|
|
23
|
+
deletedSecretRefs: string[];
|
|
24
|
+
failedSecretRefs: string[];
|
|
25
|
+
preservedSecretRefs: string[];
|
|
26
|
+
walletAction: WalletResetAction;
|
|
27
|
+
walletOldRootId: string | null;
|
|
28
|
+
walletNewRootId: string | null;
|
|
29
|
+
bootstrapSnapshot: {
|
|
30
|
+
status: WalletResetSnapshotResultStatus;
|
|
31
|
+
path: string;
|
|
32
|
+
};
|
|
33
|
+
bitcoinDataDir: {
|
|
34
|
+
status: WalletResetBitcoinDataDirResultStatus;
|
|
35
|
+
path: string;
|
|
36
|
+
};
|
|
37
|
+
removedPaths: string[];
|
|
38
|
+
}
|
|
39
|
+
export interface WalletResetPreview {
|
|
40
|
+
dataRoot: string;
|
|
41
|
+
confirmationPhrase: "permanently reset";
|
|
42
|
+
walletPrompt: null | {
|
|
43
|
+
defaultAction: "retain-mnemonic";
|
|
44
|
+
acceptedInputs: ["", "skip", "clear wallet entropy"];
|
|
45
|
+
entropyRetainingResetAvailable: boolean;
|
|
46
|
+
envelopeSource: "primary" | "backup" | null;
|
|
47
|
+
};
|
|
48
|
+
bootstrapSnapshot: {
|
|
49
|
+
status: "not-present" | "invalid" | "valid";
|
|
50
|
+
path: string;
|
|
51
|
+
defaultAction: "preserve" | "delete";
|
|
52
|
+
};
|
|
53
|
+
bitcoinDataDir: {
|
|
54
|
+
status: "not-present" | "within-reset-scope" | "outside-reset-scope";
|
|
55
|
+
path: string;
|
|
56
|
+
conditionalPrompt: null | {
|
|
57
|
+
prompt: "Delete managed Bitcoin datadir too? [y/N]: ";
|
|
58
|
+
defaultAction: "preserve";
|
|
59
|
+
acceptedInputs: ["", "n", "no", "y", "yes"];
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
trackedProcessKinds: Array<"managed-bitcoind" | "indexer-daemon" | "background-mining">;
|
|
63
|
+
willDeleteOsSecrets: boolean;
|
|
64
|
+
removedPaths: string[];
|
|
65
|
+
}
|
|
66
|
+
export type WalletEnvelopeMode = "provider-backed" | "unsupported-legacy" | "unknown";
|
|
67
|
+
export interface WalletResetPreflight {
|
|
68
|
+
dataRoot: string;
|
|
69
|
+
removedRoots: string[];
|
|
70
|
+
wallet: {
|
|
71
|
+
present: boolean;
|
|
72
|
+
mode: WalletEnvelopeMode;
|
|
73
|
+
envelopeSource: "primary" | "backup" | null;
|
|
74
|
+
secretProviderKeyId: string | null;
|
|
75
|
+
importedSeedSecretProviderKeyIds: string[];
|
|
76
|
+
rawEnvelope: RawWalletStateEnvelope | null;
|
|
77
|
+
};
|
|
78
|
+
snapshot: {
|
|
79
|
+
status: "not-present" | "invalid" | "valid";
|
|
80
|
+
path: string;
|
|
81
|
+
shouldPrompt: boolean;
|
|
82
|
+
withinResetScope: boolean;
|
|
83
|
+
};
|
|
84
|
+
bitcoinDataDir: {
|
|
85
|
+
status: "not-present" | "within-reset-scope" | "outside-reset-scope";
|
|
86
|
+
path: string;
|
|
87
|
+
shouldPrompt: boolean;
|
|
88
|
+
};
|
|
89
|
+
trackedProcesses: TrackedManagedProcess[];
|
|
90
|
+
trackedProcessKinds: Array<TrackedManagedProcess["kind"]>;
|
|
91
|
+
serviceLockPaths: string[];
|
|
92
|
+
}
|
|
93
|
+
export interface TrackedManagedProcess {
|
|
94
|
+
kind: "managed-bitcoind" | "indexer-daemon" | "background-mining";
|
|
95
|
+
pid: number;
|
|
96
|
+
}
|
|
97
|
+
export interface StagedArtifact {
|
|
98
|
+
originalPath: string;
|
|
99
|
+
stagedPath: string;
|
|
100
|
+
restorePath: string;
|
|
101
|
+
}
|
|
102
|
+
export interface WalletAccessForReset {
|
|
103
|
+
loaded: {
|
|
104
|
+
source: "primary" | "backup";
|
|
105
|
+
state: WalletStateV1;
|
|
106
|
+
};
|
|
107
|
+
access: {
|
|
108
|
+
kind: "provider";
|
|
109
|
+
provider: WalletSecretProvider;
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
export interface ResetWalletRpcClient {
|
|
113
|
+
getDescriptorInfo(descriptor: string): Promise<{
|
|
114
|
+
descriptor: string;
|
|
115
|
+
checksum: string;
|
|
116
|
+
}>;
|
|
117
|
+
createWallet(walletName: string, options: {
|
|
118
|
+
blank: boolean;
|
|
119
|
+
descriptors: boolean;
|
|
120
|
+
disablePrivateKeys: boolean;
|
|
121
|
+
loadOnStartup: boolean;
|
|
122
|
+
passphrase: string;
|
|
123
|
+
}): Promise<unknown>;
|
|
124
|
+
walletPassphrase(walletName: string, passphrase: string, timeoutSeconds: number): Promise<null>;
|
|
125
|
+
importDescriptors(walletName: string, requests: Array<{
|
|
126
|
+
desc: string;
|
|
127
|
+
timestamp: string | number;
|
|
128
|
+
active?: boolean;
|
|
129
|
+
internal?: boolean;
|
|
130
|
+
range?: number | [number, number];
|
|
131
|
+
}>): Promise<Array<{
|
|
132
|
+
success: boolean;
|
|
133
|
+
}>>;
|
|
134
|
+
walletLock(walletName: string): Promise<null>;
|
|
135
|
+
deriveAddresses(descriptor: string, range?: number | [number, number]): Promise<string[]>;
|
|
136
|
+
listDescriptors(walletName: string, privateOnly?: boolean): Promise<{
|
|
137
|
+
descriptors: Array<{
|
|
138
|
+
desc: string;
|
|
139
|
+
}>;
|
|
140
|
+
}>;
|
|
141
|
+
getWalletInfo(walletName: string): Promise<{
|
|
142
|
+
walletname: string;
|
|
143
|
+
private_keys_enabled: boolean;
|
|
144
|
+
descriptors: boolean;
|
|
145
|
+
}>;
|
|
146
|
+
loadWallet(walletName: string, loadOnStartup?: boolean): Promise<{
|
|
147
|
+
name: string;
|
|
148
|
+
warning: string;
|
|
149
|
+
}>;
|
|
150
|
+
listWallets(): Promise<string[]>;
|
|
151
|
+
}
|
|
152
|
+
export interface ResetExecutionDecision {
|
|
153
|
+
walletChoice: "" | "skip" | "clear wallet entropy";
|
|
154
|
+
deleteSnapshot: boolean;
|
|
155
|
+
deleteBitcoinDataDir: boolean;
|
|
156
|
+
loadedWalletForEntropyReset: WalletAccessForReset | null;
|
|
157
|
+
}
|
|
158
|
+
export interface WalletResetArtifactDependencies {
|
|
159
|
+
access?: typeof import("node:fs/promises").access;
|
|
160
|
+
copyFile?: typeof import("node:fs/promises").copyFile;
|
|
161
|
+
mkdir?: typeof import("node:fs/promises").mkdir;
|
|
162
|
+
readFile?: typeof import("node:fs/promises").readFile;
|
|
163
|
+
rename?: typeof import("node:fs/promises").rename;
|
|
164
|
+
remove?: typeof import("node:fs/promises").rm;
|
|
165
|
+
}
|
|
166
|
+
export interface WalletResetProcessCleanupDependencies {
|
|
167
|
+
acquireLock?: (path: string, metadata: {
|
|
168
|
+
purpose: string;
|
|
169
|
+
walletRootId: null;
|
|
170
|
+
}) => Promise<FileLockHandle>;
|
|
171
|
+
processKill?: typeof process.kill;
|
|
172
|
+
sleep?: (ms: number) => Promise<void>;
|
|
173
|
+
}
|
|
174
|
+
export interface WalletResetBaseOptions {
|
|
175
|
+
dataDir: string;
|
|
176
|
+
provider?: WalletSecretProvider;
|
|
177
|
+
paths?: WalletRuntimePaths;
|
|
178
|
+
}
|
|
179
|
+
export interface WalletResetPreflightOptions extends WalletResetBaseOptions {
|
|
180
|
+
validateSnapshotFile?: (path: string) => Promise<void>;
|
|
181
|
+
artifactDeps?: WalletResetArtifactDependencies;
|
|
182
|
+
processCleanupDeps?: WalletResetProcessCleanupDependencies;
|
|
183
|
+
}
|
|
184
|
+
export interface WalletResetExecutionOptions extends WalletResetPreflightOptions {
|
|
185
|
+
prompter: WalletPrompter;
|
|
186
|
+
nowUnixMs?: number;
|
|
187
|
+
attachService?: typeof attachOrStartManagedBitcoindService;
|
|
188
|
+
rpcFactory?: (config: Parameters<typeof createRpcClient>[0]) => ResetWalletRpcClient;
|
|
189
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import {} from "../fs/lock.js";
|
package/dist/wallet/reset.d.ts
CHANGED
|
@@ -1,119 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import type { WalletPrompter } from "./lifecycle.js";
|
|
6
|
-
export type WalletResetAction = "not-present" | "kept-unchanged" | "retain-mnemonic" | "deleted";
|
|
7
|
-
export type WalletResetSecretCleanupStatus = "deleted" | "not-found" | "failed" | "unknown";
|
|
8
|
-
export type WalletResetSnapshotResultStatus = "not-present" | "invalid-removed" | "deleted" | "preserved";
|
|
9
|
-
export type WalletResetBitcoinDataDirResultStatus = "not-present" | "preserved" | "deleted" | "outside-reset-scope";
|
|
10
|
-
export interface WalletResetResult {
|
|
11
|
-
dataRoot: string;
|
|
12
|
-
factoryResetReady: true;
|
|
13
|
-
stoppedProcesses: {
|
|
14
|
-
managedBitcoind: number;
|
|
15
|
-
indexerDaemon: number;
|
|
16
|
-
backgroundMining: number;
|
|
17
|
-
survivors: number;
|
|
18
|
-
};
|
|
19
|
-
secretCleanupStatus: WalletResetSecretCleanupStatus;
|
|
20
|
-
deletedSecretRefs: string[];
|
|
21
|
-
failedSecretRefs: string[];
|
|
22
|
-
preservedSecretRefs: string[];
|
|
23
|
-
walletAction: WalletResetAction;
|
|
24
|
-
walletOldRootId: string | null;
|
|
25
|
-
walletNewRootId: string | null;
|
|
26
|
-
bootstrapSnapshot: {
|
|
27
|
-
status: WalletResetSnapshotResultStatus;
|
|
28
|
-
path: string;
|
|
29
|
-
};
|
|
30
|
-
bitcoinDataDir: {
|
|
31
|
-
status: WalletResetBitcoinDataDirResultStatus;
|
|
32
|
-
path: string;
|
|
33
|
-
};
|
|
34
|
-
removedPaths: string[];
|
|
35
|
-
}
|
|
36
|
-
export interface WalletResetPreview {
|
|
37
|
-
dataRoot: string;
|
|
38
|
-
confirmationPhrase: "permanently reset";
|
|
39
|
-
walletPrompt: null | {
|
|
40
|
-
defaultAction: "retain-mnemonic";
|
|
41
|
-
acceptedInputs: ["", "skip", "clear wallet entropy"];
|
|
42
|
-
entropyRetainingResetAvailable: boolean;
|
|
43
|
-
envelopeSource: "primary" | "backup" | null;
|
|
44
|
-
};
|
|
45
|
-
bootstrapSnapshot: {
|
|
46
|
-
status: "not-present" | "invalid" | "valid";
|
|
47
|
-
path: string;
|
|
48
|
-
defaultAction: "preserve" | "delete";
|
|
49
|
-
};
|
|
50
|
-
bitcoinDataDir: {
|
|
51
|
-
status: "not-present" | "within-reset-scope" | "outside-reset-scope";
|
|
52
|
-
path: string;
|
|
53
|
-
conditionalPrompt: null | {
|
|
54
|
-
prompt: "Delete managed Bitcoin datadir too? [y/N]: ";
|
|
55
|
-
defaultAction: "preserve";
|
|
56
|
-
acceptedInputs: ["", "n", "no", "y", "yes"];
|
|
57
|
-
};
|
|
58
|
-
};
|
|
59
|
-
trackedProcessKinds: Array<"managed-bitcoind" | "indexer-daemon" | "background-mining">;
|
|
60
|
-
willDeleteOsSecrets: boolean;
|
|
61
|
-
removedPaths: string[];
|
|
62
|
-
}
|
|
63
|
-
interface ResetWalletRpcClient {
|
|
64
|
-
getDescriptorInfo(descriptor: string): Promise<{
|
|
65
|
-
descriptor: string;
|
|
66
|
-
checksum: string;
|
|
67
|
-
}>;
|
|
68
|
-
createWallet(walletName: string, options: {
|
|
69
|
-
blank: boolean;
|
|
70
|
-
descriptors: boolean;
|
|
71
|
-
disablePrivateKeys: boolean;
|
|
72
|
-
loadOnStartup: boolean;
|
|
73
|
-
passphrase: string;
|
|
74
|
-
}): Promise<unknown>;
|
|
75
|
-
walletPassphrase(walletName: string, passphrase: string, timeoutSeconds: number): Promise<null>;
|
|
76
|
-
importDescriptors(walletName: string, requests: Array<{
|
|
77
|
-
desc: string;
|
|
78
|
-
timestamp: string | number;
|
|
79
|
-
active?: boolean;
|
|
80
|
-
internal?: boolean;
|
|
81
|
-
range?: number | [number, number];
|
|
82
|
-
}>): Promise<Array<{
|
|
83
|
-
success: boolean;
|
|
84
|
-
}>>;
|
|
85
|
-
walletLock(walletName: string): Promise<null>;
|
|
86
|
-
deriveAddresses(descriptor: string, range?: number | [number, number]): Promise<string[]>;
|
|
87
|
-
listDescriptors(walletName: string, privateOnly?: boolean): Promise<{
|
|
88
|
-
descriptors: Array<{
|
|
89
|
-
desc: string;
|
|
90
|
-
}>;
|
|
91
|
-
}>;
|
|
92
|
-
getWalletInfo(walletName: string): Promise<{
|
|
93
|
-
walletname: string;
|
|
94
|
-
private_keys_enabled: boolean;
|
|
95
|
-
descriptors: boolean;
|
|
96
|
-
}>;
|
|
97
|
-
loadWallet(walletName: string, loadOnStartup?: boolean): Promise<{
|
|
98
|
-
name: string;
|
|
99
|
-
warning: string;
|
|
100
|
-
}>;
|
|
101
|
-
listWallets(): Promise<string[]>;
|
|
102
|
-
}
|
|
103
|
-
export declare function previewResetWallet(options: {
|
|
104
|
-
dataDir: string;
|
|
105
|
-
provider?: WalletSecretProvider;
|
|
106
|
-
paths?: WalletRuntimePaths;
|
|
107
|
-
validateSnapshotFile?: (path: string) => Promise<void>;
|
|
108
|
-
}): Promise<WalletResetPreview>;
|
|
109
|
-
export declare function resetWallet(options: {
|
|
110
|
-
dataDir: string;
|
|
111
|
-
provider?: WalletSecretProvider;
|
|
112
|
-
prompter: WalletPrompter;
|
|
113
|
-
nowUnixMs?: number;
|
|
114
|
-
paths?: WalletRuntimePaths;
|
|
115
|
-
validateSnapshotFile?: (path: string) => Promise<void>;
|
|
116
|
-
attachService?: typeof attachOrStartManagedBitcoindService;
|
|
117
|
-
rpcFactory?: (config: Parameters<typeof createRpcClient>[0]) => ResetWalletRpcClient;
|
|
118
|
-
}): Promise<WalletResetResult>;
|
|
119
|
-
export {};
|
|
1
|
+
export type { WalletResetAction, WalletResetBitcoinDataDirResultStatus, WalletResetPreview, WalletResetResult, WalletResetSecretCleanupStatus, WalletResetSnapshotResultStatus, } from "./reset/types.js";
|
|
2
|
+
import type { WalletResetExecutionOptions, WalletResetPreflightOptions, WalletResetPreview, WalletResetResult } from "./reset/types.js";
|
|
3
|
+
export declare function previewResetWallet(options: WalletResetPreflightOptions): Promise<WalletResetPreview>;
|
|
4
|
+
export declare function resetWallet(options: WalletResetExecutionOptions): Promise<WalletResetResult>;
|