Skip to content

Commit

Permalink
refactor: Hide all the boilerplate code behind interactive clap macros (
Browse files Browse the repository at this point in the history
  • Loading branch information
FroVolod authored Dec 26, 2021
1 parent 27554f6 commit 00b1dc1
Show file tree
Hide file tree
Showing 177 changed files with 4,261 additions and 14,335 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/target
/test*
.DS_Store
near-cli
*.wasm
Expand Down
26 changes: 26 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ near-primitives = { git = "https://github.com/near/nearcore", rev="6f2a290227f4f
near-jsonrpc-client = { git = "https://github.com/near/nearcore", rev="6f2a290227f4f3b41c543b615231e769e438e28c" }
near-jsonrpc-primitives = { git = "https://github.com/near/nearcore", rev="6f2a290227f4f3b41c543b615231e769e438e28c" }

interactive_clap = { git = "https://github.com/FroVolod/interactive-clap", rev="89b5bee74035b0ba6d8603fbd9fc3da0ad31eaeb" }
interactive_clap_derive = { git = "https://github.com/FroVolod/interactive-clap-derive", rev="3531e842bdf53ccb82ac261f0eb7535bbd7126ed" }

[features]
default = ["ledger"]
ledger = ["near-ledger"]
131 changes: 14 additions & 117 deletions src/commands/add_command/access_key/operation_mode/mod.rs
Original file line number Diff line number Diff line change
@@ -1,53 +1,15 @@
use dialoguer::{theme::ColorfulTheme, Select};
use strum::{EnumDiscriminants, EnumIter, EnumMessage, IntoEnumIterator};
use strum::{EnumDiscriminants, EnumIter, EnumMessage};

mod offline_mode;
mod online_mode;

/// инструмент выбора режима online/offline
#[derive(Debug, Default, Clone, clap::Clap)]
#[clap(
setting(clap::AppSettings::ColoredHelp),
setting(clap::AppSettings::DisableHelpSubcommand),
setting(clap::AppSettings::VersionlessSubcommands)
)]
pub struct CliOperationMode {
#[clap(subcommand)]
mode: Option<CliMode>,
}

#[derive(Debug, Clone)]
#[derive(Debug, Clone, interactive_clap_derive::InteractiveClap)]
#[interactive_clap(context = ())]
pub struct OperationMode {
#[interactive_clap(subcommand)]
pub mode: Mode,
}

impl CliOperationMode {
pub fn to_cli_args(&self) -> std::collections::VecDeque<String> {
self.mode
.as_ref()
.map(|subcommand| subcommand.to_cli_args())
.unwrap_or_default()
}
}

impl From<OperationMode> for CliOperationMode {
fn from(item: OperationMode) -> Self {
Self {
mode: Some(item.mode.into()),
}
}
}

impl OperationMode {
pub fn from(item: CliOperationMode) -> color_eyre::eyre::Result<Self> {
let mode = match item.mode {
Some(cli_mode) => Mode::from(cli_mode)?,
None => Mode::choose_mode()?,
};
Ok(Self { mode })
}
}

impl OperationMode {
pub async fn process(
self,
Expand All @@ -57,92 +19,23 @@ impl OperationMode {
}
}

#[derive(Debug, Clone, clap::Clap)]
pub enum CliMode {
/// Prepare and, optionally, submit a new transaction with online mode
Network(self::online_mode::CliNetworkArgs),
/// Prepare and, optionally, submit a new transaction with offline mode
Offline(self::offline_mode::CliOfflineArgs),
}

#[derive(Debug, Clone, EnumDiscriminants)]
#[derive(Debug, Clone, EnumDiscriminants, interactive_clap_derive::InteractiveClap)]
#[strum_discriminants(derive(EnumMessage, EnumIter))]
#[interactive_clap(context = ())]
///To construct a transaction you will need to provide information about sender (signer) and receiver accounts, and actions that needs to be performed.
///Do you want to derive some information required for transaction construction automatically querying it online?
pub enum Mode {
#[strum_discriminants(strum(message = "Yes, I keep it simple"))]
/// Prepare and, optionally, submit a new transaction with online mode
Network(self::online_mode::NetworkArgs),
#[strum_discriminants(strum(
message = "No, I want to work in no-network (air-gapped) environment"
))]
/// Prepare and, optionally, submit a new transaction with offline mode
Offline(self::offline_mode::OfflineArgs),
}

impl CliMode {
pub fn to_cli_args(&self) -> std::collections::VecDeque<String> {
match self {
Self::Network(subcommand) => {
let mut args = subcommand.to_cli_args();
args.push_front("network".to_owned());
args
}
Self::Offline(subcommand) => {
let mut args = subcommand.to_cli_args();
args.push_front("offline".to_owned());
args
}
}
}
}

impl From<Mode> for CliMode {
fn from(mode: Mode) -> Self {
match mode {
Mode::Network(network_args) => {
Self::Network(self::online_mode::CliNetworkArgs::from(network_args))
}
Mode::Offline(offline_args) => {
Self::Offline(self::offline_mode::CliOfflineArgs::from(offline_args))
}
}
}
}

impl Mode {
fn from(item: CliMode) -> color_eyre::eyre::Result<Self> {
match item {
CliMode::Network(cli_network_args) => Ok(Self::Network(
self::online_mode::NetworkArgs::from(cli_network_args)?,
)),
CliMode::Offline(cli_offline_args) => Ok(Self::Offline(
self::offline_mode::OfflineArgs::from(cli_offline_args)?,
)),
}
}
}

