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 /// Prepares a query to fetch the [Data](crate::Data)<[AccountView](near_api_types::AccountView)> with the account information for the given account ID.
37 ///
38 /// ## Example
39 /// ```rust,no_run
40 /// use near_api::*;
41 ///
42 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
43 /// let account_info = Account("alice.testnet".parse()?).view().fetch_from_testnet().await?;
44 /// println!("Account: {:?}", account_info);
45 /// # Ok(())
46 /// # }
47 /// ```
48 pub fn view(&self) -> RequestBuilder<AccountViewHandler> {
49 let request = QueryRequest::ViewAccount {
50 account_id: self.0.clone(),
51 };
52 RequestBuilder::new(
53 SimpleQueryRpc { request },
54 Reference::Optimistic,
55 Default::default(),
56 )
57 }
58
59 /// Prepares a query to fetch the [Data](crate::Data)<[AccessKey]> with the access key information for the given account public key.
60 ///
61 /// ## Example
62 /// ```rust,no_run
63 /// use near_api::*;
64 /// use std::str::FromStr;
65 ///
66 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
67 /// let access_key = Account("alice.testnet".parse()?)
68 /// .access_key(PublicKey::from_str("ed25519:H4sIAAAAAAAAA+2X0Q6CMBAAtVlJQgYAAAA=")?)
69 /// .fetch_from_testnet()
70 /// .await?;
71 /// println!("Access key: {:?}", access_key);
72 /// # Ok(())
73 /// # }
74 /// ```
75 pub fn access_key(
76 &self,
77 signer_public_key: impl Into<PublicKey>,
78 ) -> RequestBuilder<AccessKeyHandler> {
79 let request = QueryRequest::ViewAccessKey {
80 account_id: self.0.clone(),
81 public_key: signer_public_key.into().into(),
82 };
83 RpcBuilder::new(
84 SimpleQueryRpc { request },
85 Reference::Optimistic,
86 Default::default(),
87 )
88 }
89
90 /// Prepares a query to fetch the Vec<([`PublicKey`], [`AccessKey`])> list of access keys for the given account ID.
91 ///
92 /// ## Example
93 /// ```rust,no_run
94 /// use near_api::*;
95 ///
96 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
97 /// let access_keys = Account("alice.testnet".parse()?).list_keys().fetch_from_testnet().await?;
98 /// println!("Access keys: {:?}", access_keys);
99 /// # Ok(())
100 /// # }
101 /// ```
102 pub fn list_keys(&self) -> RequestBuilder<AccessKeyListHandler> {
103 let request = QueryRequest::ViewAccessKeyList {
104 account_id: self.0.clone(),
105 };
106 RpcBuilder::new(
107 SimpleQueryRpc { request },
108 Reference::Optimistic,
109 Default::default(),
110 )
111 }
112
113 /// Adds a new access key to the given account ID.
114 ///
115 /// ## Example
116 /// ```rust,no_run
117 /// use near_api::{*, types::AccessKeyPermission};
118 /// use std::str::FromStr;
119 ///
120 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
121 /// let pk = PublicKey::from_str("ed25519:H4sIAAAAAAAAA+2X0Q6CMBAAtVlJQgYAAAA=")?;
122 /// let result = Account("alice.testnet".parse()?)
123 /// .add_key(AccessKeyPermission::FullAccess, pk)
124 /// .with_signer(Signer::new(Signer::from_ledger())?)
125 /// .send_to_testnet()
126 /// .await?;
127 /// # Ok(())
128 /// # }
129 /// ```
130 pub fn add_key(
131 &self,
132 permission: AccessKeyPermission,
133 public_key: impl Into<PublicKey>,
134 ) -> ConstructTransaction {
135 ConstructTransaction::new(self.0.clone(), self.0.clone()).add_action(Action::AddKey(
136 Box::new(AddKeyAction {
137 access_key: AccessKey {
138 nonce: U64::from(0),
139 permission,
140 },
141 public_key: public_key.into(),
142 }),
143 ))
144 }
145
146 /// Deletes an access key from the given account ID.
147 ///
148 /// ## Example
149 /// ```rust,no_run
150 /// use near_api::*;
151 /// use std::str::FromStr;
152 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
153 /// let result = Account("alice.testnet".parse()?)
154 /// .delete_key(PublicKey::from_str("ed25519:H4sIAAAAAAAAA+2X0Q6CMBAAtVlJQgYAAAA=")?)
155 /// .with_signer(Signer::new(Signer::from_ledger())?)
156 /// .send_to_testnet()
157 /// .await?;
158 /// # Ok(())
159 /// # }
160 /// ```
161 pub fn delete_key(&self, public_key: impl Into<PublicKey>) -> ConstructTransaction {
162 ConstructTransaction::new(self.0.clone(), self.0.clone()).add_action(Action::DeleteKey(
163 Box::new(DeleteKeyAction {
164 public_key: public_key.into(),
165 }),
166 ))
167 }
168
169 /// Deletes multiple access keys from the given account ID.
170 ///
171 /// ## Example
172 /// ```rust,no_run
173 /// use near_api::*;
174 /// use std::str::FromStr;
175 ///
176 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
177 /// let result = Account("alice.testnet".parse()?)
178 /// .delete_keys(vec![PublicKey::from_str("ed25519:H4sIAAAAAAAAA+2X0Q6CMBAAtVlJQgYAAAA=")?])
179 /// .with_signer(Signer::new(Signer::from_ledger())?)
180 /// .send_to_testnet()
181 /// .await?;
182 /// # Ok(())
183 /// # }
184 /// ```
185 pub fn delete_keys(&self, public_keys: Vec<PublicKey>) -> ConstructTransaction {
186 let actions = public_keys
187 .into_iter()
188 .map(|public_key| Action::DeleteKey(Box::new(DeleteKeyAction { public_key })))
189 .collect();
190
191 ConstructTransaction::new(self.0.clone(), self.0.clone()).add_actions(actions)
192 }
193
194 /// Deletes the account with the given beneficiary ID. The account balance will be transferred to the beneficiary.
195 ///
196 /// Please note that this action is irreversible. Also, you have to understand that another person could potentially
197 /// 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.
198 /// (near.social, devhub proposal, etc)
199 ///
200 /// Do not use it unless you understand the consequences.
201 ///
202 /// ## Example
203 /// ```rust,no_run
204 /// use near_api::*;
205 ///
206 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
207 /// let result = Account("alice.testnet".parse()?)
208 /// .delete_account_with_beneficiary("bob.testnet".parse()?)
209 /// .with_signer(Signer::new(Signer::from_ledger())?)
210 /// .send_to_testnet()
211 /// .await?;
212 /// # Ok(())
213 /// # }
214 /// ```
215 pub fn delete_account_with_beneficiary(
216 &self,
217 beneficiary_id: AccountId,
218 ) -> ConstructTransaction {
219 ConstructTransaction::new(self.0.clone(), self.0.clone()).add_action(Action::DeleteAccount(
220 DeleteAccountAction { beneficiary_id },
221 ))
222 }
223
224 /// Creates a new account builder for the given account ID.
225 ///
226 /// ## Creating account sponsored by faucet service
227 ///
228 /// This is a way to create an account without having to fund it. It works only on testnet.
229 /// The account should be created as a sub-account of the [testnet](https://testnet.nearblocks.io/address/testnet) account
230 ///
231 /// ```rust,no_run
232 /// use near_api::*;
233 ///
234 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
235 /// let secret = near_api::signer::generate_secret_key()?;
236 /// let result: reqwest::Response = Account::create_account("alice.testnet".parse()?)
237 /// .sponsor_by_faucet_service()
238 /// .public_key(secret.public_key())?
239 /// .send_to_testnet_faucet()
240 /// .await?;
241 /// // You have to save the secret key somewhere safe
242 /// std::fs::write("secret.key", secret.to_string())?;
243 /// # Ok(())
244 /// # }
245 /// ```
246 ///
247 /// ## Creating sub-account of the linkdrop root account funded by your own NEAR and signed by your account
248 ///
249 /// There is a few linkdrop root accounts that you can use to create sub-accounts.
250 /// * For mainnet, you can use the [near](https://explorer.near.org/accounts/near) account.
251 /// * For testnet, you can use the [testnet](https://testnet.nearblocks.io/address/testnet) account.
252 ///
253 /// ```rust,no_run
254 /// use near_api::*;
255 ///
256 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
257 /// let secret = near_api::signer::generate_secret_key()?;
258 /// let bob_signer = Signer::new(Signer::from_seed_phrase("lucky barrel fall come bottom can rib join rough around subway cloth ", None)?)?;
259 /// let result = Account::create_account("alice.testnet".parse()?)
260 /// .fund_myself("bob.testnet".parse()?, NearToken::from_near(1))
261 /// .public_key(secret.public_key())?
262 /// .with_signer(bob_signer)
263 /// .send_to_testnet()
264 /// .await?;
265 /// # Ok(())
266 /// # }
267 /// ```
268 ///
269 /// ## Creating sub-account of your own account funded by your NEAR
270 ///
271 /// You can create only one level deep of sub-accounts.
272 ///
273 /// E.g you are `alice.testnet`, you can't create `sub.sub.alice.testnet`, but you can create `sub.alice.testnet`.
274 /// Though, 'sub.alice.testnet' can create sub-accounts of its own.
275 /// ```rust,no_run
276 /// use near_api::*;
277 ///
278 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
279 /// let secret = near_api::signer::generate_secret_key()?;
280 /// let bob_signer = Signer::new(Signer::from_seed_phrase("lucky barrel fall come bottom can rib join rough around subway cloth ", None)?)?;
281 /// let result = Account::create_account("sub.bob.testnet".parse()?)
282 /// .fund_myself("bob.testnet".parse()?, NearToken::from_near(1))
283 /// .public_key(secret.public_key())?
284 /// .with_signer(bob_signer)
285 /// .send_to_testnet()
286 /// .await?;
287 /// # Ok(())
288 /// # }
289 /// ```
290 pub const fn create_account(account_id: AccountId) -> CreateAccountBuilder {
291 CreateAccountBuilder { account_id }
292 }
293}