@cogcoin/client 0.5.0
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/LICENSE +21 -0
- package/README.md +136 -0
- package/dist/app-paths.d.ts +38 -0
- package/dist/app-paths.js +121 -0
- package/dist/art/banner.txt +13 -0
- package/dist/art/scroll.txt +13 -0
- package/dist/art/train-car.txt +6 -0
- package/dist/art/train-smoke.txt +6 -0
- package/dist/art/train.txt +6 -0
- package/dist/bitcoind/bootstrap/chainstate.d.ts +4 -0
- package/dist/bitcoind/bootstrap/chainstate.js +13 -0
- package/dist/bitcoind/bootstrap/constants.d.ts +7 -0
- package/dist/bitcoind/bootstrap/constants.js +12 -0
- package/dist/bitcoind/bootstrap/controller.d.ts +29 -0
- package/dist/bitcoind/bootstrap/controller.js +101 -0
- package/dist/bitcoind/bootstrap/download.d.ts +2 -0
- package/dist/bitcoind/bootstrap/download.js +196 -0
- package/dist/bitcoind/bootstrap/headers.d.ts +13 -0
- package/dist/bitcoind/bootstrap/headers.js +61 -0
- package/dist/bitcoind/bootstrap/paths.d.ts +4 -0
- package/dist/bitcoind/bootstrap/paths.js +15 -0
- package/dist/bitcoind/bootstrap/snapshot-file.d.ts +7 -0
- package/dist/bitcoind/bootstrap/snapshot-file.js +42 -0
- package/dist/bitcoind/bootstrap/state.d.ts +40 -0
- package/dist/bitcoind/bootstrap/state.js +70 -0
- package/dist/bitcoind/bootstrap/types.d.ts +28 -0
- package/dist/bitcoind/bootstrap/types.js +1 -0
- package/dist/bitcoind/bootstrap.d.ts +8 -0
- package/dist/bitcoind/bootstrap.js +7 -0
- package/dist/bitcoind/client/factory.d.ts +3 -0
- package/dist/bitcoind/client/factory.js +57 -0
- package/dist/bitcoind/client/follow-block-times.d.ts +8 -0
- package/dist/bitcoind/client/follow-block-times.js +25 -0
- package/dist/bitcoind/client/follow-loop.d.ts +10 -0
- package/dist/bitcoind/client/follow-loop.js +57 -0
- package/dist/bitcoind/client/internal-types.d.ts +63 -0
- package/dist/bitcoind/client/internal-types.js +18 -0
- package/dist/bitcoind/client/managed-client.d.ts +20 -0
- package/dist/bitcoind/client/managed-client.js +197 -0
- package/dist/bitcoind/client/rate-tracker.d.ts +2 -0
- package/dist/bitcoind/client/rate-tracker.js +24 -0
- package/dist/bitcoind/client/sync-engine.d.ts +3 -0
- package/dist/bitcoind/client/sync-engine.js +143 -0
- package/dist/bitcoind/client.d.ts +1 -0
- package/dist/bitcoind/client.js +1 -0
- package/dist/bitcoind/errors.d.ts +1 -0
- package/dist/bitcoind/errors.js +49 -0
- package/dist/bitcoind/index.d.ts +2 -0
- package/dist/bitcoind/index.js +1 -0
- package/dist/bitcoind/indexer-daemon-main.d.ts +1 -0
- package/dist/bitcoind/indexer-daemon-main.js +472 -0
- package/dist/bitcoind/indexer-daemon.d.ts +107 -0
- package/dist/bitcoind/indexer-daemon.js +391 -0
- package/dist/bitcoind/node.d.ts +8 -0
- package/dist/bitcoind/node.js +219 -0
- package/dist/bitcoind/normalize.d.ts +3 -0
- package/dist/bitcoind/normalize.js +47 -0
- package/dist/bitcoind/progress/assets.d.ts +10 -0
- package/dist/bitcoind/progress/assets.js +90 -0
- package/dist/bitcoind/progress/constants.d.ts +48 -0
- package/dist/bitcoind/progress/constants.js +53 -0
- package/dist/bitcoind/progress/controller.d.ts +28 -0
- package/dist/bitcoind/progress/controller.js +188 -0
- package/dist/bitcoind/progress/follow-scene.d.ts +40 -0
- package/dist/bitcoind/progress/follow-scene.js +367 -0
- package/dist/bitcoind/progress/formatting.d.ts +23 -0
- package/dist/bitcoind/progress/formatting.js +227 -0
- package/dist/bitcoind/progress/quote-scene.d.ts +4 -0
- package/dist/bitcoind/progress/quote-scene.js +137 -0
- package/dist/bitcoind/progress/train-scene.d.ts +9 -0
- package/dist/bitcoind/progress/train-scene.js +92 -0
- package/dist/bitcoind/progress/tty-renderer.d.ts +18 -0
- package/dist/bitcoind/progress/tty-renderer.js +150 -0
- package/dist/bitcoind/progress.d.ts +7 -0
- package/dist/bitcoind/progress.js +7 -0
- package/dist/bitcoind/quotes.d.ts +24 -0
- package/dist/bitcoind/quotes.js +195 -0
- package/dist/bitcoind/rpc.d.ts +71 -0
- package/dist/bitcoind/rpc.js +322 -0
- package/dist/bitcoind/service-paths.d.ts +19 -0
- package/dist/bitcoind/service-paths.js +49 -0
- package/dist/bitcoind/service.d.ts +40 -0
- package/dist/bitcoind/service.js +735 -0
- package/dist/bitcoind/testing.d.ts +9 -0
- package/dist/bitcoind/testing.js +9 -0
- package/dist/bitcoind/types.d.ts +396 -0
- package/dist/bitcoind/types.js +3 -0
- package/dist/bytes.d.ts +9 -0
- package/dist/bytes.js +36 -0
- package/dist/cli/commands/follow.d.ts +2 -0
- package/dist/cli/commands/follow.js +43 -0
- package/dist/cli/commands/mining-admin.d.ts +2 -0
- package/dist/cli/commands/mining-admin.js +92 -0
- package/dist/cli/commands/mining-read.d.ts +2 -0
- package/dist/cli/commands/mining-read.js +173 -0
- package/dist/cli/commands/mining-runtime.d.ts +2 -0
- package/dist/cli/commands/mining-runtime.js +108 -0
- package/dist/cli/commands/status.d.ts +2 -0
- package/dist/cli/commands/status.js +31 -0
- package/dist/cli/commands/sync.d.ts +2 -0
- package/dist/cli/commands/sync.js +52 -0
- package/dist/cli/commands/wallet-admin.d.ts +2 -0
- package/dist/cli/commands/wallet-admin.js +175 -0
- package/dist/cli/commands/wallet-mutation.d.ts +2 -0
- package/dist/cli/commands/wallet-mutation.js +681 -0
- package/dist/cli/commands/wallet-read.d.ts +2 -0
- package/dist/cli/commands/wallet-read.js +265 -0
- package/dist/cli/context.d.ts +3 -0
- package/dist/cli/context.js +75 -0
- package/dist/cli/io.d.ts +3 -0
- package/dist/cli/io.js +12 -0
- package/dist/cli/mining-format.d.ts +5 -0
- package/dist/cli/mining-format.js +156 -0
- package/dist/cli/mining-json.d.ts +49 -0
- package/dist/cli/mining-json.js +89 -0
- package/dist/cli/mutation-command-groups.d.ts +15 -0
- package/dist/cli/mutation-command-groups.js +71 -0
- package/dist/cli/mutation-json.d.ts +430 -0
- package/dist/cli/mutation-json.js +311 -0
- package/dist/cli/mutation-resolved-json.d.ts +124 -0
- package/dist/cli/mutation-resolved-json.js +129 -0
- package/dist/cli/mutation-success.d.ts +20 -0
- package/dist/cli/mutation-success.js +47 -0
- package/dist/cli/mutation-text-format.d.ts +22 -0
- package/dist/cli/mutation-text-format.js +171 -0
- package/dist/cli/mutation-text-write.d.ts +13 -0
- package/dist/cli/mutation-text-write.js +16 -0
- package/dist/cli/output.d.ts +185 -0
- package/dist/cli/output.js +1085 -0
- package/dist/cli/parse.d.ts +3 -0
- package/dist/cli/parse.js +971 -0
- package/dist/cli/preview-json.d.ts +416 -0
- package/dist/cli/preview-json.js +293 -0
- package/dist/cli/prompt.d.ts +3 -0
- package/dist/cli/prompt.js +33 -0
- package/dist/cli/read-json.d.ts +187 -0
- package/dist/cli/read-json.js +675 -0
- package/dist/cli/runner.d.ts +2 -0
- package/dist/cli/runner.js +129 -0
- package/dist/cli/signals.d.ts +3 -0
- package/dist/cli/signals.js +63 -0
- package/dist/cli/status-format.d.ts +2 -0
- package/dist/cli/status-format.js +48 -0
- package/dist/cli/types.d.ts +148 -0
- package/dist/cli/types.js +2 -0
- package/dist/cli/wallet-format.d.ts +29 -0
- package/dist/cli/wallet-format.js +637 -0
- package/dist/cli/workflow-hints.d.ts +13 -0
- package/dist/cli/workflow-hints.js +94 -0
- package/dist/cli-runner.d.ts +3 -0
- package/dist/cli-runner.js +3 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +6 -0
- package/dist/client/default-client.d.ts +11 -0
- package/dist/client/default-client.js +118 -0
- package/dist/client/factory.d.ts +2 -0
- package/dist/client/factory.js +15 -0
- package/dist/client/initialization.d.ts +6 -0
- package/dist/client/initialization.js +30 -0
- package/dist/client/persistence.d.ts +5 -0
- package/dist/client/persistence.js +28 -0
- package/dist/client/store-adapter.d.ts +3 -0
- package/dist/client/store-adapter.js +20 -0
- package/dist/client.d.ts +2 -0
- package/dist/client.js +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/passive-status.d.ts +36 -0
- package/dist/passive-status.js +100 -0
- package/dist/sqlite/better-sqlite3.d.ts +26 -0
- package/dist/sqlite/better-sqlite3.js +4 -0
- package/dist/sqlite/checkpoints.d.ts +11 -0
- package/dist/sqlite/checkpoints.js +27 -0
- package/dist/sqlite/driver.d.ts +17 -0
- package/dist/sqlite/driver.js +98 -0
- package/dist/sqlite/index.d.ts +4 -0
- package/dist/sqlite/index.js +9 -0
- package/dist/sqlite/migrate.d.ts +2 -0
- package/dist/sqlite/migrate.js +37 -0
- package/dist/sqlite/store.d.ts +3 -0
- package/dist/sqlite/store.js +122 -0
- package/dist/sqlite/tip-meta.d.ts +26 -0
- package/dist/sqlite/tip-meta.js +97 -0
- package/dist/sqlite/types.d.ts +10 -0
- package/dist/sqlite/types.js +1 -0
- package/dist/types.d.ts +55 -0
- package/dist/types.js +1 -0
- package/dist/wallet/archive.d.ts +4 -0
- package/dist/wallet/archive.js +39 -0
- package/dist/wallet/cogop/constants.d.ts +32 -0
- package/dist/wallet/cogop/constants.js +32 -0
- package/dist/wallet/cogop/index.d.ts +32 -0
- package/dist/wallet/cogop/index.js +213 -0
- package/dist/wallet/cogop/numeric.d.ts +3 -0
- package/dist/wallet/cogop/numeric.js +24 -0
- package/dist/wallet/cogop/scriptpubkey.d.ts +2 -0
- package/dist/wallet/cogop/scriptpubkey.js +13 -0
- package/dist/wallet/cogop/validate-name.d.ts +2 -0
- package/dist/wallet/cogop/validate-name.js +18 -0
- package/dist/wallet/fs/atomic.d.ts +6 -0
- package/dist/wallet/fs/atomic.js +46 -0
- package/dist/wallet/fs/lock.d.ts +19 -0
- package/dist/wallet/fs/lock.js +61 -0
- package/dist/wallet/fs/status-file.d.ts +1 -0
- package/dist/wallet/fs/status-file.js +4 -0
- package/dist/wallet/lifecycle.d.ts +193 -0
- package/dist/wallet/lifecycle.js +1475 -0
- package/dist/wallet/material.d.ts +45 -0
- package/dist/wallet/material.js +118 -0
- package/dist/wallet/mining/config.d.ts +18 -0
- package/dist/wallet/mining/config.js +44 -0
- package/dist/wallet/mining/constants.d.ts +24 -0
- package/dist/wallet/mining/constants.js +24 -0
- package/dist/wallet/mining/control.d.ts +53 -0
- package/dist/wallet/mining/control.js +758 -0
- package/dist/wallet/mining/coordination.d.ts +40 -0
- package/dist/wallet/mining/coordination.js +121 -0
- package/dist/wallet/mining/hook-protocol.d.ts +47 -0
- package/dist/wallet/mining/hook-protocol.js +161 -0
- package/dist/wallet/mining/hook-runner.d.ts +1 -0
- package/dist/wallet/mining/hook-runner.js +52 -0
- package/dist/wallet/mining/hooks.d.ts +38 -0
- package/dist/wallet/mining/hooks.js +520 -0
- package/dist/wallet/mining/index.d.ts +8 -0
- package/dist/wallet/mining/index.js +6 -0
- package/dist/wallet/mining/runner.d.ts +155 -0
- package/dist/wallet/mining/runner.js +2574 -0
- package/dist/wallet/mining/runtime-artifacts.d.ts +17 -0
- package/dist/wallet/mining/runtime-artifacts.js +166 -0
- package/dist/wallet/mining/sentences.d.ts +23 -0
- package/dist/wallet/mining/sentences.js +281 -0
- package/dist/wallet/mining/state.d.ts +9 -0
- package/dist/wallet/mining/state.js +75 -0
- package/dist/wallet/mining/types.d.ts +141 -0
- package/dist/wallet/mining/types.js +1 -0
- package/dist/wallet/mining/visualizer.d.ts +19 -0
- package/dist/wallet/mining/visualizer.js +134 -0
- package/dist/wallet/mining/worker-main.d.ts +1 -0
- package/dist/wallet/mining/worker-main.js +17 -0
- package/dist/wallet/read/context.d.ts +20 -0
- package/dist/wallet/read/context.js +532 -0
- package/dist/wallet/read/filter.d.ts +9 -0
- package/dist/wallet/read/filter.js +42 -0
- package/dist/wallet/read/index.d.ts +4 -0
- package/dist/wallet/read/index.js +3 -0
- package/dist/wallet/read/project.d.ts +11 -0
- package/dist/wallet/read/project.js +300 -0
- package/dist/wallet/read/types.d.ts +144 -0
- package/dist/wallet/read/types.js +1 -0
- package/dist/wallet/runtime.d.ts +26 -0
- package/dist/wallet/runtime.js +28 -0
- package/dist/wallet/state/crypto.d.ts +31 -0
- package/dist/wallet/state/crypto.js +127 -0
- package/dist/wallet/state/provider.d.ts +37 -0
- package/dist/wallet/state/provider.js +312 -0
- package/dist/wallet/state/session.d.ts +12 -0
- package/dist/wallet/state/session.js +23 -0
- package/dist/wallet/state/storage.d.ts +19 -0
- package/dist/wallet/state/storage.js +55 -0
- package/dist/wallet/tx/anchor.d.ts +40 -0
- package/dist/wallet/tx/anchor.js +1210 -0
- package/dist/wallet/tx/cog.d.ts +92 -0
- package/dist/wallet/tx/cog.js +1055 -0
- package/dist/wallet/tx/common.d.ts +89 -0
- package/dist/wallet/tx/common.js +156 -0
- package/dist/wallet/tx/confirm.d.ts +15 -0
- package/dist/wallet/tx/confirm.js +24 -0
- package/dist/wallet/tx/domain-admin.d.ts +105 -0
- package/dist/wallet/tx/domain-admin.js +869 -0
- package/dist/wallet/tx/domain-market.d.ts +112 -0
- package/dist/wallet/tx/domain-market.js +1365 -0
- package/dist/wallet/tx/field.d.ts +101 -0
- package/dist/wallet/tx/field.js +1853 -0
- package/dist/wallet/tx/identity-selector.d.ts +12 -0
- package/dist/wallet/tx/identity-selector.js +52 -0
- package/dist/wallet/tx/index.d.ts +7 -0
- package/dist/wallet/tx/index.js +7 -0
- package/dist/wallet/tx/journal.d.ts +5 -0
- package/dist/wallet/tx/journal.js +31 -0
- package/dist/wallet/tx/register.d.ts +68 -0
- package/dist/wallet/tx/register.js +952 -0
- package/dist/wallet/tx/reputation.d.ts +72 -0
- package/dist/wallet/tx/reputation.js +693 -0
- package/dist/wallet/tx/targets.d.ts +7 -0
- package/dist/wallet/tx/targets.js +122 -0
- package/dist/wallet/types.d.ts +249 -0
- package/dist/wallet/types.js +1 -0
- package/dist/writing_quotes.json +1654 -0
- package/package.json +78 -0
|
@@ -0,0 +1,637 @@
|
|
|
1
|
+
import { findDomainField, findWalletDomain, formatFieldFormat, listDomainFields, listWalletLocks, } from "../wallet/read/index.js";
|
|
2
|
+
import { formatMiningSummaryLine } from "./mining-format.js";
|
|
3
|
+
import { getBootstrapSyncNextStep } from "./workflow-hints.js";
|
|
4
|
+
function formatCogAmount(value) {
|
|
5
|
+
const sign = value < 0n ? "-" : "";
|
|
6
|
+
const absolute = value < 0n ? -value : value;
|
|
7
|
+
const whole = absolute / 100000000n;
|
|
8
|
+
const fraction = absolute % 100000000n;
|
|
9
|
+
return `${sign}${whole.toString()}.${fraction.toString().padStart(8, "0")} COG`;
|
|
10
|
+
}
|
|
11
|
+
function formatServiceHealth(health) {
|
|
12
|
+
return health.replaceAll("-", " ");
|
|
13
|
+
}
|
|
14
|
+
function formatMaybe(value) {
|
|
15
|
+
return value === null ? "unavailable" : String(value);
|
|
16
|
+
}
|
|
17
|
+
function formatIndexerTruthSource(source) {
|
|
18
|
+
switch (source) {
|
|
19
|
+
case "lease":
|
|
20
|
+
return "coherent snapshot lease";
|
|
21
|
+
case "probe":
|
|
22
|
+
return "live daemon probe";
|
|
23
|
+
case "status-file":
|
|
24
|
+
return "advisory status file";
|
|
25
|
+
default:
|
|
26
|
+
return "none";
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function formatUnlockExpiry(unlockUntilUnixMs) {
|
|
30
|
+
if (unlockUntilUnixMs === null) {
|
|
31
|
+
return "locked";
|
|
32
|
+
}
|
|
33
|
+
return `unlocked until ${new Date(unlockUntilUnixMs).toISOString()}`;
|
|
34
|
+
}
|
|
35
|
+
function isReputationMutation(mutation) {
|
|
36
|
+
return (mutation.kind === "rep-give" || mutation.kind === "rep-revoke")
|
|
37
|
+
&& mutation.recipientDomainName !== undefined
|
|
38
|
+
&& mutation.recipientDomainName !== null;
|
|
39
|
+
}
|
|
40
|
+
function formatPendingMutationKind(mutation) {
|
|
41
|
+
if (mutation.kind === "sell" && mutation.priceCogtoshi === 0n) {
|
|
42
|
+
return "unsell";
|
|
43
|
+
}
|
|
44
|
+
if (mutation.kind === "claim" && mutation.preimageHex === "0000000000000000000000000000000000000000000000000000000000000000") {
|
|
45
|
+
return "reclaim";
|
|
46
|
+
}
|
|
47
|
+
if (mutation.kind === "endpoint" && mutation.endpointValueHex === "") {
|
|
48
|
+
return "endpoint-clear";
|
|
49
|
+
}
|
|
50
|
+
if (mutation.kind === "delegate" && mutation.recipientScriptPubKeyHex === null) {
|
|
51
|
+
return "delegate-clear";
|
|
52
|
+
}
|
|
53
|
+
if (mutation.kind === "miner" && mutation.recipientScriptPubKeyHex === null) {
|
|
54
|
+
return "miner-clear";
|
|
55
|
+
}
|
|
56
|
+
return mutation.kind;
|
|
57
|
+
}
|
|
58
|
+
function formatPendingMutationSummaryLabel(mutation) {
|
|
59
|
+
if (isReputationMutation(mutation)) {
|
|
60
|
+
return `${formatPendingMutationKind(mutation)} ${mutation.domainName}->${mutation.recipientDomainName}`;
|
|
61
|
+
}
|
|
62
|
+
return `${formatPendingMutationKind(mutation)}${mutation.domainName === "" ? "" : ` ${mutation.domainName}`}${mutation.fieldName == null ? "" : `.${mutation.fieldName}`}`;
|
|
63
|
+
}
|
|
64
|
+
function formatPendingMutationDomainLabel(mutation) {
|
|
65
|
+
if (isReputationMutation(mutation)) {
|
|
66
|
+
return `${formatPendingMutationKind(mutation)} ${mutation.domainName}->${mutation.recipientDomainName}`;
|
|
67
|
+
}
|
|
68
|
+
const kind = mutation.kind === "endpoint" && mutation.endpointValueHex === ""
|
|
69
|
+
? "endpoint-clear"
|
|
70
|
+
: mutation.kind === "delegate" && mutation.recipientScriptPubKeyHex === null
|
|
71
|
+
? "delegate-clear"
|
|
72
|
+
: mutation.kind === "miner" && mutation.recipientScriptPubKeyHex === null
|
|
73
|
+
? "miner-clear"
|
|
74
|
+
: formatPendingMutationKind(mutation);
|
|
75
|
+
return kind;
|
|
76
|
+
}
|
|
77
|
+
export function getRepairRecommendation(context) {
|
|
78
|
+
if (context.localState.availability === "local-state-corrupt") {
|
|
79
|
+
return "Run `cogcoin repair` to recover local wallet state.";
|
|
80
|
+
}
|
|
81
|
+
if (context.bitcoind.health === "service-version-mismatch"
|
|
82
|
+
|| context.bitcoind.health === "wallet-root-mismatch"
|
|
83
|
+
|| context.bitcoind.health === "runtime-mismatch"
|
|
84
|
+
|| context.bitcoind.health === "replica-missing"
|
|
85
|
+
|| context.bitcoind.health === "replica-mismatch"
|
|
86
|
+
|| context.bitcoind.health === "failed") {
|
|
87
|
+
return "Run `cogcoin repair` to recover the managed bitcoind service and Core wallet replica.";
|
|
88
|
+
}
|
|
89
|
+
if (context.indexer.health === "failed"
|
|
90
|
+
|| context.indexer.health === "schema-mismatch"
|
|
91
|
+
|| context.indexer.health === "service-version-mismatch"
|
|
92
|
+
|| context.indexer.health === "wallet-root-mismatch") {
|
|
93
|
+
return "Run `cogcoin repair` to recover the managed indexer daemon and local indexer artifacts.";
|
|
94
|
+
}
|
|
95
|
+
if (context.localState.state?.miningState.state === "repair-required"
|
|
96
|
+
|| context.localState.state?.proactiveFamilies.some((family) => family.status === "repair-required")
|
|
97
|
+
|| context.localState.state?.domains.some((domain) => domain.localAnchorIntent === "repair-required")
|
|
98
|
+
|| (context.localState.state?.pendingMutations ?? []).some((mutation) => mutation.status === "repair-required")) {
|
|
99
|
+
return "Run `cogcoin repair` before relying on local wallet state.";
|
|
100
|
+
}
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
export function getMutationRecommendation(context) {
|
|
104
|
+
const unresolvedFamily = (context.localState.state?.proactiveFamilies ?? []).find((family) => (family.type === "anchor" || family.type === "field")
|
|
105
|
+
&& (family.status === "broadcast-unknown" || family.status === "repair-required"));
|
|
106
|
+
if (unresolvedFamily !== undefined) {
|
|
107
|
+
if (unresolvedFamily.status === "repair-required") {
|
|
108
|
+
return unresolvedFamily.type === "field"
|
|
109
|
+
? "Run `cogcoin repair` before starting another field family."
|
|
110
|
+
: "Run `cogcoin repair` before starting another anchor family.";
|
|
111
|
+
}
|
|
112
|
+
return unresolvedFamily.type === "field"
|
|
113
|
+
? `Rerun \`cogcoin field create ${unresolvedFamily.domainName} ${unresolvedFamily.fieldName} ...\` to reconcile the pending field family, or run \`cogcoin repair\` if it remains unresolved.`
|
|
114
|
+
: `Rerun \`cogcoin anchor ${unresolvedFamily.domainName}\` to reconcile the pending anchor family, or run \`cogcoin repair\` if it remains unresolved.`;
|
|
115
|
+
}
|
|
116
|
+
const pendingMutations = context.localState.state?.pendingMutations ?? [];
|
|
117
|
+
const unresolved = pendingMutations.find((mutation) => mutation.status === "broadcast-unknown" || mutation.status === "repair-required");
|
|
118
|
+
if (unresolved === undefined) {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
if (unresolved.status === "repair-required") {
|
|
122
|
+
return "Run `cogcoin repair` before starting another mutation.";
|
|
123
|
+
}
|
|
124
|
+
if (unresolved.kind === "register") {
|
|
125
|
+
return `Rerun \`cogcoin register ${unresolved.domainName}\` to reconcile the pending registration, or run \`cogcoin repair\` if it remains unresolved.`;
|
|
126
|
+
}
|
|
127
|
+
if (unresolved.kind === "transfer") {
|
|
128
|
+
return `Rerun \`cogcoin transfer ${unresolved.domainName}\` with the same target to reconcile the pending transfer, or run \`cogcoin repair\` if it remains unresolved.`;
|
|
129
|
+
}
|
|
130
|
+
if (unresolved.kind === "sell") {
|
|
131
|
+
const command = unresolved.priceCogtoshi === 0n ? "unsell" : "sell";
|
|
132
|
+
return `Rerun \`cogcoin ${command} ${unresolved.domainName}\` to reconcile the pending listing change, or run \`cogcoin repair\` if it remains unresolved.`;
|
|
133
|
+
}
|
|
134
|
+
if (unresolved.kind === "buy") {
|
|
135
|
+
return `Rerun \`cogcoin buy ${unresolved.domainName}\` to reconcile the pending purchase, or run \`cogcoin repair\` if it remains unresolved.`;
|
|
136
|
+
}
|
|
137
|
+
if (unresolved.kind === "endpoint") {
|
|
138
|
+
return unresolved.endpointValueHex === ""
|
|
139
|
+
? `Rerun \`cogcoin domain endpoint clear ${unresolved.domainName}\` to reconcile the pending endpoint clear, or run \`cogcoin repair\` if it remains unresolved.`
|
|
140
|
+
: `Rerun \`cogcoin domain endpoint set ${unresolved.domainName} ...\` to reconcile the pending endpoint update, or run \`cogcoin repair\` if it remains unresolved.`;
|
|
141
|
+
}
|
|
142
|
+
if (unresolved.kind === "delegate") {
|
|
143
|
+
return unresolved.recipientScriptPubKeyHex === null
|
|
144
|
+
? `Rerun \`cogcoin domain delegate clear ${unresolved.domainName}\` to reconcile the pending delegate clear, or run \`cogcoin repair\` if it remains unresolved.`
|
|
145
|
+
: `Rerun \`cogcoin domain delegate set ${unresolved.domainName} ...\` to reconcile the pending delegate update, or run \`cogcoin repair\` if it remains unresolved.`;
|
|
146
|
+
}
|
|
147
|
+
if (unresolved.kind === "miner") {
|
|
148
|
+
return unresolved.recipientScriptPubKeyHex === null
|
|
149
|
+
? `Rerun \`cogcoin domain miner clear ${unresolved.domainName}\` to reconcile the pending miner clear, or run \`cogcoin repair\` if it remains unresolved.`
|
|
150
|
+
: `Rerun \`cogcoin domain miner set ${unresolved.domainName} ...\` to reconcile the pending miner update, or run \`cogcoin repair\` if it remains unresolved.`;
|
|
151
|
+
}
|
|
152
|
+
if (unresolved.kind === "canonical") {
|
|
153
|
+
return `Rerun \`cogcoin domain canonical ${unresolved.domainName}\` to reconcile the pending canonical update, or run \`cogcoin repair\` if it remains unresolved.`;
|
|
154
|
+
}
|
|
155
|
+
if (unresolved.kind === "field-create") {
|
|
156
|
+
return `Rerun \`cogcoin field create ${unresolved.domainName} ${unresolved.fieldName} ...\` to reconcile the pending field creation, or run \`cogcoin repair\` if it remains unresolved.`;
|
|
157
|
+
}
|
|
158
|
+
if (unresolved.kind === "field-set") {
|
|
159
|
+
return `Rerun \`cogcoin field set ${unresolved.domainName} ${unresolved.fieldName} ...\` to reconcile the pending field update, or run \`cogcoin repair\` if it remains unresolved.`;
|
|
160
|
+
}
|
|
161
|
+
if (unresolved.kind === "field-clear") {
|
|
162
|
+
return `Rerun \`cogcoin field clear ${unresolved.domainName} ${unresolved.fieldName}\` to reconcile the pending field clear, or run \`cogcoin repair\` if it remains unresolved.`;
|
|
163
|
+
}
|
|
164
|
+
if (unresolved.kind === "rep-give") {
|
|
165
|
+
return `Rerun \`cogcoin rep give ${unresolved.domainName} ${unresolved.recipientDomainName ?? "..."} ...\` to reconcile the pending reputation support, or run \`cogcoin repair\` if it remains unresolved.`;
|
|
166
|
+
}
|
|
167
|
+
if (unresolved.kind === "rep-revoke") {
|
|
168
|
+
return `Rerun \`cogcoin rep revoke ${unresolved.domainName} ${unresolved.recipientDomainName ?? "..."} ...\` to reconcile the pending reputation revoke, or run \`cogcoin repair\` if it remains unresolved.`;
|
|
169
|
+
}
|
|
170
|
+
if (unresolved.kind === "send") {
|
|
171
|
+
return "Rerun the same `cogcoin send ...` command to reconcile the pending transfer, or run `cogcoin repair` if it remains unresolved.";
|
|
172
|
+
}
|
|
173
|
+
if (unresolved.kind === "lock") {
|
|
174
|
+
return "Rerun the same `cogcoin cog lock ...` command to reconcile the pending lock, or run `cogcoin repair` if it remains unresolved.";
|
|
175
|
+
}
|
|
176
|
+
return unresolved.preimageHex === "0000000000000000000000000000000000000000000000000000000000000000"
|
|
177
|
+
? "Rerun the same `cogcoin reclaim ...` command to reconcile the pending reclaim, or run `cogcoin repair` if it remains unresolved."
|
|
178
|
+
: "Rerun the same `cogcoin claim ...` command to reconcile the pending claim, or run `cogcoin repair` if it remains unresolved.";
|
|
179
|
+
}
|
|
180
|
+
function appendPendingMutationSummary(lines, context) {
|
|
181
|
+
const pendingFamilies = (context.localState.state?.proactiveFamilies ?? [])
|
|
182
|
+
.filter((family) => (family.type === "anchor" || family.type === "field")
|
|
183
|
+
&& family.status !== "confirmed"
|
|
184
|
+
&& family.status !== "canceled");
|
|
185
|
+
const pendingMutations = (context.localState.state?.pendingMutations ?? [])
|
|
186
|
+
.filter((mutation) => mutation.status !== "confirmed" && mutation.status !== "canceled");
|
|
187
|
+
if (pendingFamilies.length === 0 && pendingMutations.length === 0) {
|
|
188
|
+
lines.push("Pending mutations: none");
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
for (const family of pendingFamilies) {
|
|
192
|
+
const label = family.type === "field"
|
|
193
|
+
? `Pending field family: ${family.domainName ?? "unknown"}.${family.fieldName ?? "unknown"}`
|
|
194
|
+
: `Pending anchor family: ${family.domainName ?? "unknown"}`;
|
|
195
|
+
lines.push(`${label} ${family.status}${family.currentStep === null || family.currentStep === undefined ? "" : ` step ${family.currentStep}`}${family.reservedDedicatedIndex == null ? "" : ` index ${family.reservedDedicatedIndex}`}`);
|
|
196
|
+
}
|
|
197
|
+
for (const mutation of pendingMutations) {
|
|
198
|
+
lines.push(`Pending mutation: ${formatPendingMutationSummaryLabel(mutation)} ${mutation.status} sender spk:${mutation.senderScriptPubKeyHex}${mutation.priceCogtoshi === undefined || mutation.priceCogtoshi === null ? "" : ` price ${formatCogAmount(mutation.priceCogtoshi)}`}${mutation.amountCogtoshi === undefined || mutation.amountCogtoshi === null ? "" : ` amount ${formatCogAmount(mutation.amountCogtoshi)}`}${isReputationMutation(mutation) ? "" : mutation.recipientDomainName === undefined || mutation.recipientDomainName === null ? "" : ` domain ${mutation.recipientDomainName}`}${mutation.lockId === undefined || mutation.lockId === null ? "" : ` lock ${mutation.lockId}`}${mutation.recipientScriptPubKeyHex === undefined || mutation.recipientScriptPubKeyHex === null ? "" : ` recipient spk:${mutation.recipientScriptPubKeyHex}`}${mutation.kind === "endpoint" ? (mutation.endpointValueHex === "" ? " endpoint clear" : ` endpoint-bytes ${(mutation.endpointValueHex?.length ?? 0) / 2}`) : ""}${mutation.kind === "field-create" || mutation.kind === "field-set" ? ` format ${formatFieldFormat(mutation.fieldFormat ?? 0)}` : ""}${mutation.kind === "field-clear" ? " clear" : ""}${mutation.reviewPayloadHex === undefined || mutation.reviewPayloadHex === null ? "" : " review"}`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
function listPendingDomainMutations(context, domainName) {
|
|
202
|
+
return (context.localState.state?.pendingMutations ?? [])
|
|
203
|
+
.filter((mutation) => (mutation.kind === "register"
|
|
204
|
+
|| mutation.kind === "transfer"
|
|
205
|
+
|| mutation.kind === "sell"
|
|
206
|
+
|| mutation.kind === "buy"
|
|
207
|
+
|| mutation.kind === "endpoint"
|
|
208
|
+
|| mutation.kind === "delegate"
|
|
209
|
+
|| mutation.kind === "miner"
|
|
210
|
+
|| mutation.kind === "canonical"
|
|
211
|
+
|| mutation.kind === "field-create"
|
|
212
|
+
|| mutation.kind === "field-set"
|
|
213
|
+
|| mutation.kind === "field-clear")
|
|
214
|
+
&& mutation.domainName === domainName
|
|
215
|
+
&& mutation.status !== "confirmed"
|
|
216
|
+
&& mutation.status !== "canceled");
|
|
217
|
+
}
|
|
218
|
+
function listPendingAnchorFamilies(context, domainName) {
|
|
219
|
+
return (context.localState.state?.proactiveFamilies ?? [])
|
|
220
|
+
.filter((family) => family.type === "anchor"
|
|
221
|
+
&& family.domainName === domainName
|
|
222
|
+
&& family.status !== "confirmed"
|
|
223
|
+
&& family.status !== "canceled");
|
|
224
|
+
}
|
|
225
|
+
function listPendingFieldFamilies(context, domainName) {
|
|
226
|
+
return (context.localState.state?.proactiveFamilies ?? [])
|
|
227
|
+
.filter((family) => family.type === "field"
|
|
228
|
+
&& family.domainName === domainName
|
|
229
|
+
&& family.status !== "confirmed"
|
|
230
|
+
&& family.status !== "canceled");
|
|
231
|
+
}
|
|
232
|
+
function listPendingDomainShowMutations(context, domainName) {
|
|
233
|
+
return (context.localState.state?.pendingMutations ?? [])
|
|
234
|
+
.filter((mutation) => (mutation.kind === "register"
|
|
235
|
+
|| mutation.kind === "transfer"
|
|
236
|
+
|| mutation.kind === "sell"
|
|
237
|
+
|| mutation.kind === "buy"
|
|
238
|
+
|| mutation.kind === "endpoint"
|
|
239
|
+
|| mutation.kind === "delegate"
|
|
240
|
+
|| mutation.kind === "miner"
|
|
241
|
+
|| mutation.kind === "canonical"
|
|
242
|
+
|| mutation.kind === "field-create"
|
|
243
|
+
|| mutation.kind === "field-set"
|
|
244
|
+
|| mutation.kind === "field-clear"
|
|
245
|
+
|| mutation.kind === "rep-give"
|
|
246
|
+
|| mutation.kind === "rep-revoke")
|
|
247
|
+
&& (mutation.domainName === domainName || mutation.recipientDomainName === domainName)
|
|
248
|
+
&& mutation.status !== "confirmed"
|
|
249
|
+
&& mutation.status !== "canceled");
|
|
250
|
+
}
|
|
251
|
+
function listPendingFieldMutations(context, domainName, fieldName) {
|
|
252
|
+
return (context.localState.state?.pendingMutations ?? [])
|
|
253
|
+
.filter((mutation) => (mutation.kind === "field-create" || mutation.kind === "field-set" || mutation.kind === "field-clear")
|
|
254
|
+
&& mutation.domainName === domainName
|
|
255
|
+
&& (fieldName === undefined || mutation.fieldName === fieldName)
|
|
256
|
+
&& mutation.status !== "confirmed"
|
|
257
|
+
&& mutation.status !== "canceled");
|
|
258
|
+
}
|
|
259
|
+
function appendServiceSummary(lines, context) {
|
|
260
|
+
lines.push(`Managed bitcoind: ${formatServiceHealth(context.bitcoind.health)}`);
|
|
261
|
+
if (context.bitcoind.message !== null) {
|
|
262
|
+
lines.push(`Managed bitcoind note: ${context.bitcoind.message}`);
|
|
263
|
+
}
|
|
264
|
+
lines.push(`Bitcoin service: ${formatServiceHealth(context.nodeHealth)}`);
|
|
265
|
+
if (context.nodeStatus !== null) {
|
|
266
|
+
lines.push(`Bitcoin best height: ${formatMaybe(context.nodeStatus.nodeBestHeight)}`);
|
|
267
|
+
lines.push(`Bitcoin headers: ${formatMaybe(context.nodeStatus.nodeHeaderHeight)}`);
|
|
268
|
+
}
|
|
269
|
+
if (context.nodeMessage !== null) {
|
|
270
|
+
lines.push(`Bitcoin note: ${context.nodeMessage}`);
|
|
271
|
+
}
|
|
272
|
+
lines.push(`Indexer service: ${formatServiceHealth(context.indexer.health)}`);
|
|
273
|
+
lines.push(`Indexer truth source: ${formatIndexerTruthSource(context.indexer.source)}`);
|
|
274
|
+
if (context.indexer.daemonInstanceId !== null) {
|
|
275
|
+
lines.push(`Indexer daemon instance: ${context.indexer.daemonInstanceId}`);
|
|
276
|
+
}
|
|
277
|
+
if (context.indexer.snapshotSeq !== null) {
|
|
278
|
+
lines.push(`Indexer snapshot sequence: ${context.indexer.snapshotSeq}`);
|
|
279
|
+
}
|
|
280
|
+
if (context.indexer.status?.reorgDepth !== null && context.indexer.status?.reorgDepth !== undefined) {
|
|
281
|
+
lines.push(`Indexer reorg depth: ${context.indexer.status.reorgDepth}`);
|
|
282
|
+
}
|
|
283
|
+
if (context.indexer.snapshotTip !== null) {
|
|
284
|
+
lines.push(`Indexer tip height: ${context.indexer.snapshotTip.height}`);
|
|
285
|
+
}
|
|
286
|
+
else {
|
|
287
|
+
lines.push("Indexer tip height: unavailable");
|
|
288
|
+
}
|
|
289
|
+
if (context.indexer.message !== null) {
|
|
290
|
+
lines.push(`Indexer note: ${context.indexer.message}`);
|
|
291
|
+
}
|
|
292
|
+
if (context.mining !== undefined) {
|
|
293
|
+
lines.push(`Mining: ${formatMiningSummaryLine(context.mining)}`);
|
|
294
|
+
if (context.mining.runtime.note !== null) {
|
|
295
|
+
lines.push(`Mining note: ${context.mining.runtime.note}`);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
function appendWalletAvailability(lines, context) {
|
|
300
|
+
lines.push(`Wallet state: ${context.localState.availability}`);
|
|
301
|
+
lines.push(`Wallet root: ${context.model?.walletRootId ?? context.localState.walletRootId ?? context.nodeStatus?.walletRootId ?? "none"}`);
|
|
302
|
+
lines.push(`Wallet unlock: ${formatUnlockExpiry(context.localState.unlockUntilUnixMs)}`);
|
|
303
|
+
if (context.localState.message !== null) {
|
|
304
|
+
lines.push(`Wallet note: ${context.localState.message}`);
|
|
305
|
+
}
|
|
306
|
+
const nodeStatus = context.nodeStatus;
|
|
307
|
+
const replica = nodeStatus?.walletReplica ?? null;
|
|
308
|
+
if (replica !== null) {
|
|
309
|
+
lines.push(`Managed Core wallet: ${replica.proofStatus ?? "not-proven"}`);
|
|
310
|
+
}
|
|
311
|
+
if (nodeStatus?.walletReplicaMessage) {
|
|
312
|
+
lines.push(`Managed Core note: ${nodeStatus.walletReplicaMessage}`);
|
|
313
|
+
}
|
|
314
|
+
const repairRecommendation = getRepairRecommendation(context);
|
|
315
|
+
if (repairRecommendation !== null) {
|
|
316
|
+
lines.push(`Recommended next step: ${repairRecommendation}`);
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
const bootstrapSync = getBootstrapSyncNextStep(context);
|
|
320
|
+
if (bootstrapSync !== null) {
|
|
321
|
+
lines.push("Recommended next step: Run `cogcoin sync` to bootstrap assumeutxo and the managed Bitcoin/indexer state.");
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
const mutationRecommendation = getMutationRecommendation(context);
|
|
325
|
+
if (mutationRecommendation !== null) {
|
|
326
|
+
lines.push(`Mutation note: ${mutationRecommendation}`);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
export function formatWalletOverviewReport(context) {
|
|
330
|
+
const lines = [
|
|
331
|
+
"Cogcoin Status",
|
|
332
|
+
`DB path: ${context.databasePath}`,
|
|
333
|
+
`Bitcoin datadir: ${context.dataDir}`,
|
|
334
|
+
];
|
|
335
|
+
appendWalletAvailability(lines, context);
|
|
336
|
+
appendServiceSummary(lines, context);
|
|
337
|
+
if (context.model !== null) {
|
|
338
|
+
lines.push(`Local identities: ${context.model.identities.length}`);
|
|
339
|
+
lines.push(`Locally related domains: ${context.model.domains.length}`);
|
|
340
|
+
lines.push(`Read-only identities: ${context.model.readOnlyIdentityCount}`);
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
lines.push("Wallet-derived sections: unavailable");
|
|
344
|
+
}
|
|
345
|
+
appendPendingMutationSummary(lines, context);
|
|
346
|
+
return lines.join("\n");
|
|
347
|
+
}
|
|
348
|
+
export function formatDetailedWalletStatusReport(context) {
|
|
349
|
+
const lines = ["Cogcoin Wallet Status"];
|
|
350
|
+
appendWalletAvailability(lines, context);
|
|
351
|
+
appendServiceSummary(lines, context);
|
|
352
|
+
if (context.model === null) {
|
|
353
|
+
lines.push("Wallet details are unavailable until the encrypted wallet state can be read.");
|
|
354
|
+
return lines.join("\n");
|
|
355
|
+
}
|
|
356
|
+
lines.push(`Funding identity: ${context.model.fundingIdentity?.selectors[0] ?? "unavailable"}`);
|
|
357
|
+
lines.push(`Funding address: ${context.model.fundingIdentity?.address ?? "unavailable"}`);
|
|
358
|
+
lines.push(`Controlled identities: ${context.model.identities.length}`);
|
|
359
|
+
lines.push(`Locally related domains: ${context.model.domains.length}`);
|
|
360
|
+
lines.push(`Read-only identities: ${context.model.readOnlyIdentityCount}`);
|
|
361
|
+
appendPendingMutationSummary(lines, context);
|
|
362
|
+
return lines.join("\n");
|
|
363
|
+
}
|
|
364
|
+
export function formatFundingAddressReport(context) {
|
|
365
|
+
const lines = ["BTC Funding Address"];
|
|
366
|
+
if (context.model?.fundingIdentity === null || context.model === null) {
|
|
367
|
+
appendWalletAvailability(lines, context);
|
|
368
|
+
return lines.join("\n");
|
|
369
|
+
}
|
|
370
|
+
lines.push(`Selector: ${context.model.fundingIdentity.selectors[0]}`);
|
|
371
|
+
lines.push(`Address: ${context.model.fundingIdentity.address ?? "unavailable"}`);
|
|
372
|
+
lines.push(`ScriptPubKey: spk:${context.model.fundingIdentity.scriptPubKeyHex}`);
|
|
373
|
+
return lines.join("\n");
|
|
374
|
+
}
|
|
375
|
+
export function formatIdentityListReport(context, options = {}) {
|
|
376
|
+
const lines = ["Wallet Identities"];
|
|
377
|
+
if (context.model === null) {
|
|
378
|
+
appendWalletAvailability(lines, context);
|
|
379
|
+
return lines.join("\n");
|
|
380
|
+
}
|
|
381
|
+
const identities = context.model.identities;
|
|
382
|
+
if (identities.length === 0) {
|
|
383
|
+
lines.push("No local identities are recorded yet.");
|
|
384
|
+
return lines.join("\n");
|
|
385
|
+
}
|
|
386
|
+
const limit = options.all ? null : options.limit ?? null;
|
|
387
|
+
const renderedIdentities = limit === null ? identities : identities.slice(0, limit);
|
|
388
|
+
for (const identity of renderedIdentities) {
|
|
389
|
+
const domains = identity.ownedDomainNames.length === 0 ? "none" : identity.ownedDomainNames.join(", ");
|
|
390
|
+
const balance = identity.observedCogBalance === null ? "unavailable" : formatCogAmount(identity.observedCogBalance);
|
|
391
|
+
lines.push(`${identity.selectors[0]} ${identity.effectiveStatus} ${identity.address ?? `spk:${identity.scriptPubKeyHex}`} balance ${balance} domains ${domains} selectors ${identity.selectors.join(", ")}`);
|
|
392
|
+
}
|
|
393
|
+
if (limit !== null && identities.length > limit) {
|
|
394
|
+
lines.push(`Showing first ${renderedIdentities.length} of ${identities.length}. Use --limit <n> or --all for more.`);
|
|
395
|
+
}
|
|
396
|
+
return lines.join("\n");
|
|
397
|
+
}
|
|
398
|
+
export function formatBalanceReport(context) {
|
|
399
|
+
const lines = ["COG Balance"];
|
|
400
|
+
if (context.model === null) {
|
|
401
|
+
appendWalletAvailability(lines, context);
|
|
402
|
+
return lines.join("\n");
|
|
403
|
+
}
|
|
404
|
+
if (context.snapshot === null) {
|
|
405
|
+
lines.push(`Indexer-backed balances are unavailable while the indexer is ${formatServiceHealth(context.indexer.health)}.`);
|
|
406
|
+
return lines.join("\n");
|
|
407
|
+
}
|
|
408
|
+
const spendableTotal = context.model.identities.reduce((sum, identity) => identity.readOnly || identity.observedCogBalance === null
|
|
409
|
+
? sum
|
|
410
|
+
: sum + identity.observedCogBalance, 0n);
|
|
411
|
+
lines.push(`Spendable total: ${formatCogAmount(spendableTotal)}`);
|
|
412
|
+
for (const identity of context.model.identities) {
|
|
413
|
+
lines.push(`${identity.selectors[0]} ${identity.address ?? `spk:${identity.scriptPubKeyHex}`} ${formatCogAmount(identity.observedCogBalance ?? 0n)}${identity.readOnly ? " read-only" : ""}`);
|
|
414
|
+
}
|
|
415
|
+
for (const mutation of (context.localState.state?.pendingMutations ?? [])
|
|
416
|
+
.filter((entry) => (entry.kind === "send" || entry.kind === "lock" || entry.kind === "claim")
|
|
417
|
+
&& entry.status !== "confirmed"
|
|
418
|
+
&& entry.status !== "canceled")) {
|
|
419
|
+
const label = mutation.kind === "claim" && mutation.preimageHex === "0000000000000000000000000000000000000000000000000000000000000000"
|
|
420
|
+
? "reclaim"
|
|
421
|
+
: mutation.kind;
|
|
422
|
+
lines.push(`Pending: ${label} ${mutation.status}${mutation.amountCogtoshi === null || mutation.amountCogtoshi === undefined ? "" : ` ${formatCogAmount(mutation.amountCogtoshi)}`}`);
|
|
423
|
+
}
|
|
424
|
+
return lines.join("\n");
|
|
425
|
+
}
|
|
426
|
+
export function formatLocksReport(context, options = {}) {
|
|
427
|
+
const lines = ["COG Locks"];
|
|
428
|
+
if (context.model === null) {
|
|
429
|
+
appendWalletAvailability(lines, context);
|
|
430
|
+
return lines.join("\n");
|
|
431
|
+
}
|
|
432
|
+
const locks = listWalletLocks(context);
|
|
433
|
+
if (locks === null) {
|
|
434
|
+
lines.push(`Lock state is unavailable while the indexer is ${formatServiceHealth(context.indexer.health)}.`);
|
|
435
|
+
return lines.join("\n");
|
|
436
|
+
}
|
|
437
|
+
let filteredLocks = locks;
|
|
438
|
+
if (options.claimableOnly) {
|
|
439
|
+
filteredLocks = filteredLocks.filter((lock) => lock.claimableNow);
|
|
440
|
+
}
|
|
441
|
+
else if (options.reclaimableOnly) {
|
|
442
|
+
filteredLocks = filteredLocks.filter((lock) => lock.reclaimableNow);
|
|
443
|
+
}
|
|
444
|
+
const totalMatching = filteredLocks.length;
|
|
445
|
+
if (!options.all && options.limit !== null && options.limit !== undefined) {
|
|
446
|
+
filteredLocks = filteredLocks.slice(0, options.limit);
|
|
447
|
+
}
|
|
448
|
+
if (filteredLocks.length === 0) {
|
|
449
|
+
lines.push("No locally related active locks.");
|
|
450
|
+
return lines.join("\n");
|
|
451
|
+
}
|
|
452
|
+
for (const lock of filteredLocks) {
|
|
453
|
+
const role = lock.lockerLocalIndex !== null ? `locker ${lock.lockerLocalIndex}` : "recipient";
|
|
454
|
+
const action = lock.claimableNow
|
|
455
|
+
? "claimable-now"
|
|
456
|
+
: lock.reclaimableNow
|
|
457
|
+
? "reclaimable-now"
|
|
458
|
+
: "not-actionable-now";
|
|
459
|
+
lines.push(`lock:${lock.lockId} ${formatCogAmount(lock.amountCogtoshi)} timeout ${lock.timeoutHeight} domain ${lock.recipientDomainName ?? lock.recipientDomainId} ${role} ${action}`);
|
|
460
|
+
}
|
|
461
|
+
for (const mutation of (context.localState.state?.pendingMutations ?? [])
|
|
462
|
+
.filter((entry) => (entry.kind === "lock" || entry.kind === "claim")
|
|
463
|
+
&& entry.status !== "confirmed"
|
|
464
|
+
&& entry.status !== "canceled")) {
|
|
465
|
+
const label = mutation.kind === "claim" && mutation.preimageHex === "0000000000000000000000000000000000000000000000000000000000000000"
|
|
466
|
+
? "reclaim"
|
|
467
|
+
: mutation.kind;
|
|
468
|
+
lines.push(`Pending: ${label} ${mutation.status}${mutation.lockId === null || mutation.lockId === undefined ? "" : ` lock:${mutation.lockId}`}${mutation.recipientDomainName === null || mutation.recipientDomainName === undefined ? "" : ` domain ${mutation.recipientDomainName}`}`);
|
|
469
|
+
}
|
|
470
|
+
if (!options.all && options.limit !== null && options.limit !== undefined && totalMatching > options.limit) {
|
|
471
|
+
lines.push(`Showing first ${filteredLocks.length} of ${totalMatching}. Use --limit <n> or --all for more.`);
|
|
472
|
+
}
|
|
473
|
+
return lines.join("\n");
|
|
474
|
+
}
|
|
475
|
+
export function formatDomainsReport(context, options = {}) {
|
|
476
|
+
const lines = ["Domains"];
|
|
477
|
+
if (context.model === null) {
|
|
478
|
+
appendWalletAvailability(lines, context);
|
|
479
|
+
return lines.join("\n");
|
|
480
|
+
}
|
|
481
|
+
const visibleDomains = options.domains ?? context.model.domains;
|
|
482
|
+
if (visibleDomains.length === 0) {
|
|
483
|
+
if ((options.activeFilters?.length ?? 0) > 0) {
|
|
484
|
+
lines.push(`No locally related domains matched the active filters (${options.activeFilters.join(", ")}).`);
|
|
485
|
+
return lines.join("\n");
|
|
486
|
+
}
|
|
487
|
+
lines.push("No locally related domains.");
|
|
488
|
+
return lines.join("\n");
|
|
489
|
+
}
|
|
490
|
+
const renderedDomains = options.all || options.limit === null || options.limit === undefined
|
|
491
|
+
? visibleDomains
|
|
492
|
+
: visibleDomains.slice(0, options.limit);
|
|
493
|
+
for (const domain of renderedDomains) {
|
|
494
|
+
const pending = listPendingDomainMutations(context, domain.name);
|
|
495
|
+
const pendingAnchors = listPendingAnchorFamilies(context, domain.name);
|
|
496
|
+
const pendingFieldFamilies = listPendingFieldFamilies(context, domain.name);
|
|
497
|
+
const pendingFieldMutations = listPendingFieldMutations(context, domain.name);
|
|
498
|
+
const pendingText = pending.length === 0
|
|
499
|
+
? ""
|
|
500
|
+
: ` pending ${pending.map((mutation) => mutation.kind === "sell" && mutation.priceCogtoshi === 0n
|
|
501
|
+
? `unsell:${mutation.status}`
|
|
502
|
+
: mutation.kind === "endpoint" && mutation.endpointValueHex === ""
|
|
503
|
+
? `endpoint-clear:${mutation.status}`
|
|
504
|
+
: mutation.kind === "delegate" && mutation.recipientScriptPubKeyHex === null
|
|
505
|
+
? `delegate-clear:${mutation.status}`
|
|
506
|
+
: mutation.kind === "miner" && mutation.recipientScriptPubKeyHex === null
|
|
507
|
+
? `miner-clear:${mutation.status}`
|
|
508
|
+
: `${mutation.kind}:${mutation.status}`).join(",")}`;
|
|
509
|
+
const pendingFieldsText = pendingFieldMutations.length === 0 && pendingFieldFamilies.length === 0
|
|
510
|
+
? ""
|
|
511
|
+
: ` field-pending ${[
|
|
512
|
+
...pendingFieldMutations.map((mutation) => `${mutation.fieldName}:${mutation.kind}:${mutation.status}`),
|
|
513
|
+
...pendingFieldFamilies.map((family) => `${family.fieldName}:family:${family.status}${family.currentStep == null ? "" : `:${family.currentStep}`}`),
|
|
514
|
+
].join(",")}`;
|
|
515
|
+
const anchorText = pendingAnchors.length === 0 && (domain.localAnchorIntent === null || domain.localAnchorIntent === "none")
|
|
516
|
+
? ""
|
|
517
|
+
: ` anchor ${(domain.localAnchorIntent === null || domain.localAnchorIntent === "none")
|
|
518
|
+
? pendingAnchors.map((family) => `${family.currentStep ?? "reserved"}:${family.status}`).join(",")
|
|
519
|
+
: domain.localAnchorIntent}`;
|
|
520
|
+
lines.push(`${domain.name} ${domain.chainStatus} ${domain.localRelationship} owner ${domain.ownerLocalIndex === null ? (domain.ownerAddress ?? domain.ownerScriptPubKeyHex ?? "unknown") : `id:${domain.ownerLocalIndex}`} fields ${formatMaybe(domain.fieldCount)}${domain.readOnly ? " read-only" : ""}${anchorText}${pendingText}${pendingFieldsText}`);
|
|
521
|
+
}
|
|
522
|
+
if (!options.all && options.limit !== null && options.limit !== undefined && visibleDomains.length > options.limit) {
|
|
523
|
+
lines.push(`Showing first ${renderedDomains.length} of ${visibleDomains.length}. Use --limit <n> or --all for more.`);
|
|
524
|
+
}
|
|
525
|
+
return lines.join("\n");
|
|
526
|
+
}
|
|
527
|
+
export function formatDomainReport(context, domainName) {
|
|
528
|
+
const lines = [`Domain: ${domainName}`];
|
|
529
|
+
if (context.snapshot === null && context.model?.domains.find((domain) => domain.name === domainName) === undefined) {
|
|
530
|
+
lines.push(`Domain state is unavailable while the indexer is ${formatServiceHealth(context.indexer.health)}.`);
|
|
531
|
+
return lines.join("\n");
|
|
532
|
+
}
|
|
533
|
+
const view = findWalletDomain(context, domainName);
|
|
534
|
+
if (view === null) {
|
|
535
|
+
lines.push("Domain not found.");
|
|
536
|
+
return lines.join("\n");
|
|
537
|
+
}
|
|
538
|
+
lines.push(`Domain ID: ${formatMaybe(view.domain.domainId)}`);
|
|
539
|
+
lines.push(`Anchored: ${view.domain.anchored === null ? "unknown" : (view.domain.anchored ? "yes" : "no")}`);
|
|
540
|
+
lines.push(`Owner: ${view.domain.ownerLocalIndex === null ? (view.domain.ownerAddress ?? view.domain.ownerScriptPubKeyHex ?? "unknown") : `id:${view.domain.ownerLocalIndex}`}`);
|
|
541
|
+
lines.push(`Local relationship: ${view.localRelationship}`);
|
|
542
|
+
lines.push(`Listing price: ${view.domain.listingPriceCogtoshi === null ? "none" : formatCogAmount(view.domain.listingPriceCogtoshi)}`);
|
|
543
|
+
lines.push(`Field count: ${formatMaybe(view.domain.fieldCount)}`);
|
|
544
|
+
if (view.domain.selfStakeCogtoshi !== null
|
|
545
|
+
|| view.domain.supportedStakeCogtoshi !== null
|
|
546
|
+
|| view.domain.totalSupportedCogtoshi !== null
|
|
547
|
+
|| view.domain.totalRevokedCogtoshi !== null) {
|
|
548
|
+
lines.push(`Reputation self-stake: ${view.domain.selfStakeCogtoshi === null ? "unavailable" : formatCogAmount(view.domain.selfStakeCogtoshi)}`);
|
|
549
|
+
lines.push(`Reputation supported stake: ${view.domain.supportedStakeCogtoshi === null ? "unavailable" : formatCogAmount(view.domain.supportedStakeCogtoshi)}`);
|
|
550
|
+
lines.push(`Reputation total supported: ${view.domain.totalSupportedCogtoshi === null ? "unavailable" : formatCogAmount(view.domain.totalSupportedCogtoshi)}`);
|
|
551
|
+
lines.push(`Reputation total revoked: ${view.domain.totalRevokedCogtoshi === null ? "unavailable" : formatCogAmount(view.domain.totalRevokedCogtoshi)}`);
|
|
552
|
+
}
|
|
553
|
+
lines.push(`Local anchor intent: ${view.domain.localAnchorIntent ?? "none"}`);
|
|
554
|
+
lines.push(`Delegate: ${view.domain.delegateScriptPubKeyHex ?? "none"}`);
|
|
555
|
+
lines.push(`Designated miner: ${view.domain.minerScriptPubKeyHex ?? "none"}`);
|
|
556
|
+
lines.push(`Endpoint: ${view.domain.endpointText ?? "none"}`);
|
|
557
|
+
lines.push(`Founding message: ${view.domain.foundingMessageText ?? "none"}`);
|
|
558
|
+
for (const family of listPendingAnchorFamilies(context, domainName)) {
|
|
559
|
+
lines.push(`Pending anchor family: ${family.status}${family.currentStep == null ? "" : ` step ${family.currentStep}`}${family.reservedDedicatedIndex == null ? "" : ` index ${family.reservedDedicatedIndex}`}`);
|
|
560
|
+
}
|
|
561
|
+
for (const family of listPendingFieldFamilies(context, domainName)) {
|
|
562
|
+
lines.push(`Pending field family: ${family.fieldName ?? "unknown"} ${family.status}${family.currentStep == null ? "" : ` step ${family.currentStep}`}`);
|
|
563
|
+
}
|
|
564
|
+
for (const mutation of listPendingDomainShowMutations(context, domainName)) {
|
|
565
|
+
lines.push(`Pending mutation: ${formatPendingMutationDomainLabel(mutation)} ${mutation.status}`);
|
|
566
|
+
}
|
|
567
|
+
for (const mutation of listPendingFieldMutations(context, domainName)) {
|
|
568
|
+
lines.push(`Pending field mutation: ${mutation.fieldName ?? "unknown"} ${mutation.kind} ${mutation.status}`);
|
|
569
|
+
}
|
|
570
|
+
return lines.join("\n");
|
|
571
|
+
}
|
|
572
|
+
function renderFieldLine(field) {
|
|
573
|
+
return `${field.name} id ${field.fieldId} ${field.permanent ? "permanent" : "mutable"} ${field.hasValue ? formatFieldFormat(field.format) : "empty"} ${field.preview ?? "(no value)"}`;
|
|
574
|
+
}
|
|
575
|
+
export function formatFieldsReport(context, domainName, options = {}) {
|
|
576
|
+
const lines = [`Fields: ${domainName}`];
|
|
577
|
+
if (context.snapshot === null) {
|
|
578
|
+
lines.push(`Field state is unavailable while the indexer is ${formatServiceHealth(context.indexer.health)}.`);
|
|
579
|
+
return lines.join("\n");
|
|
580
|
+
}
|
|
581
|
+
const fields = listDomainFields(context, domainName);
|
|
582
|
+
if (fields === null) {
|
|
583
|
+
lines.push("Domain not found.");
|
|
584
|
+
return lines.join("\n");
|
|
585
|
+
}
|
|
586
|
+
const renderedFields = options.all || options.limit === null || options.limit === undefined
|
|
587
|
+
? fields
|
|
588
|
+
: fields.slice(0, options.limit);
|
|
589
|
+
if (renderedFields.length === 0) {
|
|
590
|
+
lines.push("No fields found.");
|
|
591
|
+
}
|
|
592
|
+
else {
|
|
593
|
+
for (const field of renderedFields) {
|
|
594
|
+
lines.push(renderFieldLine(field));
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
for (const mutation of listPendingFieldMutations(context, domainName)) {
|
|
598
|
+
lines.push(`Pending field mutation: ${mutation.fieldName ?? "unknown"} ${mutation.kind} ${mutation.status}`);
|
|
599
|
+
}
|
|
600
|
+
for (const family of listPendingFieldFamilies(context, domainName)) {
|
|
601
|
+
lines.push(`Pending field family: ${family.fieldName ?? "unknown"} ${family.status}${family.currentStep == null ? "" : ` step ${family.currentStep}`}`);
|
|
602
|
+
}
|
|
603
|
+
if (!options.all && options.limit !== null && options.limit !== undefined && fields.length > options.limit) {
|
|
604
|
+
lines.push(`Showing first ${renderedFields.length} of ${fields.length}. Use --limit <n> or --all for more.`);
|
|
605
|
+
}
|
|
606
|
+
return lines.join("\n");
|
|
607
|
+
}
|
|
608
|
+
export function formatFieldReport(context, domainName, fieldName) {
|
|
609
|
+
const lines = [`Field: ${domainName}.${fieldName}`];
|
|
610
|
+
if (context.snapshot === null) {
|
|
611
|
+
lines.push(`Field state is unavailable while the indexer is ${formatServiceHealth(context.indexer.health)}.`);
|
|
612
|
+
return lines.join("\n");
|
|
613
|
+
}
|
|
614
|
+
const field = findDomainField(context, domainName, fieldName);
|
|
615
|
+
const pendingMutations = listPendingFieldMutations(context, domainName, fieldName);
|
|
616
|
+
const pendingFamilies = listPendingFieldFamilies(context, domainName)
|
|
617
|
+
.filter((family) => family.fieldName === fieldName);
|
|
618
|
+
if (field === null) {
|
|
619
|
+
lines.push("Field not found.");
|
|
620
|
+
}
|
|
621
|
+
else {
|
|
622
|
+
lines.push(`Domain ID: ${field.domainId}`);
|
|
623
|
+
lines.push(`Field ID: ${field.fieldId}`);
|
|
624
|
+
lines.push(`Permanent: ${field.permanent ? "yes" : "no"}`);
|
|
625
|
+
lines.push(`Has value: ${field.hasValue ? "yes" : "no"}`);
|
|
626
|
+
lines.push(`Format: ${formatFieldFormat(field.format)}`);
|
|
627
|
+
lines.push(`Preview: ${field.preview ?? "(no value)"}`);
|
|
628
|
+
lines.push(`Raw value hex: ${field.rawValueHex ?? "none"}`);
|
|
629
|
+
}
|
|
630
|
+
for (const mutation of pendingMutations) {
|
|
631
|
+
lines.push(`Pending field mutation: ${mutation.kind} ${mutation.status}`);
|
|
632
|
+
}
|
|
633
|
+
for (const family of pendingFamilies) {
|
|
634
|
+
lines.push(`Pending field family: ${family.status}${family.currentStep == null ? "" : ` step ${family.currentStep}`}`);
|
|
635
|
+
}
|
|
636
|
+
return lines.join("\n");
|
|
637
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { WalletIdentityView, WalletLockView, WalletReadContext } from "../wallet/read/index.js";
|
|
2
|
+
export declare function formatNextStepLines(nextSteps: readonly string[]): string[];
|
|
3
|
+
export declare function getFundingQuickstartGuidance(): string;
|
|
4
|
+
export declare function getInitNextSteps(): string[];
|
|
5
|
+
export declare function getBootstrapSyncNextStep(context: Pick<WalletReadContext, "bitcoind" | "indexer" | "nodeHealth">): string | null;
|
|
6
|
+
export declare function getRegisterNextSteps(domainName: string, registerKind: "root" | "subdomain"): string[];
|
|
7
|
+
export declare function getAnchorNextSteps(domainName: string): string[];
|
|
8
|
+
export declare function getHooksEnableMiningNextSteps(): string[];
|
|
9
|
+
export declare function getMineSetupNextSteps(): string[];
|
|
10
|
+
export declare function getMineStopNextSteps(): string[];
|
|
11
|
+
export declare function getAddressNextSteps(context: Pick<WalletReadContext, "bitcoind" | "indexer" | "nodeHealth">, address: string | null | undefined): string[];
|
|
12
|
+
export declare function getIdsNextSteps(identities: readonly WalletIdentityView[] | null | undefined): string[];
|
|
13
|
+
export declare function getLocksNextSteps(locks: readonly WalletLockView[] | null | undefined): string[];
|