farcaster_rs/account/
mod.rs

1//! The Account module that handles authentication and tokens
2//!
3//! # Quickstart with the Account module
4//!
5//! 1. Use the from_mnemonic function as defined in the [Account struct](../types/account/struct.Account.html)
6//! ```no_run
7//! use farcaster_rs::Account;
8//! // Takes a mnemonic phrase and a token duration (defaults to 1 hour)
9//! let account: Account = Account::from_mnemonic("mnemonic phrase", None).await?;
10//! ```
11//!
12//! 2. Use the from_private_key function as defined in the [Account struct](../types/account/struct.Account.html)
13//! ```no_run
14//! use farcaster_rs::Account;
15//! // Takes a mnemonic phrase and a token duration (defaults to 1 hour)
16//! let account: Account = Account::from_private_key("private key", None).await?;
17//! ```
18//!
19//! 3. Regenerate your session token as defined in the [Account struct](../types/account/struct.Account.html)
20//! ```no_run
21//! use farcaster_rs::{Account, Farcaster};
22//! // Takes a mnemonic phrase and a token duration (defaults to 1 hour)
23//! let account: Account = Account::from_mnemonic("mnemonic phrase", None).await?;
24//! let mut farcaster: Farcaster = Farcaster::new("eth provider", account).await?;
25//!
26//! // Regenerate your session token with an optional new token duration (defaults to either your previously set token duration, or the default 1 hour)
27//! farcaster.account.regen_session_token(None);
28//! ```
29
30pub mod auth;
31
32use crate::constants::merkle::AUTH_TOKEN_DEFAULT_DURATION_SECS;
33use crate::types::account::auth::revoke::RevokedKeyRoot;
34use crate::types::account::Account;
35use chrono::Utc;
36use ethers::signers::coins_bip39::English;
37use ethers::signers::{LocalWallet, MnemonicBuilder};
38use std::error::Error;
39
40impl Account {
41    /// Initialize an account with a mnemonic phrase
42    ///
43    /// # Params
44    /// mnemonic_phrase: &str,
45    /// token_duration: Option<i64> - Defaults to 1hr
46    ///
47    /// # Example
48    /// ```no_run
49    /// let account = farcaster_rs::Account::from_mnemonic("phrase", None).await?;
50    /// ```
51    pub async fn from_mnemonic(
52        mnemonic_phrase: &str,
53        token_duration: Option<i64>,
54    ) -> Result<Self, Box<dyn Error>> {
55        let wallet = MnemonicBuilder::<English>::default()
56            .phrase(mnemonic_phrase)
57            .build()
58            .expect("Wallet creation using mnemonic phrase failed");
59
60        let token_duration_secs = token_duration.unwrap_or(AUTH_TOKEN_DEFAULT_DURATION_SECS);
61
62        let mut account = Self {
63            wallet,
64            bearer_token: None,
65            session_token: None,
66            token_duration_secs: Some(token_duration_secs),
67        };
68
69        // generate Bearer Token
70        account.generate_bearer().await?;
71
72        // generate Auth Token
73        account.get_session_token().await?;
74
75        Ok(account)
76    }
77
78    /// Initialize an account with a private key
79    ///
80    /// # Params:
81    /// key: &str,
82    /// token_duration: Option<i64> - Defaults to 1hr
83    ///
84    /// # Example
85    /// ```no_run
86    /// let account = farcaster_rs::Account::from_private_key("private key", None).await?;
87    /// ```
88    pub async fn from_private_key(
89        key: &str,
90        token_duration: Option<i64>,
91    ) -> Result<Self, Box<dyn Error>> {
92        let wallet = key
93            .parse::<LocalWallet>()
94            .expect("Wallet creation using private key failed");
95
96        let token_duration_secs = token_duration.unwrap_or(AUTH_TOKEN_DEFAULT_DURATION_SECS);
97
98        let mut account = Self {
99            wallet,
100            bearer_token: None,
101            session_token: None,
102            token_duration_secs: Some(token_duration_secs),
103        };
104
105        // generate Bearer Token
106        account.generate_bearer().await?;
107
108        // generate Auth Token
109        account.get_session_token().await?;
110
111        Ok(account)
112    }
113
114    /// Get your authentication token
115    pub fn get_auth_token(&self) -> Result<&str, Box<dyn Error>> {
116        // prepare session token, if not ready
117        if self.session_token.is_none() {
118            return Err(Box::from("Auth Token not ready"));
119        }
120
121        // check if token has expired
122        let timestamp = Utc::now().timestamp_millis();
123        if timestamp > self.session_token.as_ref().unwrap().expires_at {
124            return Err(Box::from("Auth Token expired"));
125        }
126
127        Ok(&self.session_token.as_ref().unwrap().secret)
128    }
129
130    /// generate Merkle v2 API bearer token
131    async fn generate_bearer(&mut self) -> Result<(), Box<dyn Error>> {
132        self.bearer_token =
133            Some(crate::Farcaster::generate_bearer(&self.wallet, self.token_duration_secs).await?);
134
135        Ok(())
136    }
137
138    /// get Merkle v2 API session token
139    async fn get_session_token(&mut self) -> Result<(), Box<dyn Error>> {
140        // generate bearer token, if not ready
141        if self.bearer_token.is_none() {
142            self.generate_bearer().await?;
143        }
144
145        self.session_token =
146            Some(crate::Farcaster::get_session_token(&self.bearer_token.as_ref().unwrap()).await?);
147
148        Ok(())
149    }
150
151    /// Function to regenete your session token.
152    /// Ideal for bots. Regenerate every hour to secure your token.
153    pub async fn regen_session_token(
154        &mut self,
155        token_duration: Option<i64>,
156    ) -> Result<(), Box<dyn Error>> {
157        let token_duration_secs = token_duration.unwrap_or(
158            self.token_duration_secs
159                .unwrap_or(AUTH_TOKEN_DEFAULT_DURATION_SECS),
160        );
161
162        self.bearer_token =
163            Some(crate::Farcaster::generate_bearer(&self.wallet, Some(token_duration_secs)).await?);
164
165        self.session_token =
166            Some(crate::Farcaster::get_session_token(&self.bearer_token.as_ref().unwrap()).await?);
167
168        Ok(())
169    }
170
171    /// Revokes a specific session token
172    pub async fn revoke_auth_token(&mut self) -> Result<RevokedKeyRoot, Box<dyn Error>> {
173        // Return error if no session token is present
174        if self.session_token.is_none() {
175            return Err(Box::from("No session token present"));
176        }
177
178        let revoke =
179            crate::Farcaster::revoke_session_token(&self.session_token.as_ref().unwrap()).await?;
180
181        Ok(revoke)
182    }
183}