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 command-line execution environment
5//! [`dfx`](https://internetcomputer.org/docs/current/developer-docs/setup/install).
6//!
7//! ## Overview
8//! The `ic-agent` is a Rust crate that can connect directly to the Internet
9//! Computer through the Internet Computer protocol (ICP).
10//! The key software components of the ICP are broadly referred to as the
11//! [replica](https://internetcomputer.org/docs/current/concepts/nodes-subnets).
12//!
13//! The agent is designed to be compatible with multiple versions of the
14//! replica API, and to expose both low-level APIs for communicating with
15//! Internet Computer protocol components like the replica and to provide
16//! higher-level APIs for communicating with software applications deployed
17//! as [canisters](https://internetcomputer.org/docs/current/concepts/canisters-code).
18//!
19//! ## Example
20//! The following example illustrates how to use the Agent interface to send
21//! a call to an Internet Computer canister that performs network management
22//! operations. In this example, the call to the Internet Computer management
23//! canister (`aaaaa-aa`) creates a placeholder for a new canister by
24//! registering a network-specific identifier. The management canister then
25//! returns the result in the form of the textual representation of the canister
26//! identifier to the caller.
27//!
28//! ```ignore
29//! # // This test is ignored because it requires an ic to be running. We run these
30//! # // in the ic-ref workflow.
31//! use ic_agent::{Agent, export::Principal};
32//! use candid::{Encode, Decode, CandidType, Nat};
33//! use serde::Deserialize;
34//!
35//! #[derive(CandidType)]
36//! struct Argument {
37//!   amount: Option<Nat>,
38//! }
39//!
40//! #[derive(CandidType, Deserialize)]
41//! struct CreateCanisterResult {
42//!   canister_id: Principal,
43//! }
44//!
45//! # fn create_identity() -> impl ic_agent::Identity {
46//! #     ic_agent::identity::BasicIdentity::from_signing_key(
47//! #         ed25519_consensus::SigningKey::new(rand::thread_rng()),
48//! #     )
49//! # }
50//! #
51//! async fn create_a_canister() -> Result<Principal, Box<dyn std::error::Error>> {
52//! # let url = format!("http://localhost:{}", option_env!("IC_REF_PORT").unwrap_or("4943"));
53//!   let agent = Agent::builder()
54//!     .with_url(url)
55//!     .with_identity(create_identity())
56//!     .build()?;
57//!   // Only do the following call when not contacting the IC main net (e.g. a local emulator).
58//!   // This is important as the main net public key is static and a rogue network could return
59//!   // a different key.
60//!   // If you know the root key ahead of time, you can use `agent.set_root_key(root_key);`.
61//!   agent.fetch_root_key().await?;
62//!   let management_canister_id = Principal::from_text("aaaaa-aa")?;
63//!
64//!   // Create a call to the management canister to create a new canister ID,
65//!   // and wait for a result.
66//!   // The effective canister id must belong to the canister ranges of the subnet at which the canister is created.
67//!   let effective_canister_id = Principal::from_text("rwlgt-iiaaa-aaaaa-aaaaa-cai").unwrap();
68//!   let response = agent.update(&management_canister_id, "provisional_create_canister_with_cycles")
69//!     .with_effective_canister_id(effective_canister_id)
70//!     .with_arg(Encode!(&Argument { amount: None})?)
71//!     .await?;
72//!
73//!   let result = Decode!(response.as_slice(), CreateCanisterResult)?;
74//!   let canister_id: Principal = result.canister_id;
75//!   Ok(canister_id)
76//! }
77//!
78//! # let mut runtime = tokio::runtime::Runtime::new().unwrap();
79//! # runtime.block_on(async {
80//! let canister_id = create_a_canister().await.unwrap();
81//! eprintln!("{}", canister_id);
82//! # });
83//! ```
84//! For more information about the Agent interface used in this example, see the
85//! [Agent] documentation.
86//!
87//! ## References
88//! For an introduction to the Internet Computer and the DFINITY Canister SDK,
89//! see the following resources:
90//!
91//! - [How the IC Works](https://internetcomputer.org/docs/current/concepts/)
92//! - [DFINITY Canister SDK](https://internetcomputer.org/docs/current/references/cli-reference/)
93//!
94//! The Internet Computer protocol and interface specifications are not
95//! publicly available yet. When these specifications are made public and
96//! generally available, additional details about the versions supported will
97//! be available here.
98
99#![warn(
100    missing_docs,
101    rustdoc::broken_intra_doc_links,
102    rustdoc::private_intra_doc_links
103)]
104#![cfg_attr(not(target_family = "wasm"), warn(clippy::future_not_send))]
105#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
106
107#[macro_use]
108mod util;
109
110pub mod agent;
111pub mod export;
112pub mod identity;
113
114use agent::response_authentication::LookupPath;
115#[doc(inline)]
116pub use agent::{agent_error, agent_error::AgentError, Agent, NonceFactory, NonceGenerator};
117#[doc(inline)]
118pub use ic_transport_types::{to_request_id, RequestId, RequestIdError, TransportCallResponse};
119#[doc(inline)]
120pub use identity::{Identity, Signature};
121
122// Re-export from ic_certification for backward compatibility.
123pub use ic_certification::{hash_tree, Certificate};
124
125/// Looks up a value in the certificate's tree at the specified hash.
126///
127/// Returns the value if it was found; otherwise, errors with `LookupPathAbsent`, `LookupPathUnknown`, or `LookupPathError`.
128pub fn lookup_value<P: LookupPath, Storage: AsRef<[u8]>>(
129    tree: &ic_certification::certificate::Certificate<Storage>,
130    path: P,
131) -> Result<&[u8], AgentError> {
132    agent::response_authentication::lookup_value(&tree.tree, path)
133}