Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add --always-assist flag for canister call/install/deploy/sign #3671

Merged
merged 2 commits into from Mar 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Expand Up @@ -63,6 +63,11 @@ Note that the default value of `allow_raw_access` is still `true`.
Removed the logic for calling a different version of dfx based on DFX_VERSION or the `dfx` field in
dfx.json. This is now performed by dfxvm.

### feat: --always-assist flag for `dfx canister call/install/sign and dfx deploy`

When all the arguments are optional, dfx automatically provides a `null` value when no arguments are provided.
`--always-assist` flag enables the candid assist feature for optional arguments, instead of providing a default `null` value.

## Dependencies

### Replica
Expand Down
17 changes: 16 additions & 1 deletion src/dfx/src/commands/canister/call.rs
Expand Up @@ -51,7 +51,12 @@ pub struct CanisterCallOpts {
update: bool,

/// Specifies the config for generating random argument.
#[arg(long, conflicts_with("argument"), conflicts_with("argument_file"))]
#[arg(
long,
conflicts_with("argument"),
conflicts_with("argument_file"),
conflicts_with("always_assist")
)]
random: Option<String>,

/// Specifies the format for displaying the method's return result.
Expand All @@ -69,6 +74,15 @@ pub struct CanisterCallOpts {
/// for project canisters.
#[arg(long)]
candid: Option<PathBuf>,

/// Always use Candid assist when the argument types are all optional.
#[arg(
long,
conflicts_with("argument"),
conflicts_with("argument_file"),
conflicts_with("random")
)]
always_assist: bool,
}

#[derive(Clone, CandidType, Deserialize, Debug)]
Expand Down Expand Up @@ -282,6 +296,7 @@ pub async fn exec(
argument_type.as_deref(),
&method_type,
false,
opts.always_assist,
)?;

// amount has been validated by cycle_amount_validator
Expand Down
2 changes: 1 addition & 1 deletion src/dfx/src/commands/canister/delete.rs
Expand Up @@ -199,7 +199,7 @@ async fn delete_canister(
"Installing temporary wallet in canister {} to enable transfer of cycles.",
canister
);
let args = blob_from_arguments(None, None, None, None, &None, false)?;
let args = blob_from_arguments(None, None, None, None, &None, false, false)?;
let mode = InstallMode::Reinstall;
let install_builder = mgr
.install_code(&canister_id, &wasm_module)
Expand Down
13 changes: 13 additions & 0 deletions src/dfx/src/commands/canister/install.rs
Expand Up @@ -64,6 +64,15 @@ pub struct CanisterInstallOpts {
/// Skips upgrading the asset canister, to only install the assets themselves.
#[arg(long)]
no_asset_upgrade: bool,

/// Always use Candid assist when the argument types are all optional.
#[arg(
long,
conflicts_with("argument"),
conflicts_with("argument_file"),
conflicts_with("yes")
)]
always_assist: bool,
}

pub async fn exec(
Expand Down Expand Up @@ -97,6 +106,7 @@ pub async fn exec(
argument_type.as_deref(),
&None,
true,
opts.always_assist,
)?;
let wasm_module = dfx_core::fs::read(wasm_path)?;
let mode = mode.context("The install mode cannot be auto when using --wasm")?;
Expand Down Expand Up @@ -157,6 +167,7 @@ pub async fn exec(
opts.yes,
None,
opts.no_asset_upgrade,
opts.always_assist,
)
.await
.map_err(Into::into)
Expand All @@ -176,6 +187,7 @@ pub async fn exec(
opts.yes,
env_file.as_deref(),
opts.no_asset_upgrade,
opts.always_assist,
)
.await
.map_err(Into::into)
Expand Down Expand Up @@ -219,6 +231,7 @@ pub async fn exec(
opts.yes,
env_file.as_deref(),
opts.no_asset_upgrade,
opts.always_assist,
)
.await?;
}
Expand Down
17 changes: 16 additions & 1 deletion src/dfx/src/commands/canister/sign.rs
Expand Up @@ -43,7 +43,12 @@ pub struct CanisterSignOpts {
update: bool,

/// Specifies the config for generating random argument.
#[arg(long, conflicts_with("argument"), conflicts_with("argument_file"))]
#[arg(
long,
conflicts_with("argument"),
conflicts_with("argument_file"),
conflicts_with("always_assist")
)]
random: Option<String>,

/// Specifies how long the message will be valid in seconds, default to be 300s (5 minutes)
Expand All @@ -53,6 +58,15 @@ pub struct CanisterSignOpts {
/// Specifies the output file name.
#[arg(long, default_value = "message.json")]
file: PathBuf,

/// Always use Candid assist when the argument types are all optional.
#[arg(
long,
conflicts_with("argument"),
conflicts_with("argument_file"),
conflicts_with("random")
)]
always_assist: bool,
}

