message: Initial implementation of `stop` command CLI
diff: @@ -3,6 +3,7 @@ use std::{
  str::FromStr,
  };
  +use casper_types::EraId;
  use serde::Serialize;
  use structopt::StructOpt;
  use thiserror::Error;
  @@ -90,10 +91,55 @@ pub(super) enum Action {
  DumpQueues,
  /// Get detailed networking insights.
  NetInfo,
  + /// Stop the node at a certain condition.
  + Stop {
  + /// When to stop the node. Supports `block:12345` for block height, `era:123` for eras,
  + /// `block:next` / `era:next` to stop on an upcoming block or eta, or `now` to stop
  + /// immediately. Defaults to `block:next`."
  + #[structopt(short, long, default_value)]
  + at: StopAtSpec,
  + /// Ignore all further options to stop and clear any currently scheduled stops.
  + #[structopt(short, long)]
  + clear: bool,
  + },
  /// Close connection server-side.
  Quit,
  }
  +/// A specification for a stopping point.
  +
  +#[derive(Copy, Clone, Debug)]
  +enum StopAtSpec {
  + /// Stop after completion of the current block.
  + NextBlock,
  + /// Stop after the completion of the next switch block.
  + NextEra,
  + /// Stop immediately.
  + Immediately,
  + /// Stop at a given block height.
  + BlockHeight(u64),
  + /// Stop at a given era id.
  + EraId(EraId),
  +}
  +
  +impl Default for StopAtSpec {
  + fn default() -> Self {
  + StopAtSpec::NextBlock
  + }
  +}
  +
  +impl Display for StopAtSpec {
  + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
  + match self {
  + StopAtSpec::NextBlock => f.write_str("block:next"),
  + StopAtSpec::NextEra => f.write_str("era:next"),
  + StopAtSpec::Immediately => f.write_str("now"),
  + StopAtSpec::BlockHeight(height) => write!(f, "block:{}", height),
  + StopAtSpec::EraId(era_id) => write!(f, "era:{}", u64::from(EraId)),
  + }
  + }
  +}
  +
  /// A command to be performed on the node's diagnostic port.
  #[derive(Debug, StructOpt)]
  pub(super) struct Command {
  