near_api/account/mod.rs
1use near_api_types::{
2 json::U64,
3 transaction::actions::{AccessKey, AddKeyAction, DeleteAccountAction, DeleteKeyAction},
4 AccessKeyPermission, AccountId, Action, PublicKey, Reference,
5};
6
7use crate::advanced::{query_request::QueryRequest, query_rpc::SimpleQueryRpc};
8use crate::common::query::{
9 AccessKeyHandler, AccessKeyListHandler, AccountViewHandler, RequestBuilder, RpcBuilder,
10};
11use crate::transactions::ConstructTransaction;
12
13use self::create::CreateAccountBuilder;
14
15mod create;
16
17/// Account management related interactions with the NEAR Protocol
18///
19/// The [`Account`] struct provides methods to interact with NEAR accounts, including querying account information, managing access keys, and creating new accounts.
20///
21/// # Examples
22///
23/// ```rust,no_run
24/// use near_api::*;
25///
26/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
27/// let account_info = Account("alice.testnet".parse()?).view().fetch_from_testnet().await?;
28/// println!("Account: {:?}", account_info);
29/// # Ok(())
30/// # }
31/// ```
32#[derive(Clone, Debug)]
33pub struct Account(pub AccountId);
34
35impl Account {
36 /// Returns the underlying account ID for this account.
37 ///
38 /// # Example
39 /// ```rust,no_run
40 /// use near_api::*;
41 ///
42 /// # fn example() -> Result<(), Box<dyn std::error::Error>> {
43 /// let account = Account("alice.testnet".parse()?);
44 /// let account_id = account.account_id();
45 /// println!("Account ID: {}", account_id);
46 /// # Ok(())
47 /// # }
48 /// ```
49 pub const fn account_id(&self) -> &AccountId {
50 &self.0
51 }
52
53 /// Converts this account to a Contract for contract-related operations.
54 ///
55 /// # Example
56 /// ```rust,no_run
57 /// use near_api::*;
58 /// use serde_json::json;
59 ///
60 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
61 /// let account = Account("contract.testnet".parse()?);
62 /// let contract = account.as_contract();
63 /// let result: String = contract.call_function("get_value", ())?.read_only().fetch_from_testnet().await?.data;
64 /// println!("Contract value: {:?}", result);
65 /// # Ok(())
66 /// # }
67 /// ```
68 pub fn as_contract(&self) -> crate::contract::Contract {
69 crate::contract::Contract(self.0.clone())
70 }
71
72 /// Creates a Tokens wrapper for token-related operations on this account.
73 ///
74 /// # Example
75 /// ```rust,no_run
76 /// use near_api::*;
77 ///
78 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
79 /// let account = Account("alice.testnet".parse()?);
80 /// let tokens = account.tokens();
81 /// let balance = tokens.near_balance().fetch_from_testnet().await?;
82 /// println!("NEAR balance: {}", balance.total);
83 /// # Ok(())
84 /// # }
85 /// ```
86 pub fn tokens(&self) -> crate::tokens::Tokens {
87 crate::tokens::Tokens::account(self.0.clone())
88 }
89
90 /// Creates a Delegation wrapper for staking-related operations on this account.
91 ///
92 /// # Example
93 /// ```rust,no_run
94 /// use near_api::*;
95 ///
96 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
97 /// let account = Account("alice.testnet".parse()?);
98 /// let delegation = account.delegation();
99 /// let staked = delegation.view_staked_balance("pool.testnet".parse()?)?.fetch_from_testnet().await?;
100 /// println!("Staked balance: {:?}", staked);
101 /// # Ok(())
102 /// # }
103 /// ```
104 pub fn delegation(&self) -> crate::stake::Delegation {
105 crate::stake::Delegation(self.0.clone())
106 }
107
108 /// Prepares a query to fetch the [Data](crate::Data)<[AccountView](near_api_types::AccountView)> with the account information for the given account ID.
109 ///
110 /// ## Example
111 /// ```rust,no_run
112 /// use near_api::*;
113 ///
114 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
115 /// let account_info = Account("alice.testnet".parse()?).view().fetch_from_testnet().await?;
116 /// println!("Account: {:?}", account_info);
117 /// # Ok(())
118 /// # }
119 /// ```
120 pub fn view(&self) -> RequestBuilder<AccountViewHandler> {
121 let request = QueryRequest::ViewAccount {
122 account_id: self.0.clone(),
123 };
124 RequestBuilder::new(
125 SimpleQueryRpc { request },
126 Reference::Optimistic,
127 Default::default(),
128 )
129 }
130
131 /// Prepares a query to fetch the [Data](crate::Data)<[AccessKey]> with the access key information for the given account public key.
132 ///
133 /// ## Example
134 /// ```rust,no_run
135 /// use near_api::*;
136 /// use std::str::FromStr;
137 ///
138 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
139 /// let access_key = Account("alice.testnet".parse()?)
140 /// .access_key(PublicKey::from_str("ed25519:H4sIAAAAAAAAA+2X0Q6CMBAAtVlJQgYAAAA=")?)
141 /// .fetch_from_testnet()
142 /// .await?;
143 /// println!("Access key: {:?}", access_key);
144 /// # Ok(())
145 /// # }
146 /// ```
147 pub fn access_key(
148 &self,
149 signer_public_key: impl Into<PublicKey>,
150 ) -> RequestBuilder<AccessKeyHandler> {
151 let request = QueryRequest::ViewAccessKey {
152 account_id: self.0.clone(),
153 public_key: signer_public_key.into().into(),
154 };
155 RpcBuilder::new(
156 SimpleQueryRpc { request },
157 Reference::Optimistic,
158 Default::default(),
159 )
160 }
161
162 /// Prepares a query to fetch the Vec<([`PublicKey`], [`AccessKey`])> list of access keys for the given account ID.
163 ///
164 /// ## Example
165 /// ```rust,no_run
166 /// use near_api::*;
167 ///
168 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
169 /// let access_keys = Account("alice.testnet".parse()?).list_keys().fetch_from_testnet().await?;
170 /// println!("Access keys: {:?}", access_keys);
171 /// # Ok(())
172 /// # }
173 /// ```
174 pub fn list_keys(&self) -> RequestBuilder<AccessKeyListHandler> {
175 let request = QueryRequest::ViewAccessKeyList {
176 account_id: self.0.clone(),
177 };
178 RpcBuilder::new(
179 SimpleQueryRpc { request },
180 Reference::Optimistic,
181 Default::default(),
182 )
183 }
184
185 /// Adds a new access key to the given account ID.
186 ///
187 /// ## Example
188 /// ```rust,no_run
189 /// use near_api::{*, types::AccessKeyPermission};
190 /// use std::str::FromStr;
191 ///
192 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
193 /// let pk = PublicKey::from_str("ed25519:H4sIAAAAAAAAA+2X0Q6CMBAAtVlJQgYAAAA=")?;
194 /// let result = Account("alice.testnet".parse()?)
195 /// .add_key(AccessKeyPermission::FullAccess, pk)
196 /// .with_signer(Signer::new(Signer::from_ledger())?)
197 /// .send_to_testnet()
198 /// .await?;
199 /// # Ok(())
200 /// # }
201 /// ```
202 pub fn add_key(
203 &self,
204 permission: AccessKeyPermission,
205 public_key: impl Into<PublicKey>,
206 ) -> ConstructTransaction {
207 ConstructTransaction::new(self.0.clone(), self.0.clone()).add_action(Action::AddKey(
208 Box::new(AddKeyAction {
209 access_key: AccessKey {
210 nonce: U64::from(0),
211 permission,
212 },
213 public_key: public_key.into(),
214 }),
215 ))
216 }
217
218 /// Deletes an access key from the given account ID.
219 ///
220 /// ## Example
221 /// ```rust,no_run
222 /// use near_api::*;
223 /// use std::str::FromStr;
224 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
225 /// let result = Account("alice.testnet".parse()?)
226 /// .delete_key(PublicKey::from_str("ed25519:H4sIAAAAAAAAA+2X0Q6CMBAAtVlJQgYAAAA=")?)
227 /// .with_signer(Signer::new(Signer::from_ledger())?)
228 /// .send_to_testnet()
229 /// .await?;
230 /// # Ok(())
231 /// # }
232 /// ```
233 pub fn delete_key(&self, public_key: impl Into<PublicKey>) -> ConstructTransaction {
234 ConstructTransaction::new(self.0.clone(), self.0.clone()).add_action(Action::DeleteKey(
235 Box::new(DeleteKeyAction {
236 public_key: public_key.into(),
237 }),
238 ))
239 }
240
241 /// Deletes multiple access keys from the given account ID.
242 ///
243 /// ## Example
244 /// ```rust,no_run
245 /// use near_api::*;
246 /// use std::str::FromStr;
247 ///
248 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
249 /// let result = Account("alice.testnet".parse()?)
250 /// .delete_keys(vec![PublicKey::from_str("ed25519:H4sIAAAAAAAAA+2X0Q6CMBAAtVlJQgYAAAA=")?])
251 /// .with_signer(Signer::new(Signer::from_ledger())?)
252 /// .send_to_testnet()
253 /// .await?;
254 /// # Ok(())
255 /// # }
256 /// ```
257 pub fn delete_keys(&self, public_keys: Vec<PublicKey>) -> ConstructTransaction {
258 let actions = public_keys
259 .into_iter()
260 .map(|public_key| Action::DeleteKey(Box::new(DeleteKeyAction { public_key })))
261 .collect();
262
263 ConstructTransaction::new(self.0.clone(), self.0.clone()).add_actions(actions)
264 }
265
266 /// Deletes the account with the given beneficiary ID. The account balance will be transferred to the beneficiary.
267 ///
268 /// Please note that this action is irreversible. Also, you have to understand that another person could potentially
269 /// re-create the account with the same name and pretend to be you on other websites that use your account ID as a unique identifier.
270 /// (near.social, devhub proposal, etc)
271 ///
272 /// Do not use it unless you understand the consequences.
273 ///
274 /// ## Example
275 /// ```rust,no_run
276 /// use near_api::*;
277 ///
278 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
279 /// let result = Account("alice.testnet".parse()?)
280 /// .delete_account_with_beneficiary("bob.testnet".parse()?)
281 /// .with_signer(Signer::new(Signer::from_ledger())?)
282 /// .send_to_testnet()
283 /// .await?;
284 /// # Ok(())
285 /// # }
286 /// ```
287 pub fn delete_account_with_beneficiary(
288 &self,
289 beneficiary_id: AccountId,
290 ) -> ConstructTransaction {
291 ConstructTransaction::new(self.0.clone(), self.0.clone()).add_action(Action::DeleteAccount(
292 DeleteAccountAction { beneficiary_id },
293 ))
294 }
295
296 /// Creates a new account builder for the given account ID.
297 ///
298 /// ## Creating account sponsored by faucet service
299 ///
300 /// This is a way to create an account without having to fund it. It works only on testnet.
301 /// The account should be created as a sub-account of the [testnet](https://testnet.nearblocks.io/address/testnet) account
302 ///
303 /// ```rust,no_run
304 /// use near_api::*;
305 ///
306 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
307 /// let secret = near_api::signer::generate_secret_key()?;
308 /// let result: reqwest::Response = Account::create_account("alice.testnet".parse()?)
309 /// .sponsor_by_faucet_service()
310 /// .public_key(secret.public_key())?
311 /// .send_to_testnet_faucet()
312 /// .await?;
313 /// // You have to save the secret key somewhere safe
314 /// std::fs::write("secret.key", secret.to_string())?;
315 /// # Ok(())
316 /// # }
317 /// ```
318 ///
319 /// ## Creating sub-account of the linkdrop root account funded by your own NEAR and signed by your account
320 ///
321 /// There is a few linkdrop root accounts that you can use to create sub-accounts.
322 /// * For mainnet, you can use the [near](https://explorer.near.org/accounts/near) account.
323 /// * For testnet, you can use the [testnet](https://testnet.nearblocks.io/address/testnet) account.
324 ///
325 /// ```rust,no_run
326 /// use near_api::*;
327 ///
328 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
329 /// let secret = near_api::signer::generate_secret_key()?;
330 /// let bob_signer = Signer::new(Signer::from_seed_phrase("lucky barrel fall come bottom can rib join rough around subway cloth ", None)?)?;
331 /// let result = Account::create_account("alice.testnet".parse()?)
332 /// .fund_myself("bob.testnet".parse()?, NearToken::from_near(1))
333 /// .public_key(secret.public_key())?
334 /// .with_signer(bob_signer)
335 /// .send_to_testnet()
336 /// .await?;
337 /// # Ok(())
338 /// # }
339 /// ```
340 ///
341 /// ## Creating sub-account of your own account funded by your NEAR
342 ///
343 /// You can create only one level deep of sub-accounts.
344 ///
345 /// E.g you are `alice.testnet`, you can't create `sub.sub.alice.testnet`, but you can create `sub.alice.testnet`.
346 /// Though, 'sub.alice.testnet' can create sub-accounts of its own.
347 /// ```rust,no_run
348 /// use near_api::*;
349 ///
350 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
351 /// let secret = near_api::signer::generate_secret_key()?;
352 /// let bob_signer = Signer::new(Signer::from_seed_phrase("lucky barrel fall come bottom can rib join rough around subway cloth ", None)?)?;
353 /// let result = Account::create_account("sub.bob.testnet".parse()?)
354 /// .fund_myself("bob.testnet".parse()?, NearToken::from_near(1))
355 /// .public_key(secret.public_key())?
356 /// .with_signer(bob_signer)
357 /// .send_to_testnet()
358 /// .await?;
359 /// # Ok(())
360 /// # }
361 /// ```
362 pub const fn create_account(account_id: AccountId) -> CreateAccountBuilder {
363 CreateAccountBuilder { account_id }
364 }
365}