pub async fn exec(
Expand Down Expand Up @@ -99,6 +113,7 @@ pub async fn exec(
argument_type.as_deref(),
&method_type,
false,
opts.always_assist,
)?;
let agent = env.get_agent();

Expand Down
10 changes: 10 additions & 0 deletions src/dfx/src/commands/deploy.rs
Expand Up @@ -113,6 +113,15 @@ pub struct DeployOpts {

#[command(flatten)]
subnet_selection: SubnetSelectionOpt,

/// Always use Candid assist when the argument types are all optional.
#[arg(
long,
conflicts_with("argument"),
conflicts_with("argument_file"),
conflicts_with("yes")
)]
always_assist: bool,
}

pub fn exec(env: &dyn Environment, opts: DeployOpts) -> DfxResult {
Expand Down Expand Up @@ -192,6 +201,7 @@ pub fn exec(env: &dyn Environment, opts: DeployOpts) -> DfxResult {
env_file,
opts.no_asset_upgrade,
&mut subnet_selection,
opts.always_assist,
))?;

if matches!(deploy_mode, NormalDeploy | ForceReinstallSingleCanister(_)) {
Expand Down
2 changes: 1 addition & 1 deletion src/dfx/src/lib/integrations/mod.rs
Expand Up @@ -49,7 +49,7 @@ pub async fn initialize_integration_canister(
};
try_create_canister(agent, logger, &canister_id, &pulled_canister).await?;

let install_arg = blob_from_arguments(None, Some(init_arg), None, None, &None, true)?;
let install_arg = blob_from_arguments(None, Some(init_arg), None, None, &None, true, false)?;
install_canister(agent, logger, &canister_id, wasm, install_arg, name).await
}

Expand Down
5 changes: 5 additions & 0 deletions src/dfx/src/lib/operations/canister/deploy_canisters.rs
Expand Up @@ -38,6 +38,7 @@ pub enum DeployMode {
}

#[context("Failed while trying to deploy canisters.")]
#[allow(clippy::too_many_arguments)]
pub async fn deploy_canisters(
env: &dyn Environment,
some_canister: Option<&str>,
Expand All @@ -55,6 +56,7 @@ pub async fn deploy_canisters(
env_file: Option<PathBuf>,
no_asset_upgrade: bool,
subnet_selection: &mut SubnetSelectionType,
always_assist: bool,
) -> DfxResult {
let log = env.get_logger();

Expand Down Expand Up @@ -156,6 +158,7 @@ pub async fn deploy_canisters(
skip_consent,
env_file.as_deref(),
no_asset_upgrade,
always_assist,
)
.await?;
info!(log, "Deployed canisters.");
Expand Down Expand Up @@ -307,6 +310,7 @@ async fn install_canisters(
skip_consent: bool,
env_file: Option<&Path>,
no_asset_upgrade: bool,
always_assist: bool,
) -> DfxResult {
info!(env.get_logger(), "Installing canisters...");

Expand Down Expand Up @@ -340,6 +344,7 @@ async fn install_canisters(
skip_consent,
env_file,
no_asset_upgrade,
always_assist,
)
.await?;
}
Expand Down
12 changes: 10 additions & 2 deletions src/dfx/src/lib/operations/canister/install_canister.rs
Expand Up @@ -50,6 +50,7 @@ pub async fn install_canister(
skip_consent: bool,
env_file: Option<&Path>,
no_asset_upgrade: bool,
always_assist: bool,
) -> DfxResult {
let log = env.get_logger();
let agent = env.get_agent();
Expand Down Expand Up @@ -165,8 +166,15 @@ The command line value will be used.",
(None, Some(_)) => (argument_from_json, Some("idl")), // `init_arg` in dfx.json is always in Candid format
(None, None) => (None, None),
};
let install_args =
blob_from_arguments(Some(env), argument, None, argument_type, &init_type, true)?;
let install_args = blob_from_arguments(
Some(env),
argument,
None,
argument_type,
&init_type,
true,
always_assist,
)?;
if let Some(timestamp) = canister_id_store.get_timestamp(canister_info.get_name()) {
let new_timestamp = playground_install_code(
env,
Expand Down
2 changes: 2 additions & 0 deletions src/dfx/src/util/mod.rs
Expand Up @@ -197,6 +197,7 @@ pub fn blob_from_arguments(
arg_type: Option<&str>,
method_type: &Option<(TypeEnv, Function)>,
is_init_arg: bool,
always_assist: bool,
) -> DfxResult<Vec<u8>> {
let arg_type = arg_type.unwrap_or("idl");
match arg_type {
Expand Down Expand Up @@ -226,6 +227,7 @@ pub fn blob_from_arguments(
.args
.iter()
.all(|t| matches!(t.as_ref(), TypeInner::Opt(_)))
&& !always_assist
{
// If the user provided no arguments, and if all the expected arguments are
// optional, then use null values.
Expand Down