1pub(crate) mod adaptors;
2pub mod payment_observer;
3pub use payment_observer::*;
4
5pub use crate::token_conversion::{
7 AmountAdjustmentReason, ConversionEstimate, ConversionInfo, ConversionOptions,
8 ConversionPurpose, ConversionStatus, ConversionType, FetchConversionLimitsRequest,
9 FetchConversionLimitsResponse,
10};
11
12use core::fmt;
13use lnurl_models::RecoverLnurlPayResponse;
14use serde::{Deserialize, Serialize};
15use serde_json::Value;
16use std::{
17 collections::{HashMap, HashSet},
18 fmt::Display,
19 str::FromStr,
20};
21
22use crate::{
23 BitcoinAddressDetails, BitcoinChainService, BitcoinNetwork, Bolt11InvoiceDetails,
24 ExternalInputParser, FiatCurrency, LnurlPayRequestDetails, LnurlWithdrawRequestDetails, Rate,
25 SdkError, SparkInvoiceDetails, SuccessAction, SuccessActionProcessed,
26 cross_chain::{CrossChainFeeMode, CrossChainProviderContext, CrossChainRoutePair},
27 error::DepositClaimError,
28};
29
30pub const DEFAULT_EXTERNAL_INPUT_PARSERS: &[(&str, &str, &str)] = &[
33 (
34 "picknpay",
35 "(.*)(za.co.electrum.picknpay)(.*)",
36 "https://cryptoqr.net/.well-known/lnurlp/<input>",
37 ),
38 (
39 "bootleggers",
40 r"(.*)(wigroup\.co|yoyogroup\.co)(.*)",
41 "https://cryptoqr.net/.well-known/lnurlw/<input>",
42 ),
43];
44
45#[derive(Debug, Clone)]
48#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
49pub enum Seed {
50 Mnemonic {
52 mnemonic: String,
54 passphrase: Option<String>,
56 },
57 Entropy(Vec<u8>),
59}
60
61impl Seed {
62 pub fn to_bytes(&self) -> Result<Vec<u8>, SdkError> {
63 match self {
64 Seed::Mnemonic {
65 mnemonic,
66 passphrase,
67 } => {
68 let mnemonic = bip39::Mnemonic::parse(mnemonic)
69 .map_err(|e| SdkError::Generic(e.to_string()))?;
70
71 Ok(mnemonic
72 .to_seed(passphrase.as_deref().unwrap_or(""))
73 .to_vec())
74 }
75 Seed::Entropy(entropy) => Ok(entropy.clone()),
76 }
77 }
78}
79
80#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
81pub struct ConnectRequest {
82 pub config: Config,
83 pub seed: Seed,
84 pub storage_dir: String,
85}
86
87#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
91#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
92pub struct ConnectWithSignerRequest {
93 pub config: Config,
94 pub breez_signer: std::sync::Arc<dyn crate::signer::ExternalBreezSigner>,
97 pub spark_signer: std::sync::Arc<dyn crate::signer::ExternalSparkSigner>,
99 pub storage_dir: String,
100}
101
102#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
110#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
111pub struct ConnectWithSigningOnlySignerRequest {
112 pub config: Config,
113 pub breez_signer: std::sync::Arc<dyn crate::signer::ExternalSigningSigner>,
115 pub spark_signer: std::sync::Arc<dyn crate::signer::ExternalSparkSigner>,
117 pub storage_dir: String,
118}
119
120#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
122#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
123pub enum PaymentType {
124 Send,
126 Receive,
128}
129
130impl fmt::Display for PaymentType {
131 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132 match self {
133 PaymentType::Send => write!(f, "send"),
134 PaymentType::Receive => write!(f, "receive"),
135 }
136 }
137}
138
139impl FromStr for PaymentType {
140 type Err = String;
141
142 fn from_str(s: &str) -> Result<Self, Self::Err> {
143 Ok(match s.to_lowercase().as_str() {
144 "receive" => PaymentType::Receive,
145 "send" => PaymentType::Send,
146 _ => return Err(format!("invalid payment type '{s}'")),
147 })
148 }
149}
150
151#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
153#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
154pub enum PaymentStatus {
155 Completed,
157 Pending,
159 Failed,
161}
162
163impl PaymentStatus {
164 pub fn is_final(&self) -> bool {
166 matches!(self, PaymentStatus::Completed | PaymentStatus::Failed)
167 }
168}
169
170impl fmt::Display for PaymentStatus {
171 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
172 match self {
173 PaymentStatus::Completed => write!(f, "completed"),
174 PaymentStatus::Pending => write!(f, "pending"),
175 PaymentStatus::Failed => write!(f, "failed"),
176 }
177 }
178}
179
180impl FromStr for PaymentStatus {
181 type Err = String;
182
183 fn from_str(s: &str) -> Result<Self, Self::Err> {
184 Ok(match s.to_lowercase().as_str() {
185 "completed" => PaymentStatus::Completed,
186 "pending" => PaymentStatus::Pending,
187 "failed" => PaymentStatus::Failed,
188 _ => return Err(format!("Invalid payment status '{s}'")),
189 })
190 }
191}
192
193#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
194#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
195pub enum PaymentMethod {
196 Lightning,
197 Spark,
198 Token,
199 Deposit,
200 Withdraw,
201 Unknown,
202}
203
204impl Display for PaymentMethod {
205 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
206 match self {
207 PaymentMethod::Lightning => write!(f, "lightning"),
208 PaymentMethod::Spark => write!(f, "spark"),
209 PaymentMethod::Token => write!(f, "token"),
210 PaymentMethod::Deposit => write!(f, "deposit"),
211 PaymentMethod::Withdraw => write!(f, "withdraw"),
212 PaymentMethod::Unknown => write!(f, "unknown"),
213 }
214 }
215}
216
217impl FromStr for PaymentMethod {
218 type Err = ();
219
220 fn from_str(s: &str) -> Result<Self, Self::Err> {
221 match s {
222 "lightning" => Ok(PaymentMethod::Lightning),
223 "spark" => Ok(PaymentMethod::Spark),
224 "token" => Ok(PaymentMethod::Token),
225 "deposit" => Ok(PaymentMethod::Deposit),
226 "withdraw" => Ok(PaymentMethod::Withdraw),
227 "unknown" => Ok(PaymentMethod::Unknown),
228 _ => Err(()),
229 }
230 }
231}
232
233#[derive(Debug, Clone, Serialize, Deserialize)]
235#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
236pub struct Payment {
237 pub id: String,
239 pub payment_type: PaymentType,
241 pub status: PaymentStatus,
243 pub amount: u128,
245 pub fees: u128,
247 pub timestamp: u64,
249 pub method: PaymentMethod,
252 pub details: Option<PaymentDetails>,
254 pub conversion_details: Option<ConversionDetails>,
256}
257
258impl Payment {
259 pub fn is_conversion_child(&self) -> bool {
265 matches!(
266 &self.details,
267 Some(
268 PaymentDetails::Spark {
269 conversion_info: Some(_),
270 ..
271 } | PaymentDetails::Token {
272 conversion_info: Some(_),
273 ..
274 }
275 )
276 )
277 }
278}
279
280#[derive(Debug, Clone, Serialize, Deserialize)]
285#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
286pub struct ConversionDetails {
287 pub status: ConversionStatus,
289 #[serde(default)]
292 pub conversions: Vec<Conversion>,
293}
294
295#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
297#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
298pub enum ConversionProvider {
299 Amm,
301 Orchestra,
303 Boltz,
305}
306
307#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
309#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
310pub enum ConversionChain {
311 Spark,
313 Lightning,
315 External {
317 name: String,
319 chain_id: Option<String>,
323 },
324}
325
326#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
329#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
330pub struct ConversionAsset {
331 pub ticker: String,
335 pub identifier: Option<String>,
338 pub decimals: u32,
343}
344
345#[derive(Debug, Clone, Serialize, Deserialize)]
347#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
348pub struct ConversionSide {
349 pub chain: ConversionChain,
351 pub asset: ConversionAsset,
353 pub amount: u128,
355 pub fee: u128,
357}
358
359#[derive(Debug, Clone, Serialize, Deserialize)]
361#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
362pub struct Conversion {
363 pub provider: ConversionProvider,
365 pub status: ConversionStatus,
367 pub from: ConversionSide,
369 pub to: ConversionSide,
371 #[serde(default)]
373 pub amount_adjustment: Option<AmountAdjustmentReason>,
374}
375
376#[cfg(feature = "uniffi")]
377uniffi::custom_type!(u128, String, {
378 remote,
379 try_lift: |val| val.parse::<u128>().map_err(uniffi::deps::anyhow::Error::msg),
380 lower: |obj| obj.to_string(),
381});
382
383#[allow(clippy::large_enum_variant)]
386#[derive(Debug, Clone, Serialize, Deserialize)]
387#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
388pub enum PaymentDetails {
389 Spark {
390 invoice_details: Option<SparkInvoicePaymentDetails>,
392 htlc_details: Option<SparkHtlcDetails>,
394 conversion_info: Option<ConversionInfo>,
396 },
397 Token {
398 metadata: TokenMetadata,
399 tx_hash: String,
400 tx_type: TokenTransactionType,
401 invoice_details: Option<SparkInvoicePaymentDetails>,
403 conversion_info: Option<ConversionInfo>,
405 },
406 Lightning {
407 description: Option<String>,
409 invoice: String,
413
414 destination_pubkey: String,
416
417 htlc_details: SparkHtlcDetails,
419
420 lnurl_pay_info: Option<LnurlPayInfo>,
422
423 lnurl_withdraw_info: Option<LnurlWithdrawInfo>,
425
426 lnurl_receive_metadata: Option<LnurlReceiveMetadata>,
428
429 conversion_info: Option<ConversionInfo>,
433 },
434 Withdraw {
435 tx_id: String,
436 },
437 Deposit {
438 tx_id: String,
439 vout: u32,
440 },
441}
442
443#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
444#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
445pub enum TokenTransactionType {
446 Transfer,
447 Mint,
448 Burn,
449}
450
451impl fmt::Display for TokenTransactionType {
452 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
453 match self {
454 TokenTransactionType::Transfer => write!(f, "transfer"),
455 TokenTransactionType::Mint => write!(f, "mint"),
456 TokenTransactionType::Burn => write!(f, "burn"),
457 }
458 }
459}
460
461impl FromStr for TokenTransactionType {
462 type Err = String;
463
464 fn from_str(s: &str) -> Result<Self, Self::Err> {
465 match s.to_lowercase().as_str() {
466 "transfer" => Ok(TokenTransactionType::Transfer),
467 "mint" => Ok(TokenTransactionType::Mint),
468 "burn" => Ok(TokenTransactionType::Burn),
469 _ => Err(format!("Invalid token transaction type '{s}'")),
470 }
471 }
472}
473
474#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
475#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
476pub struct SparkInvoicePaymentDetails {
477 pub description: Option<String>,
479 pub invoice: String,
481}
482
483#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
484#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
485pub struct SparkHtlcDetails {
486 pub payment_hash: String,
488 pub preimage: Option<String>,
490 pub expiry_time: u64,
492 pub status: SparkHtlcStatus,
494}
495
496#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
497#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
498pub enum SparkHtlcStatus {
499 WaitingForPreimage,
501 PreimageShared,
503 Returned,
505}
506
507impl fmt::Display for SparkHtlcStatus {
508 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
509 match self {
510 SparkHtlcStatus::WaitingForPreimage => write!(f, "WaitingForPreimage"),
511 SparkHtlcStatus::PreimageShared => write!(f, "PreimageShared"),
512 SparkHtlcStatus::Returned => write!(f, "Returned"),
513 }
514 }
515}
516
517impl FromStr for SparkHtlcStatus {
518 type Err = String;
519
520 fn from_str(s: &str) -> Result<Self, Self::Err> {
521 match s {
522 "WaitingForPreimage" => Ok(SparkHtlcStatus::WaitingForPreimage),
523 "PreimageShared" => Ok(SparkHtlcStatus::PreimageShared),
524 "Returned" => Ok(SparkHtlcStatus::Returned),
525 _ => Err("Invalid Spark HTLC status".to_string()),
526 }
527 }
528}
529
530#[derive(Debug, Clone, Copy, PartialEq, Eq)]
531#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
532pub enum Network {
533 Mainnet,
534 Regtest,
535}
536
537impl std::fmt::Display for Network {
538 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
539 match self {
540 Network::Mainnet => write!(f, "Mainnet"),
541 Network::Regtest => write!(f, "Regtest"),
542 }
543 }
544}
545
546impl From<Network> for BitcoinNetwork {
547 fn from(network: Network) -> Self {
548 match network {
549 Network::Mainnet => BitcoinNetwork::Bitcoin,
550 Network::Regtest => BitcoinNetwork::Regtest,
551 }
552 }
553}
554
555impl From<Network> for breez_sdk_common::network::BitcoinNetwork {
556 fn from(network: Network) -> Self {
557 match network {
558 Network::Mainnet => breez_sdk_common::network::BitcoinNetwork::Bitcoin,
559 Network::Regtest => breez_sdk_common::network::BitcoinNetwork::Regtest,
560 }
561 }
562}
563
564impl From<Network> for bitcoin::Network {
565 fn from(network: Network) -> Self {
566 match network {
567 Network::Mainnet => bitcoin::Network::Bitcoin,
568 Network::Regtest => bitcoin::Network::Regtest,
569 }
570 }
571}
572
573impl FromStr for Network {
574 type Err = String;
575
576 fn from_str(s: &str) -> Result<Self, Self::Err> {
577 match s {
578 "mainnet" => Ok(Network::Mainnet),
579 "regtest" => Ok(Network::Regtest),
580 _ => Err("Invalid network".to_string()),
581 }
582 }
583}
584
585#[derive(Debug, Clone)]
586#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
587#[allow(clippy::struct_excessive_bools)]
588pub struct Config {
589 pub api_key: Option<String>,
590 pub network: Network,
591 pub sync_interval_secs: u32,
592
593 pub max_deposit_claim_fee: Option<MaxFee>,
596
597 pub lnurl_domain: Option<String>,
599
600 pub prefer_spark_over_lightning: bool,
604
605 pub external_input_parsers: Option<Vec<ExternalInputParser>>,
609 pub use_default_external_input_parsers: bool,
613
614 pub real_time_sync_server_url: Option<String>,
616
617 pub private_enabled_default: bool,
629
630 pub leaf_optimization_config: LeafOptimizationConfig,
636
637 pub token_optimization_config: TokenOptimizationConfig,
644
645 pub stable_balance_config: Option<StableBalanceConfig>,
650
651 pub max_concurrent_claims: u32,
655
656 pub spark_config: Option<SparkConfig>,
662
663 pub background_tasks_enabled: bool,
688
689 pub cross_chain_config: Option<CrossChainConfig>,
697}
698
699#[derive(Debug, Clone, Default)]
704#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
705pub struct CrossChainConfig {
706 #[cfg_attr(feature = "uniffi", uniffi(default = None))]
711 pub default_slippage_bps: Option<u32>,
712 #[cfg_attr(feature = "uniffi", uniffi(default = None))]
718 pub default_target_overpay_bps: Option<u32>,
719}
720
721#[derive(Debug, Clone)]
723#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
724pub struct LeafOptimizationConfig {
725 pub auto_enabled: bool,
732 pub multiplicity: u8,
744}
745
746#[derive(Debug, Clone)]
748#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
749pub struct TokenOptimizationConfig {
750 pub auto_enabled: bool,
758 pub target_output_count: u32,
771 pub min_outputs_threshold: u32,
780}
781
782#[derive(Debug, Clone)]
784#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
785pub struct StableBalanceToken {
786 pub label: String,
792
793 pub token_identifier: String,
795}
796
797#[derive(Debug, Clone)]
811#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
812pub struct StableBalanceConfig {
813 pub tokens: Vec<StableBalanceToken>,
815
816 #[cfg_attr(feature = "uniffi", uniffi(default = None))]
822 pub default_active_label: Option<String>,
823
824 #[cfg_attr(feature = "uniffi", uniffi(default = None))]
829 pub threshold_sats: Option<u64>,
830
831 #[cfg_attr(feature = "uniffi", uniffi(default = None))]
835 pub max_slippage_bps: Option<u32>,
836}
837
838#[derive(Debug, Clone)]
840#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
841pub enum StableBalanceActiveLabel {
842 Set { label: String },
844 Unset,
846}
847
848#[derive(Debug, Clone)]
854#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
855pub struct SparkConfig {
856 pub coordinator_identifier: String,
858 pub threshold: u32,
860 pub signing_operators: Vec<SparkSigningOperator>,
862 pub ssp_config: SparkSspConfig,
864 pub expected_withdraw_bond_sats: u64,
866 pub expected_withdraw_relative_block_locktime: u64,
868 pub max_token_transaction_inputs: Option<u32>,
872}
873
874#[derive(Debug, Clone)]
876#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
877pub struct SparkSigningOperator {
878 pub id: u32,
880 pub identifier: String,
882 pub address: String,
884 pub identity_public_key: String,
886 pub ca_cert_pem: Option<String>,
891}
892
893#[derive(Debug, Clone)]
895#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
896pub struct SparkSspConfig {
897 pub base_url: String,
899 pub identity_public_key: String,
901 pub schema_endpoint: Option<String>,
904}
905
906impl Config {
907 pub fn validate(&self) -> Result<(), SdkError> {
911 if self.max_concurrent_claims == 0 {
912 return Err(SdkError::InvalidInput(
913 "max_concurrent_claims must be greater than 0".to_string(),
914 ));
915 }
916
917 if let Some(sb) = &self.stable_balance_config {
918 if sb.tokens.is_empty() {
919 return Err(SdkError::InvalidInput(
920 "tokens must not be empty".to_string(),
921 ));
922 }
923
924 let mut seen_labels = HashSet::new();
925 let mut seen_identifiers = HashSet::new();
926 for token in &sb.tokens {
927 if token.label.is_empty() {
928 return Err(SdkError::InvalidInput(
929 "token label must not be empty".to_string(),
930 ));
931 }
932 if token.token_identifier.is_empty() {
933 return Err(SdkError::InvalidInput(
934 "token_identifier must not be empty".to_string(),
935 ));
936 }
937 if !seen_labels.insert(&token.label) {
938 return Err(SdkError::InvalidInput(format!(
939 "tokens contains duplicate label: {}",
940 token.label
941 )));
942 }
943 if !seen_identifiers.insert(&token.token_identifier) {
944 return Err(SdkError::InvalidInput(format!(
945 "tokens contains duplicate token_identifier: {}",
946 token.token_identifier
947 )));
948 }
949 }
950
951 if let Some(bps) = sb.max_slippage_bps
952 && bps > 10000
953 {
954 return Err(SdkError::InvalidInput(
955 "max_slippage_bps must be <= 10000".to_string(),
956 ));
957 }
958
959 if let Some(default_label) = &sb.default_active_label
960 && !seen_labels.contains(default_label)
961 {
962 return Err(SdkError::InvalidInput(format!(
963 "default_active_label '{default_label}' not found in tokens list"
964 )));
965 }
966 }
967
968 let token_opt = &self.token_optimization_config;
969 if token_opt.min_outputs_threshold <= 1 {
970 return Err(SdkError::InvalidInput(
971 "token optimization minimum outputs threshold must be greater than 1".to_string(),
972 ));
973 }
974 if token_opt.target_output_count < 1 {
975 return Err(SdkError::InvalidInput(
976 "token optimization target output count must be at least 1".to_string(),
977 ));
978 }
979 if token_opt.target_output_count >= token_opt.min_outputs_threshold {
980 return Err(SdkError::InvalidInput(
981 "token optimization target output count must be less than the minimum outputs threshold".to_string(),
982 ));
983 }
984
985 if let Some(cc) = &self.cross_chain_config {
986 if self.network != Network::Mainnet {
987 return Err(SdkError::InvalidInput(format!(
988 "Cross-chain sends are only available on Mainnet, not on {}.",
989 self.network,
990 )));
991 }
992 if let Some(bps) = cc.default_slippage_bps
993 && !(crate::cross_chain::MIN_CROSS_CHAIN_SLIPPAGE_BPS
994 ..=crate::cross_chain::MAX_CROSS_CHAIN_SLIPPAGE_BPS)
995 .contains(&bps)
996 {
997 return Err(SdkError::InvalidInput(format!(
998 "Default cross-chain slippage must be between {} and {} basis points, but got {bps}.",
999 crate::cross_chain::MIN_CROSS_CHAIN_SLIPPAGE_BPS,
1000 crate::cross_chain::MAX_CROSS_CHAIN_SLIPPAGE_BPS,
1001 )));
1002 }
1003 if let Some(bps) = cc.default_target_overpay_bps
1004 && !(crate::cross_chain::MIN_TARGET_OVERPAY_BPS
1005 ..=crate::cross_chain::MAX_TARGET_OVERPAY_BPS)
1006 .contains(&bps)
1007 {
1008 return Err(SdkError::InvalidInput(format!(
1009 "Default cross-chain target-overpay must be between {} and {} basis points, but got {bps}.",
1010 crate::cross_chain::MIN_TARGET_OVERPAY_BPS,
1011 crate::cross_chain::MAX_TARGET_OVERPAY_BPS,
1012 )));
1013 }
1014 }
1015
1016 Ok(())
1017 }
1018
1019 pub(crate) fn get_all_external_input_parsers(&self) -> Vec<ExternalInputParser> {
1020 let mut external_input_parsers = Vec::new();
1021 if self.use_default_external_input_parsers {
1022 let default_parsers = DEFAULT_EXTERNAL_INPUT_PARSERS
1023 .iter()
1024 .map(|(id, regex, url)| ExternalInputParser {
1025 provider_id: (*id).to_string(),
1026 input_regex: (*regex).to_string(),
1027 parser_url: (*url).to_string(),
1028 })
1029 .collect::<Vec<_>>();
1030 external_input_parsers.extend(default_parsers);
1031 }
1032 external_input_parsers.extend(self.external_input_parsers.clone().unwrap_or_default());
1033
1034 external_input_parsers
1035 }
1036}
1037
1038#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1039#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1040pub enum MaxFee {
1041 Fixed { amount: u64 },
1043 Rate { sat_per_vbyte: u64 },
1045 NetworkRecommended { leeway_sat_per_vbyte: u64 },
1047}
1048
1049impl MaxFee {
1050 pub(crate) async fn to_fee(&self, client: &dyn BitcoinChainService) -> Result<Fee, SdkError> {
1051 match self {
1052 MaxFee::Fixed { amount } => Ok(Fee::Fixed { amount: *amount }),
1053 MaxFee::Rate { sat_per_vbyte } => Ok(Fee::Rate {
1054 sat_per_vbyte: *sat_per_vbyte,
1055 }),
1056 MaxFee::NetworkRecommended {
1057 leeway_sat_per_vbyte,
1058 } => {
1059 let recommended_fees = client.recommended_fees().await?;
1060 let max_fee_rate = recommended_fees
1061 .fastest_fee
1062 .saturating_add(*leeway_sat_per_vbyte);
1063 Ok(Fee::Rate {
1064 sat_per_vbyte: max_fee_rate,
1065 })
1066 }
1067 }
1068 }
1069}
1070
1071#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1072#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1073pub enum Fee {
1074 Fixed { amount: u64 },
1076 Rate { sat_per_vbyte: u64 },
1078}
1079
1080impl Fee {
1081 pub fn to_sats(&self, vbytes: u64) -> u64 {
1082 match self {
1083 Fee::Fixed { amount } => *amount,
1084 Fee::Rate { sat_per_vbyte } => sat_per_vbyte.saturating_mul(vbytes),
1085 }
1086 }
1087}
1088
1089#[derive(Debug, Clone, Serialize, Deserialize)]
1090#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1091pub struct DepositInfo {
1092 pub txid: String,
1093 pub vout: u32,
1094 pub amount_sats: u64,
1095 pub is_mature: bool,
1096 pub refund_tx: Option<String>,
1097 pub refund_tx_id: Option<String>,
1098 pub claim_error: Option<DepositClaimError>,
1099}
1100
1101#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1102pub struct ClaimDepositRequest {
1103 pub txid: String,
1104 pub vout: u32,
1105 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1106 pub max_fee: Option<MaxFee>,
1107}
1108
1109#[derive(Debug, Clone, Serialize)]
1110#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1111pub struct ClaimDepositResponse {
1112 pub payment: Payment,
1113}
1114
1115#[derive(Debug, Clone, Serialize)]
1116#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1117pub struct RefundDepositRequest {
1118 pub txid: String,
1119 pub vout: u32,
1120 pub destination_address: String,
1121 pub fee: Fee,
1122}
1123
1124#[derive(Debug, Clone, Serialize)]
1125#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1126pub struct RefundDepositResponse {
1127 pub tx_id: String,
1128 pub tx_hex: String,
1129}
1130
1131#[derive(Debug, Clone, Serialize)]
1132#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1133pub struct ListUnclaimedDepositsRequest {}
1134
1135#[derive(Debug, Clone, Serialize)]
1136#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1137pub struct ListUnclaimedDepositsResponse {
1138 pub deposits: Vec<DepositInfo>,
1139}
1140
1141#[derive(Debug, Clone)]
1146#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1147pub enum BuyBitcoinRequest {
1148 Moonpay {
1151 locked_amount_sat: Option<u64>,
1153 redirect_url: Option<String>,
1155 },
1156 CashApp {
1165 amount_sats: u64,
1167 },
1168}
1169
1170impl Default for BuyBitcoinRequest {
1171 fn default() -> Self {
1172 Self::Moonpay {
1173 locked_amount_sat: None,
1174 redirect_url: None,
1175 }
1176 }
1177}
1178
1179#[derive(Debug, Clone, Serialize)]
1181#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1182pub struct BuyBitcoinResponse {
1183 pub url: String,
1185}
1186
1187impl std::fmt::Display for MaxFee {
1188 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1189 match self {
1190 MaxFee::Fixed { amount } => write!(f, "Fixed: {amount}"),
1191 MaxFee::Rate { sat_per_vbyte } => write!(f, "Rate: {sat_per_vbyte}"),
1192 MaxFee::NetworkRecommended {
1193 leeway_sat_per_vbyte,
1194 } => write!(f, "NetworkRecommended: {leeway_sat_per_vbyte}"),
1195 }
1196 }
1197}
1198
1199#[derive(Debug, Clone)]
1200#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1201pub struct Credentials {
1202 pub username: String,
1203 pub password: String,
1204}
1205
1206#[derive(Debug, Clone)]
1208#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1209pub struct GetInfoRequest {
1210 pub ensure_synced: Option<bool>,
1217}
1218
1219#[derive(Debug, Clone, Serialize)]
1221#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1222pub struct GetInfoResponse {
1223 pub identity_pubkey: String,
1225 pub balance_sats: u64,
1227 pub token_balances: HashMap<String, TokenBalance>,
1229}
1230
1231#[derive(Debug, Clone, Serialize, Deserialize)]
1232#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1233pub struct TokenBalance {
1234 pub balance: u128,
1235 pub token_metadata: TokenMetadata,
1236}
1237
1238#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1239#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1240pub struct TokenMetadata {
1241 pub identifier: String,
1242 pub issuer_public_key: String,
1244 pub name: String,
1245 pub ticker: String,
1246 pub decimals: u32,
1248 pub max_supply: u128,
1249 pub is_freezable: bool,
1250}
1251
1252#[derive(Debug, Clone)]
1254#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1255pub struct SyncWalletRequest {}
1256
1257#[derive(Debug, Clone, Serialize)]
1259#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1260pub struct SyncWalletResponse {}
1261
1262#[derive(Debug, Clone, Serialize)]
1263#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1264pub enum ReceivePaymentMethod {
1265 SparkAddress,
1266 SparkInvoice {
1267 amount: Option<u128>,
1269 token_identifier: Option<String>,
1272 expiry_time: Option<u64>,
1274 description: Option<String>,
1276 sender_public_key: Option<String>,
1278 },
1279 BitcoinAddress {
1280 new_address: Option<bool>,
1284 },
1285 Bolt11Invoice {
1286 description: String,
1287 amount_sats: Option<u64>,
1288 expiry_secs: Option<u32>,
1290 payment_hash: Option<String>,
1294 },
1295}
1296
1297#[derive(Debug, Clone, Serialize)]
1298#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1299pub enum SendPaymentMethod {
1300 BitcoinAddress {
1301 address: BitcoinAddressDetails,
1302 fee_quote: SendOnchainFeeQuote,
1303 },
1304 Bolt11Invoice {
1305 invoice_details: Bolt11InvoiceDetails,
1306 spark_transfer_fee_sats: Option<u64>,
1307 lightning_fee_sats: u64,
1308 }, SparkAddress {
1310 address: String,
1311 fee: u128,
1314 token_identifier: Option<String>,
1317 },
1318 SparkInvoice {
1319 spark_invoice_details: SparkInvoiceDetails,
1320 fee: u128,
1323 token_identifier: Option<String>,
1326 },
1327 CrossChainAddress {
1329 route: CrossChainRoutePair,
1331 recipient_address: String,
1333 amount_in: u128,
1339 asset_amount_in: u128,
1342 estimated_out: u128,
1344 fee_amount: u128,
1350 service_fee_amount: u128,
1352 service_fee_asset: Option<String>,
1354 source_transfer_fee_sats: u64,
1356 fee_mode: CrossChainFeeMode,
1358 expires_at: String,
1360 provider_context: CrossChainProviderContext,
1363 },
1364}
1365
1366#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1367#[derive(Debug, Clone, Serialize, Deserialize)]
1368pub struct SendOnchainFeeQuote {
1369 pub id: String,
1370 pub expires_at: u64,
1371 pub speed_fast: SendOnchainSpeedFeeQuote,
1372 pub speed_medium: SendOnchainSpeedFeeQuote,
1373 pub speed_slow: SendOnchainSpeedFeeQuote,
1374}
1375
1376#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1377#[derive(Debug, Clone, Serialize, Deserialize)]
1378pub struct SendOnchainSpeedFeeQuote {
1379 pub user_fee_sat: u64,
1380 pub l1_broadcast_fee_sat: u64,
1381}
1382
1383impl SendOnchainSpeedFeeQuote {
1384 pub fn total_fee_sat(&self) -> u64 {
1385 self.user_fee_sat.saturating_add(self.l1_broadcast_fee_sat)
1386 }
1387}
1388
1389#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1390pub struct ReceivePaymentRequest {
1391 pub payment_method: ReceivePaymentMethod,
1392}
1393
1394#[derive(Debug, Clone, Serialize)]
1395#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1396pub struct ReceivePaymentResponse {
1397 pub payment_request: String,
1398 pub fee: u128,
1401}
1402
1403#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1404pub struct PrepareLnurlPayRequest {
1405 pub amount: u128,
1408 pub pay_request: LnurlPayRequestDetails,
1409 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1410 pub comment: Option<String>,
1411 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1412 pub validate_success_action_url: Option<bool>,
1413 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1415 pub token_identifier: Option<String>,
1416 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1418 pub conversion_options: Option<ConversionOptions>,
1419 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1421 pub fee_policy: Option<FeePolicy>,
1422}
1423
1424#[derive(Debug, Clone)]
1425#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1426pub struct PrepareLnurlPayResponse {
1427 pub amount_sats: u64,
1432 pub comment: Option<String>,
1433 pub pay_request: LnurlPayRequestDetails,
1434 pub fee_sats: u64,
1437 pub invoice_details: Bolt11InvoiceDetails,
1438 pub success_action: Option<SuccessAction>,
1439 pub conversion_estimate: Option<ConversionEstimate>,
1441 pub fee_policy: FeePolicy,
1445}
1446
1447#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1448pub struct LnurlPayRequest {
1449 pub prepare_response: PrepareLnurlPayResponse,
1450 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1454 pub idempotency_key: Option<String>,
1455}
1456
1457#[derive(Debug, Serialize)]
1458#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1459pub struct LnurlPayResponse {
1460 pub payment: Payment,
1461 pub success_action: Option<SuccessActionProcessed>,
1462}
1463
1464#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1465pub struct BuildUnsignedLnurlPayPackageRequest {
1466 pub prepare_response: PrepareLnurlPayResponse,
1467}
1468
1469#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1470pub struct PublishSignedLnurlPayPackageRequest {
1471 pub signed_package: SignedTransferPackage,
1472}
1473
1474#[allow(clippy::large_enum_variant)]
1475#[derive(Debug)]
1476#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1477pub enum PublishSignedLnurlPayResponse {
1478 SwapCompleted,
1479 PaymentSent { response: LnurlPayResponse },
1480}
1481
1482#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1483pub struct LnurlWithdrawRequest {
1484 pub amount_sats: u64,
1487 pub withdraw_request: LnurlWithdrawRequestDetails,
1488 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1492 pub completion_timeout_secs: Option<u32>,
1493}
1494
1495#[derive(Debug, Serialize)]
1496#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1497pub struct LnurlWithdrawResponse {
1498 pub payment_request: String,
1500 pub payment: Option<Payment>,
1501}
1502
1503#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
1505#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1506pub struct LnurlPayInfo {
1507 pub ln_address: Option<String>,
1508 pub comment: Option<String>,
1509 pub domain: Option<String>,
1510 pub metadata: Option<String>,
1511 pub processed_success_action: Option<SuccessActionProcessed>,
1512 pub raw_success_action: Option<SuccessAction>,
1513}
1514
1515#[derive(Clone, Debug, Deserialize, Serialize)]
1517#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1518pub struct LnurlWithdrawInfo {
1519 pub withdraw_url: String,
1520}
1521
1522impl LnurlPayInfo {
1523 pub fn extract_description(&self) -> Option<String> {
1524 let Some(metadata) = &self.metadata else {
1525 return None;
1526 };
1527
1528 let Ok(metadata) = serde_json::from_str::<Vec<Vec<Value>>>(metadata) else {
1529 return None;
1530 };
1531
1532 for arr in metadata {
1533 if arr.len() != 2 {
1534 continue;
1535 }
1536 if let (Some(key), Some(value)) = (arr[0].as_str(), arr[1].as_str())
1537 && key == "text/plain"
1538 {
1539 return Some(value.to_string());
1540 }
1541 }
1542
1543 None
1544 }
1545}
1546
1547#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
1555#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1556pub enum FeePolicy {
1557 #[default]
1561 FeesExcluded,
1562 FeesIncluded,
1566}
1567
1568#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1569#[derive(Debug, Clone, Serialize, Deserialize)]
1570pub enum OnchainConfirmationSpeed {
1571 Fast,
1572 Medium,
1573 Slow,
1574}
1575
1576#[derive(Debug, Clone, Serialize)]
1580#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1581pub enum PaymentRequest {
1582 Input { input: String },
1584 CrossChain {
1587 address: String,
1588 route: CrossChainRoutePair,
1589 max_slippage_bps: Option<u32>,
1594 target_overpay_bps: Option<u32>,
1601 },
1602}
1603
1604#[allow(clippy::large_enum_variant)]
1605#[derive(Debug, Clone, Serialize, Deserialize)]
1606#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1607pub enum UnsignedTransferPackage {
1608 Swap {
1609 prepare_transfer: crate::signer::ExternalPrepareTransferRequest,
1610 target_amounts: Vec<u64>,
1611 amount_sat: u64,
1612 fee_sat: u64,
1613 },
1614 Transfer {
1615 prepare_transfer: crate::signer::ExternalPrepareTransferRequest,
1616 amount_sat: u64,
1617 fee_sat: u64,
1618 target: TransferTarget,
1619 },
1620 Token {
1621 prepare_token_transaction: crate::signer::ExternalPrepareTokenTransactionRequest,
1622 token_context: Vec<u8>,
1623 token_identifier: String,
1624 amount: u128,
1625 fee: u128,
1626 is_swap: bool,
1630 },
1631}
1632
1633#[derive(Debug, Clone, Serialize, Deserialize)]
1634#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1635pub enum TransferTarget {
1636 Spark {
1637 address: String,
1638 spark_invoice: Option<String>,
1639 },
1640 Lightning {
1641 bolt11: String,
1642 lnurl_pay: Option<LnurlPayContext>,
1643 fee_policy: FeePolicy,
1644 completion_timeout_secs: Option<u32>,
1645 },
1646 CoopExit {
1647 address: String,
1648 fee_quote: SendOnchainFeeQuote,
1649 confirmation_speed: OnchainConfirmationSpeed,
1650 },
1651}
1652
1653#[derive(Debug, Clone, Serialize, Deserialize)]
1654#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1655pub struct LnurlPayContext {
1656 pub pay_request: LnurlPayRequestDetails,
1657 pub comment: Option<String>,
1658 pub success_action: Option<SuccessAction>,
1659}
1660
1661#[derive(Debug, Clone, Serialize, Deserialize)]
1662#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1663pub struct SignedTransferPackage {
1664 pub unsigned: UnsignedTransferPackage,
1665 pub signature: TransferSignature,
1666}
1667
1668#[derive(Debug, Clone, Serialize, Deserialize)]
1669#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1670pub enum TransferSignature {
1671 Transfer {
1672 signed: crate::signer::ExternalPreparedTransfer,
1673 },
1674 Token {
1675 signed: crate::signer::ExternalPreparedTokenTransaction,
1676 },
1677}
1678
1679#[derive(Debug, Clone)]
1680#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1681pub enum BuildTransferPackageOptions {
1682 BitcoinAddress {
1683 confirmation_speed: OnchainConfirmationSpeed,
1684 },
1685 Bolt11Invoice {
1686 prefer_spark: bool,
1687
1688 completion_timeout_secs: Option<u32>,
1692 },
1693}
1694
1695#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1696pub struct BuildUnsignedTransferPackageRequest {
1697 pub prepare_response: PrepareSendPaymentResponse,
1698 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1699 pub options: Option<BuildTransferPackageOptions>,
1700}
1701
1702#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1703pub struct PrepareSendPaymentRequest {
1704 pub payment_request: PaymentRequest,
1705 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1710 pub amount: Option<u128>,
1711 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1714 pub token_identifier: Option<String>,
1715 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1717 pub conversion_options: Option<ConversionOptions>,
1718 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1726 pub fee_policy: Option<FeePolicy>,
1727}
1728
1729#[derive(Debug, Clone, Serialize)]
1730#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1731pub struct PrepareSendPaymentResponse {
1732 pub payment_method: SendPaymentMethod,
1733 pub amount: u128,
1738 pub token_identifier: Option<String>,
1741 pub conversion_estimate: Option<ConversionEstimate>,
1743 pub fee_policy: FeePolicy,
1746}
1747
1748#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1749pub enum SendPaymentOptions {
1750 BitcoinAddress {
1751 confirmation_speed: OnchainConfirmationSpeed,
1753 },
1754 Bolt11Invoice {
1755 prefer_spark: bool,
1756
1757 completion_timeout_secs: Option<u32>,
1760 },
1761 SparkAddress {
1762 htlc_options: Option<SparkHtlcOptions>,
1765 },
1766}
1767
1768#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1769pub struct SparkHtlcOptions {
1770 pub payment_hash: String,
1772 pub expiry_duration_secs: u64,
1775}
1776
1777#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1778pub struct SendPaymentRequest {
1779 pub prepare_response: PrepareSendPaymentResponse,
1780 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1781 pub options: Option<SendPaymentOptions>,
1782 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1788 pub idempotency_key: Option<String>,
1789}
1790
1791#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1792pub struct PublishSignedTransferPackageRequest {
1793 pub signed_package: SignedTransferPackage,
1794}
1795
1796#[allow(clippy::large_enum_variant)]
1797#[derive(Debug, Clone)]
1798#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1799pub enum PublishSignedTransferPackageResponse {
1800 SwapCompleted,
1801 PaymentSent { payment: Payment },
1802}
1803
1804#[derive(Debug, Clone, Serialize)]
1805#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1806pub struct SendPaymentResponse {
1807 pub payment: Payment,
1808}
1809
1810#[derive(Debug, Clone)]
1811#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1812pub enum PaymentDetailsFilter {
1813 Spark {
1814 htlc_status: Option<Vec<SparkHtlcStatus>>,
1816 conversion_refund_needed: Option<bool>,
1818 },
1819 Token {
1820 conversion_refund_needed: Option<bool>,
1822 tx_hash: Option<String>,
1824 tx_type: Option<TokenTransactionType>,
1826 },
1827 Lightning {
1828 htlc_status: Option<Vec<SparkHtlcStatus>>,
1830 },
1831}
1832
1833#[derive(Debug, Clone, Default)]
1835#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1836pub struct ListPaymentsRequest {
1837 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1838 pub type_filter: Option<Vec<PaymentType>>,
1839 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1840 pub status_filter: Option<Vec<PaymentStatus>>,
1841 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1842 pub asset_filter: Option<AssetFilter>,
1843 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1845 pub payment_details_filter: Option<Vec<PaymentDetailsFilter>>,
1846 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1848 pub from_timestamp: Option<u64>,
1849 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1851 pub to_timestamp: Option<u64>,
1852 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1854 pub offset: Option<u32>,
1855 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1857 pub limit: Option<u32>,
1858 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1859 pub sort_ascending: Option<bool>,
1860}
1861
1862#[derive(Debug, Clone)]
1864#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1865pub enum AssetFilter {
1866 Bitcoin,
1867 Token {
1868 token_identifier: Option<String>,
1870 },
1871}
1872
1873impl FromStr for AssetFilter {
1874 type Err = String;
1875
1876 fn from_str(s: &str) -> Result<Self, Self::Err> {
1877 Ok(match s.to_lowercase().as_str() {
1878 "bitcoin" => AssetFilter::Bitcoin,
1879 "token" => AssetFilter::Token {
1880 token_identifier: None,
1881 },
1882 str if str.starts_with("token:") => AssetFilter::Token {
1883 token_identifier: Some(
1884 str.split_once(':')
1885 .ok_or(format!("Invalid asset filter '{s}'"))?
1886 .1
1887 .to_string(),
1888 ),
1889 },
1890 _ => return Err(format!("Invalid asset filter '{s}'")),
1891 })
1892 }
1893}
1894
1895#[derive(Debug, Clone, Serialize)]
1897#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1898pub struct ListPaymentsResponse {
1899 pub payments: Vec<Payment>,
1901}
1902
1903#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1904pub struct GetPaymentRequest {
1905 pub payment_id: String,
1906}
1907
1908#[derive(Debug, Clone, Serialize)]
1909#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1910pub struct GetPaymentResponse {
1911 pub payment: Payment,
1912}
1913
1914#[cfg_attr(feature = "uniffi", uniffi::export(callback_interface))]
1915pub trait Logger: Send + Sync {
1916 fn log(&self, l: LogEntry);
1917}
1918
1919#[derive(Debug, Clone, Serialize)]
1920#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1921pub struct LogEntry {
1922 pub line: String,
1923 pub level: String,
1924}
1925
1926#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1927#[derive(Debug, Clone, Serialize, Deserialize)]
1928pub struct CheckLightningAddressRequest {
1929 pub username: String,
1930}
1931
1932#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1933#[derive(Debug, Clone, Serialize, Deserialize)]
1934pub struct RegisterLightningAddressRequest {
1935 pub username: String,
1936 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1937 pub description: Option<String>,
1938}
1939
1940#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1946#[derive(Debug, Clone, Serialize, Deserialize)]
1947pub struct TransferAuthorization {
1948 pub username: String,
1950 pub pubkey: String,
1952 pub signature: String,
1954}
1955
1956#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1960#[derive(Debug, Clone, Serialize, Deserialize)]
1961pub struct AuthorizeTransferRequest {
1962 pub transferee_pubkey: String,
1964}
1965
1966#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1970#[derive(Debug, Clone, Serialize, Deserialize)]
1971pub struct ClaimTransferRequest {
1972 pub authorization: TransferAuthorization,
1975 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1977 pub description: Option<String>,
1978}
1979
1980#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1981#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
1982pub struct LnurlInfo {
1983 pub url: String,
1984 pub bech32: String,
1985}
1986
1987impl LnurlInfo {
1988 pub fn new(url: String) -> Self {
1989 let bech32 =
1990 breez_sdk_common::lnurl::encode_lnurl_to_bech32(&url).unwrap_or_else(|_| url.clone());
1991 Self { url, bech32 }
1992 }
1993}
1994
1995#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1996#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
1997pub struct LightningAddressInfo {
1998 pub description: String,
1999 pub lightning_address: String,
2000 pub lnurl: LnurlInfo,
2001 pub username: String,
2002}
2003
2004impl From<RecoverLnurlPayResponse> for LightningAddressInfo {
2005 fn from(resp: RecoverLnurlPayResponse) -> Self {
2006 Self {
2007 description: resp.description,
2008 lightning_address: resp.lightning_address,
2009 lnurl: LnurlInfo::new(resp.lnurl),
2010 username: resp.username,
2011 }
2012 }
2013}
2014
2015#[derive(Debug, Clone, Serialize)]
2017#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2018pub struct ListFiatCurrenciesResponse {
2019 pub currencies: Vec<FiatCurrency>,
2021}
2022
2023#[derive(Debug, Clone, Serialize)]
2025#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2026pub struct ListFiatRatesResponse {
2027 pub rates: Vec<Rate>,
2029}
2030
2031#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
2033#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
2034pub enum ServiceStatus {
2035 Operational,
2037 Degraded,
2039 Partial,
2041 Unknown,
2043 Major,
2045}
2046
2047#[derive(Debug, Clone, Serialize)]
2049#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2050pub struct SparkStatus {
2051 pub status: ServiceStatus,
2053 pub last_updated: u64,
2055}
2056
2057pub(crate) enum WaitForPaymentIdentifier {
2058 PaymentId(String),
2059 LightningReceive { invoice: String, ssp_id: String },
2060}
2061
2062#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2063pub struct GetTokensMetadataRequest {
2064 pub token_identifiers: Vec<String>,
2065}
2066
2067#[derive(Debug, Clone, Serialize)]
2068#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2069pub struct GetTokensMetadataResponse {
2070 pub tokens_metadata: Vec<TokenMetadata>,
2071}
2072
2073#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2074pub struct SignMessageRequest {
2075 pub message: String,
2076 pub compact: bool,
2078}
2079
2080#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2081pub struct SignMessageResponse {
2082 pub pubkey: String,
2083 pub signature: String,
2085}
2086
2087#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2088pub struct CheckMessageRequest {
2089 pub message: String,
2091 pub pubkey: String,
2093 pub signature: String,
2095}
2096
2097#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2098pub struct CheckMessageResponse {
2099 pub is_valid: bool,
2100}
2101
2102#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2103#[derive(Debug, Clone, Serialize)]
2104pub struct UserSettings {
2105 pub spark_private_mode_enabled: bool,
2106
2107 pub stable_balance_active_label: Option<String>,
2109}
2110
2111#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2112pub struct UpdateUserSettingsRequest {
2113 pub spark_private_mode_enabled: Option<bool>,
2114
2115 #[cfg_attr(feature = "uniffi", uniffi(default = None))]
2117 pub stable_balance_active_label: Option<StableBalanceActiveLabel>,
2118}
2119
2120#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2121pub struct ClaimHtlcPaymentRequest {
2122 pub preimage: String,
2123}
2124
2125#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2126pub struct ClaimHtlcPaymentResponse {
2127 pub payment: Payment,
2128}
2129
2130#[derive(Debug, Clone, Deserialize, Serialize)]
2131#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2132pub struct LnurlReceiveMetadata {
2133 pub nostr_zap_request: Option<String>,
2134 pub nostr_zap_receipt: Option<String>,
2135 pub sender_comment: Option<String>,
2136}
2137
2138#[derive(Debug, Clone, Default, Deserialize, Serialize, PartialEq)]
2140#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
2141pub enum OptimizationMode {
2142 #[default]
2144 Full,
2145 SingleRound,
2147}
2148
2149#[derive(Debug, Clone, Default, Deserialize, Serialize)]
2152#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2153pub struct OptimizeLeavesRequest {
2154 pub mode: OptimizationMode,
2156}
2157
2158#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
2160#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2161pub struct OptimizeLeavesResponse {
2162 pub outcome: OptimizationOutcome,
2164}
2165
2166#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
2190#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
2191pub enum OptimizationOutcome {
2192 Completed { rounds_executed: u32 },
2199 InProgress,
2203}
2204
2205#[derive(Debug, Clone, Serialize, Deserialize)]
2207#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2208pub struct Contact {
2209 pub id: String,
2210 pub name: String,
2211 pub payment_identifier: String,
2213 pub created_at: u64,
2214 pub updated_at: u64,
2215}
2216
2217#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2219pub struct AddContactRequest {
2220 pub name: String,
2221 pub payment_identifier: String,
2223}
2224
2225#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2227pub struct UpdateContactRequest {
2228 pub id: String,
2229 pub name: String,
2230 pub payment_identifier: String,
2232}
2233
2234#[derive(Debug, Clone, Default)]
2236#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2237pub struct ListContactsRequest {
2238 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
2239 pub offset: Option<u32>,
2240 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
2241 pub limit: Option<u32>,
2242}
2243
2244#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
2246#[allow(clippy::enum_variant_names)]
2247#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
2248pub enum WebhookEventType {
2249 LightningReceiveFinished,
2251 LightningSendFinished,
2253 CoopExitFinished,
2255 StaticDepositFinished,
2257 Unknown(String),
2259}
2260
2261#[derive(Debug, Clone, Serialize)]
2263#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2264pub struct Webhook {
2265 pub id: String,
2267 pub url: String,
2269 pub event_types: Vec<WebhookEventType>,
2271}
2272
2273#[derive(Debug, Clone)]
2275#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2276pub struct RegisterWebhookRequest {
2277 pub url: String,
2279 pub secret: String,
2281 pub event_types: Vec<WebhookEventType>,
2283}
2284
2285#[derive(Debug, Clone, Serialize)]
2287#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2288pub struct RegisterWebhookResponse {
2289 pub webhook_id: String,
2291}
2292
2293#[derive(Debug, Clone)]
2295#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2296pub struct UnregisterWebhookRequest {
2297 pub webhook_id: String,
2299}