etopay_sdk/core/
share.rs

1//! The share module provides functionality for dealing with shares of the user wallet mnemonic.
2
3use super::Sdk;
4use crate::error::Result;
5use crate::share::Share;
6use log::info;
7
8impl Sdk {
9    /// Get/download the recovery share.
10    ///
11    /// # Returns
12    ///
13    /// The recovery share, or `None` if none exists.
14    ///
15    /// # Error
16    ///
17    /// Returns error if the user is not initialized.
18    pub async fn get_recovery_share(&self) -> Result<Option<Share>> {
19        info!("Getting recovery share");
20        let Some(active_user) = &self.active_user else {
21            return Err(crate::Error::UserNotInitialized);
22        };
23        Ok(active_user.wallet_manager.get_recovery_share())
24    }
25
26    /// Set/upload the recovery share.
27    ///
28    /// # Arguments
29    ///
30    /// * `share` - The recovery share to upload.
31    ///
32    /// # Error
33    ///
34    /// Returns error if the user is not initialized.
35    pub async fn set_recovery_share(&mut self, share: Share) -> Result<()> {
36        info!("Setting recovery share");
37        let Some(active_user) = &mut self.active_user else {
38            return Err(crate::Error::UserNotInitialized);
39        };
40        active_user.wallet_manager.set_recovery_share(Some(share));
41        Ok(())
42    }
43}
44
45#[cfg(test)]
46mod tests {
47    use crate::core::core_testing_utils::handle_error_test_cases;
48    use crate::{
49        core::Sdk,
50        error::Result,
51        share::Share,
52        testing_utils::{USERNAME, set_config},
53        wallet_manager::MockWalletManager,
54    };
55    use mockall::predicate::eq;
56    use rstest::rstest;
57    use secrecy::ExposeSecret;
58
59    fn example_share() -> String {
60        Share::mock_share().to_string().expose_secret().to_owned()
61    }
62
63    #[rstest]
64    #[case::success(Ok(example_share()))]
65    #[case::user_init_error(Err(crate::Error::UserNotInitialized))]
66    #[tokio::test]
67    async fn test_get_recovery_share(#[case] expected: Result<String>) {
68        // Arrange
69        let (_srv, config, _cleanup) = set_config().await;
70        let mut sdk = Sdk::new(config).unwrap();
71
72        match &expected {
73            Ok(_) => {
74                let mut mock_wallet_manager = MockWalletManager::new();
75                mock_wallet_manager
76                    .expect_get_recovery_share()
77                    .once()
78                    .returning(|| Some(Share::mock_share()));
79                sdk.active_user = Some(crate::types::users::ActiveUser {
80                    username: USERNAME.into(),
81                    wallet_manager: Box::new(mock_wallet_manager),
82                });
83            }
84            Err(error) => {
85                handle_error_test_cases(error, &mut sdk, 0, 0).await;
86            }
87        }
88
89        // Act
90        let response = sdk.get_recovery_share().await;
91
92        // Assert
93        match expected {
94            Ok(resp) => {
95                assert_eq!(response.unwrap().unwrap().to_string().expose_secret(), resp);
96            }
97            Err(ref expected_err) => {
98                assert_eq!(response.err().unwrap().to_string(), expected_err.to_string());
99            }
100        }
101    }
102
103    #[rstest]
104    #[case::success(Ok(()))]
105    #[case::user_init_error(Err(crate::Error::UserNotInitialized))]
106    #[tokio::test]
107    async fn test_set_recovery_share(#[case] expected: Result<()>) {
108        // Arrange
109        let (_srv, config, _cleanup) = set_config().await;
110        let mut sdk = Sdk::new(config).unwrap();
111
112        match &expected {
113            Ok(_) => {
114                let mut mock_wallet_manager = MockWalletManager::new();
115                mock_wallet_manager
116                    .expect_set_recovery_share()
117                    .once()
118                    .with(eq(Some(Share::mock_share())))
119                    .returning(|_share| ());
120                sdk.active_user = Some(crate::types::users::ActiveUser {
121                    username: USERNAME.into(),
122                    wallet_manager: Box::new(mock_wallet_manager),
123                });
124            }
125            Err(error) => {
126                handle_error_test_cases(error, &mut sdk, 0, 0).await;
127            }
128        }
129
130        // Act
131        let response = sdk.set_recovery_share(Share::mock_share()).await;
132
133        // Assert
134        match expected {
135            Ok(()) => response.unwrap(),
136            Err(ref expected_err) => {
137                assert_eq!(response.err().unwrap().to_string(), expected_err.to_string());
138            }
139        }
140    }
141}