Skip to content

Commit

Permalink
feat: New command - create-dev-account (#108)
Browse files Browse the repository at this point in the history
  • Loading branch information
FroVolod authored and frol committed Oct 19, 2023
1 parent e26f74e commit 577c41b
Show file tree
Hide file tree
Showing 8 changed files with 941 additions and 262 deletions.
959 changes: 809 additions & 150 deletions Cargo.lock

Large diffs are not rendered by default.

8 changes: 5 additions & 3 deletions cargo-near/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,11 @@ color-eyre = "0.6"
inquire = "0.6"
strum = { version = "0.24", features = ["derive"] }
strum_macros = "0.24"
interactive-clap = "0.2.5"
interactive-clap-derive = "0.2.5"
near-cli-rs = { version = "0.5.2" }
interactive-clap = "0.2.6"
interactive-clap-derive = "0.2.6"
linked-hash-map = { version = "0.5", features = ["serde_impl"] }
names = { version = "0.14.0", default-features = false }
near-cli-rs = { git = "https://github.com/near/near-cli-rs" }
derive_more = "0.99.9"
shell-words = "1.0.0"
dunce = "1"
58 changes: 7 additions & 51 deletions cargo-near/src/commands/abi_command/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,45 +30,21 @@ impl interactive_clap::FromCli for AbiCommand {
type FromCliError = color_eyre::eyre::Error;
fn from_cli(
optional_clap_variant: Option<<Self as interactive_clap::ToCli>::CliVariant>,
context: Self::FromCliContext,
_context: Self::FromCliContext,
) -> interactive_clap::ResultFromCli<
<Self as interactive_clap::ToCli>::CliVariant,
Self::FromCliError,
>
where
Self: Sized + interactive_clap::ToCli,
{
let mut clap_variant = optional_clap_variant.unwrap_or_default();
let doc = clap_variant.doc;
let compact_abi = clap_variant.compact_abi;
if clap_variant.out_dir.is_none() {
clap_variant.out_dir = match Self::input_out_dir(&context) {
Ok(optional_out_dir) => optional_out_dir,
Err(err) => return interactive_clap::ResultFromCli::Err(Some(clap_variant), err),
};
};
let out_dir = clap_variant.out_dir.clone();
if clap_variant.manifest_path.is_none() {
clap_variant.manifest_path = match Self::input_manifest_path(&context) {
Ok(optional_manifest_path) => optional_manifest_path,
Err(err) => return interactive_clap::ResultFromCli::Err(Some(clap_variant), err),
};
};
let manifest_path = clap_variant.manifest_path.clone();
if clap_variant.color.is_none() {
clap_variant.color = match Self::input_color(&context) {
Ok(optional_color) => optional_color,
Err(err) => return interactive_clap::ResultFromCli::Err(Some(clap_variant), err),
};
};
let color = clap_variant.color.clone();

let clap_variant = optional_clap_variant.unwrap_or_default();
let args = Self {
doc,
compact_abi,
out_dir,
manifest_path,
color,
doc: clap_variant.doc,
compact_abi: clap_variant.compact_abi,
out_dir: clap_variant.out_dir.clone(),
manifest_path: clap_variant.manifest_path.clone(),
color: clap_variant.color.clone(),
};
if let Err(err) = self::abi::run(args) {
interactive_clap::ResultFromCli::Err(Some(clap_variant), color_eyre::eyre::eyre!(err))
Expand All @@ -77,23 +53,3 @@ impl interactive_clap::FromCli for AbiCommand {
}
}
}

impl AbiCommand {
fn input_color(
_context: &near_cli_rs::GlobalContext,
) -> color_eyre::eyre::Result<Option<crate::common::ColorPreference>> {
Ok(None)
}

fn input_out_dir(
_context: &near_cli_rs::GlobalContext,
) -> color_eyre::eyre::Result<Option<crate::types::utf8_path_buf::Utf8PathBufInner>> {
Ok(None)
}

fn input_manifest_path(
_context: &near_cli_rs::GlobalContext,
) -> color_eyre::eyre::Result<Option<crate::types::utf8_path_buf::Utf8PathBufInner>> {
Ok(None)
}
}
66 changes: 10 additions & 56 deletions cargo-near/src/commands/build_command/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pub mod build;

#[derive(Debug, Clone, interactive_clap::InteractiveClap)]
#[derive(Debug, Default, Clone, interactive_clap::InteractiveClap)]
#[interactive_clap(context = near_cli_rs::GlobalContext)]
#[interactive_clap(skip_default_from_cli)]
pub struct BuildCommand {
Expand Down Expand Up @@ -36,49 +36,23 @@ impl interactive_clap::FromCli for BuildCommand {
type FromCliError = color_eyre::eyre::Error;
fn from_cli(
optional_clap_variant: Option<<Self as interactive_clap::ToCli>::CliVariant>,
context: Self::FromCliContext,
_context: Self::FromCliContext,
) -> interactive_clap::ResultFromCli<
<Self as interactive_clap::ToCli>::CliVariant,
Self::FromCliError,
>
where
Self: Sized + interactive_clap::ToCli,
{
let mut clap_variant = optional_clap_variant.unwrap_or_default();
let release = clap_variant.release;
let embed_abi = clap_variant.embed_abi;
let doc = clap_variant.doc;
let no_abi = clap_variant.no_abi;
if clap_variant.out_dir.is_none() {
clap_variant.out_dir = match Self::input_out_dir(&context) {
Ok(optional_out_dir) => optional_out_dir,
Err(err) => return interactive_clap::ResultFromCli::Err(Some(clap_variant), err),
};
};
let out_dir = clap_variant.out_dir.clone();
if clap_variant.manifest_path.is_none() {
clap_variant.manifest_path = match Self::input_manifest_path(&context) {
Ok(optional_manifest_path) => optional_manifest_path,
Err(err) => return interactive_clap::ResultFromCli::Err(Some(clap_variant), err),
};
};
let manifest_path = clap_variant.manifest_path.clone();
if clap_variant.color.is_none() {
clap_variant.color = match Self::input_color(&context) {
Ok(optional_color) => optional_color,
Err(err) => return interactive_clap::ResultFromCli::Err(Some(clap_variant), err),
};
};
let color = clap_variant.color.clone();

let clap_variant = optional_clap_variant.unwrap_or_default();
let args = Self {
release,
embed_abi,
doc,
no_abi,
out_dir,
manifest_path,
color,
release: clap_variant.release,
embed_abi: clap_variant.embed_abi,
doc: clap_variant.doc,
no_abi: clap_variant.no_abi,
out_dir: clap_variant.out_dir.clone(),
manifest_path: clap_variant.manifest_path.clone(),
color: clap_variant.color.clone(),
};
if let Err(err) = self::build::run(args).map(|_| ()) {
interactive_clap::ResultFromCli::Err(Some(clap_variant), color_eyre::eyre::eyre!(err))
Expand All @@ -87,23 +61,3 @@ impl interactive_clap::FromCli for BuildCommand {
}
}
}

impl BuildCommand {
fn input_color(
_context: &near_cli_rs::GlobalContext,
) -> color_eyre::eyre::Result<Option<crate::common::ColorPreference>> {
Ok(None)
}

fn input_out_dir(
_context: &near_cli_rs::GlobalContext,
) -> color_eyre::eyre::Result<Option<crate::types::utf8_path_buf::Utf8PathBufInner>> {
Ok(None)
}

fn input_manifest_path(
_context: &near_cli_rs::GlobalContext,
) -> color_eyre::eyre::Result<Option<crate::types::utf8_path_buf::Utf8PathBufInner>> {
Ok(None)
}
}
29 changes: 29 additions & 0 deletions cargo-near/src/commands/create_dev_account/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use strum::{EnumDiscriminants, EnumIter, EnumMessage};

pub mod use_random_account_id;

#[derive(Debug, Clone, interactive_clap::InteractiveClap)]
#[interactive_clap(context = near_cli_rs::GlobalContext)]
pub struct CreateAccount {
#[interactive_clap(subcommand)]
account_actions: CreateAccountMethod,
}

#[derive(Debug, EnumDiscriminants, Clone, interactive_clap::InteractiveClap)]
#[interactive_clap(context = near_cli_rs::GlobalContext)]
#[strum_discriminants(derive(EnumMessage, EnumIter))]
/// How do you cover the costs of account creation?
pub enum CreateAccountMethod {
#[strum_discriminants(strum(
message = "use-random-account-id - I would like to create a random account (useful for quick start development)"
))]
/// Use a random name for account (useful for quick start development)
UseRandomAccountId(self::use_random_account_id::RandomAccount),
#[strum_discriminants(strum(
message = "use-specific-account-id - I would like to create a specific account"
))]
/// I would like to create a specific account
UseSpecificAccountId(
near_cli_rs::commands::account::create_account::sponsor_by_faucet_service::NewAccount,
),
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
use std::str::FromStr;

