ex3_ic_agent/lib.rs
1//! The `ic-agent` is a simple-to-use library that enables you to
2//! build applications and interact with the [Internet Computer](https://internetcomputer.org)
3//! in Rust. It serves as a Rust-based low-level backend for the
4//! DFINITY Canister Software Development Kit (SDK) and the
5//! [Canister SDK](https://sdk.dfinity.org) command-line execution environment
6//! [`dfx`](https://sdk.dfinity.org/docs/developers-guide/install-upgrade-remove.html#_what_gets_installed).
7//!
8//! ## Overview
9//! The `ic-agent` is a Rust crate that can connect directly to the Internet
10//! Computer through the Internet Computer protocol (ICP).
11//! The key software components of the ICP are broadly referred to as the
12//! [replica](https://sdk.dfinity.org/docs/developers-guide/introduction-key-concepts.html#_basic_architecture).
13//!
14//! The agent is designed to be compatible with multiple versions of the
15//! replica API, and to expose both low-level APIs for communicating with
16//! Internet Computer protocol components like the replica and to provide
17//! higher-level APIs for communicating with software applications deployed
18//! as [canisters](https://sdk.dfinity.org/docs/developers-guide/introduction-key-concepts.html#_writing_deploying_and_running_software).
19//!
20//! ## Example
21//! The following example illustrates how to use the Agent interface to send
22//! a call to an Internet Computer canister that performs network management
23//! operations. In this example, the call to the Internet Computer management
24//! canister (`aaaaa-aa`) creates a placeholder for a new canister by
25//! registering a network-specific identifier. The management canister then
26//! returns the result in the form of the textual representation of the canister
27//! identifier to the caller.
28//!
29//! ```ignore
30//! # // This test is ignored because it requires an ic to be running. We run these
31//! # // in the ic-ref workflow.
32//! use ic_agent::{Agent, export::Principal};
33//! use candid::{Encode, Decode, CandidType, Nat};
34//! use serde::Deserialize;
35//!
36//! #[derive(CandidType)]
37//! struct Argument {
38//! amount: Option<Nat>,
39//! }
40//!
41//! #[derive(CandidType, Deserialize)]
42//! struct CreateCanisterResult {
43//! canister_id: Principal,
44//! }
45//!
46//! # fn create_identity() -> impl ic_agent::Identity {
47//! # let rng = ring::rand::SystemRandom::new();
48//! # let key_pair = ring::signature::Ed25519KeyPair::generate_pkcs8(&rng)
49//! # .expect("Could not generate a key pair.");
50//! #
51//! # ic_agent::identity::BasicIdentity::from_key_pair(
52//! # ring::signature::Ed25519KeyPair::from_pkcs8(key_pair.as_ref())
53//! # .expect("Could not read the key pair."),
54//! # )
55//! # }
56//! #
57//! # const URL: &'static str = concat!("http://localhost:", env!("IC_REF_PORT"));
58//! #
59//! async fn create_a_canister() -> Result<Principal, Box<dyn std::error::Error>> {
60//! let agent = Agent::builder()
61//! .with_url(URL)
62//! .with_identity(create_identity())
63//! .build()?;
64//! // Only do the following call when not contacting the IC main net (e.g. a local emulator).
65//! // This is important as the main net public key is static and a rogue network could return
66//! // a different key.
67//! // If you know the root key ahead of time, you can use `agent.set_root_key(root_key);`.
68//! agent.fetch_root_key().await?;
69//! let management_canister_id = Principal::from_text("aaaaa-aa")?;
70//!
71//! // Create a call to the management canister to create a new canister ID,
72//! // and wait for a result.
73//! // The effective canister id must belong to the canister ranges of the subnet at which the canister is created.
74//! let effective_canister_id = Principal::from_text("rwlgt-iiaaa-aaaaa-aaaaa-cai").unwrap();
75//! let response = agent.update(&management_canister_id, "provisional_create_canister_with_cycles")
76//! .with_effective_canister_id(effective_canister_id)
77//! .with_arg(&Encode!(&Argument { amount: None})?)
78//! .call_and_wait()
79//! .await?;
80//!
81//! let result = Decode!(response.as_slice(), CreateCanisterResult)?;
82//! let canister_id: Principal = result.canister_id;
83//! Ok(canister_id)
84//! }
85//!
86//! # let mut runtime = tokio::runtime::Runtime::new().unwrap();
87//! # runtime.block_on(async {
88//! let canister_id = create_a_canister().await.unwrap();
89//! eprintln!("{}", canister_id);
90//! # });
91//! ```
92//! For more information about the Agent interface used in this example, see the
93//! [Agent] documentation.
94//!
95//! ## References
96//! For an introduction to the Internet Computer and the DFINITY Canister SDK,
97//! see the following resources:
98//!
99//! - [Frequently Asked Questions](https://dfinity.org/faq)
100//! - [DFINITY Canister SDK](https://sdk.dfinity.org/docs/index.html)
101//!
102//! The Internet Computer protocol and interface specifications are not
103//! publicly available yet. When these specifications are made public and
104//! generally available, additional details about the versions supported will
105//! be available here.
106
107#![deny(
108 missing_docs,
109 rustdoc::broken_intra_doc_links,
110 rustdoc::private_intra_doc_links
111)]
112#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
113
114#[cfg(all(feature = "hyper", target_family = "wasm"))]
115compile_error!("Feature `hyper` cannot be used from WASM.");
116
117pub mod agent;
118pub mod export;
119pub mod identity;
120pub mod request_id;
121
122#[doc(inline)]
123pub use agent::{
124 agent_error, agent_error::AgentError, response_authentication::lookup_value, Agent,
125 NonceFactory, NonceGenerator,
126};
127#[doc(inline)]
128pub use identity::{Identity, Signature};
129#[doc(inline)]
130pub use request_id::{to_request_id, RequestId, RequestIdError};
131
132// Re-export from ic_certification for backward compatibility.
133pub use ic_certification::{hash_tree, Certificate};