Add documentation to the commands for the CLI

This commit is contained in:
2026-05-04 12:14:40 +00:00
parent 8d7856f32e
commit 3c47ee8a4c
11 changed files with 480 additions and 55 deletions
+53 -3
View File
@@ -30,18 +30,27 @@ function formatResource(
resource: UnspentOutputData,
showReserved = false,
): string {
// Format the outpoint
const outpoint = bold(
`${resource.outpointTransactionHash}:${resource.outpointIndex}`,
);
// Format the value
const value = dim(`${resource.valueSatoshis} sats`);
// Format the output
const output = dim(resource.outputIdentifier);
// Format the height
const height = dim(`(height ${resource.minedAtHeight})`);
// If the resource is reserved, format the reservation info
if (showReserved && resource.reservedBy) {
const inv = dim(`reserved for ${resource.reservedBy}`);
return `${outpoint} ${value} ${output} ${height} ${inv}`;
}
// Otherwise, format the resource without reservation info
return `${outpoint} ${value} ${output} ${height}`;
}
@@ -60,6 +69,7 @@ export const handleResourceCommand = async (
const subCommand = args[0];
deps.io.verbose(`Resource sub-command: ${subCommand}`);
// If no sub-command is provided, print the help message and throw an error
if (!subCommand) {
deps.io.verbose("No sub-command provided");
printResourceHelp(deps.io);
@@ -69,39 +79,59 @@ export const handleResourceCommand = async (
);
}
// Handle the sub-command
switch (subCommand) {
case "list": {
// Get the qualifier from the arguments - This could be "reserved", "all", or omitted (which defaults to "unreserved")
const qualifier = args[1];
// List all the unspent outputs data
const allResources = await deps.app.engine.listUnspentOutputsData();
let filtered;
// If the qualifier is "reserved", return only the reserved resources
if (qualifier === "reserved") {
filtered = allResources.filter((r) => r.reservedBy);
} else if (qualifier === "all") {
}
// If the qualifier is "all", return all the resources
else if (qualifier === "all") {
filtered = allResources;
} else {
}
// If the qualifier is not "reserved" or "all", return only the unreserved resources
else {
filtered = allResources.filter((r) => !r.reservedBy);
}
// If no resources are found, print a message and return 0
if (filtered.length === 0) {
deps.io.out(dim("No resources found."));
return { count: 0 };
}
// Format the resources into a list of strings that we can display to the user
const showReserved = qualifier === "all" || qualifier === "reserved";
const formattedResources = filtered.map((r) =>
formatResource(r, showReserved),
);
// Display the resources to the user
deps.io.out(formattedResources.join("\n"));
// Display the total satoshis
deps.io.out(
`Total satoshis: ${filtered.reduce((acc, r) => acc + r.valueSatoshis, 0)}`,
);
// Display the total resources
deps.io.out(`Total resources: ${filtered.length}`);
return { count: filtered.length };
}
case "unreserve": {
// Get the outpoint from the arguments
const outpointArg = args[1];
// If no outpoint is provided, print a message and throw an error
if (!outpointArg) {
deps.io.err("Please provide a UTXO in <txhash>:<vout> format.");
printResourceHelp(deps.io);
@@ -111,8 +141,10 @@ export const handleResourceCommand = async (
);
}
// Get the separator index
const separatorIndex = outpointArg.lastIndexOf(":");
if (separatorIndex === -1) {
// If the separator index is -1 (not found), print a message and throw an error
deps.io.err(
`Invalid format "${outpointArg}". Expected <txhash>:<vout>.`,
);
@@ -122,8 +154,11 @@ export const handleResourceCommand = async (
);
}
// Get the tx hash and vout
const txHash = outpointArg.substring(0, separatorIndex);
const vout = parseInt(outpointArg.substring(separatorIndex + 1), 10);
// If the tx hash or vout is not a string or isNaN, print a message and throw an error
if (!txHash || isNaN(vout)) {
deps.io.err(
`Invalid format "${outpointArg}". Expected <txhash>:<vout>.`,
@@ -134,11 +169,15 @@ export const handleResourceCommand = async (
);
}
// Gather all of our resources
const allResources = await deps.app.engine.listUnspentOutputsData();
// Find the target resource
const target = allResources.find(
(r) => r.outpointTransactionHash === txHash && r.outpointIndex === vout,
);
// If the target resource is not found, print a message and throw an error
if (!target) {
deps.io.err(`UTXO not found: ${txHash}:${vout}`);
throw new CommandError(
@@ -147,28 +186,39 @@ export const handleResourceCommand = async (
);
}
// If the target resource is not reserved, print a message and return
if (!target.reservedBy) {
deps.io.out(dim("UTXO is not reserved. Nothing to do."));
return {};
}
// Unreserve the resources
await deps.app.engine.unreserveResources(
[{ outpointTransactionHash: hexToBin(txHash), outpointIndex: vout }],
target.reservedBy,
);
deps.io.out(
`Unreserved ${bold(`${txHash}:${vout}`)} (was reserved for ${target.reservedBy})`,
);
// TODO: What do I want to return here?
return {};
}
case "unreserve-all": {
// Unreserve all the resources
const count = await deps.app.unreserveAllResources();
// If no resources are reserved, print a message and return
if (count === 0) {
deps.io.out(dim("No reserved resources to unreserve."));
} else {
}
// If some resources were unreserved, print a message and return the count
else {
deps.io.out(`Unreserved ${bold(String(count))} resource(s).`);
}
return { count };
}