diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index e593a6fb1c..54929a1fb2 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -33,6 +33,10 @@ Calls made to retrieve the help output for `canister update-settings` was missin `WARN` and `ERROR` messages are now clearly labelled as such, and the labels are colored accordingly. This is now included when running `dfx canister update-settings -h`. +=== fix: canister call uses candid file if canister type cannot be determined + +The candid file specified in the field `canisters..candid` of dfx.json, or if that not exists `canisters..remote.candid`, is now used when running `dfx canister call`, even when dfx fails to determine the canister type. + === fix: btc/canister http adapter socket not found by replica after restart After running `dfx start --enable-bitcoin` twice in a row (stopping dfx in between), the second diff --git a/e2e/assets/remote/call/mock/dfx.json b/e2e/assets/remote/call/mock/dfx.json index 29c4447a3d..314ee5c4d5 100644 --- a/e2e/assets/remote/call/mock/dfx.json +++ b/e2e/assets/remote/call/mock/dfx.json @@ -3,10 +3,15 @@ "canisters": { "basic": { "main": "basic.mo", - "dependencies": [ "remote" ] + "dependencies": [ + "remote" + ] }, "remote": { - "main": "remote.mo" + "main": "remote.mo", + "remote": { + "candid": "remote.did" + } } }, "defaults": { @@ -19,4 +24,4 @@ "bind": "127.0.0.1:8000" } } -} +} \ No newline at end of file diff --git a/e2e/tests-dfx/remote.bash b/e2e/tests-dfx/remote.bash index 2aaa17c41a..5ac250987f 100644 --- a/e2e/tests-dfx/remote.bash +++ b/e2e/tests-dfx/remote.bash @@ -15,7 +15,6 @@ teardown() { } @test "canister call and sign" { - skip install_asset remote/call/actual dfx_start setup_actuallylocal_network @@ -36,8 +35,6 @@ teardown() { setup_local_network # shellcheck disable=SC2094 cat <<<"$(jq .canisters.remote.remote.id.actuallylocal=\""$REMOTE_CANISTER_ID"\" dfx.json)" >dfx.json - # shellcheck disable=SC2094 - cat <<<"$(jq '.canisters.remote.remote.candid="remote.did"' dfx.json)" >dfx.json # set up: remote method is update, local is query # call remote method as update to make a change @@ -68,6 +65,12 @@ teardown() { assert_command dfx canister --network actuallylocal call --update remote make_struct '("A update by name", "B update by name")' assert_eq '(record { a = "A update by name"; b = "B update by name" })' + # This also should work when no canister type can be determined / if no info but the bare minimum of remote id and remote candid is given: + # shellcheck disable=SC2094 + cat <<<"$(jq 'del(.canisters.remote.main)' dfx.json)" >dfx.json + assert_command dfx canister --network actuallylocal call --query remote make_struct '("A query by name", "B query by name")' + assert_eq '(record { a = "A query by name"; b = "B query by name" })' + # We can't check this for sign, because dfx canister send outputs something like this: # To see the content of response, copy-paste the encoded string into cbor.me. # Response: d9d9f7a2667374617475736[snip]2696e636970616c @@ -93,7 +96,6 @@ teardown() { } @test "canister create fails for a remote canister" { - skip install_asset remote/actual dfx_start setup_actuallylocal_network diff --git a/src/dfx/src/commands/remote/generate_binding.rs b/src/dfx/src/commands/remote/generate_binding.rs index 392bf56a36..e8a3aede0a 100644 --- a/src/dfx/src/commands/remote/generate_binding.rs +++ b/src/dfx/src/commands/remote/generate_binding.rs @@ -51,7 +51,7 @@ pub fn exec(env: &dyn Environment, opts: GenerateBindingOpts) -> DfxResult { info!( log, "Candid file {} for canister {} does not exist. Skipping.", - candid, + candid.to_string_lossy(), canister.get_name() ); continue; @@ -104,7 +104,7 @@ pub fn exec(env: &dyn Environment, opts: GenerateBindingOpts) -> DfxResult { log, "Generated {} using {} for canister {}.", main, - candid, + candid.to_string_lossy(), canister.get_name() ) } diff --git a/src/dfx/src/config/dfinity.rs b/src/dfx/src/config/dfinity.rs index 47e4537c74..b0277f0f78 100644 --- a/src/dfx/src/config/dfinity.rs +++ b/src/dfx/src/config/dfinity.rs @@ -48,7 +48,7 @@ const EMPTY_CONFIG_DEFAULTS_REPLICA: ConfigDefaultsReplica = ConfigDefaultsRepli #[derive(Clone, Debug, Default, Serialize, Deserialize)] pub struct ConfigCanistersCanisterRemote { - pub candid: Option, + pub candid: Option, // network -> canister ID pub id: BTreeMap, diff --git a/src/dfx/src/lib/canister_info.rs b/src/dfx/src/lib/canister_info.rs index 290f990bd2..0d4fa55136 100644 --- a/src/dfx/src/lib/canister_info.rs +++ b/src/dfx/src/lib/canister_info.rs @@ -8,6 +8,7 @@ use crate::lib::provider::get_network_context; use crate::util; use anyhow::{anyhow, bail, Context}; +use core::panic; use fn_error_context::context; use ic_types::principal::Principal as CanisterId; use ic_types::Principal; @@ -38,7 +39,7 @@ pub struct CanisterInfo { declarations_config: CanisterDeclarationsConfig, remote_id: Option, // id on the currently selected network - remote_candid: Option, // always exists if the field is configured + remote_candid: Option, // always exists if the field is configured workspace_root: PathBuf, build_root: PathBuf, @@ -115,18 +116,14 @@ impl CanisterInfo { let canister_info = CanisterInfo { name: name.to_string(), canister_type, - declarations_config, remote_id, remote_candid, - workspace_root: workspace_root.to_path_buf(), build_root, output_root, canister_root, - canister_id, - packtool: build_defaults.get_packtool(), args: build_defaults.get_args(), extras, @@ -153,13 +150,16 @@ impl CanisterInfo { pub fn get_declarations_config(&self) -> &CanisterDeclarationsConfig { &self.declarations_config } + pub fn is_remote(&self) -> bool { + self.remote_id.is_some() + } pub fn get_remote_id(&self) -> Option { self.remote_id } - pub fn get_remote_candid(&self) -> Option { + pub fn get_remote_candid(&self) -> Option { self.remote_candid.as_ref().cloned() } - pub fn get_remote_candid_if_remote(&self) -> Option { + pub fn get_remote_candid_if_remote(&self) -> Option { if self.remote_id.is_some() { self.get_remote_candid() } else { @@ -282,7 +282,9 @@ impl CanisterInfo { } else if let Ok(info) = self.as_info::() { Some(info.get_output_idl_path().to_path_buf()) } else { - None + self.get_extra_optional("candid") + .unwrap_or(None) + .or_else(|| self.remote_candid.clone()) } } diff --git a/src/dfx/src/lib/canister_info/custom.rs b/src/dfx/src/lib/canister_info/custom.rs index 17eb340506..8939f5f1f5 100644 --- a/src/dfx/src/lib/canister_info/custom.rs +++ b/src/dfx/src/lib/canister_info/custom.rs @@ -25,7 +25,7 @@ impl CanisterInfoFactory for CustomCanisterInfo { let workspace_root = info.get_workspace_root(); let output_wasm_path = workspace_root.join(info.get_extra::("wasm")?); let candid = if let Some(remote_candid) = info.get_remote_candid_if_remote() { - PathBuf::from(remote_candid) + remote_candid } else { info.get_extra::("candid")? }; diff --git a/src/dfx/src/lib/canister_info/rust.rs b/src/dfx/src/lib/canister_info/rust.rs index 09baf68728..402c0ba929 100644 --- a/src/dfx/src/lib/canister_info/rust.rs +++ b/src/dfx/src/lib/canister_info/rust.rs @@ -52,7 +52,7 @@ impl CanisterInfoFactory for RustCanisterInfo { let output_wasm_path = target_directory.join(format!("wasm32-unknown-unknown/release/{package}.wasm")); let candid = if let Some(remote_candid) = info.get_remote_candid_if_remote() { - PathBuf::from(remote_candid) + remote_candid } else { info.get_extra::("candid")? };