Skip to content

Commit 5aa1e6d

Browse files
chore: Update agent for transport changes (#3888)
1 parent 4f6670a commit 5aa1e6d

File tree

17 files changed

+291
-376
lines changed

17 files changed

+291
-376
lines changed

Cargo.lock

Lines changed: 148 additions & 68 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ license = "Apache-2.0"
2121
[workspace.dependencies]
2222
candid = "0.10.4"
2323
candid_parser = "0.1.4"
24-
ic-agent = { git = "https://github.com/dfinity/agent-rs.git", rev = "60a64dd2d5368180f03a75df80f475d6e2caf21a" }
24+
ic-agent = { git = "https://github.com/dfinity/agent-rs.git", rev = "6e11a350112f9b907c4d590d8217f340e153d898" }
2525
ic-asset = { path = "src/canisters/frontend/ic-asset" }
2626
ic-cdk = "0.13.1"
27-
ic-identity-hsm = { git = "https://github.com/dfinity/agent-rs.git", rev = "60a64dd2d5368180f03a75df80f475d6e2caf21a" }
28-
ic-utils = { git = "https://github.com/dfinity/agent-rs.git", rev = "60a64dd2d5368180f03a75df80f475d6e2caf21a" }
27+
ic-identity-hsm = { git = "https://github.com/dfinity/agent-rs.git", rev = "6e11a350112f9b907c4d590d8217f340e153d898" }
28+
ic-utils = { git = "https://github.com/dfinity/agent-rs.git", rev = "6e11a350112f9b907c4d590d8217f340e153d898" }
2929

3030
aes-gcm = "0.10.3"
3131
anyhow = "1.0.56"
@@ -72,7 +72,7 @@ tempfile = "3.3.0"
7272
thiserror = "1.0.24"
7373
time = "0.3.9"
7474
tokio = "1.35"
75-
url = { version="2.1.0", features=["serde"] }
75+
url = { version = "2.1.0", features = ["serde"] }
7676
walkdir = "2.3.2"
7777

7878
[profile.release]

e2e/tests-dfx/sign_send.bash

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,12 @@ teardown() {
3232
assert_eq "Error: [message.json] already exists, please specify a different output file name."
3333

3434
assert_command dfx canister sign --update hello_backend inc --file message-inc.json
35-
assert_eq "Update message generated at [message-inc.json]
36-
Signed request_status append to update message in [message-inc.json]"
35+
assert_eq "Update and request_status message generated at [message-inc.json]"
3736

3837
sleep 10
3938
echo y | assert_command dfx canister send message-inc.json
4039
assert_command dfx canister send message-inc.json --status
41-
assert_match "To see the content of response, copy-paste the encoded string into cbor.me."
40+
assert_match "Response:"
4241
}
4342

4443
@test "sign outside of a dfx project" {

src/canisters/frontend/ic-asset/src/batch_upload/retryable.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use ic_agent::agent::http_transport::reqwest_transport::reqwest::StatusCode;
1+
use ic_agent::export::reqwest::StatusCode;
22
use ic_agent::AgentError;
33

44
pub(crate) fn retryable(agent_error: &AgentError) -> bool {

src/canisters/frontend/ic-asset/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//! # Example
44
//!
55
//! ```rust,no_run
6-
//! use ic_agent::agent::{Agent, http_transport::ReqwestTransport};
6+
//! use ic_agent::agent::Agent;
77
//! use ic_agent::identity::BasicIdentity;
88
//! use ic_utils::Canister;
99
//! use std::time::Duration;
@@ -12,7 +12,7 @@
1212
//! # let pemfile = "";
1313
//! # let canister_id = "";
1414
//! let agent = Agent::builder()
15-
//! .with_transport(ReqwestTransport::create(replica_url)?)
15+
//! .with_url(replica_url)
1616
//! .with_identity(BasicIdentity::from_pem_file(pemfile)?)
1717
//! .build()?;
1818
//! let canister = Canister::builder()

src/canisters/frontend/icx-asset/src/main.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use candid::Principal;
88
use clap::builder::Styles;
99
use clap::{crate_authors, crate_version, Parser, ValueEnum};
1010
use ic_agent::identity::{AnonymousIdentity, BasicIdentity, Secp256k1Identity};
11-
use ic_agent::{agent, Agent, Identity};
11+
use ic_agent::{Agent, Identity};
1212
use slog::Level;
1313
use std::path::PathBuf;
1414

@@ -139,9 +139,7 @@ async fn main() -> anyhow::Result<()> {
139139
let logger = support::new_logger(opts.log_level.into());
140140

141141
let agent = Agent::builder()
142-
.with_transport(agent::http_transport::ReqwestTransport::create(
143-
opts.replica.clone(),
144-
)?)
142+
.with_url(&opts.replica)
145143
.with_boxed_identity(create_identity(opts.pem))
146144
.build()?;
147145

src/dfx-core/Cargo.toml

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ flate2 = { workspace = true, default-features = false, features = ["zlib-ng"] }
2323
handlebars.workspace = true
2424
hex = { workspace = true, features = ["serde"] }
2525
humantime-serde = "1.1.1"
26-
ic-agent = { workspace = true, features = ["reqwest"] }
26+
ic-agent.workspace = true
2727
ic-utils.workspace = true
28-
ic-identity-hsm = { workspace = true }
28+
ic-identity-hsm.workspace = true
2929
k256 = { version = "0.11.4", features = ["pem"] }
3030
keyring.workspace = true
3131
lazy_static.workspace = true
@@ -42,10 +42,7 @@ tar.workspace = true
4242
tempfile.workspace = true
4343
thiserror.workspace = true
4444
tiny-bip39 = "1.0.0"
45-
time = { workspace = true, features = [
46-
"serde",
47-
"serde-human-readable",
48-
] }
45+
time = { workspace = true, features = ["serde", "serde-human-readable"] }
4946
url.workspace = true
5047

5148
[dev-dependencies]

src/dfx-core/src/interface/builder.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,7 @@ use crate::{
1414
},
1515
DfxInterface,
1616
};
17-
use ic_agent::{
18-
agent::http_transport::{route_provider::RoundRobinRouteProvider, ReqwestTransport},
19-
Agent, Identity,
20-
};
17+
use ic_agent::{agent::route_provider::RoundRobinRouteProvider, Agent, Identity};
2118
use reqwest::Client;
2219
use std::sync::Arc;
2320

@@ -120,11 +117,9 @@ impl DfxInterfaceBuilder {
120117
.use_rustls_tls()
121118
.build()
122119
.map_err(BuildAgentError::CreateHttpClient)?;
123-
let transport =
124-
ReqwestTransport::create_with_client_route(Arc::new(route_provider), client)
125-
.map_err(BuildAgentError::CreateTransport)?;
126120
let agent = Agent::builder()
127-
.with_transport(transport)
121+
.with_http_client(client)
122+
.with_route_provider(route_provider)
128123
.with_arc_identity(identity)
129124
.build()
130125
.map_err(BuildAgentError::CreateAgent)?;

src/dfx/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,11 @@ hyper-rustls = { version = "0.24.1", default-features = false, features = [
6666
"webpki-roots",
6767
"http2",
6868
] }
69-
ic-agent = { workspace = true, features = ["reqwest"] }
69+
ic-agent.workspace = true
7070
ic-asset.workspace = true
7171
ic-cdk.workspace = true
72-
ic-identity-hsm = { workspace = true }
73-
ic-utils = { workspace = true }
72+
ic-identity-hsm.workspace = true
73+
ic-utils.workspace = true
7474
ic-wasm = "0.8.0"
7575
icrc-ledger-types = "0.1.5"
7676
idl2json = "0.10.1"

src/dfx/src/commands/canister/send.rs

Lines changed: 84 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
use crate::lib::environment::Environment;
22
use crate::lib::error::DfxResult;
33
use crate::lib::sign::signed_message::SignedMessageV1;
4-
use anyhow::{anyhow, bail, Context};
5-
use candid::Principal;
4+
use anyhow::{bail, Context};
5+
use candid::{IDLArgs, Principal};
66
use clap::Parser;
77
use dfx_core::identity::CallSender;
8-
use ic_agent::agent::Transport;
9-
use ic_agent::{agent::http_transport::ReqwestTransport, RequestId};
10-
use std::{fs::File, path::Path};
11-
use std::{io::Read, str::FromStr};
8+
use dfx_core::json::load_json_file;
9+
use ic_agent::agent::{CallResponse, RequestStatusResponse};
10+
use ic_agent::Agent;
11+
use ic_agent::RequestId;
12+
use std::path::PathBuf;
1213

1314
/// Send a previously-signed message.
1415
#[derive(Parser)]
1516
pub struct CanisterSendOpts {
1617
/// Specifies the file name of the message
17-
file_name: String,
18+
file_name: PathBuf,
1819

1920
/// Send the signed request-status call in the message
2021
#[arg(long)]
@@ -30,38 +31,64 @@ pub async fn exec(
3031
bail!("`send` currently doesn't support proxying through the wallet canister, please use `dfx canister send --no-wallet ...`.");
3132
}
3233
let file_name = opts.file_name;
33-
let path = Path::new(&file_name);
34-
let mut file = File::open(path).map_err(|_| anyhow!("Message file doesn't exist."))?;
35-
let mut json = String::new();
36-
file.read_to_string(&mut json)
37-
.map_err(|_| anyhow!("Cannot read the message file."))?;
38-
let message: SignedMessageV1 =
39-
serde_json::from_str(&json).map_err(|_| anyhow!("Invalid json message."))?;
34+
let message: SignedMessageV1 = load_json_file(&file_name)?;
4035
message.validate()?;
4136

4237
let network = message.network.clone();
43-
let transport =
44-
ReqwestTransport::create(network).context("Failed to create transport object.")?;
38+
let agent = Agent::builder().with_url(&network).build()?;
39+
if !message.is_ic {
40+
agent.fetch_root_key().await?;
41+
}
4542
let content = hex::decode(&message.content).context("Failed to decode message content.")?;
46-
let canister_id = Principal::from_text(message.canister_id.clone())
43+
let canister_id = Principal::from_text(&message.canister_id)
4744
.with_context(|| format!("Failed to parse canister id {:?}.", message.canister_id))?;
4845

4946
if opts.status {
50-
if message.call_type.clone().as_str() != "update" {
47+
if message.call_type != "update" {
5148
bail!("Can only check request_status on update calls.");
5249
}
53-
if message.signed_request_status.is_none() {
54-
bail!("No signed_request_status in [{}].", file_name);
55-
}
56-
let envelope = hex::decode(message.signed_request_status.unwrap())
57-
.context("Failed to decode envelope.")?;
58-
let response = transport
59-
.read_state(canister_id, envelope)
50+
let Some(signed_request_status) = message.signed_request_status else {
51+
bail!("No signed_request_status in [{}].", file_name.display());
52+
};
53+
let envelope = hex::decode(signed_request_status).context("Failed to decode envelope.")?;
54+
let Some(request_id) = message.request_id else {
55+
bail!("No request_id in [{}].", file_name.display());
56+
};
57+
let request_id = request_id
58+
.parse::<RequestId>()
59+
.context("Failed to decode request ID.")?;
60+
let response = agent
61+
.request_status_signed(&request_id, canister_id, envelope)
6062
.await
6163
.with_context(|| format!("Failed to read canister state of {}.", canister_id))?;
62-
eprintln!("To see the content of response, copy-paste the encoded string into cbor.me.");
6364
eprint!("Response: ");
64-
println!("{}", hex::encode(response));
65+
match response {
66+
RequestStatusResponse::Received => eprintln!("Received, not yet processing"),
67+
RequestStatusResponse::Processing => eprintln!("Processing, not yet done"),
68+
RequestStatusResponse::Rejected(response) => {
69+
if let Some(error_code) = response.error_code {
70+
println!(
71+
"Rejected ({:?}): {}, error code {}",
72+
response.reject_code, response.reject_message, error_code
73+
);
74+
} else {
75+
println!(
76+
"Rejected ({:?}): {}",
77+
response.reject_code, response.reject_message
78+
);
79+
}
80+
}
81+
RequestStatusResponse::Replied(response) => {
82+
eprint!("Replied: ");
83+
if let Ok(idl) = IDLArgs::from_bytes(&response.arg) {
84+
println!("{idl}");
85+
} else {
86+
println!("{}", hex::encode(&response.arg));
87+
}
88+
}
89+
RequestStatusResponse::Done => println!("Done, response no longer available"),
90+
RequestStatusResponse::Unknown => println!("Unknown"),
91+
}
6592
return Ok(());
6693
}
6794

@@ -87,37 +114,43 @@ pub async fn exec(
87114

88115
match message.call_type.as_str() {
89116
"query" => {
90-
let response = transport
91-
.query(canister_id, content)
117+
let response = agent
118+
.query_signed(canister_id, content)
92119
.await
93120
.with_context(|| format!("Query call to {} failed.", canister_id))?;
94-
eprintln!(
95-
"To see the content of response, copy-paste the encoded string into cbor.me."
96-
);
97121
eprint!("Response: ");
98-
println!("{}", hex::encode(response));
122+
if let Ok(idl) = IDLArgs::from_bytes(&response) {
123+
println!("{}", idl)
124+
} else {
125+
println!("{}", hex::encode(&response));
126+
}
99127
}
100128
"update" => {
101-
let request_id = RequestId::from_str(
102-
&message
103-
.request_id
104-
.expect("Cannot get request_id from the update message."),
105-
)
106-
.context("Failed to read request_id.")?;
107-
transport
108-
.call(canister_id, content)
129+
let call_response = agent
130+
.update_signed(canister_id, content)
109131
.await
110132
.with_context(|| format!("Update call to {} failed.", canister_id))?;
111-
112-
eprintln!(
113-
"To check the status of this update call, append `--status` to current command."
114-
);
115-
eprintln!("e.g. `dfx canister send message.json --status`");
116-
eprintln!("Alternatively, if you have the correct identity on this machine, using `dfx canister request-status` with following arguments.");
117-
eprint!("Request ID: ");
118-
println!("0x{}", String::from(request_id));
119-
eprint!("Canister ID: ");
120-
println!("{}", canister_id);
133+
match call_response {
134+
CallResponse::Poll(request_id) => {
135+
eprintln!(
136+
"To check the status of this update call, append `--status` to current command."
137+
);
138+
eprintln!("e.g. `dfx canister send message.json --status`");
139+
eprintln!("Alternatively, if you have the correct identity on this machine, using `dfx canister request-status` with following arguments.");
140+
eprint!("Request ID: ");
141+
println!("0x{}", String::from(request_id));
142+
eprint!("Canister ID: ");
143+
println!("{}", canister_id);
144+
}
145+
CallResponse::Response(response) => {
146+
eprint!("Response: ");
147+
if let Ok(idl) = IDLArgs::from_bytes(&response) {
148+
println!("{idl}");
149+
} else {
150+
println!("{}", hex::encode(&response));
151+
}
152+
}
153+
}
121154
}
122155
// message.validate() guarantee that call_type must be query or update
123156
_ => unreachable!(),

0 commit comments

Comments
 (0)