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}