use color_eyre::eyre::ContextCompat;
use names::Generator;

use near_cli_rs::commands::account::create_account::sponsor_by_faucet_service::{
add_key, before_creating_account, network, NewAccountContext,
};

#[derive(Debug, Clone, interactive_clap::InteractiveClap)]
#[interactive_clap(input_context = near_cli_rs::GlobalContext)]
#[interactive_clap(output_context = RandomAccountContext)]
pub struct RandomAccount {
#[interactive_clap(subcommand)]
access_key_mode: add_key::AccessKeyMode,
}

#[derive(Clone)]
pub struct RandomAccountContext(NewAccountContext);

impl RandomAccountContext {
pub fn from_previous_context(
previous_context: near_cli_rs::GlobalContext,
_scope: &<RandomAccount as interactive_clap::ToInteractiveClapContextScope>::InteractiveClapContextScope,
) -> color_eyre::eyre::Result<Self> {
let credentials_home_dir = previous_context.config.credentials_home_dir.clone();
let random_account_id = random_account_id(&previous_context.config.network_connection)?;

let on_before_creating_account_callback: network::OnBeforeCreatingAccountCallback =
std::sync::Arc::new({
move |network_config, new_account_id, public_key| {
before_creating_account(
network_config,
new_account_id,
public_key,
&credentials_home_dir,
)
}
});

Ok(Self(NewAccountContext {
config: previous_context.config,
new_account_id: random_account_id,
on_before_creating_account_callback,
}))
}
}