impl Mode {
fn choose_mode() -> color_eyre::eyre::Result<Self> {
println!();
let variants = ModeDiscriminants::iter().collect::<Vec<_>>();
let modes = variants
.iter()
.map(|p| p.get_message().unwrap().to_owned())
.collect::<Vec<_>>();
let selected_mode = Select::with_theme(&ColorfulTheme::default())
.with_prompt(
"To construct a transaction you will need to provide information about sender (signer) and receiver accounts, and actions that needs to be performed.
\nDo you want to derive some information required for transaction construction automatically querying it online?"
)
.items(&modes)
.default(0)
.interact()
.unwrap();
let cli_mode = match variants[selected_mode] {
ModeDiscriminants::Network => CliMode::Network(Default::default()),
ModeDiscriminants::Offline => CliMode::Offline(Default::default()),
};
Ok(Self::from(cli_mode)?)
}

pub async fn process(
self,
prepopulated_unsigned_transaction: near_primitives::transaction::Transaction,
Expand All @@ -161,3 +54,7 @@ impl Mode {
}
}
}

pub struct AddAccessKeyCommandNetworkContext {
pub connection_config: Option<crate::common::ConnectionConfig>,
}
Original file line number Diff line number Diff line change
@@ -1,56 +1,38 @@
/// аргументы, необходимые для создания трансфера в offline mode
#[derive(Debug, Default, Clone, clap::Clap)]
#[clap(
setting(clap::AppSettings::ColoredHelp),
setting(clap::AppSettings::DisableHelpSubcommand),
setting(clap::AppSettings::VersionlessSubcommands)
)]
pub struct CliOfflineArgs {
#[clap(subcommand)]
pub send_from: Option<super::online_mode::select_server::server::CliSendFrom>,
}

#[derive(Debug, Clone)]
#[derive(Debug, Clone, interactive_clap_derive::InteractiveClap)]
#[interactive_clap(context = ())]
#[interactive_clap(output_context = OfflineArgsContext)]
pub struct OfflineArgs {
send_from: super::online_mode::select_server::server::SendFrom,
#[interactive_clap(named_arg)]
///Specify a sender
account: super::super::sender::Sender,
}

impl CliOfflineArgs {
pub fn to_cli_args(&self) -> std::collections::VecDeque<String> {
self.send_from
.as_ref()
.map(|subcommand| subcommand.to_cli_args())
.unwrap_or_default()
struct OfflineArgsContext {}

impl OfflineArgsContext {
fn from_previous_context(
_previous_context: (),
_scope: &<OfflineArgs as interactive_clap::ToInteractiveClapContextScope>::InteractiveClapContextScope,
) -> Self {
Self {}
}
}

impl From<OfflineArgs> for CliOfflineArgs {
fn from(offline_args: OfflineArgs) -> Self {
impl From<OfflineArgsContext> for super::AddAccessKeyCommandNetworkContext {
fn from(_: OfflineArgsContext) -> Self {
Self {
send_from: Some(offline_args.send_from.into()),
connection_config: None,
}
}
}

impl OfflineArgs {
pub fn from(item: CliOfflineArgs) -> color_eyre::eyre::Result<Self> {
let send_from = match item.send_from {
Some(cli_send_from) => {
super::online_mode::select_server::server::SendFrom::from(cli_send_from, None)?
}
None => super::online_mode::select_server::server::SendFrom::choose_send_from(None)?,
};
Ok(Self { send_from })
}
}

impl OfflineArgs {
pub async fn process(
self,
prepopulated_unsigned_transaction: near_primitives::transaction::Transaction,
) -> crate::CliResult {
let selected_server_url = None;
self.send_from
self.account
.process(prepopulated_unsigned_transaction, selected_server_url)
.await
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,51 +1,12 @@
pub mod select_server;

/// аргументы, необходимые для создания транзакции в online mode
#[derive(Debug, Default, Clone, clap::Clap)]
#[clap(
setting(clap::AppSettings::ColoredHelp),
setting(clap::AppSettings::DisableHelpSubcommand),
setting(clap::AppSettings::VersionlessSubcommands)
)]
pub struct CliNetworkArgs {
#[clap(subcommand)]
selected_server: Option<self::select_server::CliSelectServer>,
}

#[derive(Debug, Clone)]
#[derive(Debug, Clone, interactive_clap_derive::InteractiveClap)]
#[interactive_clap(context = ())]
pub struct NetworkArgs {
#[interactive_clap(subcommand)]
selected_server: self::select_server::SelectServer,
}

impl CliNetworkArgs {
pub fn to_cli_args(&self) -> std::collections::VecDeque<String> {
self.selected_server
.as_ref()
.map(|subcommand| subcommand.to_cli_args())
.unwrap_or_default()
}
}

impl From<NetworkArgs> for CliNetworkArgs {
fn from(network_args: NetworkArgs) -> Self {
Self {
selected_server: Some(network_args.selected_server.into()),
}
}
}

impl NetworkArgs {
pub fn from(item: CliNetworkArgs) -> color_eyre::eyre::Result<Self> {
let selected_server = match item.selected_server {
Some(cli_selected_server) => {
self::select_server::SelectServer::from(cli_selected_server)?
}
None => self::select_server::SelectServer::choose_server()?,
};
Ok(Self { selected_server })
}
}

impl NetworkArgs {
pub async fn process(
self,
Expand Down
Loading

0 comments on commit 00b1dc1

Please sign in to comment.