breez_sdk_spark/token_conversion/
models.rs

1use flashnet::{BTC_ASSET_ADDRESS, Pool};
2use serde::{Deserialize, Serialize};
3
4use crate::SdkError;
5
6/// Default maximum slippage for conversions in basis points (0.1%)
7pub const DEFAULT_CONVERSION_MAX_SLIPPAGE_BPS: u32 = 10;
8/// Default timeout for conversion operations in seconds
9pub const DEFAULT_CONVERSION_TIMEOUT_SECS: u32 = 30;
10/// Default integrator pubkey used when executing conversions
11pub const DEFAULT_INTEGRATOR_PUBKEY: &str =
12    "037e26d9d62e0b3df2d3e66805f61de2a33914465297abf76817296a92ac3f2379";
13/// Default integrator fee BPS used when simulating/executing conversions
14pub const DEFAULT_INTEGRATOR_FEE_BPS: u32 = 5;
15
16/// Response from estimating a conversion, used when preparing a payment that requires conversion
17#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
18#[derive(Debug, Clone, Serialize)]
19pub struct ConversionEstimate {
20    /// The conversion options used for the estimate
21    pub options: ConversionOptions,
22    /// The estimated amount to be received from the conversion
23    /// Denominated in satoshis if converting from Bitcoin, otherwise in the token base units.
24    pub amount: u128,
25    /// The fee estimated for the conversion
26    /// Denominated in satoshis if converting from Bitcoin, otherwise in the token base units.
27    pub fee: u128,
28}
29
30/// The purpose of the conversion, which is used to provide context for the conversion
31/// if its related to an ongoing payment or a self-transfer.
32#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
33#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
34pub enum ConversionPurpose {
35    /// Conversion is associated with an ongoing payment
36    OngoingPayment {
37        /// The payment request of the ongoing payment
38        payment_request: String,
39    },
40    /// Conversion is for self-transfer
41    SelfTransfer,
42    /// Conversion triggered automatically
43    AutoConversion,
44}
45
46/// Specifies how to determine the conversion amount.
47#[derive(Debug, Clone)]
48pub(crate) enum ConversionAmount {
49    /// Specify the minimum output amount - the input will be calculated.
50    /// Used for payment conversions where we know the required output.
51    MinAmountOut(u128),
52    /// Specify the exact input amount - used for auto-conversion where we know the sats balance.
53    AmountIn(u128),
54}
55
56/// The status of the conversion
57#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
58#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
59pub enum ConversionStatus {
60    /// The conversion was successful
61    Completed,
62    /// The conversion failed and no refund was made yet, which requires action by the SDK to
63    /// perform the refund. This can happen if there was a failure during the conversion process.
64    RefundNeeded,
65    /// The conversion failed and a refund was made
66    Refunded,
67}
68
69#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
70#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
71pub struct ConversionInfo {
72    /// The pool id associated with the conversion
73    pub pool_id: String,
74    /// The conversion id shared by both sides of the conversion
75    pub conversion_id: String,
76    /// The status of the conversion
77    pub status: ConversionStatus,
78    /// The fee paid for the conversion
79    /// Denominated in satoshis if converting from Bitcoin, otherwise in the token base units.
80    pub fee: Option<u128>,
81    /// The purpose of the conversion
82    pub purpose: Option<ConversionPurpose>,
83}
84
85pub(crate) struct TokenConversionPool {
86    pub(crate) asset_in_address: String,
87    pub(crate) asset_out_address: String,
88    pub(crate) pool: Pool,
89}
90
91pub(crate) struct TokenConversionResponse {
92    /// The sent payment id for the conversion
93    pub(crate) sent_payment_id: String,
94    /// The received payment id for the conversion
95    pub(crate) received_payment_id: String,
96}
97
98/// Options for conversion when fulfilling a payment. When set, the SDK will
99/// perform a conversion before fulfilling the payment. If not set, the payment
100/// will only be fulfilled if the wallet has sufficient balance of the required asset.
101#[derive(Debug, Clone, Serialize)]
102#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
103pub struct ConversionOptions {
104    /// The type of conversion to perform when fulfilling the payment
105    pub conversion_type: ConversionType,
106    /// The optional maximum slippage in basis points (1/100 of a percent) allowed when
107    /// a conversion is needed to fulfill the payment. Defaults to 10 bps (0.1%) if not set.
108    /// The conversion will fail if the actual amount received is less than
109    /// `estimated_amount * (1 - max_slippage_bps / 10_000)`.
110    #[cfg_attr(feature = "uniffi", uniffi(default = None))]
111    pub max_slippage_bps: Option<u32>,
112    /// The optional timeout in seconds to wait for the conversion to complete
113    /// when fulfilling the payment. This timeout only concerns waiting for the received
114    /// payment of the conversion. If the timeout is reached before the conversion
115    /// is complete, the payment will fail. Defaults to 30 seconds if not set.
116    #[cfg_attr(feature = "uniffi", uniffi(default = None))]
117    pub completion_timeout_secs: Option<u32>,
118}
119
120#[derive(Debug, Clone, Serialize, PartialEq)]
121#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
122pub enum ConversionType {
123    /// Converting from Bitcoin to a token
124    FromBitcoin,
125    /// Converting from a token to Bitcoin
126    ToBitcoin { from_token_identifier: String },
127}
128
129impl ConversionType {
130    /// Returns the asset addresses for the conversion type
131    ///
132    /// # Arguments
133    ///
134    /// * `token_identifier` - The token identifier when converting from Bitcoin to a token
135    ///
136    /// # Returns
137    ///
138    /// Result containing:
139    /// * (String, String): A tuple containing the asset in address and asset out address
140    /// * `SdkError`: If the token identifier is required but not provided
141    pub(crate) fn as_asset_addresses(
142        &self,
143        token_identifier: Option<&String>,
144    ) -> Result<(String, String), SdkError> {
145        Ok(match self {
146            ConversionType::FromBitcoin => (
147                BTC_ASSET_ADDRESS.to_string(),
148                token_identifier
149                    .ok_or(SdkError::InvalidInput(
150                        "Token identifier is required for from Bitcoin conversion".to_string(),
151                    ))?
152                    .clone(),
153            ),
154            ConversionType::ToBitcoin {
155                from_token_identifier,
156            } => (from_token_identifier.clone(), BTC_ASSET_ADDRESS.to_string()),
157        })
158    }
159}
160
161#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
162pub struct FetchConversionLimitsRequest {
163    /// The type of conversion, either from or to Bitcoin.
164    pub conversion_type: ConversionType,
165    /// The token identifier when converting to a token.
166    #[cfg_attr(feature = "uniffi", uniffi(default = None))]
167    pub token_identifier: Option<String>,
168}
169
170#[derive(Debug, Clone, Serialize)]
171#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
172pub struct FetchConversionLimitsResponse {
173    /// The minimum amount to be converted.
174    /// Denominated in satoshis if converting from Bitcoin, otherwise in the token base units.
175    pub min_from_amount: Option<u128>,
176    /// The minimum amount to be received from the conversion.
177    /// Denominated in satoshis if converting to Bitcoin, otherwise in the token base units.
178    pub min_to_amount: Option<u128>,
179}