Skip to content

Commit

Permalink
feat: api v2 support (#1577)
Browse files Browse the repository at this point in the history
- [x] update all tests
- [x] update segregated send and sign interface
- [X] update agent
- [X] update ic-ref to `0.16.0`
- [X] update replica to `c851e777547e2d3ed7b45162277e9c160860e7a0` (when api/v2 support landed)

depends on dfinity/agent-rs#137
  • Loading branch information
p-shahi authored Apr 9, 2021
1 parent 20895c2 commit 7e2c2b9
Show file tree
Hide file tree
Showing 16 changed files with 248 additions and 83 deletions.
28 changes: 24 additions & 4 deletions Cargo.lock

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

8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,22 @@ members = [
version = "0.2.0"
git = "https://github.com/dfinity/agent-rs.git"
branch = "next"
rev = "87ca70d82e67b5c7c6367a35580fe1d491c793f5"
rev = "5472fb610faa6cc1f0c12c82a745e435603fae08"

[patch.crates-io.ic-identity-hsm]
version = "0.2.0"
git = "https://github.com/dfinity/agent-rs.git"
branch = "next"
rev = "87ca70d82e67b5c7c6367a35580fe1d491c793f5"
rev = "5472fb610faa6cc1f0c12c82a745e435603fae08"

[patch.crates-io.ic-types]
version = "0.1.2"
git = "https://github.com/dfinity/agent-rs.git"
branch = "next"
rev = "87ca70d82e67b5c7c6367a35580fe1d491c793f5"
rev = "5472fb610faa6cc1f0c12c82a745e435603fae08"

[patch.crates-io.ic-utils]
version = "0.2.0"
git = "https://github.com/dfinity/agent-rs.git"
branch = "next"
rev = "87ca70d82e67b5c7c6367a35580fe1d491c793f5"
rev = "5472fb610faa6cc1f0c12c82a745e435603fae08"
10 changes: 5 additions & 5 deletions e2e/tests-dfx/basic-project.bash
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@ teardown() {
assert_command dfx canister --no-wallet call --async hello greet Blueberry
# At this point $output is the request ID.
# shellcheck disable=SC2154
assert_command dfx canister request-status "$stdout"
assert_command dfx canister request-status "$stdout" "$(dfx canister id hello)"
assert_eq '("Hello, Blueberry!")'

# Call using the wallet's call forwarding
assert_command dfx canister call --async hello greet Blueberry
# At this point $output is the request ID.
# shellcheck disable=SC2154
assert_command dfx canister request-status "$stdout"
assert_command dfx canister request-status "$stdout" "$(dfx identity get-wallet)"
assert_eq '( variant { 17_724 = record { 153_986_224 = blob "DIDL\00\01q\11Hello, Blueberry!" } }, )'
}

Expand Down Expand Up @@ -80,7 +80,7 @@ teardown() {
assert_eq "(3)"

assert_command dfx canister call hello inc --async
assert_command dfx canister request-status "$stdout"
assert_command dfx canister request-status "$stdout" "$(dfx identity get-wallet)"

# Call write.
assert_command dfx canister call hello write 1337
Expand All @@ -89,12 +89,12 @@ teardown() {
# Write has no return value. But we can _call_ read too.
# Call with user Identity as Sender
assert_command dfx canister --no-wallet call hello read --async
assert_command dfx canister request-status "$stdout"
assert_command dfx canister request-status "$stdout" "$(dfx canister id hello)"
assert_eq "(1_337)"

# Call using the wallet's call forwarding
assert_command dfx canister call hello read --async
assert_command dfx canister request-status "$stdout"
assert_command dfx canister request-status "$stdout" "$(dfx identity get-wallet)"
assert_eq '(variant { 17_724 = record { 153_986_224 = blob "DIDL\00\01}\b9\0a" } })'

}
Expand Down
6 changes: 3 additions & 3 deletions nix/sources.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@
"dfinity": {
"branch": "master",
"repo": "ssh://git@github.com/dfinity-lab/dfinity",
"rev": "a7d3a895e7c7f684a4c983f226adf5d41e29a64f",
"rev": "c851e777547e2d3ed7b45162277e9c160860e7a0",
"type": "git"
},
"ic-ref": {
"tag": "0.16.0",
"repo": "ssh://git@github.com/dfinity-lab/ic-ref",
"rev": "77f368d006c337eab0df1620659133c1f7e48b10",
"tag": "0.15.5",
"rev": "215641629ace2d590013f89bb3f3fe3b0a0d3c3b",
"type": "git"
},
"motoko": {
Expand Down
8 changes: 4 additions & 4 deletions src/dfx/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -76,26 +76,26 @@ webpki-roots = "0.21.0"
version = "0.2.0"
git = "https://github.com/dfinity/agent-rs.git"
branch = "next"
rev = "87ca70d82e67b5c7c6367a35580fe1d491c793f5"
rev = "5472fb610faa6cc1f0c12c82a745e435603fae08"
features = ["reqwest"]

[dependencies.ic-identity-hsm]
version = "0.2.0"
git = "https://github.com/dfinity/agent-rs.git"
branch = "next"
rev = "87ca70d82e67b5c7c6367a35580fe1d491c793f5"
rev = "5472fb610faa6cc1f0c12c82a745e435603fae08"

[dependencies.ic-types]
version = "0.1.2"
git = "https://github.com/dfinity/agent-rs.git"
branch = "next"
rev = "87ca70d82e67b5c7c6367a35580fe1d491c793f5"
rev = "5472fb610faa6cc1f0c12c82a745e435603fae08"

[dependencies.ic-utils]
version = "0.2.0"
git = "https://github.com/dfinity/agent-rs.git"
branch = "next"
rev = "87ca70d82e67b5c7c6367a35580fe1d491c793f5"
rev = "5472fb610faa6cc1f0c12c82a745e435603fae08"

[dev-dependencies]
env_logger = "0.6"
Expand Down
79 changes: 78 additions & 1 deletion src/dfx/src/commands/canister/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ use crate::util::clap::validators::cycle_amount_validator;
use crate::util::{blob_from_arguments, expiry_duration, get_candid_type, print_idl_blob};

use anyhow::{anyhow, bail, Context};
use candid::{CandidType, Deserialize};
use candid::{CandidType, Decode, Deserialize};
use clap::{ArgSettings, Clap};
use ic_types::principal::Principal as CanisterId;
use ic_utils::canister::{Argument, Canister};
use ic_utils::interfaces::management_canister::{CanisterInstall, MgmtMethod};
use ic_utils::interfaces::wallet::{CallForwarder, CallResult};
use ic_utils::interfaces::Wallet;
use std::option::Option;
use std::str::FromStr;

/// Calls a method on a deployed canister.
#[derive(Clap)]
Expand Down Expand Up @@ -98,6 +100,58 @@ async fn request_id_via_wallet_call(
.map_err(|err| anyhow!("Agent error {}", err))
}

pub fn get_effective_canister_id(
is_management_canister: bool,
method_name: &str,
arg_value: &[u8],
canister_id: CanisterId,
) -> DfxResult<CanisterId> {
if is_management_canister {
let method_name = MgmtMethod::from_str(method_name).map_err(|_| {
anyhow!(
"Attempted to call an unsupported management canister method: {}",
method_name
)
})?;
match method_name {
MgmtMethod::CreateCanister
| MgmtMethod::RawRand => {
bail!(format!("{} can only be called via an inter-canister call. Try calling this without `--no-wallet`.",
method_name.as_ref()))
},
MgmtMethod::InstallCode => {
let install_args = candid::Decode!(arg_value, CanisterInstall)?;
Ok(install_args.canister_id)
}
MgmtMethod::SetController => {
#[derive(CandidType, Deserialize)]
struct In {
canister_id: CanisterId,
new_controller: CanisterId,
}
let in_args = candid::Decode!(arg_value, In)?;
Ok(in_args.canister_id)
}
MgmtMethod::StartCanister
| MgmtMethod::StopCanister
| MgmtMethod::CanisterStatus
| MgmtMethod::DeleteCanister
| MgmtMethod::DepositCycles
| MgmtMethod::ProvisionalTopUpCanister => {
#[derive(CandidType, Deserialize)]
struct In {
canister_id: CanisterId,
}
let in_args = candid::Decode!(arg_value, In)?;
Ok(in_args.canister_id)
}
MgmtMethod::ProvisionalCreateCanisterWithCycles => Ok(CanisterId::management_canister()),
}
} else {
Ok(canister_id)
}
}

pub async fn exec(
env: &dyn Environment,
opts: CanisterCallOpts,
Expand All @@ -122,6 +176,8 @@ pub async fn exec(
}
};

let is_management_canister = canister_id == CanisterId::management_canister();

let method_type = maybe_candid_path.and_then(|path| get_candid_type(&path, method_name));
let is_query_method = match &method_type {
Some((_, f)) => Some(f.is_query()),
Expand Down Expand Up @@ -170,8 +226,15 @@ pub async fn exec(
if is_query {
let blob = match call_sender {
CallSender::SelectedId => {
let effective_canister_id = get_effective_canister_id(
is_management_canister,
method_name,
&arg_value,
canister_id.clone(),
)?;
agent
.query(&canister_id, method_name)
.with_effective_canister_id(effective_canister_id)
.with_arg(&arg_value)
.call()
.await?
Expand All @@ -195,8 +258,15 @@ pub async fn exec(
} else if opts.r#async {
let request_id = match call_sender {
CallSender::SelectedId => {
let effective_canister_id = get_effective_canister_id(
is_management_canister,
method_name,
&arg_value,
canister_id.clone(),
)?;
agent
.update(&canister_id, method_name)
.with_effective_canister_id(effective_canister_id)
.with_arg(&arg_value)
.call()
.await?
Expand All @@ -221,8 +291,15 @@ pub async fn exec(
} else {
let blob = match call_sender {
CallSender::SelectedId => {
let effective_canister_id = get_effective_canister_id(
is_management_canister,
method_name,
&arg_value,
canister_id.clone(),
)?;
agent
.update(&canister_id, method_name)
.with_effective_canister_id(effective_canister_id)
.with_arg(&arg_value)
.expire_after(timeout)
.call_and_wait(waiter_with_exponential_backoff())
Expand Down
18 changes: 17 additions & 1 deletion src/dfx/src/commands/canister/request_status.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::lib::environment::Environment;
use crate::lib::error::{DfxError, DfxResult};
use crate::lib::models::canister_id_store::CanisterIdStore;
use crate::lib::root_key::fetch_root_key_if_needed;
use crate::lib::waiter::waiter_with_exponential_backoff;
use crate::util::clap::validators;
Expand All @@ -10,6 +11,7 @@ use clap::Clap;
use delay::Waiter;
use ic_agent::agent::{Replied, RequestStatusResponse};
use ic_agent::{AgentError, RequestId};
use ic_types::Principal;
use std::str::FromStr;

/// Requests the status of a specified call from a canister.
Expand All @@ -19,6 +21,11 @@ pub struct RequestStatusOpts {
/// The request identifier is an hexadecimal string starting with 0x.
#[clap(validator(validators::is_request_id))]
request_id: String,

/// Specifies the name or id of the canister onto which the request was made.
/// If the request was made to the Management canister, specify the id of the
/// canister it is updating/querying.
canister_name: String,
}

pub async fn exec(env: &dyn Environment, opts: RequestStatusOpts) -> DfxResult {
Expand All @@ -30,12 +37,21 @@ pub async fn exec(env: &dyn Environment, opts: RequestStatusOpts) -> DfxResult {

fetch_root_key_if_needed(env).await?;

let callee_canister = opts.canister_name.as_str();
let canister_id_store = CanisterIdStore::for_env(env)?;

let canister_id = Principal::from_text(callee_canister)
.or_else(|_| canister_id_store.get(callee_canister))?;

let mut waiter = waiter_with_exponential_backoff();
let Replied::CallReplied(blob) = async {
waiter.start();
let mut request_accepted = false;
loop {
match agent.request_status_raw(&request_id).await? {
match agent
.request_status_raw(&request_id, canister_id.clone())
.await?
{
RequestStatusResponse::Replied { reply } => return Ok(reply),
RequestStatusResponse::Rejected {
reject_code,
Expand Down
Loading

0 comments on commit 7e2c2b9

Please sign in to comment.