Skip to content

Commit

Permalink
CSUB-638: Add chain/era info to the Status command (#1201)
Browse files Browse the repository at this point in the history
* add: add --chain & --validator flag to status

* rename status util to validatorStatus

* rename getStatus to getValidatorStatus

* add: implement cli-table for validatorStatus
  • Loading branch information
pLabarta authored and atodorov committed Aug 15, 2023
1 parent b5693f7 commit d664284
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 37 deletions.
6 changes: 3 additions & 3 deletions scripts/cc-cli/src/commands/chill.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
initKeyringPair,
} from "../utils/account";
import { chill } from "../utils/validate";
import { getStatus, requireStatus } from "../utils/status";
import { getValidatorStatus, requireStatus } from "../utils/validatorStatus";

export function makeChillCommand() {
const cmd = new Command("chill");
Expand All @@ -23,13 +23,13 @@ async function chillAction(options: OptionValues) {
const controllerKeyring = initKeyringPair(controllerSeed);
const controllerAddress = controllerKeyring.address;

const controllerStatus = await getStatus(controllerAddress, api);
const controllerStatus = await getValidatorStatus(controllerAddress, api);

if (!controllerStatus.stash) {
console.error(`Cannot chill, ${controllerAddress} is not staked`);
process.exit(1);
}
const stashStatus = await getStatus(controllerStatus.stash, api);
const stashStatus = await getValidatorStatus(controllerStatus.stash, api);

requireStatus(stashStatus, "validating");

Expand Down
39 changes: 27 additions & 12 deletions scripts/cc-cli/src/commands/status.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,45 @@
import { Command, OptionValues } from "commander";
import { newApi } from "../api";
import { getStatus, printValidatorStatus } from "../utils/status";
import { parseAddressOrExit, requiredInput } from "../utils/parsing";
import {
getValidatorStatus,
printValidatorStatus,
} from "../utils/validatorStatus";
import { parseAddressOrExit, parseBoolean } from "../utils/parsing";
import { getChainStatus, printChainStatus } from "../utils/chainStatus";

export function makeStatusCommand() {
const cmd = new Command("status");
cmd.description("Get staking status for an address");
cmd.option("-a, --address [address]", "Address to get status for");
cmd.option(
"--validator [address]",
"Validator stash address to get status for"
);
cmd.option("--chain", "Show chain status");
cmd.action(statusAction);
return cmd;
}

async function statusAction(options: OptionValues) {
const { api } = await newApi(options.url);

// Check options
const address = parseAddressOrExit(
requiredInput(
options.address,
"Failed to show validator status: Must specify an address"
)
);
const showValidatorStatus = parseBoolean(options.validator);
let showChainStatus = parseBoolean(options.chain);

if (!showValidatorStatus && !showChainStatus) {
showChainStatus = true;
}

const validatorStatus = await getStatus(address, api);
if (showChainStatus) {
const chainStatus = await getChainStatus(api);
printChainStatus(chainStatus);
}

await printValidatorStatus(validatorStatus, api);
if (showValidatorStatus) {
const validator = parseAddressOrExit(options.validator);
const validatorStatus = await getValidatorStatus(validator, api);
console.log(`Validator ${validator}:`);
await printValidatorStatus(validatorStatus, api);
}

process.exit(0);
}
8 changes: 4 additions & 4 deletions scripts/cc-cli/src/commands/unbond.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import {
initKeyringPair,
} from "../utils/account";
import { getBalance } from "../utils/balance";
import { getStatus, requireStatus } from "../utils/status";
import { requireEnoughFundsToSend, signSendAndWatch } from "../utils/tx";
import { ApiPromise, BN } from "creditcoin-js";
import { promptContinue } from "../utils/promptContinue";
import { parseAmountOrExit, requiredInput } from "../utils/parsing";
import { getValidatorStatus, requireStatus } from "../utils/validatorStatus";
import { requireEnoughFundsToSend, signSendAndWatch } from "../utils/tx";

export function makeUnbondCommand() {
const cmd = new Command("unbond");
Expand All @@ -31,14 +31,14 @@ async function unbondAction(options: OptionValues) {
const controllerKeyring = initKeyringPair(controllerSeed);
const controllerAddress = controllerKeyring.address;

const controllerStatus = await getStatus(controllerAddress, api);
const controllerStatus = await getValidatorStatus(controllerAddress, api);
if (!controllerStatus.stash) {
console.error(
`Cannot unbond, ${controllerAddress} is not a controller account`
);
process.exit(1);
}
const stashStatus = await getStatus(controllerStatus.stash, api);
const stashStatus = await getValidatorStatus(controllerStatus.stash, api);
requireStatus(stashStatus, "bonded");

// Check if amount specified exceeds total bonded funds
Expand Down
6 changes: 3 additions & 3 deletions scripts/cc-cli/src/commands/withdrawUnbonded.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Command, OptionValues } from "commander";
import { newApi } from "../api";
import { getStatus, requireStatus } from "../utils/status";
import { getValidatorStatus, requireStatus } from "../utils/validatorStatus";
import {
getControllerSeedFromEnvOrPrompt,
initKeyringPair,
Expand All @@ -20,7 +20,7 @@ async function withdrawUnbondedAction(options: OptionValues) {
const controllerSeed = await getControllerSeedFromEnvOrPrompt();
const controller = initKeyringPair(controllerSeed);

const controllerStatus = await getStatus(controller.address, api);
const controllerStatus = await getValidatorStatus(controller.address, api);

if (!controllerStatus.stash) {
console.error(
Expand All @@ -29,7 +29,7 @@ async function withdrawUnbondedAction(options: OptionValues) {
process.exit(1);
}

const status = await getStatus(controllerStatus.stash, api);
const status = await getValidatorStatus(controllerStatus.stash, api);
requireStatus(
status,
"canWithdraw",
Expand Down
53 changes: 53 additions & 0 deletions scripts/cc-cli/src/utils/chainStatus.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { ApiPromise } from "creditcoin-js";
import Table from "cli-table3";

interface ChainStatus {
name: string;
bestNumber: number;
bestFinalizedNumber: number;
eraInfo: EraInfo;
}

export async function getChainStatus(api: ApiPromise): Promise<ChainStatus> {
const bestNumber = await api.derive.chain.bestNumber();
const bestFinalizedNumber = await api.derive.chain.bestNumberFinalized();
const eraInfo = await getEraInfo(api);
return {
name: api.runtimeVersion.specName.toString(),
bestNumber: bestNumber.toNumber(),
bestFinalizedNumber: bestFinalizedNumber.toNumber(),
eraInfo,
};
}

interface EraInfo {
era: number;
currentSession: number;
sessionsPerEra: number;
}

async function getEraInfo(api: ApiPromise): Promise<EraInfo> {
const session = await api.derive.session.info();
return {
era: session.activeEra.toNumber(),
currentSession:
(session.currentIndex.toNumber() % session.sessionsPerEra.toNumber()) + 1,
sessionsPerEra: session.sessionsPerEra.toNumber(),
};
}

export function printChainStatus(status: ChainStatus) {
const { eraInfo } = status;
const table = new Table({
head: [status.name],
});

table.push(
["Best Block", status.bestNumber],
["Best Finalized Block", status.bestFinalizedNumber],
["Era", eraInfo.era],
["Session", `${eraInfo.currentSession}/${eraInfo.sessionsPerEra}`]
);
console.log("Chain status:");
console.log(table.toString());
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ApiPromise, BN } from "creditcoin-js";
import { readAmount, readAmountFromHex, toCTCString } from "./balance";
import { timeTillEra } from "./era";
import Table from "cli-table3";

function formatDaysHoursMinutes(ms: number) {
const days = Math.floor(ms / (24 * 60 * 60 * 1000));
Expand All @@ -19,7 +20,7 @@ function formatDaysHoursMinutes(ms: number) {
return `${daysString}${hoursString}${minutesString}${secString}`;
}

export async function getStatus(address: string, api: ApiPromise) {
export async function getValidatorStatus(address: string, api: ApiPromise) {
const res = await api.derive.staking.account(address);
const totalStaked = readAmount(res.stakingLedger.total.toString());
const bonded = totalStaked.gt(new BN(0));
Expand Down Expand Up @@ -94,23 +95,22 @@ export async function getStatus(address: string, api: ApiPromise) {
}

export async function printValidatorStatus(status: Status, api: ApiPromise) {
console.log("Bonded: ", status.bonded);
if (status.stash) console.log("Stash: ", status.stash);
console.log("Controller: ", status.controller);
console.log("Validating: ", status.validating);
console.log("Waiting: ", status.waiting);
console.log("Active: ", status.active);

console.log("Can withdraw: ", status.canWithdraw);
const table = new Table({
head: ["Status"],
});

table.push(["Bonded", status.bonded ? "Yes" : "No"]);
table.push(["Stash", status.stash ? status.stash : "None"]);
table.push(["Controller", status.controller]);
table.push(["Validating", status.validating ? "Yes" : "No"]);
table.push(["Waiting", status.waiting ? "Yes" : "No"]);
table.push(["Active", status.active ? "Yes" : "No"]);
table.push(["Can withdraw", status.canWithdraw ? "Yes" : "No"]);
if (status.canWithdraw) {
console.log("Unlocked chunks: ");
status.readyForWithdraw.forEach((chunk) => {
console.log(
` ${toCTCString(chunk.value)} unlocked since era ${chunk.era}`
);
table.push([`Unlocked since era ${chunk.era}`, toCTCString(chunk.value)]);
});
}

let nextUnlocking = "None";
if (status.nextUnbondingAmount && status.nextUnbondingAmount.eq(new BN(0))) {
nextUnlocking = "None";
Expand All @@ -121,7 +121,9 @@ export async function printValidatorStatus(status: Status, api: ApiPromise) {
nextUnbondingDate.toNumber()
)}`;
}
console.log(`Next unbonding chunk: ${nextUnlocking}`);
table.push(["Next unlocking", nextUnlocking]);

console.log(table.toString());
}

export function requireStatus(
Expand Down

0 comments on commit d664284

Please sign in to comment.