spark_sdk/wallet/internal_handlers/implementations/
split.rs1use crate::constants::spark::DUST_AMOUNT;
2use crate::error::SparkSdkError;
3use crate::signer::traits::SparkSigner;
4use crate::wallet::internal_handlers::traits::leaves::LeavesInternalHandlers;
5use crate::wallet::internal_handlers::traits::split::SplitInternalHandlers;
6use crate::wallet::internal_handlers::utils::bitcoin_tx_from_bytes;
7use crate::wallet::leaf_manager::{LeafNode, LeafNodeStatus};
8use crate::SparkSdk;
9use parking_lot::RwLock;
10use tonic::async_trait;
11
12use std::sync::Arc;
15
16#[async_trait]
17impl<S: SparkSigner + Send + Sync + Clone + 'static> SplitInternalHandlers<S> for SparkSdk<S> {
18 async fn split(&mut self, target_value: u64) -> Result<(), SparkSdkError> {
19 if target_value < DUST_AMOUNT {
21 return Err(SparkSdkError::InvalidArgument(
22 "Target value is less than the dust amount".to_string(),
23 ));
24 }
25
26 let target_value_clone = target_value.clone();
28 let parent_node = self.query_single_node(
29 Some(Box::new(move |node: &LeafNode| {
30 node.is_available() && node.value > node.value + target_value_clone + DUST_AMOUNT
31 })),
32 Some(LeafNodeStatus::InSplit),
33 )?;
34
35 let (refund_tx, signing_public_key, tree_node) =
36 self.leaf_manager.update_node_status_for_split(
37 &parent_node.id,
38 &self.get_identity_public_key(),
39 &self.config.spark_config.network,
40 )?;
41
42 let parent_refund_tx = bitcoin_tx_from_bytes(&refund_tx)?;
45 if parent_refund_tx.output.len() != 1 {
46 return Err(SparkSdkError::InvalidArgument(
47 "Cannot split: parent refund transaction must have exactly one output".to_string(),
48 ));
49 }
50
51 let _tree = self
53 .create_tree(
54 None,
55 Some(Arc::new(RwLock::new(tree_node))),
56 0,
57 1,
58 signing_public_key,
59 )
60 .await?;
61
62 Ok(())
63 }
64}