Skip to main content

breez_sdk_spark/token_conversion/
mod.rs

1mod error;
2mod flashnet;
3mod middleware;
4mod models;
5
6pub use error::ConversionError;
7pub(crate) use flashnet::FlashnetTokenConverter;
8pub(crate) use middleware::TokenConversionMiddleware;
9pub use models::*;
10
11use std::sync::Arc;
12
13use spark_wallet::TransferId;
14use tokio::sync::broadcast;
15
16use crate::EventEmitter;
17
18/// Trait for conversion implementations.
19///
20/// This trait abstracts the conversion mechanics, allowing different
21/// implementations (e.g., Flashnet) to be used interchangeably.
22/// Business logic for when/how much to convert is handled by `StableBalance`.
23///
24/// Implementations are reachable from the `EventEmitter` (the stable balance
25/// middleware holds the converter), so they must not store an emitter
26/// reference; the caller passes one into [`convert`](Self::convert) instead.
27#[macros::async_trait]
28pub(crate) trait TokenConverter: Send + Sync {
29    /// Execute a conversion swap.
30    ///
31    /// # Arguments
32    /// * `event_emitter` - Emitter for the payment events of the swap legs
33    /// * `options` - The conversion options including type and slippage
34    /// * `purpose` - The purpose of the conversion
35    /// * `token_identifier` - Optional token identifier for `FromBitcoin` conversions
36    /// * `amount` - Either the minimum output amount or exact input amount
37    /// * `transfer_id` - Optional transfer ID for idempotency
38    async fn convert(
39        &self,
40        event_emitter: Arc<EventEmitter>,
41        options: &ConversionOptions,
42        purpose: &ConversionPurpose,
43        token_identifier: Option<&String>,
44        amount: ConversionAmount,
45        transfer_id: Option<TransferId>,
46    ) -> Result<TokenConversionResponse, ConversionError>;
47
48    /// Validate a conversion and return the estimated conversion.
49    ///
50    /// Called during `prepare_send_payment` to calculate the conversion fee,
51    /// and during auto-conversion to estimate the token output.
52    ///
53    /// # Arguments
54    /// * `options` - The conversion options to validate
55    /// * `token_identifier` - Optional token identifier for `FromBitcoin` conversions
56    /// * `amount` - Either the minimum output amount or exact input amount
57    ///
58    /// # Returns
59    /// The estimated conversion including amount and fee, or None if options is None.
60    /// `estimate.amount_in` is the input amount, `estimate.amount_out` is the estimated output.
61    async fn validate(
62        &self,
63        options: Option<&ConversionOptions>,
64        token_identifier: Option<&String>,
65        amount: ConversionAmount,
66    ) -> Result<Option<ConversionEstimate>, ConversionError>;
67
68    /// Fetch conversion limits for a given conversion type.
69    ///
70    /// # Arguments
71    /// * `request` - The request containing conversion type and optional token identifier
72    async fn fetch_limits(
73        &self,
74        request: &FetchConversionLimitsRequest,
75    ) -> Result<FetchConversionLimitsResponse, ConversionError>;
76
77    /// Process any conversions whose pending refunds need to be issued.
78    ///
79    /// Iterates over payments marked as needing a refund and attempts to
80    /// refund each one. Surfaced through `BreezSdk::refund_pending_conversions`
81    /// so partners can drive this explicitly — required in server mode (where
82    /// no periodic refunder runs) and available in client mode as a way to
83    /// force an immediate refund pass instead of waiting for the next tick.
84    async fn refund_pending(&self) -> Result<(), ConversionError>;
85
86    /// Optional signal that wakes the client-mode periodic refunder.
87    fn subscribe_refund_requests(&self) -> Option<broadcast::Receiver<()>> {
88        None
89    }
90}