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
1187#[derive(Debug, Clone, Serialize, Default)]
1189#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1190pub struct RefundPendingConversionsResponse {
1191 pub refunded: u32,
1193 pub skipped: u32,
1196 pub failed: u32,
1199}
1200
1201impl std::fmt::Display for MaxFee {
1202 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1203 match self {
1204 MaxFee::Fixed { amount } => write!(f, "Fixed: {amount}"),
1205 MaxFee::Rate { sat_per_vbyte } => write!(f, "Rate: {sat_per_vbyte}"),
1206 MaxFee::NetworkRecommended {
1207 leeway_sat_per_vbyte,
1208 } => write!(f, "NetworkRecommended: {leeway_sat_per_vbyte}"),
1209 }
1210 }
1211}
1212
1213#[derive(Debug, Clone)]
1214#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1215pub struct Credentials {
1216 pub username: String,
1217 pub password: String,
1218}
1219
1220#[derive(Debug, Clone)]
1222#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1223pub struct GetInfoRequest {
1224 pub ensure_synced: Option<bool>,
1231}
1232
1233#[derive(Debug, Clone, Serialize)]
1235#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1236pub struct GetInfoResponse {
1237 pub identity_pubkey: String,
1239 pub balance_sats: u64,
1241 pub token_balances: HashMap<String, TokenBalance>,
1243}
1244
1245#[derive(Debug, Clone, Serialize, Deserialize)]
1246#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1247pub struct TokenBalance {
1248 pub balance: u128,
1249 pub token_metadata: TokenMetadata,
1250}
1251
1252#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1253#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1254pub struct TokenMetadata {
1255 pub identifier: String,
1256 pub issuer_public_key: String,
1258 pub name: String,
1259 pub ticker: String,
1260 pub decimals: u32,
1262 pub max_supply: u128,
1263 pub is_freezable: bool,
1264}
1265
1266#[derive(Debug, Clone)]
1268#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1269pub struct SyncWalletRequest {}
1270
1271#[derive(Debug, Clone, Serialize)]
1273#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1274pub struct SyncWalletResponse {}
1275
1276#[derive(Debug, Clone, Serialize)]
1277#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1278pub enum ReceivePaymentMethod {
1279 SparkAddress,
1280 SparkInvoice {
1281 amount: Option<u128>,
1283 token_identifier: Option<String>,
1286 expiry_time: Option<u64>,
1288 description: Option<String>,
1290 sender_public_key: Option<String>,
1292 },
1293 BitcoinAddress {
1294 new_address: Option<bool>,
1298 },
1299 Bolt11Invoice {
1300 description: String,
1301 amount_sats: Option<u64>,
1302 expiry_secs: Option<u32>,
1304 payment_hash: Option<String>,
1308 },
1309}
1310
1311#[derive(Debug, Clone, Serialize)]
1312#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1313pub enum SendPaymentMethod {
1314 BitcoinAddress {
1315 address: BitcoinAddressDetails,
1316 fee_quote: SendOnchainFeeQuote,
1317 },
1318 Bolt11Invoice {
1319 invoice_details: Bolt11InvoiceDetails,
1320 spark_transfer_fee_sats: Option<u64>,
1321 lightning_fee_sats: u64,
1322 }, SparkAddress {
1324 address: String,
1325 fee: u128,
1328 token_identifier: Option<String>,
1331 },
1332 SparkInvoice {
1333 spark_invoice_details: SparkInvoiceDetails,
1334 fee: u128,
1337 token_identifier: Option<String>,
1340 },
1341 CrossChainAddress {
1343 route: CrossChainRoutePair,
1345 recipient_address: String,
1347 amount_in: u128,
1353 asset_amount_in: u128,
1356 estimated_out: u128,
1358 fee_amount: u128,
1364 service_fee_amount: u128,
1366 service_fee_asset: Option<String>,
1368 source_transfer_fee_sats: u64,
1370 fee_mode: CrossChainFeeMode,
1372 expires_at: String,
1374 provider_context: CrossChainProviderContext,
1377 },
1378}
1379
1380#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1381#[derive(Debug, Clone, Serialize, Deserialize)]
1382pub struct SendOnchainFeeQuote {
1383 pub id: String,
1384 pub expires_at: u64,
1385 pub speed_fast: SendOnchainSpeedFeeQuote,
1386 pub speed_medium: SendOnchainSpeedFeeQuote,
1387 pub speed_slow: SendOnchainSpeedFeeQuote,
1388}
1389
1390#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1391#[derive(Debug, Clone, Serialize, Deserialize)]
1392pub struct SendOnchainSpeedFeeQuote {
1393 pub user_fee_sat: u64,
1394 pub l1_broadcast_fee_sat: u64,
1395}
1396
1397impl SendOnchainSpeedFeeQuote {
1398 pub fn total_fee_sat(&self) -> u64 {
1399 self.user_fee_sat.saturating_add(self.l1_broadcast_fee_sat)
1400 }
1401}
1402
1403#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1404pub struct ReceivePaymentRequest {
1405 pub payment_method: ReceivePaymentMethod,
1406}
1407
1408#[derive(Debug, Clone, Serialize)]
1409#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1410pub struct ReceivePaymentResponse {
1411 pub payment_request: String,
1412 pub fee: u128,
1415}
1416
1417#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1418pub struct PrepareLnurlPayRequest {
1419 pub amount: u128,
1422 pub pay_request: LnurlPayRequestDetails,
1423 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1424 pub comment: Option<String>,
1425 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1426 pub validate_success_action_url: Option<bool>,
1427 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1429 pub token_identifier: Option<String>,
1430 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1432 pub conversion_options: Option<ConversionOptions>,
1433 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1435 pub fee_policy: Option<FeePolicy>,
1436}
1437
1438#[derive(Debug, Clone)]
1439#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1440pub struct PrepareLnurlPayResponse {
1441 pub amount_sats: u64,
1446 pub comment: Option<String>,
1447 pub pay_request: LnurlPayRequestDetails,
1448 pub fee_sats: u64,
1451 pub invoice_details: Bolt11InvoiceDetails,
1452 pub success_action: Option<SuccessAction>,
1453 pub conversion_estimate: Option<ConversionEstimate>,
1455 pub fee_policy: FeePolicy,
1459}
1460
1461#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1462pub struct LnurlPayRequest {
1463 pub prepare_response: PrepareLnurlPayResponse,
1464 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1468 pub idempotency_key: Option<String>,
1469}
1470
1471#[derive(Debug, Serialize)]
1472#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1473pub struct LnurlPayResponse {
1474 pub payment: Payment,
1475 pub success_action: Option<SuccessActionProcessed>,
1476}
1477
1478#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1479pub struct BuildUnsignedLnurlPayPackageRequest {
1480 pub prepare_response: PrepareLnurlPayResponse,
1481}
1482
1483#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1484pub struct PublishSignedLnurlPayPackageRequest {
1485 pub signed_package: SignedTransferPackage,
1486}
1487
1488#[allow(clippy::large_enum_variant)]
1489#[derive(Debug)]
1490#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1491pub enum PublishSignedLnurlPayResponse {
1492 SwapCompleted,
1493 PaymentSent { response: LnurlPayResponse },
1494}
1495
1496#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1497pub struct LnurlWithdrawRequest {
1498 pub amount_sats: u64,
1501 pub withdraw_request: LnurlWithdrawRequestDetails,
1502 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1506 pub completion_timeout_secs: Option<u32>,
1507}
1508
1509#[derive(Debug, Serialize)]
1510#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1511pub struct LnurlWithdrawResponse {
1512 pub payment_request: String,
1514 pub payment: Option<Payment>,
1515}
1516
1517#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
1519#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1520pub struct LnurlPayInfo {
1521 pub ln_address: Option<String>,
1522 pub comment: Option<String>,
1523 pub domain: Option<String>,
1524 pub metadata: Option<String>,
1525 pub processed_success_action: Option<SuccessActionProcessed>,
1526 pub raw_success_action: Option<SuccessAction>,
1527}
1528
1529#[derive(Clone, Debug, Deserialize, Serialize)]
1531#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1532pub struct LnurlWithdrawInfo {
1533 pub withdraw_url: String,
1534}
1535
1536impl LnurlPayInfo {
1537 pub fn extract_description(&self) -> Option<String> {
1538 let Some(metadata) = &self.metadata else {
1539 return None;
1540 };
1541
1542 let Ok(metadata) = serde_json::from_str::<Vec<Vec<Value>>>(metadata) else {
1543 return None;
1544 };
1545
1546 for arr in metadata {
1547 if arr.len() != 2 {
1548 continue;
1549 }
1550 if let (Some(key), Some(value)) = (arr[0].as_str(), arr[1].as_str())
1551 && key == "text/plain"
1552 {
1553 return Some(value.to_string());
1554 }
1555 }
1556
1557 None
1558 }
1559}
1560
1561#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
1569#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1570pub enum FeePolicy {
1571 #[default]
1575 FeesExcluded,
1576 FeesIncluded,
1580}
1581
1582#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1583#[derive(Debug, Clone, Serialize, Deserialize)]
1584pub enum OnchainConfirmationSpeed {
1585 Fast,
1586 Medium,
1587 Slow,
1588}
1589
1590#[derive(Debug, Clone, Serialize)]
1594#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1595pub enum PaymentRequest {
1596 Input { input: String },
1598 CrossChain {
1601 address: String,
1602 route: CrossChainRoutePair,
1603 max_slippage_bps: Option<u32>,
1608 target_overpay_bps: Option<u32>,
1615 },
1616}
1617
1618#[allow(clippy::large_enum_variant)]
1619#[derive(Debug, Clone, Serialize, Deserialize)]
1620#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1621pub enum UnsignedTransferPackage {
1622 Swap {
1623 prepare_transfer: crate::signer::ExternalPrepareTransferRequest,
1624 target_amounts: Vec<u64>,
1625 amount_sat: u64,
1626 fee_sat: u64,
1627 },
1628 Transfer {
1629 prepare_transfer: crate::signer::ExternalPrepareTransferRequest,
1630 amount_sat: u64,
1631 fee_sat: u64,
1632 target: TransferTarget,
1633 },
1634 Token {
1635 prepare_token_transaction: crate::signer::ExternalPrepareTokenTransactionRequest,
1636 token_context: Vec<u8>,
1637 token_identifier: String,
1638 amount: u128,
1639 fee: u128,
1640 is_swap: bool,
1644 },
1645}
1646
1647#[derive(Debug, Clone, Serialize, Deserialize)]
1648#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1649pub enum TransferTarget {
1650 Spark {
1651 address: String,
1652 spark_invoice: Option<String>,
1653 },
1654 Lightning {
1655 bolt11: String,
1656 lnurl_pay: Option<LnurlPayContext>,
1657 fee_policy: FeePolicy,
1658 completion_timeout_secs: Option<u32>,
1659 },
1660 CoopExit {
1661 address: String,
1662 fee_quote: SendOnchainFeeQuote,
1663 confirmation_speed: OnchainConfirmationSpeed,
1664 },
1665}
1666
1667#[derive(Debug, Clone, Serialize, Deserialize)]
1668#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1669pub struct LnurlPayContext {
1670 pub pay_request: LnurlPayRequestDetails,
1671 pub comment: Option<String>,
1672 pub success_action: Option<SuccessAction>,
1673}
1674
1675#[derive(Debug, Clone, Serialize, Deserialize)]
1676#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1677pub struct SignedTransferPackage {
1678 pub unsigned: UnsignedTransferPackage,
1679 pub signature: TransferSignature,
1680}
1681
1682#[derive(Debug, Clone, Serialize, Deserialize)]
1683#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1684pub enum TransferSignature {
1685 Transfer {
1686 signed: crate::signer::ExternalPreparedTransfer,
1687 },
1688 Token {
1689 signed: crate::signer::ExternalPreparedTokenTransaction,
1690 },
1691}
1692
1693#[derive(Debug, Clone)]
1694#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1695pub enum BuildTransferPackageOptions {
1696 BitcoinAddress {
1697 confirmation_speed: OnchainConfirmationSpeed,
1698 },
1699 Bolt11Invoice {
1700 prefer_spark: bool,
1701
1702 completion_timeout_secs: Option<u32>,
1706 },
1707}
1708
1709#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1710pub struct BuildUnsignedTransferPackageRequest {
1711 pub prepare_response: PrepareSendPaymentResponse,
1712 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1713 pub options: Option<BuildTransferPackageOptions>,
1714}
1715
1716#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1717pub struct PrepareSendPaymentRequest {
1718 pub payment_request: PaymentRequest,
1719 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1724 pub amount: Option<u128>,
1725 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1728 pub token_identifier: Option<String>,
1729 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1731 pub conversion_options: Option<ConversionOptions>,
1732 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1740 pub fee_policy: Option<FeePolicy>,
1741}
1742
1743#[derive(Debug, Clone, Serialize)]
1744#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1745pub struct PrepareSendPaymentResponse {
1746 pub payment_method: SendPaymentMethod,
1747 pub amount: u128,
1752 pub token_identifier: Option<String>,
1755 pub conversion_estimate: Option<ConversionEstimate>,
1757 pub fee_policy: FeePolicy,
1760}
1761
1762#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1763pub enum SendPaymentOptions {
1764 BitcoinAddress {
1765 confirmation_speed: OnchainConfirmationSpeed,
1767 },
1768 Bolt11Invoice {
1769 prefer_spark: bool,
1770
1771 completion_timeout_secs: Option<u32>,
1774 },
1775 SparkAddress {
1776 htlc_options: Option<SparkHtlcOptions>,
1779 },
1780}
1781
1782#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1783pub struct SparkHtlcOptions {
1784 pub payment_hash: String,
1786 pub expiry_duration_secs: u64,
1789}
1790
1791#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1792pub struct SendPaymentRequest {
1793 pub prepare_response: PrepareSendPaymentResponse,
1794 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1795 pub options: Option<SendPaymentOptions>,
1796 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1802 pub idempotency_key: Option<String>,
1803}
1804
1805#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1806pub struct PublishSignedTransferPackageRequest {
1807 pub signed_package: SignedTransferPackage,
1808}
1809
1810#[allow(clippy::large_enum_variant)]
1811#[derive(Debug, Clone)]
1812#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1813pub enum PublishSignedTransferPackageResponse {
1814 SwapCompleted,
1815 PaymentSent { payment: Payment },
1816}
1817
1818#[derive(Debug, Clone, Serialize)]
1819#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1820pub struct SendPaymentResponse {
1821 pub payment: Payment,
1822}
1823
1824#[derive(Debug, Clone)]
1825#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1826pub enum PaymentDetailsFilter {
1827 Spark {
1828 htlc_status: Option<Vec<SparkHtlcStatus>>,
1830 conversion_refund_needed: Option<bool>,
1832 },
1833 Token {
1834 conversion_refund_needed: Option<bool>,
1836 tx_hash: Option<String>,
1838 tx_type: Option<TokenTransactionType>,
1840 },
1841 Lightning {
1842 htlc_status: Option<Vec<SparkHtlcStatus>>,
1844 },
1845}
1846
1847#[derive(Debug, Clone, Default)]
1849#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1850pub struct ListPaymentsRequest {
1851 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1852 pub type_filter: Option<Vec<PaymentType>>,
1853 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1854 pub status_filter: Option<Vec<PaymentStatus>>,
1855 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1856 pub asset_filter: Option<AssetFilter>,
1857 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1859 pub payment_details_filter: Option<Vec<PaymentDetailsFilter>>,
1860 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1862 pub from_timestamp: Option<u64>,
1863 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1865 pub to_timestamp: Option<u64>,
1866 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1868 pub offset: Option<u32>,
1869 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1871 pub limit: Option<u32>,
1872 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1873 pub sort_ascending: Option<bool>,
1874}
1875
1876#[derive(Debug, Clone)]
1878#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1879pub enum AssetFilter {
1880 Bitcoin,
1881 Token {
1882 token_identifier: Option<String>,
1884 },
1885}
1886
1887impl FromStr for AssetFilter {
1888 type Err = String;
1889
1890 fn from_str(s: &str) -> Result<Self, Self::Err> {
1891 Ok(match s.to_lowercase().as_str() {
1892 "bitcoin" => AssetFilter::Bitcoin,
1893 "token" => AssetFilter::Token {
1894 token_identifier: None,
1895 },
1896 str if str.starts_with("token:") => AssetFilter::Token {
1897 token_identifier: Some(
1898 str.split_once(':')
1899 .ok_or(format!("Invalid asset filter '{s}'"))?
1900 .1
1901 .to_string(),
1902 ),
1903 },
1904 _ => return Err(format!("Invalid asset filter '{s}'")),
1905 })
1906 }
1907}
1908
1909#[derive(Debug, Clone, Serialize)]
1911#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1912pub struct ListPaymentsResponse {
1913 pub payments: Vec<Payment>,
1915}
1916
1917#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1918pub struct GetPaymentRequest {
1919 pub payment_id: String,
1920}
1921
1922#[derive(Debug, Clone, Serialize)]
1923#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1924pub struct GetPaymentResponse {
1925 pub payment: Payment,
1926}
1927
1928#[cfg_attr(feature = "uniffi", uniffi::export(callback_interface))]
1929pub trait Logger: Send + Sync {
1930 fn log(&self, l: LogEntry);
1931}
1932
1933#[derive(Debug, Clone, Serialize)]
1934#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1935pub struct LogEntry {
1936 pub line: String,
1937 pub level: String,
1938}
1939
1940#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1941#[derive(Debug, Clone, Serialize, Deserialize)]
1942pub struct CheckLightningAddressRequest {
1943 pub username: String,
1944}
1945
1946#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1947#[derive(Debug, Clone, Serialize, Deserialize)]
1948pub struct RegisterLightningAddressRequest {
1949 pub username: String,
1950 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1951 pub description: Option<String>,
1952}
1953
1954#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1960#[derive(Debug, Clone, Serialize, Deserialize)]
1961pub struct TransferAuthorization {
1962 pub username: String,
1964 pub pubkey: String,
1966 pub signature: String,
1968}
1969
1970#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1974#[derive(Debug, Clone, Serialize, Deserialize)]
1975pub struct AuthorizeTransferRequest {
1976 pub transferee_pubkey: String,
1978}
1979
1980#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1984#[derive(Debug, Clone, Serialize, Deserialize)]
1985pub struct ClaimTransferRequest {
1986 pub authorization: TransferAuthorization,
1989 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1991 pub description: Option<String>,
1992}
1993
1994#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1995#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
1996pub struct LnurlInfo {
1997 pub url: String,
1998 pub bech32: String,
1999}
2000
2001impl LnurlInfo {
2002 pub fn new(url: String) -> Self {
2003 let bech32 =
2004 breez_sdk_common::lnurl::encode_lnurl_to_bech32(&url).unwrap_or_else(|_| url.clone());
2005 Self { url, bech32 }
2006 }
2007}
2008
2009#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2010#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
2011pub struct LightningAddressInfo {
2012 pub description: String,
2013 pub lightning_address: String,
2014 pub lnurl: LnurlInfo,
2015 pub username: String,
2016}
2017
2018impl From<RecoverLnurlPayResponse> for LightningAddressInfo {
2019 fn from(resp: RecoverLnurlPayResponse) -> Self {
2020 Self {
2021 description: resp.description,
2022 lightning_address: resp.lightning_address,
2023 lnurl: LnurlInfo::new(resp.lnurl),
2024 username: resp.username,
2025 }
2026 }
2027}
2028
2029#[derive(Debug, Clone, Serialize)]
2031#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2032pub struct ListFiatCurrenciesResponse {
2033 pub currencies: Vec<FiatCurrency>,
2035}
2036
2037#[derive(Debug, Clone, Serialize)]
2039#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2040pub struct ListFiatRatesResponse {
2041 pub rates: Vec<Rate>,
2043}
2044
2045#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
2047#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
2048pub enum ServiceStatus {
2049 Operational,
2051 Degraded,
2053 Partial,
2055 Unknown,
2057 Major,
2059}
2060
2061#[derive(Debug, Clone, Serialize)]
2063#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2064pub struct SparkStatus {
2065 pub status: ServiceStatus,
2067 pub last_updated: u64,
2069}
2070
2071pub(crate) enum WaitForPaymentIdentifier {
2072 PaymentId(String),
2073 LightningReceive { invoice: String, ssp_id: String },
2074}
2075
2076#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2077pub struct GetTokensMetadataRequest {
2078 pub token_identifiers: Vec<String>,
2079}
2080
2081#[derive(Debug, Clone, Serialize)]
2082#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2083pub struct GetTokensMetadataResponse {
2084 pub tokens_metadata: Vec<TokenMetadata>,
2085}
2086
2087#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2088pub struct SignMessageRequest {
2089 pub message: String,
2090 pub compact: bool,
2092}
2093
2094#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2095pub struct SignMessageResponse {
2096 pub pubkey: String,
2097 pub signature: String,
2099}
2100
2101#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2102pub struct CheckMessageRequest {
2103 pub message: String,
2105 pub pubkey: String,
2107 pub signature: String,
2109}
2110
2111#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2112pub struct CheckMessageResponse {
2113 pub is_valid: bool,
2114}
2115
2116#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2117#[derive(Debug, Clone, Serialize)]
2118pub struct UserSettings {
2119 pub spark_private_mode_enabled: bool,
2120
2121 pub stable_balance_active_label: Option<String>,
2123
2124 pub spark_master_identity_public_key: Option<String>,
2127}
2128
2129#[derive(Debug, Clone)]
2131#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
2132pub enum SparkMasterIdentityPublicKey {
2133 Set { public_key: String },
2137 Unset,
2140}
2141
2142#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2143pub struct UpdateUserSettingsRequest {
2144 pub spark_private_mode_enabled: Option<bool>,
2145
2146 #[cfg_attr(feature = "uniffi", uniffi(default = None))]
2148 pub stable_balance_active_label: Option<StableBalanceActiveLabel>,
2149
2150 #[cfg_attr(feature = "uniffi", uniffi(default = None))]
2156 pub spark_master_identity_public_key: Option<SparkMasterIdentityPublicKey>,
2157}
2158
2159#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2160pub struct ClaimHtlcPaymentRequest {
2161 pub preimage: String,
2162}
2163
2164#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2165pub struct ClaimHtlcPaymentResponse {
2166 pub payment: Payment,
2167}
2168
2169#[derive(Debug, Clone, Deserialize, Serialize)]
2170#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2171pub struct LnurlReceiveMetadata {
2172 pub nostr_zap_request: Option<String>,
2173 pub nostr_zap_receipt: Option<String>,
2174 pub sender_comment: Option<String>,
2175}
2176
2177#[derive(Debug, Clone, Default, Deserialize, Serialize, PartialEq)]
2179#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
2180pub enum OptimizationMode {
2181 #[default]
2183 Full,
2184 SingleRound,
2186}
2187
2188#[derive(Debug, Clone, Default, Deserialize, Serialize)]
2191#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2192pub struct OptimizeLeavesRequest {
2193 pub mode: OptimizationMode,
2195}
2196
2197#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
2199#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2200pub struct OptimizeLeavesResponse {
2201 pub outcome: OptimizationOutcome,
2203}
2204
2205#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
2229#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
2230pub enum OptimizationOutcome {
2231 Completed { rounds_executed: u32 },
2238 InProgress,
2242}
2243
2244#[derive(Debug, Clone, Serialize, Deserialize)]
2246#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2247pub struct Contact {
2248 pub id: String,
2249 pub name: String,
2250 pub payment_identifier: String,
2252 pub created_at: u64,
2253 pub updated_at: u64,
2254}
2255
2256#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2258pub struct AddContactRequest {
2259 pub name: String,
2260 pub payment_identifier: String,
2262}
2263
2264#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2266pub struct UpdateContactRequest {
2267 pub id: String,
2268 pub name: String,
2269 pub payment_identifier: String,
2271}
2272
2273#[derive(Debug, Clone, Default)]
2275#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2276pub struct ListContactsRequest {
2277 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
2278 pub offset: Option<u32>,
2279 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
2280 pub limit: Option<u32>,
2281}
2282
2283#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
2285#[allow(clippy::enum_variant_names)]
2286#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
2287pub enum WebhookEventType {
2288 LightningReceiveFinished,
2290 LightningSendFinished,
2292 CoopExitFinished,
2294 StaticDepositFinished,
2296 Unknown(String),
2298}
2299
2300#[derive(Debug, Clone, Serialize)]
2302#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2303pub struct Webhook {
2304 pub id: String,
2306 pub url: String,
2308 pub event_types: Vec<WebhookEventType>,
2310}
2311
2312#[derive(Debug, Clone)]
2314#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2315pub struct RegisterWebhookRequest {
2316 pub url: String,
2318 pub secret: String,
2320 pub event_types: Vec<WebhookEventType>,
2322}
2323
2324#[derive(Debug, Clone, Serialize)]
2326#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2327pub struct RegisterWebhookResponse {
2328 pub webhook_id: String,
2330}
2331
2332#[derive(Debug, Clone)]
2334#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2335pub struct UnregisterWebhookRequest {
2336 pub webhook_id: String,
2338}
2339
2340#[derive(Debug, Clone, Serialize, Deserialize)]
2346#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
2347pub enum CpfpInput {
2348 P2wpkh {
2351 txid: String,
2352 vout: u32,
2353 value: u64,
2354 pubkey: String,
2355 },
2356 P2tr {
2363 txid: String,
2364 vout: u32,
2365 value: u64,
2366 pubkey: String,
2367 },
2368 Custom {
2373 txid: String,
2374 vout: u32,
2375 value: u64,
2376 script_pubkey_hex: String,
2377 signed_input_weight: u64,
2378 },
2379}
2380
2381#[derive(Debug, Clone, Serialize, Deserialize)]
2383#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
2384pub enum CpfpFundingKind {
2385 P2wpkh,
2387 P2tr,
2389 Custom {
2395 script_pubkey_hex: String,
2396 signed_input_weight: u64,
2397 },
2398}
2399
2400#[derive(Debug, Clone, Serialize, Deserialize)]
2402#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
2403pub enum ExitLeafSelection {
2404 Auto,
2411 Specific { leaf_ids: Vec<String> },
2413}
2414
2415#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
2417#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
2418pub enum UnilateralExitTxKind {
2419 FanOut,
2422 Node,
2424 Refund,
2426 Sweep,
2428}
2429
2430#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
2432#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
2433pub enum ConfirmationStatus {
2434 Confirmed,
2436 Unconfirmed,
2438 Unverified,
2441}
2442
2443#[derive(Debug, Clone, Serialize, Deserialize)]
2446#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2447pub struct UnilateralExitTransaction {
2448 pub kind: UnilateralExitTxKind,
2449 pub node_id: Option<String>,
2452 pub txid: String,
2453 pub tx_hex: String,
2454 pub cpfp_tx_hex: Option<String>,
2458 pub csv_timelock_blocks: Option<u32>,
2461 pub depends_on: Vec<String>,
2464 pub status: ConfirmationStatus,
2465}
2466
2467#[derive(Debug, Clone, Serialize, Deserialize)]
2469#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2470pub struct UnilateralExitLeaf {
2471 pub leaf_id: String,
2472 pub value: u64,
2474}
2475
2476#[derive(Debug, Clone)]
2478#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2479pub struct PrepareUnilateralExitRequest {
2480 pub fee_rate_sat_per_vbyte: u64,
2483 pub funding_kind: CpfpFundingKind,
2484 pub destination: String,
2486 pub selection: ExitLeafSelection,
2487}
2488
2489#[derive(Debug, Clone, Serialize, Deserialize)]
2491#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2492pub struct PerBranchFunding {
2493 pub leaf_id: String,
2495 pub funding_sat: u64,
2497}
2498
2499#[derive(Debug, Clone, Serialize, Deserialize)]
2502#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2503pub struct PrepareUnilateralExitResponse {
2504 pub leaves: Vec<UnilateralExitLeaf>,
2505 pub recoverable_value_sat: u64,
2507 pub total_fee_sat: u64,
2512 pub fanout_fee_sat: u64,
2516 pub single_utxo_funding_sat: u64,
2518 pub per_branch_funding: Vec<PerBranchFunding>,
2521 pub fee_rate_sat_per_vbyte: u64,
2523 pub destination: String,
2524}
2525
2526#[derive(Debug, Clone)]
2530#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2531pub struct UnilateralExitRequest {
2532 pub prepared: PrepareUnilateralExitResponse,
2534 pub funding_inputs: Vec<CpfpInput>,
2537}
2538
2539#[derive(Debug, Clone, Serialize)]
2542#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
2543pub struct UnilateralExitResponse {
2544 pub recoverable_value_sat: u64,
2546 pub total_fee_sat: u64,
2550 pub leaves: Vec<UnilateralExitLeaf>,
2551 pub transactions: Vec<UnilateralExitTransaction>,
2554}