Skip to content

Commit

Permalink
[CLI] Direct users to dev docs for testnet faucet, improve messaging
Browse files Browse the repository at this point in the history
  • Loading branch information
banool committed Dec 11, 2024
1 parent 809457f commit 6087ac3
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 37 deletions.
31 changes: 31 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,7 @@ num-derive = "0.3.3"
num-integer = "0.1.42"
num-traits = "0.2.15"
once_cell = "1.10.0"
open = "5.3.1"
ordered-float = "3.9.1"
ouroboros = "0.15.6"
owo-colors = "3.5.0"
Expand Down
1 change: 1 addition & 0 deletions crates/aptos/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
All notable changes to the Aptos CLI will be captured in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) and the format set out by [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

# Unreleased
- [**Breaking Change**] `aptos init` and `aptos account fund-with-faucet` no longer work directly with testnet, you must now use the minting page at [Aptos Learn](https://aptos.dev/network/faucet).

## [4.6.0] - 2024/11/29
- Add `--node-api-key` flag to `aptos move replay` to allow for querying the fullnode with an API key.
Expand Down
1 change: 1 addition & 0 deletions crates/aptos/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ move-prover-boogie-backend = { workspace = true }
move-symbol-pool = { workspace = true }
move-unit-test = { workspace = true, features = ["debugging"] }
move-vm-runtime = { workspace = true, features = ["testing"] }
open = { workspace = true }
pathsearch = { workspace = true }
poem = { workspace = true }
# We set default-features to false so we don't onboard the libpq dep. See more here:
Expand Down
83 changes: 61 additions & 22 deletions crates/aptos/src/common/init.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
// Copyright © Aptos Foundation
// SPDX-License-Identifier: Apache-2.0

use super::types::FaucetOptions;
use crate::{
account::key_rotation::lookup_address,
common::{
types::{
account_address_from_public_key, CliCommand, CliConfig, CliError, CliTypedResult,
ConfigSearchMode, EncodingOptions, HardwareWalletOptions, PrivateKeyInputOptions,
ProfileConfig, ProfileOptions, PromptOptions, RngArgs, DEFAULT_PROFILE,
account_address_from_public_key, get_mint_site_url, CliCommand, CliConfig, CliError,
CliTypedResult, ConfigSearchMode, EncodingOptions, HardwareWalletOptions,
PrivateKeyInputOptions, ProfileConfig, ProfileOptions, PromptOptions, RngArgs,
DEFAULT_PROFILE,
},
utils::{
explorer_account_link, fund_account, prompt_yes_with_override, read_line,
Expand Down Expand Up @@ -49,14 +51,8 @@ pub struct InitTool {
#[clap(long)]
pub rest_url: Option<Url>,

/// URL for the Faucet endpoint
#[clap(long)]
pub faucet_url: Option<Url>,

/// Auth token, if we're using the faucet. This is only used this time, we don't
/// store it.
#[clap(long, env)]
pub faucet_auth_token: Option<String>,
#[clap(flatten)]
pub faucet_options: FaucetOptions,

/// Whether to skip the faucet for a non-faucet endpoint
#[clap(long)]
Expand Down Expand Up @@ -129,6 +125,19 @@ impl CliCommand<()> for InitTool {
}
};

if network != Network::Custom {
if self.rest_url.is_some() {
return Err(CliError::CommandArgumentError(
"--rest-url can only be used with --network custom".to_string(),
));
}
if self.faucet_options.faucet_url.is_some() {
return Err(CliError::CommandArgumentError(
"--faucet-url can only be used with --network custom".to_string(),
));
}
}

// Ensure the config contains the network used
profile_config.network = Some(network);

Expand All @@ -142,8 +151,12 @@ impl CliCommand<()> for InitTool {
Network::Testnet => {
profile_config.rest_url =
Some("https://fullnode.testnet.aptoslabs.com".to_string());
profile_config.faucet_url =
Some("https://faucet.testnet.aptoslabs.com".to_string());
// The faucet in testnet is only accessible with some kind of bypass.
// For regular users this can only really mean an auth token. So if
// there is no auth token set, we don't set the faucet URL. If the user
// is confident they want to use the testnet faucet without a token
// they can set it manually with `--network custom` and `--faucet-url`.
profile_config.faucet_url = None;
},
Network::Devnet => {
profile_config.rest_url = Some("https://fullnode.devnet.aptoslabs.com".to_string());
Expand Down Expand Up @@ -323,17 +336,17 @@ impl CliCommand<()> for InitTool {
client,
Url::parse(faucet_url)
.map_err(|err| CliError::UnableToParse("rest_url", err.to_string()))?,
self.faucet_auth_token.as_deref(),
self.faucet_options.faucet_auth_token.as_deref(),
address,
NUM_DEFAULT_OCTAS,
)
.await?;
eprintln!("Account {} funded successfully", address);
}
} else if account_exists {
eprintln!("Account {} has been already found onchain", address);
} else if network == Network::Mainnet {
eprintln!("Account {} does not exist, you will need to create and fund the account by transferring funds from another account", address);
eprintln!("Account {} has been already found on chain", address);
} else if network == Network::Mainnet || network == Network::Testnet {
// Do nothing, we print information later.
} else {
eprintln!("Account {} has been initialized locally, but you must transfer coins to it to create the account onchain", address);
}
Expand All @@ -348,16 +361,42 @@ impl CliCommand<()> for InitTool {
.expect("Must have profiles, as created above")
.insert(profile_name.to_string(), profile_config);
config.save()?;

let profile_name = self
.profile_options
.profile_name()
.unwrap_or(DEFAULT_PROFILE);

eprintln!(
"\n---\nAptos CLI is now set up for account {} as profile {}!\n See the account here: {}\n Run `aptos --help` for more information about commands",
address,
profile_name,
explorer_account_link(address, Some(network))
"\n---\nAptos CLI is now set up for account {} as profile {}!\n---\n",
address, profile_name,
);

match network {
Network::Mainnet => {
eprintln!("The account has not been created on chain yet, you will need to create and fund the account by transferring funds from another account");
},
Network::Testnet => {
let mint_site_url = get_mint_site_url(Some(address));
eprintln!("The account has not been created on chain yet. To create the account and get APT on testnet you must visit {}", mint_site_url);
// We don't use `prompt_yes_with_override` here because we only want to
// automatically open the minting site if they're in an interactive setting.
if !self.prompt_options.assume_yes {
eprint!("Press [Enter] to go there now > ");
read_line("Confirmation")?;
open::that(&mint_site_url).map_err(|err| {
CliError::UnexpectedError(format!("Failed to open minting site: {}", err))
})?;
}
},
wildcard => {
eprintln!(
"See the account here: {}",
explorer_account_link(address, Some(wildcard))
);
},
}

Ok(())
}
}
Expand Down Expand Up @@ -399,7 +438,7 @@ impl InitTool {
let faucet_url = if self.skip_faucet {
eprintln!("Not configuring a faucet because --skip-faucet was provided");
None
} else if let Some(ref faucet_url) = self.faucet_url {
} else if let Some(ref faucet_url) = self.faucet_options.faucet_url {
eprintln!("Using command line argument for faucet URL {}", faucet_url);
Some(faucet_url.to_string())
} else {
Expand Down
54 changes: 41 additions & 13 deletions crates/aptos/src/common/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1511,12 +1511,12 @@ pub struct ChangeSummary {
pub struct FaucetOptions {
/// URL for the faucet endpoint e.g. `https://faucet.devnet.aptoslabs.com`
#[clap(long)]
faucet_url: Option<reqwest::Url>,
pub faucet_url: Option<reqwest::Url>,

/// Auth token to bypass faucet ratelimits. You can also set this as an environment
/// variable with FAUCET_AUTH_TOKEN.
#[clap(long, env)]
faucet_auth_token: Option<String>,
pub faucet_auth_token: Option<String>,
}

impl FaucetOptions {
Expand All @@ -1527,19 +1527,38 @@ impl FaucetOptions {
}
}

fn faucet_url(&self, profile: &ProfileOptions) -> CliTypedResult<reqwest::Url> {
fn faucet_url(&self, profile_options: &ProfileOptions) -> CliTypedResult<reqwest::Url> {
if let Some(ref faucet_url) = self.faucet_url {
Ok(faucet_url.clone())
} else if let Some(Some(url)) = CliConfig::load_profile(
profile.profile_name(),
return Ok(faucet_url.clone());
}
let profile = CliConfig::load_profile(
profile_options.profile_name(),
ConfigSearchMode::CurrentDirAndParents,
)?
.map(|profile| profile.faucet_url)
{
reqwest::Url::parse(&url)
.map_err(|err| CliError::UnableToParse("config faucet_url", err.to_string()))
} else {
Err(CliError::CommandArgumentError("No faucet given. Please add --faucet-url or add a faucet URL to the .aptos/config.yaml for the current profile".to_string()))
)?;
let profile = match profile {
Some(profile) => profile,
None => {
return Err(CliError::CommandArgumentError(format!(
"Profile \"{}\" not found.",
profile_options.profile_name().unwrap_or(DEFAULT_PROFILE)
)))
},
};

match profile.faucet_url {
Some(url) => reqwest::Url::parse(&url)
.map_err(|err| CliError::UnableToParse("config faucet_url", err.to_string())),
None => match profile.network {
Some(Network::Mainnet) => {
Err(CliError::CommandArgumentError("There is no faucet for mainnet. Please create and fund the account by transferring funds from another account. If you are confident you want to use a faucet, set --faucet-url or add a faucet URL to .aptos/config.yaml for the current profile".to_string()))
},
Some(Network::Testnet) => {
Err(CliError::CommandArgumentError(format!("To get testnet APT you must visit {}. If you are confident you want to use a faucet programmatically, set --faucet-url or add a faucet URL to .aptos/config.yaml for the current profile", get_mint_site_url(None))))
},
_ => {
Err(CliError::CommandArgumentError("No faucet given. Please set --faucet-url or add a faucet URL to .aptos/config.yaml for the current profile".to_string()))
},
},
}
}

Expand Down Expand Up @@ -2383,3 +2402,12 @@ pub struct ChunkedPublishOption {
#[clap(long, default_value_t = CHUNK_SIZE_IN_BYTES)]
pub(crate) chunk_size: usize,
}

/// For minting testnet APT.
pub fn get_mint_site_url(address: Option<AccountAddress>) -> String {
let params = match address {
Some(address) => format!("?address={}", address.to_standard_string()),
None => "".to_string(),
};
format!("https://aptos.dev/network/faucet{}", params)
}
6 changes: 4 additions & 2 deletions crates/aptos/src/test/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,8 +559,10 @@ impl CliTestFramework {
InitTool {
network: Some(Network::Custom),
rest_url: Some(self.endpoint.clone()),
faucet_url: Some(self.faucet_endpoint.clone()),
faucet_auth_token: None,
faucet_options: FaucetOptions {
faucet_url: Some(self.faucet_endpoint.clone()),
faucet_auth_token: None,
},
rng_args: RngArgs::from_seed([0; 32]),
private_key_options: PrivateKeyInputOptions::from_private_key(private_key)?,
profile_options: Default::default(),
Expand Down

0 comments on commit 6087ac3

Please sign in to comment.