@cogcoin/client 0.5.14 → 1.0.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/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 +16 -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 +38 -3
- package/dist/cli/commands/service-runtime.js +0 -2
- package/dist/cli/commands/status.js +8 -2
- package/dist/cli/commands/sync.js +51 -4
- 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 +4 -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/types.d.ts +8 -17
- package/dist/cli/types.js +0 -2
- package/dist/cli/wallet-format.d.ts +1 -0
- package/dist/cli/wallet-format.js +205 -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 -11
- package/dist/wallet/coin-control.js +100 -357
- 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 +3 -4
- package/dist/wallet/mining/index.js +1 -2
- package/dist/wallet/mining/runner.d.ts +179 -6
- package/dist/wallet/mining/runner.js +891 -501
- 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 -1240
- 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 +74 -10
- package/dist/wallet/tx/common.js +315 -138
- 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 +84 -914
- 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,175 @@ 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
|
+
return ["Run `cogcoin mine` to start mining with your anchored root domain."];
|
|
562
|
+
}
|
|
563
|
+
return [];
|
|
564
|
+
}
|
|
565
|
+
if (unanchoredDomains.length > 0) {
|
|
566
|
+
return [`Run \`cogcoin anchor ${unanchoredDomains[0].name}\` to anchor your unanchored domain.`];
|
|
567
|
+
}
|
|
568
|
+
if (context.fundingSpendableSats !== null && context.fundingSpendableSats > BALANCE_BUY_ROOT_THRESHOLD_SATS) {
|
|
569
|
+
return ["Buy a 6+ character root domain with `cogcoin register <root>`."];
|
|
570
|
+
}
|
|
571
|
+
return [];
|
|
572
|
+
}
|
|
573
|
+
function listPendingBalanceLines(context) {
|
|
574
|
+
const lines = [];
|
|
575
|
+
for (const mutation of (context.localState.state?.pendingMutations ?? [])
|
|
576
|
+
.filter((entry) => (entry.kind === "send" || entry.kind === "lock" || entry.kind === "claim")
|
|
577
|
+
&& entry.status !== "confirmed"
|
|
578
|
+
&& entry.status !== "canceled")) {
|
|
579
|
+
const label = mutation.kind === "claim" && mutation.preimageHex === "0000000000000000000000000000000000000000000000000000000000000000"
|
|
580
|
+
? "reclaim"
|
|
581
|
+
: mutation.kind;
|
|
582
|
+
lines.push(`Pending: ${label} ${mutation.status}${mutation.amountCogtoshi === null || mutation.amountCogtoshi === undefined ? "" : ` ${formatCogAmount(mutation.amountCogtoshi)}`}`);
|
|
583
|
+
}
|
|
584
|
+
return lines;
|
|
585
|
+
}
|
|
586
|
+
function formatReadyBalanceReport(context) {
|
|
587
|
+
const anchoredDomains = listBalanceDomainsByStatus(context.model, "anchored");
|
|
588
|
+
const unanchoredDomains = listBalanceDomainsByStatus(context.model, "registered-unanchored");
|
|
589
|
+
const nextStepLines = formatNextStepLines(getBalanceNextSteps(context));
|
|
590
|
+
const lines = [
|
|
591
|
+
"",
|
|
592
|
+
...renderBalanceArtCard(context),
|
|
593
|
+
"",
|
|
594
|
+
...formatBalanceDomainSection("Anchored Domains", "⌂", anchoredDomains, "--- No anchored domains ---"),
|
|
595
|
+
"",
|
|
596
|
+
...formatBalanceDomainSection("Unanchored Domains", "~", unanchoredDomains, "--- No unanchored domains ---"),
|
|
597
|
+
];
|
|
598
|
+
if (shouldShowBalanceQuickstart(context)) {
|
|
599
|
+
lines.push("");
|
|
600
|
+
lines.push(`Quickstart: ${getFundingQuickstartGuidance()}`);
|
|
601
|
+
}
|
|
602
|
+
if (nextStepLines.length > 0) {
|
|
603
|
+
lines.push("");
|
|
604
|
+
lines.push(...nextStepLines);
|
|
605
|
+
}
|
|
606
|
+
const pendingLines = listPendingBalanceLines(context);
|
|
607
|
+
if (pendingLines.length > 0) {
|
|
608
|
+
lines.push("");
|
|
609
|
+
lines.push(...pendingLines);
|
|
610
|
+
}
|
|
502
611
|
return lines.join("\n");
|
|
503
612
|
}
|
|
504
613
|
export function formatIdentityListReport(context, options = {}) {
|
|
505
|
-
const lines = ["Wallet
|
|
614
|
+
const lines = ["Wallet Address"];
|
|
506
615
|
if (context.model === null) {
|
|
507
616
|
appendWalletAvailability(lines, context);
|
|
508
617
|
return lines.join("\n");
|
|
509
618
|
}
|
|
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
|
-
}
|
|
619
|
+
const domains = context.model.domains
|
|
620
|
+
.filter((domain) => domain.localRelationship === "local")
|
|
621
|
+
.map((domain) => domain.name)
|
|
622
|
+
.sort();
|
|
623
|
+
const balance = context.snapshot === null
|
|
624
|
+
? null
|
|
625
|
+
: getBalance(context.snapshot.state, new Uint8Array(Buffer.from(context.model.walletScriptPubKeyHex, "hex")));
|
|
626
|
+
lines.push(`${context.model.walletAddress ?? `spk:${context.model.walletScriptPubKeyHex}`} balance ${balance === null ? "unavailable" : formatCogAmount(balance)} domains ${domains.length === 0 ? "none" : domains.join(", ")}`);
|
|
525
627
|
return lines.join("\n");
|
|
526
628
|
}
|
|
527
629
|
export function formatBalanceReport(context) {
|
|
@@ -534,23 +636,7 @@ export function formatBalanceReport(context) {
|
|
|
534
636
|
lines.push(`Indexer-backed balances are unavailable while the indexer is ${formatServiceHealth(context.indexer.health)}.`);
|
|
535
637
|
return lines.join("\n");
|
|
536
638
|
}
|
|
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");
|
|
639
|
+
return formatReadyBalanceReport(context);
|
|
554
640
|
}
|
|
555
641
|
export function formatLocksReport(context, options = {}) {
|
|
556
642
|
const lines = ["COG Locks"];
|
|
@@ -621,8 +707,6 @@ export function formatDomainsReport(context, options = {}) {
|
|
|
621
707
|
: visibleDomains.slice(0, options.limit);
|
|
622
708
|
for (const domain of renderedDomains) {
|
|
623
709
|
const pending = listPendingDomainMutations(context, domain.name);
|
|
624
|
-
const pendingAnchors = listPendingAnchorFamilies(context, domain.name);
|
|
625
|
-
const pendingFieldFamilies = listPendingFieldFamilies(context, domain.name);
|
|
626
710
|
const pendingFieldMutations = listPendingFieldMutations(context, domain.name);
|
|
627
711
|
const pendingText = pending.length === 0
|
|
628
712
|
? ""
|
|
@@ -635,18 +719,10 @@ export function formatDomainsReport(context, options = {}) {
|
|
|
635
719
|
: mutation.kind === "miner" && mutation.recipientScriptPubKeyHex === null
|
|
636
720
|
? `miner-clear:${mutation.status}`
|
|
637
721
|
: `${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")
|
|
722
|
+
const pendingFieldsText = pendingFieldMutations.length === 0
|
|
645
723
|
? ""
|
|
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}`);
|
|
724
|
+
: ` field-pending ${pendingFieldMutations.map((mutation) => `${mutation.fieldName}:${mutation.kind}:${mutation.status}`).join(",")}`;
|
|
725
|
+
lines.push(`${domain.name} ${domain.chainStatus} ${domain.localRelationship} owner ${domain.ownerAddress ?? domain.ownerScriptPubKeyHex ?? "unknown"} fields ${formatMaybe(domain.fieldCount)}${pendingText}${pendingFieldsText}`);
|
|
650
726
|
}
|
|
651
727
|
if (!options.all && options.limit !== null && options.limit !== undefined && visibleDomains.length > options.limit) {
|
|
652
728
|
lines.push(`Showing first ${renderedDomains.length} of ${visibleDomains.length}. Use --limit <n> or --all for more.`);
|
|
@@ -666,7 +742,7 @@ export function formatDomainReport(context, domainName) {
|
|
|
666
742
|
}
|
|
667
743
|
lines.push(`Domain ID: ${formatMaybe(view.domain.domainId)}`);
|
|
668
744
|
lines.push(`Anchored: ${view.domain.anchored === null ? "unknown" : (view.domain.anchored ? "yes" : "no")}`);
|
|
669
|
-
lines.push(`Owner: ${view.domain.
|
|
745
|
+
lines.push(`Owner: ${view.domain.ownerAddress ?? view.domain.ownerScriptPubKeyHex ?? "unknown"}`);
|
|
670
746
|
lines.push(`Local relationship: ${view.localRelationship}`);
|
|
671
747
|
lines.push(`Listing price: ${view.domain.listingPriceCogtoshi === null ? "none" : formatCogAmount(view.domain.listingPriceCogtoshi)}`);
|
|
672
748
|
lines.push(`Field count: ${formatMaybe(view.domain.fieldCount)}`);
|
|
@@ -679,17 +755,10 @@ export function formatDomainReport(context, domainName) {
|
|
|
679
755
|
lines.push(`Reputation total supported: ${view.domain.totalSupportedCogtoshi === null ? "unavailable" : formatCogAmount(view.domain.totalSupportedCogtoshi)}`);
|
|
680
756
|
lines.push(`Reputation total revoked: ${view.domain.totalRevokedCogtoshi === null ? "unavailable" : formatCogAmount(view.domain.totalRevokedCogtoshi)}`);
|
|
681
757
|
}
|
|
682
|
-
lines.push(`Local anchor intent: ${view.domain.localAnchorIntent ?? "none"}`);
|
|
683
758
|
lines.push(`Delegate: ${view.domain.delegateScriptPubKeyHex ?? "none"}`);
|
|
684
759
|
lines.push(`Designated miner: ${view.domain.minerScriptPubKeyHex ?? "none"}`);
|
|
685
760
|
lines.push(`Endpoint: ${view.domain.endpointText ?? "none"}`);
|
|
686
761
|
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
762
|
for (const mutation of listPendingDomainShowMutations(context, domainName)) {
|
|
694
763
|
lines.push(`Pending mutation: ${formatPendingMutationDomainLabel(mutation)} ${mutation.status}`);
|
|
695
764
|
}
|
|
@@ -726,9 +795,6 @@ export function formatFieldsReport(context, domainName, options = {}) {
|
|
|
726
795
|
for (const mutation of listPendingFieldMutations(context, domainName)) {
|
|
727
796
|
lines.push(`Pending field mutation: ${mutation.fieldName ?? "unknown"} ${mutation.kind} ${mutation.status}`);
|
|
728
797
|
}
|
|
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
798
|
if (!options.all && options.limit !== null && options.limit !== undefined && fields.length > options.limit) {
|
|
733
799
|
lines.push(`Showing first ${renderedFields.length} of ${fields.length}. Use --limit <n> or --all for more.`);
|
|
734
800
|
}
|
|
@@ -742,8 +808,6 @@ export function formatFieldReport(context, domainName, fieldName) {
|
|
|
742
808
|
}
|
|
743
809
|
const field = findDomainField(context, domainName, fieldName);
|
|
744
810
|
const pendingMutations = listPendingFieldMutations(context, domainName, fieldName);
|
|
745
|
-
const pendingFamilies = listPendingFieldFamilies(context, domainName)
|
|
746
|
-
.filter((family) => family.fieldName === fieldName);
|
|
747
811
|
if (field === null) {
|
|
748
812
|
lines.push("Field not found.");
|
|
749
813
|
}
|
|
@@ -759,8 +823,5 @@ export function formatFieldReport(context, domainName, fieldName) {
|
|
|
759
823
|
for (const mutation of pendingMutations) {
|
|
760
824
|
lines.push(`Pending field mutation: ${mutation.kind} ${mutation.status}`);
|
|
761
825
|
}
|
|
762
|
-
for (const family of pendingFamilies) {
|
|
763
|
-
lines.push(`Pending field family: ${family.status}${family.currentStep == null ? "" : ` step ${family.currentStep}`}`);
|
|
764
|
-
}
|
|
765
826
|
return lines.join("\n");
|
|
766
827
|
}
|
|
@@ -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
|
}
|