impl From<RandomAccountContext> for NewAccountContext {
fn from(item: RandomAccountContext) -> Self {
item.0
}
}

pub fn random_account_id(
networks: &linked_hash_map::LinkedHashMap<String, near_cli_rs::config::NetworkConfig>,
) -> color_eyre::eyre::Result<near_cli_rs::types::account_id::AccountId> {
loop {
let mut generator = Generator::default();
let random_name = generator.next().wrap_err("Random name generator error")?;
let account_id =
near_cli_rs::types::account_id::AccountId::from_str(&format!("{random_name}.testnet"))?;
if !near_cli_rs::common::is_account_exist(networks, account_id.clone().into()) {
return Ok(account_id);
}
}
}
15 changes: 13 additions & 2 deletions cargo-near/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use strum::{EnumDiscriminants, EnumIter, EnumMessage};

pub mod abi_command;
pub mod build_command;
pub mod create_dev_account;

#[derive(Debug, EnumDiscriminants, Clone, interactive_clap::InteractiveClap)]
#[interactive_clap(context = near_cli_rs::GlobalContext)]
Expand All @@ -10,11 +11,21 @@ pub mod build_command;
/// What are you up to? (select one of the options with the up-down arrows on your keyboard and press Enter)
pub enum NearCommand {
#[strum_discriminants(strum(
message = "build - Build a NEAR contract and optionally embed ABI"
message = "build - Build a NEAR contract and optionally embed ABI"
))]
/// Build a NEAR contract and optionally embed ABI
Build(self::build_command::BuildCommand),
#[strum_discriminants(strum(message = "abi - Generates ABI for the contract"))]
#[strum_discriminants(strum(
message = "abi - Generates ABI for the contract"
))]
/// Generates ABI for the contract
Abi(self::abi_command::AbiCommand),
#[strum_discriminants(strum(
message = "create-dev-account - Create a development account using the faucet service sponsor to cover
the cost of creating an account (testnet only for now).
To create an account on another network, you need to use \"near-cli-rs\":
https://github.com/near/near-cli-rs"
))]
/// Create a development account using the faucet service sponsor to cover the cost of creating an account (testnet only for now)
CreateDevAccount(self::create_dev_account::CreateAccount),
}
1 change: 1 addition & 0 deletions integration-tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ macro_rules! invoke_cargo_near {
};
cargo_near::commands::build_command::build::run(args)?;
},
Some(cargo_near::commands::CliNearCommand::CreateDevAccount(_)) => todo!(),
None => ()
}

Expand Down

0 comments on commit 577c41b

Please sign in to comment.