spark_rust/wallet/handlers/
init.rs

1use std::sync::Arc;
2
3use bitcoin::secp256k1::PublicKey;
4
5use crate::{
6    error::SparkSdkError,
7    signer::traits::SparkSigner,
8    wallet::{
9        config::WalletConfig,
10        internal_handlers::traits::{
11            authenticate::AuthenticateInternalHandlers, leaves::LeavesInternalHandlers,
12        },
13        leaf_manager::LeafManager,
14    },
15    SparkNetwork, SparkSdk,
16};
17
18impl<S: SparkSigner + Send + Sync + Clone + 'static> SparkSdk<S> {
19    /// Creates a new instance of the Spark SDK.
20    ///
21    /// This is the main entry point for interacting with the Spark protocol. It initializes the SDK with
22    /// the provided network configuration, signer implementation, and optional data storage path.
23    ///
24    /// # Arguments
25    ///
26    /// * `network` - The Spark network to connect to (e.g. Regtest or Mainnet)
27    /// * `signer` - Implementation of the SparkSigner trait wrapped in Arc for thread-safe access
28    ///
29    /// # Returns
30    ///
31    /// Returns a Result containing either:
32    /// * The initialized SparkSdk instance
33    /// * A SparkSdkError if initialization fails
34    ///
35    /// # Examples
36    ///
37    /// ```
38    /// use spark_rust::{
39    ///     error::SparkSdkError,
40    ///     signer::default_signer::DefaultSigner,
41    ///     signer::traits::SparkSigner,
42    ///     SparkNetwork, SparkSdk,
43    /// };
44    ///
45    /// async fn init_sdk() {
46    ///     let mnemonic = "abandon ability able about above absent absorb abstract absurd abuse access accident";
47    ///     let network = SparkNetwork::Regtest;
48    ///     let signer = DefaultSigner::from_mnemonic(mnemonic, network.clone()).await.unwrap();
49    ///     let sdk = SparkSdk::new(
50    ///         network,
51    ///         signer
52    ///     ).await.unwrap();
53    /// }
54    /// ```
55    #[cfg_attr(feature = "telemetry", tracing::instrument(skip_all, fields(network = ?network)))]
56    pub async fn new(network: SparkNetwork, signer: Arc<S>) -> Result<Self, SparkSdkError> {
57        let config = WalletConfig::new(network).await?;
58        let leaf_manager = Arc::new(LeafManager::new());
59
60        let sdk = Self {
61            config,
62            signer: signer.clone(),
63            leaf_manager,
64            handler_lock: Arc::new(tokio::sync::Mutex::new(())),
65        };
66
67        let sessions = sdk.authenticate().await?;
68
69        {
70            let mut write = sdk.config.spark_config.sessions.write();
71            *write = sessions;
72        }
73
74        let sdk_clone = sdk.clone();
75
76        // refresh BTC leaves
77        sdk_clone.sync_leaves().await?;
78
79        Ok(sdk)
80    }
81
82    /// Returns the Spark address of the wallet, which is the identity public key.
83    ///
84    /// The Spark address is derived from the identity public key of the wallet.
85    /// This key is generated when the wallet is first created and remains constant throughout the
86    /// wallet's lifetime.
87    ///
88    /// The Spark address serves several purposes:
89    /// - Authenticates the wallet with Spark operators during API calls
90    /// - Used in deposit address generation to prove ownership
91    /// - Required for validating operator signatures
92    /// - Helps prevent unauthorized access to wallet funds
93    ///
94    /// # Returns
95    /// A byte slice containing the 33-byte compressed secp256k1 public key in SEC format.
96    /// The first byte is either 0x02 or 0x03 (the parity), followed by the 32-byte X coordinate.
97    ///
98    /// # Examples
99    /// ```
100    /// # use spark_rust::{SparkSdk, SparkNetwork, signer::default_signer::DefaultSigner, signer::traits::SparkSigner};
101    ///
102    /// # async fn example() {
103    /// let network = SparkNetwork::Regtest;
104    /// let mnemonic = "abandon ability able about above absent absorb abstract absurd abuse access accident";
105    /// let signer = DefaultSigner::from_mnemonic(mnemonic, network.clone()).await.unwrap();
106    /// let sdk = SparkSdk::new(network, signer).await.unwrap();
107    ///
108    /// // Spark address is the identity public key of the user. This is derived using Spark's custom derivation path explained in the docs.
109    /// let spark_address = sdk.get_spark_address().unwrap();
110    ///
111    /// // Currently, a user's Spark address is their public key.
112    /// assert_eq!(spark_address.serialize().len(), 33);
113    /// # }
114    /// ```
115    #[cfg_attr(feature = "telemetry", tracing::instrument(skip_all))]
116    pub fn get_spark_address(&self) -> Result<PublicKey, SparkSdkError> {
117        let account_index = 0;
118        let network = self.config.spark_config.network.to_bitcoin_network();
119        let pubkey = self
120            .signer
121            .get_identity_public_key(account_index, network)?;
122
123        Ok(pubkey)
124    }
125
126    /// Returns the Bitcoin network that this wallet is connected to.
127    ///
128    /// The network determines which Spark operators the wallet communicates with and which Bitcoin network
129    /// (mainnet or regtest) is used for transactions.
130    ///
131    /// # Network Types
132    /// - [`SparkNetwork::Mainnet`] - Production Bitcoin mainnet environment
133    /// - [`SparkNetwork::Regtest`] - Testing environment using Lightspark's regtest network
134    ///
135    /// The network is set when creating the wallet and cannot be changed after initialization.
136    /// All transactions and addresses will be created for the configured network.
137    ///
138    /// # Returns
139    /// Returns a [`SparkNetwork`] enum indicating whether this is a mainnet or regtest wallet.
140    ///
141    /// # Examples
142    /// ```
143    /// # use spark_rust::{SparkSdk, SparkNetwork, signer::default_signer::DefaultSigner, signer::traits::SparkSigner};
144    /// # async fn example() {
145    /// let mnemonic = "abandon ability able about above absent absorb abstract absurd abuse access accident";
146    /// let network = SparkNetwork::Regtest;
147    ///
148    /// // Create a DefaultSigner that implements SparkSigner
149    /// let signer = DefaultSigner::from_mnemonic(mnemonic, network.clone()).await.unwrap();
150    /// let sdk = SparkSdk::new(network, signer).await.unwrap();
151    ///
152    /// assert_eq!(sdk.get_network(), SparkNetwork::Regtest);
153    ///
154    /// # }
155    /// ```
156    #[cfg_attr(feature = "telemetry", tracing::instrument(skip_all))]
157    pub fn get_network(&self) -> SparkNetwork {
158        self.config.spark_config.network
159    }
160}