Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@

== DFX

- feat: add option to specify initial cycles for newly created canisters (#1433)

Added a new option to the canister create command which allows the user to specify the initial cycle balance of a canister created by their wallet.
This option is a no-op for the Sodium network.
Added option to `dfx canister create` and `dfx deploy`: `--with-cycles <with-cycles>`
Specifies the initial cycle balance to deposit into the newly
created canister. The specified amount needs to take the
canister create fee into account. This amount is deducted
from the wallet's cycle balance

[source, bash]
----
dfx canister create --with-cycles 8000000000 some_canister
dfx canister deploy --with-cycles 8000000000
----

- feat: install `dfx` by version or tag (#1426)

This feature adds a new dfx command `toolchain` which have intuitive subcommands.
Expand Down
13 changes: 10 additions & 3 deletions src/dfx/src/commands/canister/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::lib::environment::Environment;
use crate::lib::error::DfxResult;
use crate::lib::operations::canister::create_canister;
use crate::lib::root_key::fetch_root_key_if_needed;
use crate::util::clap::validators::cycle_amount_validator;
use crate::util::expiry_duration;

use anyhow::bail;
Expand All @@ -17,21 +18,27 @@ pub struct CanisterCreateOpts {
/// Creates all canisters configured in dfx.json.
#[clap(long, required_unless_present("canister-name"))]
all: bool,

/// Specifies the initial cycle balance to deposit into the newly created canister.
/// The specified amount needs to take the canister create fee into account.
/// This amount is deducted from the wallet's cycle balance.
#[clap(long, validator(cycle_amount_validator))]
with_cycles: Option<String>,
}

pub async fn exec(env: &dyn Environment, opts: CanisterCreateOpts) -> DfxResult {
let config = env.get_config_or_anyhow()?;
let timeout = expiry_duration();

fetch_root_key_if_needed(env).await?;

let with_cycles = opts.with_cycles.as_deref();
if let Some(canister_name) = opts.canister_name.clone() {
create_canister(env, canister_name.as_str(), timeout).await
create_canister(env, canister_name.as_str(), timeout, with_cycles).await
} else if opts.all {
// Create all canisters.
if let Some(canisters) = &config.get_config().canisters {
for canister_name in canisters.keys() {
create_canister(env, canister_name, timeout).await?;
create_canister(env, canister_name, timeout, with_cycles).await?;
}
}
Ok(())
Expand Down
9 changes: 9 additions & 0 deletions src/dfx/src/commands/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::lib::error::DfxResult;
use crate::lib::operations::canister::deploy_canisters;
use crate::lib::provider::create_agent_environment;
use crate::lib::root_key::fetch_root_key_if_needed;
use crate::util::clap::validators::cycle_amount_validator;
use crate::util::expiry_duration;

use clap::Clap;
Expand All @@ -29,6 +30,12 @@ pub struct DeployOpts {
/// "http://localhost:12345/" is a valid network name.
#[clap(long)]
network: Option<String>,

/// Specifies the initial cycle balance to deposit into the newly created canister.
/// The specified amount needs to take the canister create fee into account.
/// This amount is deducted from the wallet's cycle balance.
#[clap(long, validator(cycle_amount_validator))]
with_cycles: Option<String>,
}

pub fn exec(env: &dyn Environment, opts: DeployOpts) -> DfxResult {
Expand All @@ -38,6 +45,7 @@ pub fn exec(env: &dyn Environment, opts: DeployOpts) -> DfxResult {
let canister_name = opts.canister_name.as_deref();
let argument = opts.argument.as_deref();
let argument_type = opts.argument_type.as_deref();
let with_cycles = opts.with_cycles.as_deref();

let mut runtime = Runtime::new().expect("Unable to create a runtime");
runtime.block_on(fetch_root_key_if_needed(&env))?;
Expand All @@ -48,5 +56,6 @@ pub fn exec(env: &dyn Environment, opts: DeployOpts) -> DfxResult {
argument,
argument_type,
timeout,
with_cycles,
))
}
7 changes: 6 additions & 1 deletion src/dfx/src/lib/operations/canister/create_canister.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub async fn create_canister(
env: &dyn Environment,
canister_name: &str,
timeout: Duration,
with_cycles: Option<&str>,
) -> DfxResult {
let log = env.get_logger();
info!(log, "Creating canister {:?}...", canister_name);
Expand Down Expand Up @@ -68,8 +69,12 @@ pub async fn create_canister(
.await?;
create_result.canister_id
} else {
let cycles = match with_cycles {
None => 1000000000001_u64,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some(amount) => amount.parse::<u64>()?,
};
wallet
.wallet_create_canister(1000000000001_u64, None)
.wallet_create_canister(cycles, None)
.call_and_wait(waiter_with_timeout(timeout))
.await?
.0
Expand Down
13 changes: 11 additions & 2 deletions src/dfx/src/lib/operations/canister/deploy_canisters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub async fn deploy_canisters(
argument: Option<&str>,
argument_type: Option<&str>,
timeout: Duration,
with_cycles: Option<&str>,
) -> DfxResult {
let log = env.get_logger();

Expand All @@ -38,7 +39,14 @@ pub async fn deploy_canisters(
info!(log, "Deploying all canisters.");
}

register_canisters(env, &canister_names, &initial_canister_id_store, timeout).await?;
register_canisters(
env,
&canister_names,
&initial_canister_id_store,
timeout,
with_cycles,
)
.await?;

build_canisters(env, &canister_names, &config)?;

Expand Down Expand Up @@ -71,6 +79,7 @@ async fn register_canisters(
canister_names: &[String],
canister_id_store: &CanisterIdStore,
timeout: Duration,
with_cycles: Option<&str>,
) -> DfxResult {
let canisters_to_create = canister_names
.iter()
Expand All @@ -82,7 +91,7 @@ async fn register_canisters(
} else {
info!(env.get_logger(), "Creating canisters...");
for canister_name in &canisters_to_create {
create_canister(env, &canister_name, timeout).await?;
create_canister(env, &canister_name, timeout, with_cycles).await?;
}
}
Ok(())
Expand Down
7 changes: 7 additions & 0 deletions src/dfx/src/util/clap/validators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ pub fn is_request_id(v: &str) -> Result<(), String> {
}
}

pub fn cycle_amount_validator(cycles: &str) -> Result<(), String> {
if cycles.parse::<u64>().is_ok() {
return Ok(());
}
Err("Must be a non negative amount.".to_string())
}

pub fn compute_allocation_validator(compute_allocation: &str) -> Result<(), String> {
if let Ok(num) = compute_allocation.parse::<u64>() {
if num <= 100 {
Expand Down