breez_sdk_spark/sdk/
deposits.rs

1use bitcoin::{consensus::serialize, hex::DisplayHex};
2use tracing::error;
3
4use crate::{
5    ClaimDepositRequest, ClaimDepositResponse, DepositInfo, ListUnclaimedDepositsRequest,
6    ListUnclaimedDepositsResponse, RefundDepositRequest, RefundDepositResponse, error::SdkError,
7    persist::UpdateDepositPayload, utils::utxo_fetcher::CachedUtxoFetcher,
8};
9
10use super::{BreezSdk, SyncType};
11
12#[cfg_attr(feature = "uniffi", uniffi::export(async_runtime = "tokio"))]
13#[allow(clippy::needless_pass_by_value)]
14impl BreezSdk {
15    pub async fn claim_deposit(
16        &self,
17        request: ClaimDepositRequest,
18    ) -> Result<ClaimDepositResponse, SdkError> {
19        self.ensure_spark_private_mode_initialized().await?;
20        let detailed_utxo =
21            CachedUtxoFetcher::new(self.chain_service.clone(), self.storage.clone())
22                .fetch_detailed_utxo(&request.txid, request.vout)
23                .await?;
24
25        let max_fee = request
26            .max_fee
27            .or(self.config.max_deposit_claim_fee.clone());
28        match self.claim_utxo(&detailed_utxo, max_fee).await {
29            Ok(transfer) => {
30                self.storage
31                    .delete_deposit(detailed_utxo.txid.to_string(), detailed_utxo.vout)
32                    .await?;
33                self.sync_coordinator
34                    .trigger_sync_no_wait(SyncType::WalletState, true)
35                    .await;
36                Ok(ClaimDepositResponse {
37                    payment: transfer.try_into()?,
38                })
39            }
40            Err(e) => {
41                error!("Failed to claim deposit: {e:?}");
42                self.storage
43                    .update_deposit(
44                        detailed_utxo.txid.to_string(),
45                        detailed_utxo.vout,
46                        UpdateDepositPayload::ClaimError {
47                            error: e.clone().into(),
48                        },
49                    )
50                    .await?;
51                Err(e)
52            }
53        }
54    }
55
56    pub async fn refund_deposit(
57        &self,
58        request: RefundDepositRequest,
59    ) -> Result<RefundDepositResponse, SdkError> {
60        let detailed_utxo =
61            CachedUtxoFetcher::new(self.chain_service.clone(), self.storage.clone())
62                .fetch_detailed_utxo(&request.txid, request.vout)
63                .await?;
64        let tx = self
65            .spark_wallet
66            .refund_static_deposit(
67                detailed_utxo.clone().tx,
68                Some(detailed_utxo.vout),
69                &request.destination_address,
70                request.fee.into(),
71            )
72            .await?;
73        let deposit: DepositInfo = detailed_utxo.into();
74        let tx_hex = serialize(&tx).as_hex().to_string();
75        let tx_id = tx.compute_txid().as_raw_hash().to_string();
76
77        // Store the refund transaction details separately
78        self.storage
79            .update_deposit(
80                deposit.txid.clone(),
81                deposit.vout,
82                UpdateDepositPayload::Refund {
83                    refund_tx: tx_hex.clone(),
84                    refund_txid: tx_id.clone(),
85                },
86            )
87            .await?;
88
89        self.chain_service
90            .broadcast_transaction(tx_hex.clone())
91            .await?;
92        Ok(RefundDepositResponse { tx_id, tx_hex })
93    }
94
95    #[allow(unused_variables)]
96    pub async fn list_unclaimed_deposits(
97        &self,
98        request: ListUnclaimedDepositsRequest,
99    ) -> Result<ListUnclaimedDepositsResponse, SdkError> {
100        let deposits = self.storage.list_deposits().await?;
101        Ok(ListUnclaimedDepositsResponse { deposits })
102    }
103}