@cogcoin/client 0.5.15 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +80 -25
- package/dist/app-paths.d.ts +5 -6
- package/dist/app-paths.js +8 -16
- package/dist/art/balance.txt +10 -0
- package/dist/art/welcome.txt +16 -0
- package/dist/bitcoind/bootstrap/controller.d.ts +1 -0
- package/dist/bitcoind/bootstrap/controller.js +53 -1
- package/dist/bitcoind/client/follow-block-times.d.ts +1 -0
- package/dist/bitcoind/client/follow-block-times.js +1 -1
- package/dist/bitcoind/client/internal-types.d.ts +7 -3
- package/dist/bitcoind/client/managed-client.d.ts +4 -2
- package/dist/bitcoind/client/managed-client.js +14 -0
- package/dist/bitcoind/client/sync-engine.js +72 -11
- package/dist/bitcoind/hash-order.d.ts +4 -0
- package/dist/bitcoind/hash-order.js +13 -0
- package/dist/bitcoind/indexer-daemon-main.js +11 -3
- package/dist/bitcoind/normalize.js +3 -2
- package/dist/bitcoind/processing-start-height.d.ts +5 -0
- package/dist/bitcoind/processing-start-height.js +7 -0
- package/dist/bitcoind/progress/constants.d.ts +4 -0
- package/dist/bitcoind/progress/constants.js +4 -0
- package/dist/bitcoind/progress/controller.d.ts +2 -1
- package/dist/bitcoind/progress/controller.js +3 -3
- package/dist/bitcoind/progress/follow-scene.d.ts +6 -2
- package/dist/bitcoind/progress/follow-scene.js +29 -6
- package/dist/bitcoind/progress/formatting.d.ts +1 -0
- package/dist/bitcoind/progress/formatting.js +6 -0
- package/dist/bitcoind/progress/train-scene.js +37 -18
- package/dist/bitcoind/progress/tty-renderer.d.ts +6 -1
- package/dist/bitcoind/progress/tty-renderer.js +8 -4
- package/dist/bitcoind/rpc.d.ts +2 -1
- package/dist/bitcoind/rpc.js +3 -0
- package/dist/bitcoind/types.d.ts +6 -0
- package/dist/bytes.d.ts +1 -0
- package/dist/bytes.js +3 -0
- package/dist/cli/art.d.ts +2 -0
- package/dist/cli/art.js +37 -0
- package/dist/cli/commands/client-admin.d.ts +2 -0
- package/dist/cli/commands/client-admin.js +91 -0
- package/dist/cli/commands/follow.js +0 -2
- package/dist/cli/commands/mining-admin.js +6 -47
- package/dist/cli/commands/mining-read.js +11 -50
- package/dist/cli/commands/mining-runtime.js +142 -5
- package/dist/cli/commands/service-runtime.js +0 -2
- package/dist/cli/commands/status.js +8 -2
- package/dist/cli/commands/sync.js +49 -92
- package/dist/cli/commands/wallet-admin.js +142 -136
- package/dist/cli/commands/wallet-mutation.js +91 -79
- package/dist/cli/commands/wallet-read.js +15 -18
- package/dist/cli/context.js +5 -14
- package/dist/cli/mining-format.d.ts +0 -1
- package/dist/cli/mining-format.js +5 -37
- package/dist/cli/mining-json.d.ts +0 -18
- package/dist/cli/mining-json.js +0 -35
- package/dist/cli/mutation-command-groups.d.ts +1 -2
- package/dist/cli/mutation-command-groups.js +0 -5
- package/dist/cli/mutation-json.d.ts +24 -145
- package/dist/cli/mutation-json.js +30 -136
- package/dist/cli/mutation-resolved-json.d.ts +0 -7
- package/dist/cli/mutation-resolved-json.js +4 -10
- package/dist/cli/mutation-success.d.ts +2 -0
- package/dist/cli/mutation-success.js +11 -1
- package/dist/cli/mutation-text-format.js +1 -3
- package/dist/cli/output.d.ts +1 -1
- package/dist/cli/output.js +254 -231
- package/dist/cli/parse.d.ts +1 -1
- package/dist/cli/parse.js +93 -122
- package/dist/cli/preview-json.d.ts +17 -120
- package/dist/cli/preview-json.js +14 -97
- package/dist/cli/prompt.js +8 -13
- package/dist/cli/read-json.d.ts +15 -37
- package/dist/cli/read-json.js +44 -140
- package/dist/cli/runner.js +10 -13
- package/dist/cli/sync-progress.d.ts +6 -0
- package/dist/cli/sync-progress.js +91 -0
- package/dist/cli/types.d.ts +9 -17
- package/dist/cli/types.js +0 -2
- package/dist/cli/wallet-format.d.ts +1 -0
- package/dist/cli/wallet-format.js +208 -144
- package/dist/cli/workflow-hints.d.ts +3 -3
- package/dist/cli/workflow-hints.js +11 -8
- package/dist/client/default-client.d.ts +3 -1
- package/dist/client/default-client.js +45 -2
- package/dist/client/factory.js +1 -1
- package/dist/client/initialization.js +23 -0
- package/dist/client/persistence.js +5 -5
- package/dist/client/store-adapter.js +1 -0
- package/dist/sqlite/checkpoints.d.ts +1 -0
- package/dist/sqlite/checkpoints.js +7 -0
- package/dist/sqlite/store.js +14 -1
- package/dist/types.d.ts +1 -0
- package/dist/wallet/coin-control.d.ts +41 -12
- package/dist/wallet/coin-control.js +100 -428
- package/dist/wallet/descriptor-normalization.d.ts +1 -3
- package/dist/wallet/descriptor-normalization.js +0 -16
- package/dist/wallet/lifecycle.d.ts +7 -99
- package/dist/wallet/lifecycle.js +513 -968
- package/dist/wallet/managed-core-wallet.d.ts +13 -0
- package/dist/wallet/managed-core-wallet.js +20 -0
- package/dist/wallet/mining/constants.d.ts +5 -12
- package/dist/wallet/mining/constants.js +5 -12
- package/dist/wallet/mining/control.d.ts +1 -13
- package/dist/wallet/mining/control.js +45 -349
- package/dist/wallet/mining/index.d.ts +4 -5
- package/dist/wallet/mining/index.js +2 -3
- package/dist/wallet/mining/runner.d.ts +123 -13
- package/dist/wallet/mining/runner.js +899 -511
- package/dist/wallet/mining/runtime-artifacts.js +23 -3
- package/dist/wallet/mining/sentence-protocol.d.ts +44 -0
- package/dist/wallet/mining/sentence-protocol.js +123 -0
- package/dist/wallet/mining/sentences.d.ts +4 -8
- package/dist/wallet/mining/sentences.js +3 -52
- package/dist/wallet/mining/state.d.ts +11 -6
- package/dist/wallet/mining/state.js +7 -6
- package/dist/wallet/mining/types.d.ts +2 -30
- package/dist/wallet/mining/visualizer.d.ts +31 -3
- package/dist/wallet/mining/visualizer.js +135 -13
- package/dist/wallet/read/context.d.ts +0 -2
- package/dist/wallet/read/context.js +119 -140
- package/dist/wallet/read/filter.js +2 -11
- package/dist/wallet/read/index.d.ts +1 -1
- package/dist/wallet/read/project.js +24 -77
- package/dist/wallet/read/types.d.ts +10 -25
- package/dist/wallet/reset.d.ts +0 -1
- package/dist/wallet/reset.js +60 -138
- package/dist/wallet/root-resolution.d.ts +1 -5
- package/dist/wallet/root-resolution.js +0 -18
- package/dist/wallet/runtime.d.ts +0 -6
- package/dist/wallet/runtime.js +0 -8
- package/dist/wallet/state/client-password-agent.js +208 -0
- package/dist/wallet/state/client-password.d.ts +65 -0
- package/dist/wallet/state/client-password.js +952 -0
- package/dist/wallet/state/crypto.d.ts +1 -20
- package/dist/wallet/state/crypto.js +0 -63
- package/dist/wallet/state/provider.d.ts +23 -11
- package/dist/wallet/state/provider.js +248 -290
- package/dist/wallet/state/storage.d.ts +2 -2
- package/dist/wallet/state/storage.js +48 -16
- package/dist/wallet/tx/anchor.d.ts +3 -28
- package/dist/wallet/tx/anchor.js +349 -1250
- package/dist/wallet/tx/bitcoin-transfer.d.ts +35 -0
- package/dist/wallet/tx/bitcoin-transfer.js +200 -0
- package/dist/wallet/tx/cog.d.ts +5 -1
- package/dist/wallet/tx/cog.js +149 -185
- package/dist/wallet/tx/common.d.ts +61 -8
- package/dist/wallet/tx/common.js +266 -146
- package/dist/wallet/tx/domain-admin.d.ts +3 -1
- package/dist/wallet/tx/domain-admin.js +61 -99
- package/dist/wallet/tx/domain-market.d.ts +5 -1
- package/dist/wallet/tx/domain-market.js +221 -228
- package/dist/wallet/tx/field.d.ts +4 -10
- package/dist/wallet/tx/field.js +83 -924
- package/dist/wallet/tx/identity-selector.d.ts +9 -3
- package/dist/wallet/tx/identity-selector.js +17 -35
- package/dist/wallet/tx/index.d.ts +3 -1
- package/dist/wallet/tx/index.js +2 -1
- package/dist/wallet/tx/register.d.ts +3 -1
- package/dist/wallet/tx/register.js +62 -220
- package/dist/wallet/tx/reputation.d.ts +3 -1
- package/dist/wallet/tx/reputation.js +58 -95
- package/dist/wallet/types.d.ts +8 -122
- package/package.json +5 -5
- package/dist/wallet/archive.d.ts +0 -4
- package/dist/wallet/archive.js +0 -41
- package/dist/wallet/mining/hook-protocol.d.ts +0 -47
- package/dist/wallet/mining/hook-protocol.js +0 -161
- package/dist/wallet/mining/hook-runner.js +0 -52
- package/dist/wallet/mining/hooks.d.ts +0 -38
- package/dist/wallet/mining/hooks.js +0 -520
- package/dist/wallet/state/explicit-lock.d.ts +0 -4
- package/dist/wallet/state/explicit-lock.js +0 -19
- package/dist/wallet/state/session.d.ts +0 -12
- package/dist/wallet/state/session.js +0 -23
- /package/dist/wallet/{mining/hook-runner.d.ts → state/client-password-agent.d.ts} +0 -0
|
@@ -1,12 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getBalance } from "@cogcoin/indexer/queries";
|
|
2
|
+
import { findDomainField, findWalletDomain, formatFieldFormat, isRootDomainName, listDomainFields, listWalletLocks, } from "../wallet/read/index.js";
|
|
3
|
+
import { loadBalanceArtText } from "./art.js";
|
|
2
4
|
import { formatMiningSummaryLine } from "./mining-format.js";
|
|
3
|
-
import { getBootstrapSyncNextStep } from "./workflow-hints.js";
|
|
4
|
-
|
|
5
|
+
import { formatNextStepLines, getBootstrapSyncNextStep, getFundingQuickstartGuidance, } from "./workflow-hints.js";
|
|
6
|
+
const BALANCE_QUICKSTART_THRESHOLD_SATS = 150000n;
|
|
7
|
+
const BALANCE_BUY_ROOT_THRESHOLD_SATS = 100000n;
|
|
8
|
+
const BALANCE_MINING_THRESHOLD_SATS = 10000n;
|
|
9
|
+
function formatUnitAmount(value, unit) {
|
|
5
10
|
const sign = value < 0n ? "-" : "";
|
|
6
11
|
const absolute = value < 0n ? -value : value;
|
|
7
12
|
const whole = absolute / 100000000n;
|
|
8
13
|
const fraction = absolute % 100000000n;
|
|
9
|
-
return `${sign}${whole.toString()}.${fraction.toString().padStart(8, "0")}
|
|
14
|
+
return `${sign}${whole.toString()}.${fraction.toString().padStart(8, "0")} ${unit}`;
|
|
15
|
+
}
|
|
16
|
+
function formatCogAmount(value) {
|
|
17
|
+
return formatUnitAmount(value, "COG");
|
|
18
|
+
}
|
|
19
|
+
function formatBitcoinAmount(value) {
|
|
20
|
+
return value === null ? "unavailable BTC" : formatUnitAmount(value, "BTC");
|
|
10
21
|
}
|
|
11
22
|
function formatServiceHealth(health) {
|
|
12
23
|
return health.replaceAll("-", " ");
|
|
@@ -26,12 +37,6 @@ function formatIndexerTruthSource(source) {
|
|
|
26
37
|
return "none";
|
|
27
38
|
}
|
|
28
39
|
}
|
|
29
|
-
function formatUnlockExpiry(unlockUntilUnixMs) {
|
|
30
|
-
if (unlockUntilUnixMs === null) {
|
|
31
|
-
return "locked";
|
|
32
|
-
}
|
|
33
|
-
return `unlocked until ${new Date(unlockUntilUnixMs).toISOString()}`;
|
|
34
|
-
}
|
|
35
40
|
function isReputationMutation(mutation) {
|
|
36
41
|
return (mutation.kind === "rep-give" || mutation.kind === "rep-revoke")
|
|
37
42
|
&& mutation.recipientDomainName !== undefined
|
|
@@ -75,6 +80,13 @@ function formatPendingMutationDomainLabel(mutation) {
|
|
|
75
80
|
return kind;
|
|
76
81
|
}
|
|
77
82
|
export function getRepairRecommendation(context) {
|
|
83
|
+
if (context.localState.clientPasswordReadiness === "setup-required"
|
|
84
|
+
|| context.localState.clientPasswordReadiness === "migration-required") {
|
|
85
|
+
return "Run `cogcoin init` to configure the client password and migrate local wallet secrets.";
|
|
86
|
+
}
|
|
87
|
+
if (context.localState.unlockRequired) {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
78
90
|
if (context.localState.availability === "uninitialized") {
|
|
79
91
|
return "Run `cogcoin init` to create a new local wallet root.";
|
|
80
92
|
}
|
|
@@ -96,32 +108,18 @@ export function getRepairRecommendation(context) {
|
|
|
96
108
|
return "Run `cogcoin repair` to recover the managed indexer daemon and local indexer artifacts.";
|
|
97
109
|
}
|
|
98
110
|
if (context.localState.state?.miningState.state === "repair-required"
|
|
99
|
-
|| context.localState.state?.proactiveFamilies.some((family) => family.status === "repair-required")
|
|
100
|
-
|| context.localState.state?.domains.some((domain) => domain.localAnchorIntent === "repair-required")
|
|
101
111
|
|| (context.localState.state?.pendingMutations ?? []).some((mutation) => mutation.status === "repair-required")) {
|
|
102
112
|
return "Run `cogcoin repair` before relying on local wallet state.";
|
|
103
113
|
}
|
|
104
114
|
return null;
|
|
105
115
|
}
|
|
106
|
-
export function
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
&& family.currentStep === "reserved");
|
|
110
|
-
if (clearableAnchorFamily?.domainName != null) {
|
|
111
|
-
return `Run \`cogcoin anchor clear ${clearableAnchorFamily.domainName}\` to cancel the local pending anchor reservation, or rerun \`cogcoin anchor ${clearableAnchorFamily.domainName}\` to continue anchoring.`;
|
|
112
|
-
}
|
|
113
|
-
const unresolvedFamily = (context.localState.state?.proactiveFamilies ?? []).find((family) => (family.type === "anchor" || family.type === "field")
|
|
114
|
-
&& (family.status === "broadcast-unknown" || family.status === "repair-required"));
|
|
115
|
-
if (unresolvedFamily !== undefined) {
|
|
116
|
-
if (unresolvedFamily.status === "repair-required") {
|
|
117
|
-
return unresolvedFamily.type === "field"
|
|
118
|
-
? "Run `cogcoin repair` before starting another field family."
|
|
119
|
-
: "Run `cogcoin repair` before starting another anchor family.";
|
|
120
|
-
}
|
|
121
|
-
return unresolvedFamily.type === "field"
|
|
122
|
-
? `Rerun \`cogcoin field create ${unresolvedFamily.domainName} ${unresolvedFamily.fieldName} ...\` to reconcile the pending field family, or run \`cogcoin repair\` if it remains unresolved.`
|
|
123
|
-
: `Rerun \`cogcoin anchor ${unresolvedFamily.domainName}\` to reconcile the pending anchor family, or run \`cogcoin repair\` if it remains unresolved.`;
|
|
116
|
+
export function getClientUnlockRecommendation(context) {
|
|
117
|
+
if (context.localState.unlockRequired) {
|
|
118
|
+
return "Run `cogcoin client unlock` to temporarily unlock wallet-local secrets.";
|
|
124
119
|
}
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
export function getMutationRecommendation(context) {
|
|
125
123
|
const pendingMutations = context.localState.state?.pendingMutations ?? [];
|
|
126
124
|
const unresolved = pendingMutations.find((mutation) => mutation.status === "broadcast-unknown" || mutation.status === "repair-required");
|
|
127
125
|
if (unresolved === undefined) {
|
|
@@ -133,6 +131,9 @@ export function getMutationRecommendation(context) {
|
|
|
133
131
|
if (unresolved.kind === "register") {
|
|
134
132
|
return `Rerun \`cogcoin register ${unresolved.domainName}\` to reconcile the pending registration, or run \`cogcoin repair\` if it remains unresolved.`;
|
|
135
133
|
}
|
|
134
|
+
if (unresolved.kind === "anchor") {
|
|
135
|
+
return `Rerun \`cogcoin anchor ${unresolved.domainName}\` to reconcile the pending anchor, or run \`cogcoin repair\` if it remains unresolved.`;
|
|
136
|
+
}
|
|
136
137
|
if (unresolved.kind === "transfer") {
|
|
137
138
|
return `Rerun \`cogcoin transfer ${unresolved.domainName}\` with the same target to reconcile the pending transfer, or run \`cogcoin repair\` if it remains unresolved.`;
|
|
138
139
|
}
|
|
@@ -187,22 +188,12 @@ export function getMutationRecommendation(context) {
|
|
|
187
188
|
: "Rerun the same `cogcoin claim ...` command to reconcile the pending claim, or run `cogcoin repair` if it remains unresolved.";
|
|
188
189
|
}
|
|
189
190
|
function appendPendingMutationSummary(lines, context) {
|
|
190
|
-
const pendingFamilies = (context.localState.state?.proactiveFamilies ?? [])
|
|
191
|
-
.filter((family) => (family.type === "anchor" || family.type === "field")
|
|
192
|
-
&& family.status !== "confirmed"
|
|
193
|
-
&& family.status !== "canceled");
|
|
194
191
|
const pendingMutations = (context.localState.state?.pendingMutations ?? [])
|
|
195
192
|
.filter((mutation) => mutation.status !== "confirmed" && mutation.status !== "canceled");
|
|
196
|
-
if (
|
|
193
|
+
if (pendingMutations.length === 0) {
|
|
197
194
|
lines.push("Pending mutations: none");
|
|
198
195
|
return;
|
|
199
196
|
}
|
|
200
|
-
for (const family of pendingFamilies) {
|
|
201
|
-
const label = family.type === "field"
|
|
202
|
-
? `Pending field family: ${family.domainName ?? "unknown"}.${family.fieldName ?? "unknown"}`
|
|
203
|
-
: `Pending anchor family: ${family.domainName ?? "unknown"}`;
|
|
204
|
-
lines.push(`${label} ${family.status}${family.currentStep === null || family.currentStep === undefined ? "" : ` step ${family.currentStep}`}${family.reservedDedicatedIndex == null ? "" : ` index ${family.reservedDedicatedIndex}`}`);
|
|
205
|
-
}
|
|
206
197
|
for (const mutation of pendingMutations) {
|
|
207
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"}`);
|
|
208
199
|
}
|
|
@@ -213,6 +204,7 @@ function listPendingDomainMutations(context, domainName) {
|
|
|
213
204
|
|| mutation.kind === "transfer"
|
|
214
205
|
|| mutation.kind === "sell"
|
|
215
206
|
|| mutation.kind === "buy"
|
|
207
|
+
|| mutation.kind === "anchor"
|
|
216
208
|
|| mutation.kind === "endpoint"
|
|
217
209
|
|| mutation.kind === "delegate"
|
|
218
210
|
|| mutation.kind === "miner"
|
|
@@ -224,26 +216,13 @@ function listPendingDomainMutations(context, domainName) {
|
|
|
224
216
|
&& mutation.status !== "confirmed"
|
|
225
217
|
&& mutation.status !== "canceled");
|
|
226
218
|
}
|
|
227
|
-
function listPendingAnchorFamilies(context, domainName) {
|
|
228
|
-
return (context.localState.state?.proactiveFamilies ?? [])
|
|
229
|
-
.filter((family) => family.type === "anchor"
|
|
230
|
-
&& family.domainName === domainName
|
|
231
|
-
&& family.status !== "confirmed"
|
|
232
|
-
&& family.status !== "canceled");
|
|
233
|
-
}
|
|
234
|
-
function listPendingFieldFamilies(context, domainName) {
|
|
235
|
-
return (context.localState.state?.proactiveFamilies ?? [])
|
|
236
|
-
.filter((family) => family.type === "field"
|
|
237
|
-
&& family.domainName === domainName
|
|
238
|
-
&& family.status !== "confirmed"
|
|
239
|
-
&& family.status !== "canceled");
|
|
240
|
-
}
|
|
241
219
|
function listPendingDomainShowMutations(context, domainName) {
|
|
242
220
|
return (context.localState.state?.pendingMutations ?? [])
|
|
243
221
|
.filter((mutation) => (mutation.kind === "register"
|
|
244
222
|
|| mutation.kind === "transfer"
|
|
245
223
|
|| mutation.kind === "sell"
|
|
246
224
|
|| mutation.kind === "buy"
|
|
225
|
+
|| mutation.kind === "anchor"
|
|
247
226
|
|| mutation.kind === "endpoint"
|
|
248
227
|
|| mutation.kind === "delegate"
|
|
249
228
|
|| mutation.kind === "miner"
|
|
@@ -308,7 +287,6 @@ function appendServiceSummary(lines, context) {
|
|
|
308
287
|
function appendWalletAvailability(lines, context) {
|
|
309
288
|
lines.push(`Wallet state: ${context.localState.availability}`);
|
|
310
289
|
lines.push(`Wallet root: ${context.model?.walletRootId ?? context.localState.walletRootId ?? context.nodeStatus?.walletRootId ?? "none"}`);
|
|
311
|
-
lines.push(`Wallet unlock: ${formatUnlockExpiry(context.localState.unlockUntilUnixMs)}`);
|
|
312
290
|
if (context.localState.message !== null) {
|
|
313
291
|
lines.push(`Wallet note: ${context.localState.message}`);
|
|
314
292
|
}
|
|
@@ -325,8 +303,11 @@ function appendWalletAvailability(lines, context) {
|
|
|
325
303
|
lines.push(`Recommended next step: ${repairRecommendation}`);
|
|
326
304
|
}
|
|
327
305
|
else {
|
|
328
|
-
const
|
|
329
|
-
if (
|
|
306
|
+
const clientUnlockRecommendation = getClientUnlockRecommendation(context);
|
|
307
|
+
if (clientUnlockRecommendation !== null) {
|
|
308
|
+
lines.push(`Recommended next step: ${clientUnlockRecommendation}`);
|
|
309
|
+
}
|
|
310
|
+
else if (getBootstrapSyncNextStep(context) !== null) {
|
|
330
311
|
lines.push("Recommended next step: Run `cogcoin sync` to bootstrap assumeutxo and the managed Bitcoin/indexer state.");
|
|
331
312
|
}
|
|
332
313
|
}
|
|
@@ -347,7 +328,7 @@ function isMiningOverviewOk(mining) {
|
|
|
347
328
|
&& mining.runtime.indexerHealth === "synced"
|
|
348
329
|
&& mining.runtime.miningState !== "repair-required"
|
|
349
330
|
&& mining.runtime.miningState !== "paused-stale"
|
|
350
|
-
&& !(mining.runtime.miningState === "paused" && mining.runtime.
|
|
331
|
+
&& !(mining.runtime.miningState === "paused" && mining.runtime.livePublishInMempool === true);
|
|
351
332
|
}
|
|
352
333
|
function buildOverviewPathsSection(context) {
|
|
353
334
|
return [
|
|
@@ -360,7 +341,6 @@ function buildOverviewWalletSection(context) {
|
|
|
360
341
|
const lines = [
|
|
361
342
|
overviewEntry(`State: ${context.localState.availability}`, context.localState.availability === "ready"),
|
|
362
343
|
overviewEntry(`Root: ${walletRoot}`, walletRoot !== "none"),
|
|
363
|
-
overviewEntry(`Unlock: ${formatUnlockExpiry(context.localState.unlockUntilUnixMs)}`, context.localState.unlockUntilUnixMs !== null),
|
|
364
344
|
];
|
|
365
345
|
if (context.localState.message !== null) {
|
|
366
346
|
lines.push(overviewEntry(`Note: ${context.localState.message}`, false));
|
|
@@ -422,28 +402,17 @@ function buildOverviewLocalInventorySection(context) {
|
|
|
422
402
|
return [overviewEntry("Status: Wallet-derived sections unavailable", false)];
|
|
423
403
|
}
|
|
424
404
|
return [
|
|
425
|
-
overviewEntry(
|
|
405
|
+
overviewEntry("Local wallet address: 1", true),
|
|
426
406
|
overviewEntry(`Locally related domains: ${context.model.domains.length}`, true),
|
|
427
|
-
overviewEntry(`Read-only identities: ${context.model.readOnlyIdentityCount}`, true),
|
|
428
407
|
];
|
|
429
408
|
}
|
|
430
409
|
function buildOverviewPendingWorkSection(context) {
|
|
431
|
-
const pendingFamilies = (context.localState.state?.proactiveFamilies ?? [])
|
|
432
|
-
.filter((family) => (family.type === "anchor" || family.type === "field")
|
|
433
|
-
&& family.status !== "confirmed"
|
|
434
|
-
&& family.status !== "canceled");
|
|
435
410
|
const pendingMutations = (context.localState.state?.pendingMutations ?? [])
|
|
436
411
|
.filter((mutation) => mutation.status !== "confirmed" && mutation.status !== "canceled");
|
|
437
|
-
if (
|
|
412
|
+
if (pendingMutations.length === 0) {
|
|
438
413
|
return [overviewEntry("Status: none", true)];
|
|
439
414
|
}
|
|
440
415
|
const lines = [];
|
|
441
|
-
for (const family of pendingFamilies) {
|
|
442
|
-
const label = family.type === "field"
|
|
443
|
-
? `Field family: ${family.domainName ?? "unknown"}.${family.fieldName ?? "unknown"}`
|
|
444
|
-
: `Anchor family: ${family.domainName ?? "unknown"}`;
|
|
445
|
-
lines.push(overviewEntry(`${label} ${family.status}${family.currentStep === null || family.currentStep === undefined ? "" : ` step ${family.currentStep}`}${family.reservedDedicatedIndex == null ? "" : ` index ${family.reservedDedicatedIndex}`}`, false));
|
|
446
|
-
}
|
|
447
416
|
for (const mutation of pendingMutations) {
|
|
448
417
|
lines.push(overviewEntry(`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"}`, false));
|
|
449
418
|
}
|
|
@@ -454,6 +423,10 @@ function getOverviewNextStep(context) {
|
|
|
454
423
|
if (repairRecommendation !== null) {
|
|
455
424
|
return repairRecommendation;
|
|
456
425
|
}
|
|
426
|
+
const clientUnlockRecommendation = getClientUnlockRecommendation(context);
|
|
427
|
+
if (clientUnlockRecommendation !== null) {
|
|
428
|
+
return clientUnlockRecommendation;
|
|
429
|
+
}
|
|
457
430
|
if (getBootstrapSyncNextStep(context) !== null) {
|
|
458
431
|
return "Run `cogcoin sync` to bootstrap assumeutxo and the managed Bitcoin/indexer state.";
|
|
459
432
|
}
|
|
@@ -482,46 +455,178 @@ export function formatDetailedWalletStatusReport(context) {
|
|
|
482
455
|
lines.push("Wallet details are unavailable until the encrypted wallet state can be read.");
|
|
483
456
|
return lines.join("\n");
|
|
484
457
|
}
|
|
485
|
-
lines.push(`
|
|
486
|
-
lines.push(`
|
|
487
|
-
lines.push(
|
|
458
|
+
lines.push(`Wallet address: ${context.model.walletAddress ?? "unavailable"}`);
|
|
459
|
+
lines.push(`Wallet script: spk:${context.model.walletScriptPubKeyHex ?? "unavailable"}`);
|
|
460
|
+
lines.push("Local wallet addresses: 1");
|
|
488
461
|
lines.push(`Locally related domains: ${context.model.domains.length}`);
|
|
489
|
-
lines.push(`Read-only identities: ${context.model.readOnlyIdentityCount}`);
|
|
490
462
|
appendPendingMutationSummary(lines, context);
|
|
491
463
|
return lines.join("\n");
|
|
492
464
|
}
|
|
493
465
|
export function formatFundingAddressReport(context) {
|
|
494
|
-
const lines = ["BTC
|
|
495
|
-
if (context.model
|
|
466
|
+
const lines = ["BTC Wallet Address"];
|
|
467
|
+
if (context.model === null) {
|
|
496
468
|
appendWalletAvailability(lines, context);
|
|
497
469
|
return lines.join("\n");
|
|
498
470
|
}
|
|
499
|
-
lines.push(`
|
|
500
|
-
lines.push(`
|
|
501
|
-
lines.
|
|
471
|
+
lines.push(`Address: ${context.model.walletAddress ?? "unavailable"}`);
|
|
472
|
+
lines.push(`ScriptPubKey: spk:${context.model.walletScriptPubKeyHex}`);
|
|
473
|
+
return lines.join("\n");
|
|
474
|
+
}
|
|
475
|
+
function renderBalanceArtLine(templateLine, label, value) {
|
|
476
|
+
const labelIndex = templateLine.indexOf(label);
|
|
477
|
+
if (labelIndex === -1) {
|
|
478
|
+
throw new Error(`balance_art_label_missing_${label}`);
|
|
479
|
+
}
|
|
480
|
+
const fieldStart = labelIndex + label.length;
|
|
481
|
+
const borderIndex = Math.max(templateLine.lastIndexOf("│"), templateLine.lastIndexOf("|"));
|
|
482
|
+
if (borderIndex <= fieldStart) {
|
|
483
|
+
throw new Error(`balance_art_field_invalid_${label}`);
|
|
484
|
+
}
|
|
485
|
+
const fieldWidth = borderIndex - fieldStart;
|
|
486
|
+
const fieldValue = value.slice(0, fieldWidth).padEnd(fieldWidth, " ");
|
|
487
|
+
const rendered = `${templateLine.slice(0, fieldStart)}${fieldValue}${templateLine.slice(borderIndex)}`;
|
|
488
|
+
if (rendered.length !== templateLine.length) {
|
|
489
|
+
throw new Error(`balance_art_render_width_invalid_${label}`);
|
|
490
|
+
}
|
|
491
|
+
return rendered;
|
|
492
|
+
}
|
|
493
|
+
function renderBalanceArtCard(context) {
|
|
494
|
+
const templateLines = loadBalanceArtText().split("\n");
|
|
495
|
+
const fundingAddress = context.model.walletAddress ?? "unavailable";
|
|
496
|
+
const spendableCog = getBalance(context.snapshot.state, new Uint8Array(Buffer.from(context.model.walletScriptPubKeyHex, "hex")));
|
|
497
|
+
return templateLines.map((line) => {
|
|
498
|
+
if (line.includes("Funding address:")) {
|
|
499
|
+
return renderBalanceArtLine(line, "Funding address:", ` ${fundingAddress}`);
|
|
500
|
+
}
|
|
501
|
+
if (line.includes("Bitcoin Balance:")) {
|
|
502
|
+
return renderBalanceArtLine(line, "Bitcoin Balance:", ` ${formatBitcoinAmount(context.fundingSpendableSats ?? null)}`);
|
|
503
|
+
}
|
|
504
|
+
if (line.includes("Cogcoin Balance:")) {
|
|
505
|
+
return renderBalanceArtLine(line, "Cogcoin Balance:", ` ${formatCogAmount(spendableCog)}`);
|
|
506
|
+
}
|
|
507
|
+
if (line.includes("mempool.space/address/")) {
|
|
508
|
+
return renderBalanceArtLine(line, "mempool.space/address/", fundingAddress);
|
|
509
|
+
}
|
|
510
|
+
return line;
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
function hasRegisteredOrAnchoredDomain(model) {
|
|
514
|
+
return model.domains.some((domain) => domain.localRelationship === "local"
|
|
515
|
+
&& (domain.chainStatus === "registered-unanchored" || domain.chainStatus === "anchored"));
|
|
516
|
+
}
|
|
517
|
+
function listBalanceDomainsByStatus(model, status) {
|
|
518
|
+
return model.domains
|
|
519
|
+
.filter((domain) => domain.localRelationship === "local" && domain.chainStatus === status)
|
|
520
|
+
.sort((left, right) => left.name.localeCompare(right.name));
|
|
521
|
+
}
|
|
522
|
+
function shouldShowBalanceQuickstart(context) {
|
|
523
|
+
return context.fundingSpendableSats !== null
|
|
524
|
+
&& context.fundingSpendableSats < BALANCE_QUICKSTART_THRESHOLD_SATS
|
|
525
|
+
&& !hasRegisteredOrAnchoredDomain(context.model);
|
|
526
|
+
}
|
|
527
|
+
function formatBalanceDomainSection(title, icon, domains, emptyLabel) {
|
|
528
|
+
const domainItems = domains.map((domain) => `${icon} ${domain.name}`);
|
|
529
|
+
const wrappedDomainLines = [];
|
|
530
|
+
let currentLine = "";
|
|
531
|
+
for (const item of domainItems) {
|
|
532
|
+
const candidate = currentLine.length === 0 ? item : `${currentLine}, ${item}`;
|
|
533
|
+
if (candidate.length <= 80) {
|
|
534
|
+
currentLine = candidate;
|
|
535
|
+
continue;
|
|
536
|
+
}
|
|
537
|
+
if (currentLine.length > 0) {
|
|
538
|
+
wrappedDomainLines.push(currentLine);
|
|
539
|
+
}
|
|
540
|
+
currentLine = item;
|
|
541
|
+
}
|
|
542
|
+
if (currentLine.length > 0) {
|
|
543
|
+
wrappedDomainLines.push(currentLine);
|
|
544
|
+
}
|
|
545
|
+
return [
|
|
546
|
+
title,
|
|
547
|
+
...(domains.length === 0
|
|
548
|
+
? [emptyLabel]
|
|
549
|
+
: wrappedDomainLines),
|
|
550
|
+
];
|
|
551
|
+
}
|
|
552
|
+
function getBalanceNextSteps(context) {
|
|
553
|
+
const anchoredDomains = listBalanceDomainsByStatus(context.model, "anchored");
|
|
554
|
+
const anchoredRootDomains = anchoredDomains.filter((domain) => isRootDomainName(domain.name));
|
|
555
|
+
const unanchoredDomains = listBalanceDomainsByStatus(context.model, "registered-unanchored");
|
|
556
|
+
if (anchoredRootDomains.length > 0) {
|
|
557
|
+
if (context.fundingSpendableSats !== null && context.fundingSpendableSats < BALANCE_MINING_THRESHOLD_SATS) {
|
|
558
|
+
return [`Transfer BTC to ${context.model.walletAddress ?? "this wallet address"} so your anchored root domain can keep mining.`];
|
|
559
|
+
}
|
|
560
|
+
if (context.fundingSpendableSats !== null && context.fundingSpendableSats > BALANCE_MINING_THRESHOLD_SATS) {
|
|
561
|
+
if (context.mining?.provider.status === "missing") {
|
|
562
|
+
return ["Run `cogcoin mine setup` to configure your mining provider."];
|
|
563
|
+
}
|
|
564
|
+
return ["Run `cogcoin mine` to start mining with your anchored root domain."];
|
|
565
|
+
}
|
|
566
|
+
return [];
|
|
567
|
+
}
|
|
568
|
+
if (unanchoredDomains.length > 0) {
|
|
569
|
+
return [`Run \`cogcoin anchor ${unanchoredDomains[0].name}\` to anchor your unanchored domain.`];
|
|
570
|
+
}
|
|
571
|
+
if (context.fundingSpendableSats !== null && context.fundingSpendableSats > BALANCE_BUY_ROOT_THRESHOLD_SATS) {
|
|
572
|
+
return ["Buy a 6+ character root domain with `cogcoin register <root>`."];
|
|
573
|
+
}
|
|
574
|
+
return [];
|
|
575
|
+
}
|
|
576
|
+
function listPendingBalanceLines(context) {
|
|
577
|
+
const lines = [];
|
|
578
|
+
for (const mutation of (context.localState.state?.pendingMutations ?? [])
|
|
579
|
+
.filter((entry) => (entry.kind === "send" || entry.kind === "lock" || entry.kind === "claim")
|
|
580
|
+
&& entry.status !== "confirmed"
|
|
581
|
+
&& entry.status !== "canceled")) {
|
|
582
|
+
const label = mutation.kind === "claim" && mutation.preimageHex === "0000000000000000000000000000000000000000000000000000000000000000"
|
|
583
|
+
? "reclaim"
|
|
584
|
+
: mutation.kind;
|
|
585
|
+
lines.push(`Pending: ${label} ${mutation.status}${mutation.amountCogtoshi === null || mutation.amountCogtoshi === undefined ? "" : ` ${formatCogAmount(mutation.amountCogtoshi)}`}`);
|
|
586
|
+
}
|
|
587
|
+
return lines;
|
|
588
|
+
}
|
|
589
|
+
function formatReadyBalanceReport(context) {
|
|
590
|
+
const anchoredDomains = listBalanceDomainsByStatus(context.model, "anchored");
|
|
591
|
+
const unanchoredDomains = listBalanceDomainsByStatus(context.model, "registered-unanchored");
|
|
592
|
+
const nextStepLines = formatNextStepLines(getBalanceNextSteps(context));
|
|
593
|
+
const lines = [
|
|
594
|
+
"",
|
|
595
|
+
...renderBalanceArtCard(context),
|
|
596
|
+
"",
|
|
597
|
+
...formatBalanceDomainSection("Anchored Domains", "⌂", anchoredDomains, "--- No anchored domains ---"),
|
|
598
|
+
"",
|
|
599
|
+
...formatBalanceDomainSection("Unanchored Domains", "~", unanchoredDomains, "--- No unanchored domains ---"),
|
|
600
|
+
];
|
|
601
|
+
if (shouldShowBalanceQuickstart(context)) {
|
|
602
|
+
lines.push("");
|
|
603
|
+
lines.push(`Quickstart: ${getFundingQuickstartGuidance()}`);
|
|
604
|
+
}
|
|
605
|
+
if (nextStepLines.length > 0) {
|
|
606
|
+
lines.push("");
|
|
607
|
+
lines.push(...nextStepLines);
|
|
608
|
+
}
|
|
609
|
+
const pendingLines = listPendingBalanceLines(context);
|
|
610
|
+
if (pendingLines.length > 0) {
|
|
611
|
+
lines.push("");
|
|
612
|
+
lines.push(...pendingLines);
|
|
613
|
+
}
|
|
502
614
|
return lines.join("\n");
|
|
503
615
|
}
|
|
504
616
|
export function formatIdentityListReport(context, options = {}) {
|
|
505
|
-
const lines = ["Wallet
|
|
617
|
+
const lines = ["Wallet Address"];
|
|
506
618
|
if (context.model === null) {
|
|
507
619
|
appendWalletAvailability(lines, context);
|
|
508
620
|
return lines.join("\n");
|
|
509
621
|
}
|
|
510
|
-
const
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
const domains = identity.ownedDomainNames.length === 0 ? "none" : identity.ownedDomainNames.join(", ");
|
|
519
|
-
const balance = identity.observedCogBalance === null ? "unavailable" : formatCogAmount(identity.observedCogBalance);
|
|
520
|
-
lines.push(`${identity.selectors[0]} ${identity.effectiveStatus} ${identity.address ?? `spk:${identity.scriptPubKeyHex}`} balance ${balance} domains ${domains} selectors ${identity.selectors.join(", ")}`);
|
|
521
|
-
}
|
|
522
|
-
if (limit !== null && identities.length > limit) {
|
|
523
|
-
lines.push(`Showing first ${renderedIdentities.length} of ${identities.length}. Use --limit <n> or --all for more.`);
|
|
524
|
-
}
|
|
622
|
+
const domains = context.model.domains
|
|
623
|
+
.filter((domain) => domain.localRelationship === "local")
|
|
624
|
+
.map((domain) => domain.name)
|
|
625
|
+
.sort();
|
|
626
|
+
const balance = context.snapshot === null
|
|
627
|
+
? null
|
|
628
|
+
: getBalance(context.snapshot.state, new Uint8Array(Buffer.from(context.model.walletScriptPubKeyHex, "hex")));
|
|
629
|
+
lines.push(`${context.model.walletAddress ?? `spk:${context.model.walletScriptPubKeyHex}`} balance ${balance === null ? "unavailable" : formatCogAmount(balance)} domains ${domains.length === 0 ? "none" : domains.join(", ")}`);
|
|
525
630
|
return lines.join("\n");
|
|
526
631
|
}
|
|
527
632
|
export function formatBalanceReport(context) {
|
|
@@ -534,23 +639,7 @@ export function formatBalanceReport(context) {
|
|
|
534
639
|
lines.push(`Indexer-backed balances are unavailable while the indexer is ${formatServiceHealth(context.indexer.health)}.`);
|
|
535
640
|
return lines.join("\n");
|
|
536
641
|
}
|
|
537
|
-
|
|
538
|
-
? sum
|
|
539
|
-
: sum + identity.observedCogBalance, 0n);
|
|
540
|
-
lines.push(`Spendable total: ${formatCogAmount(spendableTotal)}`);
|
|
541
|
-
for (const identity of context.model.identities) {
|
|
542
|
-
lines.push(`${identity.selectors[0]} ${identity.address ?? `spk:${identity.scriptPubKeyHex}`} ${formatCogAmount(identity.observedCogBalance ?? 0n)}${identity.readOnly ? " read-only" : ""}`);
|
|
543
|
-
}
|
|
544
|
-
for (const mutation of (context.localState.state?.pendingMutations ?? [])
|
|
545
|
-
.filter((entry) => (entry.kind === "send" || entry.kind === "lock" || entry.kind === "claim")
|
|
546
|
-
&& entry.status !== "confirmed"
|
|
547
|
-
&& entry.status !== "canceled")) {
|
|
548
|
-
const label = mutation.kind === "claim" && mutation.preimageHex === "0000000000000000000000000000000000000000000000000000000000000000"
|
|
549
|
-
? "reclaim"
|
|
550
|
-
: mutation.kind;
|
|
551
|
-
lines.push(`Pending: ${label} ${mutation.status}${mutation.amountCogtoshi === null || mutation.amountCogtoshi === undefined ? "" : ` ${formatCogAmount(mutation.amountCogtoshi)}`}`);
|
|
552
|
-
}
|
|
553
|
-
return lines.join("\n");
|
|
642
|
+
return formatReadyBalanceReport(context);
|
|
554
643
|
}
|
|
555
644
|
export function formatLocksReport(context, options = {}) {
|
|
556
645
|
const lines = ["COG Locks"];
|
|
@@ -621,8 +710,6 @@ export function formatDomainsReport(context, options = {}) {
|
|
|
621
710
|
: visibleDomains.slice(0, options.limit);
|
|
622
711
|
for (const domain of renderedDomains) {
|
|
623
712
|
const pending = listPendingDomainMutations(context, domain.name);
|
|
624
|
-
const pendingAnchors = listPendingAnchorFamilies(context, domain.name);
|
|
625
|
-
const pendingFieldFamilies = listPendingFieldFamilies(context, domain.name);
|
|
626
713
|
const pendingFieldMutations = listPendingFieldMutations(context, domain.name);
|
|
627
714
|
const pendingText = pending.length === 0
|
|
628
715
|
? ""
|
|
@@ -635,18 +722,10 @@ export function formatDomainsReport(context, options = {}) {
|
|
|
635
722
|
: mutation.kind === "miner" && mutation.recipientScriptPubKeyHex === null
|
|
636
723
|
? `miner-clear:${mutation.status}`
|
|
637
724
|
: `${mutation.kind}:${mutation.status}`).join(",")}`;
|
|
638
|
-
const pendingFieldsText = pendingFieldMutations.length === 0
|
|
639
|
-
? ""
|
|
640
|
-
: ` field-pending ${[
|
|
641
|
-
...pendingFieldMutations.map((mutation) => `${mutation.fieldName}:${mutation.kind}:${mutation.status}`),
|
|
642
|
-
...pendingFieldFamilies.map((family) => `${family.fieldName}:family:${family.status}${family.currentStep == null ? "" : `:${family.currentStep}`}`),
|
|
643
|
-
].join(",")}`;
|
|
644
|
-
const anchorText = pendingAnchors.length === 0 && (domain.localAnchorIntent === null || domain.localAnchorIntent === "none")
|
|
725
|
+
const pendingFieldsText = pendingFieldMutations.length === 0
|
|
645
726
|
? ""
|
|
646
|
-
: `
|
|
647
|
-
|
|
648
|
-
: domain.localAnchorIntent}`;
|
|
649
|
-
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}`);
|
|
727
|
+
: ` field-pending ${pendingFieldMutations.map((mutation) => `${mutation.fieldName}:${mutation.kind}:${mutation.status}`).join(",")}`;
|
|
728
|
+
lines.push(`${domain.name} ${domain.chainStatus} ${domain.localRelationship} owner ${domain.ownerAddress ?? domain.ownerScriptPubKeyHex ?? "unknown"} fields ${formatMaybe(domain.fieldCount)}${pendingText}${pendingFieldsText}`);
|
|
650
729
|
}
|
|
651
730
|
if (!options.all && options.limit !== null && options.limit !== undefined && visibleDomains.length > options.limit) {
|
|
652
731
|
lines.push(`Showing first ${renderedDomains.length} of ${visibleDomains.length}. Use --limit <n> or --all for more.`);
|
|
@@ -666,7 +745,7 @@ export function formatDomainReport(context, domainName) {
|
|
|
666
745
|
}
|
|
667
746
|
lines.push(`Domain ID: ${formatMaybe(view.domain.domainId)}`);
|
|
668
747
|
lines.push(`Anchored: ${view.domain.anchored === null ? "unknown" : (view.domain.anchored ? "yes" : "no")}`);
|
|
669
|
-
lines.push(`Owner: ${view.domain.
|
|
748
|
+
lines.push(`Owner: ${view.domain.ownerAddress ?? view.domain.ownerScriptPubKeyHex ?? "unknown"}`);
|
|
670
749
|
lines.push(`Local relationship: ${view.localRelationship}`);
|
|
671
750
|
lines.push(`Listing price: ${view.domain.listingPriceCogtoshi === null ? "none" : formatCogAmount(view.domain.listingPriceCogtoshi)}`);
|
|
672
751
|
lines.push(`Field count: ${formatMaybe(view.domain.fieldCount)}`);
|
|
@@ -679,17 +758,10 @@ export function formatDomainReport(context, domainName) {
|
|
|
679
758
|
lines.push(`Reputation total supported: ${view.domain.totalSupportedCogtoshi === null ? "unavailable" : formatCogAmount(view.domain.totalSupportedCogtoshi)}`);
|
|
680
759
|
lines.push(`Reputation total revoked: ${view.domain.totalRevokedCogtoshi === null ? "unavailable" : formatCogAmount(view.domain.totalRevokedCogtoshi)}`);
|
|
681
760
|
}
|
|
682
|
-
lines.push(`Local anchor intent: ${view.domain.localAnchorIntent ?? "none"}`);
|
|
683
761
|
lines.push(`Delegate: ${view.domain.delegateScriptPubKeyHex ?? "none"}`);
|
|
684
762
|
lines.push(`Designated miner: ${view.domain.minerScriptPubKeyHex ?? "none"}`);
|
|
685
763
|
lines.push(`Endpoint: ${view.domain.endpointText ?? "none"}`);
|
|
686
764
|
lines.push(`Founding message: ${view.domain.foundingMessageText ?? "none"}`);
|
|
687
|
-
for (const family of listPendingAnchorFamilies(context, domainName)) {
|
|
688
|
-
lines.push(`Pending anchor family: ${family.status}${family.currentStep == null ? "" : ` step ${family.currentStep}`}${family.reservedDedicatedIndex == null ? "" : ` index ${family.reservedDedicatedIndex}`}`);
|
|
689
|
-
}
|
|
690
|
-
for (const family of listPendingFieldFamilies(context, domainName)) {
|
|
691
|
-
lines.push(`Pending field family: ${family.fieldName ?? "unknown"} ${family.status}${family.currentStep == null ? "" : ` step ${family.currentStep}`}`);
|
|
692
|
-
}
|
|
693
765
|
for (const mutation of listPendingDomainShowMutations(context, domainName)) {
|
|
694
766
|
lines.push(`Pending mutation: ${formatPendingMutationDomainLabel(mutation)} ${mutation.status}`);
|
|
695
767
|
}
|
|
@@ -726,9 +798,6 @@ export function formatFieldsReport(context, domainName, options = {}) {
|
|
|
726
798
|
for (const mutation of listPendingFieldMutations(context, domainName)) {
|
|
727
799
|
lines.push(`Pending field mutation: ${mutation.fieldName ?? "unknown"} ${mutation.kind} ${mutation.status}`);
|
|
728
800
|
}
|
|
729
|
-
for (const family of listPendingFieldFamilies(context, domainName)) {
|
|
730
|
-
lines.push(`Pending field family: ${family.fieldName ?? "unknown"} ${family.status}${family.currentStep == null ? "" : ` step ${family.currentStep}`}`);
|
|
731
|
-
}
|
|
732
801
|
if (!options.all && options.limit !== null && options.limit !== undefined && fields.length > options.limit) {
|
|
733
802
|
lines.push(`Showing first ${renderedFields.length} of ${fields.length}. Use --limit <n> or --all for more.`);
|
|
734
803
|
}
|
|
@@ -742,8 +811,6 @@ export function formatFieldReport(context, domainName, fieldName) {
|
|
|
742
811
|
}
|
|
743
812
|
const field = findDomainField(context, domainName, fieldName);
|
|
744
813
|
const pendingMutations = listPendingFieldMutations(context, domainName, fieldName);
|
|
745
|
-
const pendingFamilies = listPendingFieldFamilies(context, domainName)
|
|
746
|
-
.filter((family) => family.fieldName === fieldName);
|
|
747
814
|
if (field === null) {
|
|
748
815
|
lines.push("Field not found.");
|
|
749
816
|
}
|
|
@@ -759,8 +826,5 @@ export function formatFieldReport(context, domainName, fieldName) {
|
|
|
759
826
|
for (const mutation of pendingMutations) {
|
|
760
827
|
lines.push(`Pending field mutation: ${mutation.kind} ${mutation.status}`);
|
|
761
828
|
}
|
|
762
|
-
for (const family of pendingFamilies) {
|
|
763
|
-
lines.push(`Pending field family: ${family.status}${family.currentStep == null ? "" : ` step ${family.currentStep}`}`);
|
|
764
|
-
}
|
|
765
829
|
return lines.join("\n");
|
|
766
830
|
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { WalletLockView, WalletReadContext } from "../wallet/read/index.js";
|
|
2
2
|
export declare function formatNextStepLines(nextSteps: readonly string[]): string[];
|
|
3
3
|
export declare function getFundingQuickstartGuidance(): string;
|
|
4
4
|
export declare function getInitNextSteps(): string[];
|
|
5
5
|
export declare function getRestoreNextSteps(): string[];
|
|
6
|
+
export declare function getSetupUnlockGuidanceLines(unlockSeconds: number): string[];
|
|
6
7
|
export declare function getBootstrapSyncNextStep(context: Pick<WalletReadContext, "bitcoind" | "indexer" | "nodeHealth">): string | null;
|
|
7
8
|
export declare function getRegisterNextSteps(domainName: string, registerKind: "root" | "subdomain"): string[];
|
|
8
9
|
export declare function getAnchorNextSteps(domainName: string): string[];
|
|
9
|
-
export declare function getHooksEnableMiningNextSteps(): string[];
|
|
10
10
|
export declare function getMineSetupNextSteps(): string[];
|
|
11
11
|
export declare function getMineStopNextSteps(): string[];
|
|
12
12
|
export declare function getAddressNextSteps(context: Pick<WalletReadContext, "bitcoind" | "indexer" | "nodeHealth">, address: string | null | undefined): string[];
|
|
13
|
-
export declare function getIdsNextSteps(
|
|
13
|
+
export declare function getIdsNextSteps(walletAddress: string | null | undefined): string[];
|
|
14
14
|
export declare function getLocksNextSteps(locks: readonly WalletLockView[] | null | undefined): string[];
|
|
@@ -13,6 +13,12 @@ export function getInitNextSteps() {
|
|
|
13
13
|
export function getRestoreNextSteps() {
|
|
14
14
|
return ["cogcoin sync", "cogcoin address"];
|
|
15
15
|
}
|
|
16
|
+
export function getSetupUnlockGuidanceLines(unlockSeconds) {
|
|
17
|
+
return [
|
|
18
|
+
`Client unlock: active for ${unlockSeconds} seconds.`,
|
|
19
|
+
"Use `cogcoin client unlock` to lengthen this unlock window, or `cogcoin client lock` to lock immediately.",
|
|
20
|
+
];
|
|
21
|
+
}
|
|
16
22
|
function blocksSyncBootstrap(context) {
|
|
17
23
|
return context.bitcoind.health === "service-version-mismatch"
|
|
18
24
|
|| context.bitcoind.health === "wallet-root-mismatch"
|
|
@@ -50,9 +56,6 @@ export function getAnchorNextSteps(domainName) {
|
|
|
50
56
|
}
|
|
51
57
|
return nextSteps;
|
|
52
58
|
}
|
|
53
|
-
export function getHooksEnableMiningNextSteps() {
|
|
54
|
-
return ["cogcoin mine", "cogcoin mine start"];
|
|
55
|
-
}
|
|
56
59
|
export function getMineSetupNextSteps() {
|
|
57
60
|
return ["cogcoin mine", "cogcoin mine start"];
|
|
58
61
|
}
|
|
@@ -71,13 +74,13 @@ export function getAddressNextSteps(context, address) {
|
|
|
71
74
|
nextSteps.push("fund this wallet, then run cogcoin status");
|
|
72
75
|
return nextSteps;
|
|
73
76
|
}
|
|
74
|
-
export function getIdsNextSteps(
|
|
75
|
-
return
|
|
77
|
+
export function getIdsNextSteps(walletAddress) {
|
|
78
|
+
return walletAddress === null || walletAddress === undefined || walletAddress.length === 0
|
|
76
79
|
? []
|
|
77
80
|
: [
|
|
78
|
-
"cogcoin register <root>
|
|
79
|
-
"cogcoin send ...
|
|
80
|
-
"cogcoin cog lock ...
|
|
81
|
+
"cogcoin register <root>",
|
|
82
|
+
"cogcoin send ...",
|
|
83
|
+
"cogcoin cog lock ...",
|
|
81
84
|
];
|
|
82
85
|
}
|
|
83
86
|
export function getLocksNextSteps(locks) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { BitcoinBlock, GenesisParameters, IndexerState } from "@cogcoin/indexer/types";
|
|
2
|
-
import type { ApplyBlockResult, Client, ClientStoreAdapter, ClientTip } from "../types.js";
|
|
2
|
+
import type { ApplyBlockResult, Client, ClientCheckpoint, ClientStoreAdapter, ClientTip } from "../types.js";
|
|
3
3
|
export declare class DefaultClient implements Client {
|
|
4
4
|
#private;
|
|
5
5
|
constructor(store: ClientStoreAdapter, genesisParameters: GenesisParameters, state: IndexerState, tip: ClientTip | null, snapshotInterval: number, blockRecordRetention: number);
|
|
@@ -7,5 +7,7 @@ export declare class DefaultClient implements Client {
|
|
|
7
7
|
getState(): Promise<IndexerState>;
|
|
8
8
|
applyBlock(block: BitcoinBlock): Promise<ApplyBlockResult>;
|
|
9
9
|
rewindToHeight(height: number): Promise<ClientTip | null>;
|
|
10
|
+
restoreCheckpoint(checkpoint: ClientCheckpoint): Promise<ClientTip>;
|
|
11
|
+
resetToInitialState(): Promise<null>;
|
|
10
12
|
close(): Promise<void>;
|
|
11
13
|
}
|