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, error::DepositClaimError,
26};
27
28pub const DEFAULT_EXTERNAL_INPUT_PARSERS: &[(&str, &str, &str)] = &[
31 (
32 "picknpay",
33 "(.*)(za.co.electrum.picknpay)(.*)",
34 "https://cryptoqr.net/.well-known/lnurlp/<input>",
35 ),
36 (
37 "bootleggers",
38 r"(.*)(wigroup\.co|yoyogroup\.co)(.*)",
39 "https://cryptoqr.net/.well-known/lnurlw/<input>",
40 ),
41];
42
43#[derive(Debug, Clone)]
46#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
47pub enum Seed {
48 Mnemonic {
50 mnemonic: String,
52 passphrase: Option<String>,
54 },
55 Entropy(Vec<u8>),
57}
58
59impl Seed {
60 pub fn to_bytes(&self) -> Result<Vec<u8>, SdkError> {
61 match self {
62 Seed::Mnemonic {
63 mnemonic,
64 passphrase,
65 } => {
66 let mnemonic = bip39::Mnemonic::parse(mnemonic)
67 .map_err(|e| SdkError::Generic(e.to_string()))?;
68
69 Ok(mnemonic
70 .to_seed(passphrase.as_deref().unwrap_or(""))
71 .to_vec())
72 }
73 Seed::Entropy(entropy) => Ok(entropy.clone()),
74 }
75 }
76}
77
78#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
79pub struct ConnectRequest {
80 pub config: Config,
81 pub seed: Seed,
82 pub storage_dir: String,
83}
84
85#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
89#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
90pub struct ConnectWithSignerRequest {
91 pub config: Config,
92 pub signer: std::sync::Arc<dyn crate::signer::ExternalSigner>,
93 pub storage_dir: String,
94}
95
96#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
98#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
99pub enum PaymentType {
100 Send,
102 Receive,
104}
105
106impl fmt::Display for PaymentType {
107 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108 match self {
109 PaymentType::Send => write!(f, "send"),
110 PaymentType::Receive => write!(f, "receive"),
111 }
112 }
113}
114
115impl FromStr for PaymentType {
116 type Err = String;
117
118 fn from_str(s: &str) -> Result<Self, Self::Err> {
119 Ok(match s.to_lowercase().as_str() {
120 "receive" => PaymentType::Receive,
121 "send" => PaymentType::Send,
122 _ => return Err(format!("invalid payment type '{s}'")),
123 })
124 }
125}
126
127#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
129#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
130pub enum PaymentStatus {
131 Completed,
133 Pending,
135 Failed,
137}
138
139impl PaymentStatus {
140 pub fn is_final(&self) -> bool {
142 matches!(self, PaymentStatus::Completed | PaymentStatus::Failed)
143 }
144}
145
146impl fmt::Display for PaymentStatus {
147 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
148 match self {
149 PaymentStatus::Completed => write!(f, "completed"),
150 PaymentStatus::Pending => write!(f, "pending"),
151 PaymentStatus::Failed => write!(f, "failed"),
152 }
153 }
154}
155
156impl FromStr for PaymentStatus {
157 type Err = String;
158
159 fn from_str(s: &str) -> Result<Self, Self::Err> {
160 Ok(match s.to_lowercase().as_str() {
161 "completed" => PaymentStatus::Completed,
162 "pending" => PaymentStatus::Pending,
163 "failed" => PaymentStatus::Failed,
164 _ => return Err(format!("Invalid payment status '{s}'")),
165 })
166 }
167}
168
169#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
170#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
171pub enum PaymentMethod {
172 Lightning,
173 Spark,
174 Token,
175 Deposit,
176 Withdraw,
177 Unknown,
178}
179
180impl Display for PaymentMethod {
181 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
182 match self {
183 PaymentMethod::Lightning => write!(f, "lightning"),
184 PaymentMethod::Spark => write!(f, "spark"),
185 PaymentMethod::Token => write!(f, "token"),
186 PaymentMethod::Deposit => write!(f, "deposit"),
187 PaymentMethod::Withdraw => write!(f, "withdraw"),
188 PaymentMethod::Unknown => write!(f, "unknown"),
189 }
190 }
191}
192
193impl FromStr for PaymentMethod {
194 type Err = ();
195
196 fn from_str(s: &str) -> Result<Self, Self::Err> {
197 match s {
198 "lightning" => Ok(PaymentMethod::Lightning),
199 "spark" => Ok(PaymentMethod::Spark),
200 "token" => Ok(PaymentMethod::Token),
201 "deposit" => Ok(PaymentMethod::Deposit),
202 "withdraw" => Ok(PaymentMethod::Withdraw),
203 "unknown" => Ok(PaymentMethod::Unknown),
204 _ => Err(()),
205 }
206 }
207}
208
209#[derive(Debug, Clone, Serialize, Deserialize)]
211#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
212pub struct Payment {
213 pub id: String,
215 pub payment_type: PaymentType,
217 pub status: PaymentStatus,
219 pub amount: u128,
221 pub fees: u128,
223 pub timestamp: u64,
225 pub method: PaymentMethod,
228 pub details: Option<PaymentDetails>,
230 pub conversion_details: Option<ConversionDetails>,
232}
233
234impl Payment {
235 pub fn is_conversion_child(&self) -> bool {
241 matches!(
242 &self.details,
243 Some(
244 PaymentDetails::Spark {
245 conversion_info: Some(_),
246 ..
247 } | PaymentDetails::Token {
248 conversion_info: Some(_),
249 ..
250 }
251 )
252 )
253 }
254}
255
256#[derive(Debug, Clone, Serialize, Deserialize)]
261#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
262pub struct ConversionDetails {
263 pub status: ConversionStatus,
265 pub from: Option<ConversionStep>,
267 pub to: Option<ConversionStep>,
269}
270
271pub fn conversion_steps_from_payments(
280 payments: &[Payment],
281) -> Result<(Option<ConversionStep>, Option<ConversionStep>), SdkError> {
282 let from = payments
283 .iter()
284 .find(|p| p.payment_type == PaymentType::Send)
285 .map(TryInto::try_into)
286 .transpose()?;
287 let to = payments
288 .iter()
289 .find(|p| p.payment_type == PaymentType::Receive)
290 .map(TryInto::try_into)
291 .transpose()?;
292 Ok((from, to))
293}
294
295#[derive(Debug, Clone, Serialize, Deserialize)]
297#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
298pub struct ConversionStep {
299 pub payment_id: String,
301 pub amount: u128,
303 pub fee: u128,
306 pub method: PaymentMethod,
308 pub token_metadata: Option<TokenMetadata>,
310 #[serde(default)]
312 pub amount_adjustment: Option<AmountAdjustmentReason>,
313}
314
315impl TryFrom<&Payment> for ConversionStep {
319 type Error = SdkError;
320 fn try_from(payment: &Payment) -> Result<Self, Self::Error> {
321 let (conversion_info, token_metadata) = match &payment.details {
322 Some(PaymentDetails::Spark {
323 conversion_info: Some(info),
324 ..
325 }) => (info, None),
326 Some(PaymentDetails::Token {
327 conversion_info: Some(info),
328 metadata,
329 ..
330 }) => (info, Some(metadata.clone())),
331 _ => {
332 return Err(SdkError::Generic(format!(
333 "No conversion info available for payment {}",
334 payment.id
335 )));
336 }
337 };
338 Ok(ConversionStep {
339 payment_id: payment.id.clone(),
340 amount: payment.amount,
341 fee: payment
342 .fees
343 .saturating_add(conversion_info.fee.unwrap_or(0)),
344 method: payment.method,
345 token_metadata,
346 amount_adjustment: conversion_info.amount_adjustment.clone(),
347 })
348 }
349}
350
351#[cfg(feature = "uniffi")]
352uniffi::custom_type!(u128, String, {
353 remote,
354 try_lift: |val| val.parse::<u128>().map_err(uniffi::deps::anyhow::Error::msg),
355 lower: |obj| obj.to_string(),
356});
357
358#[allow(clippy::large_enum_variant)]
361#[derive(Debug, Clone, Serialize, Deserialize)]
362#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
363pub enum PaymentDetails {
364 Spark {
365 invoice_details: Option<SparkInvoicePaymentDetails>,
367 htlc_details: Option<SparkHtlcDetails>,
369 conversion_info: Option<ConversionInfo>,
371 },
372 Token {
373 metadata: TokenMetadata,
374 tx_hash: String,
375 tx_type: TokenTransactionType,
376 invoice_details: Option<SparkInvoicePaymentDetails>,
378 conversion_info: Option<ConversionInfo>,
380 },
381 Lightning {
382 description: Option<String>,
384 invoice: String,
388
389 destination_pubkey: String,
391
392 htlc_details: SparkHtlcDetails,
394
395 lnurl_pay_info: Option<LnurlPayInfo>,
397
398 lnurl_withdraw_info: Option<LnurlWithdrawInfo>,
400
401 lnurl_receive_metadata: Option<LnurlReceiveMetadata>,
403 },
404 Withdraw {
405 tx_id: String,
406 },
407 Deposit {
408 tx_id: String,
409 },
410}
411
412#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
413#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
414pub enum TokenTransactionType {
415 Transfer,
416 Mint,
417 Burn,
418}
419
420impl fmt::Display for TokenTransactionType {
421 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
422 match self {
423 TokenTransactionType::Transfer => write!(f, "transfer"),
424 TokenTransactionType::Mint => write!(f, "mint"),
425 TokenTransactionType::Burn => write!(f, "burn"),
426 }
427 }
428}
429
430impl FromStr for TokenTransactionType {
431 type Err = String;
432
433 fn from_str(s: &str) -> Result<Self, Self::Err> {
434 match s.to_lowercase().as_str() {
435 "transfer" => Ok(TokenTransactionType::Transfer),
436 "mint" => Ok(TokenTransactionType::Mint),
437 "burn" => Ok(TokenTransactionType::Burn),
438 _ => Err(format!("Invalid token transaction type '{s}'")),
439 }
440 }
441}
442
443#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
444#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
445pub struct SparkInvoicePaymentDetails {
446 pub description: Option<String>,
448 pub invoice: String,
450}
451
452#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
453#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
454pub struct SparkHtlcDetails {
455 pub payment_hash: String,
457 pub preimage: Option<String>,
459 pub expiry_time: u64,
461 pub status: SparkHtlcStatus,
463}
464
465#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
466#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
467pub enum SparkHtlcStatus {
468 WaitingForPreimage,
470 PreimageShared,
472 Returned,
474}
475
476impl fmt::Display for SparkHtlcStatus {
477 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
478 match self {
479 SparkHtlcStatus::WaitingForPreimage => write!(f, "WaitingForPreimage"),
480 SparkHtlcStatus::PreimageShared => write!(f, "PreimageShared"),
481 SparkHtlcStatus::Returned => write!(f, "Returned"),
482 }
483 }
484}
485
486impl FromStr for SparkHtlcStatus {
487 type Err = String;
488
489 fn from_str(s: &str) -> Result<Self, Self::Err> {
490 match s {
491 "WaitingForPreimage" => Ok(SparkHtlcStatus::WaitingForPreimage),
492 "PreimageShared" => Ok(SparkHtlcStatus::PreimageShared),
493 "Returned" => Ok(SparkHtlcStatus::Returned),
494 _ => Err("Invalid Spark HTLC status".to_string()),
495 }
496 }
497}
498
499#[derive(Debug, Clone, Copy)]
500#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
501pub enum Network {
502 Mainnet,
503 Regtest,
504}
505
506impl std::fmt::Display for Network {
507 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
508 match self {
509 Network::Mainnet => write!(f, "Mainnet"),
510 Network::Regtest => write!(f, "Regtest"),
511 }
512 }
513}
514
515impl From<Network> for BitcoinNetwork {
516 fn from(network: Network) -> Self {
517 match network {
518 Network::Mainnet => BitcoinNetwork::Bitcoin,
519 Network::Regtest => BitcoinNetwork::Regtest,
520 }
521 }
522}
523
524impl From<Network> for breez_sdk_common::network::BitcoinNetwork {
525 fn from(network: Network) -> Self {
526 match network {
527 Network::Mainnet => breez_sdk_common::network::BitcoinNetwork::Bitcoin,
528 Network::Regtest => breez_sdk_common::network::BitcoinNetwork::Regtest,
529 }
530 }
531}
532
533impl From<Network> for bitcoin::Network {
534 fn from(network: Network) -> Self {
535 match network {
536 Network::Mainnet => bitcoin::Network::Bitcoin,
537 Network::Regtest => bitcoin::Network::Regtest,
538 }
539 }
540}
541
542impl FromStr for Network {
543 type Err = String;
544
545 fn from_str(s: &str) -> Result<Self, Self::Err> {
546 match s {
547 "mainnet" => Ok(Network::Mainnet),
548 "regtest" => Ok(Network::Regtest),
549 _ => Err("Invalid network".to_string()),
550 }
551 }
552}
553
554#[derive(Debug, Clone)]
555#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
556#[allow(clippy::struct_excessive_bools)]
557pub struct Config {
558 pub api_key: Option<String>,
559 pub network: Network,
560 pub sync_interval_secs: u32,
561
562 pub max_deposit_claim_fee: Option<MaxFee>,
565
566 pub lnurl_domain: Option<String>,
568
569 pub prefer_spark_over_lightning: bool,
573
574 pub external_input_parsers: Option<Vec<ExternalInputParser>>,
578 pub use_default_external_input_parsers: bool,
582
583 pub real_time_sync_server_url: Option<String>,
585
586 pub private_enabled_default: bool,
591
592 pub optimization_config: OptimizationConfig,
598
599 pub stable_balance_config: Option<StableBalanceConfig>,
604
605 pub max_concurrent_claims: u32,
609
610 pub spark_config: Option<SparkConfig>,
616}
617
618#[derive(Debug, Clone)]
619#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
620pub struct OptimizationConfig {
621 pub auto_enabled: bool,
628 pub multiplicity: u8,
640}
641
642#[derive(Debug, Clone)]
644#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
645pub struct StableBalanceToken {
646 pub label: String,
652
653 pub token_identifier: String,
655}
656
657#[derive(Debug, Clone)]
671#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
672pub struct StableBalanceConfig {
673 pub tokens: Vec<StableBalanceToken>,
675
676 #[cfg_attr(feature = "uniffi", uniffi(default = None))]
682 pub default_active_label: Option<String>,
683
684 #[cfg_attr(feature = "uniffi", uniffi(default = None))]
689 pub threshold_sats: Option<u64>,
690
691 #[cfg_attr(feature = "uniffi", uniffi(default = None))]
695 pub max_slippage_bps: Option<u32>,
696}
697
698#[derive(Debug, Clone)]
700#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
701pub enum StableBalanceActiveLabel {
702 Set { label: String },
704 Unset,
706}
707
708#[derive(Debug, Clone)]
714#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
715pub struct SparkConfig {
716 pub coordinator_identifier: String,
718 pub threshold: u32,
720 pub signing_operators: Vec<SparkSigningOperator>,
722 pub ssp_config: SparkSspConfig,
724 pub expected_withdraw_bond_sats: u64,
726 pub expected_withdraw_relative_block_locktime: u64,
728}
729
730#[derive(Debug, Clone)]
732#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
733pub struct SparkSigningOperator {
734 pub id: u32,
736 pub identifier: String,
738 pub address: String,
740 pub identity_public_key: String,
742}
743
744#[derive(Debug, Clone)]
746#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
747pub struct SparkSspConfig {
748 pub base_url: String,
750 pub identity_public_key: String,
752 pub schema_endpoint: Option<String>,
755}
756
757impl Config {
758 pub fn validate(&self) -> Result<(), SdkError> {
762 if self.max_concurrent_claims == 0 {
763 return Err(SdkError::InvalidInput(
764 "max_concurrent_claims must be greater than 0".to_string(),
765 ));
766 }
767
768 if let Some(sb) = &self.stable_balance_config {
769 if sb.tokens.is_empty() {
770 return Err(SdkError::InvalidInput(
771 "tokens must not be empty".to_string(),
772 ));
773 }
774
775 let mut seen_labels = HashSet::new();
776 let mut seen_identifiers = HashSet::new();
777 for token in &sb.tokens {
778 if token.label.is_empty() {
779 return Err(SdkError::InvalidInput(
780 "token label must not be empty".to_string(),
781 ));
782 }
783 if token.token_identifier.is_empty() {
784 return Err(SdkError::InvalidInput(
785 "token_identifier must not be empty".to_string(),
786 ));
787 }
788 if !seen_labels.insert(&token.label) {
789 return Err(SdkError::InvalidInput(format!(
790 "tokens contains duplicate label: {}",
791 token.label
792 )));
793 }
794 if !seen_identifiers.insert(&token.token_identifier) {
795 return Err(SdkError::InvalidInput(format!(
796 "tokens contains duplicate token_identifier: {}",
797 token.token_identifier
798 )));
799 }
800 }
801
802 if let Some(bps) = sb.max_slippage_bps
803 && bps > 10000
804 {
805 return Err(SdkError::InvalidInput(
806 "max_slippage_bps must be <= 10000".to_string(),
807 ));
808 }
809
810 if let Some(default_label) = &sb.default_active_label
811 && !seen_labels.contains(default_label)
812 {
813 return Err(SdkError::InvalidInput(format!(
814 "default_active_label '{default_label}' not found in tokens list"
815 )));
816 }
817 }
818
819 Ok(())
820 }
821
822 pub(crate) fn get_all_external_input_parsers(&self) -> Vec<ExternalInputParser> {
823 let mut external_input_parsers = Vec::new();
824 if self.use_default_external_input_parsers {
825 let default_parsers = DEFAULT_EXTERNAL_INPUT_PARSERS
826 .iter()
827 .map(|(id, regex, url)| ExternalInputParser {
828 provider_id: (*id).to_string(),
829 input_regex: (*regex).to_string(),
830 parser_url: (*url).to_string(),
831 })
832 .collect::<Vec<_>>();
833 external_input_parsers.extend(default_parsers);
834 }
835 external_input_parsers.extend(self.external_input_parsers.clone().unwrap_or_default());
836
837 external_input_parsers
838 }
839}
840
841#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
842#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
843pub enum MaxFee {
844 Fixed { amount: u64 },
846 Rate { sat_per_vbyte: u64 },
848 NetworkRecommended { leeway_sat_per_vbyte: u64 },
850}
851
852impl MaxFee {
853 pub(crate) async fn to_fee(&self, client: &dyn BitcoinChainService) -> Result<Fee, SdkError> {
854 match self {
855 MaxFee::Fixed { amount } => Ok(Fee::Fixed { amount: *amount }),
856 MaxFee::Rate { sat_per_vbyte } => Ok(Fee::Rate {
857 sat_per_vbyte: *sat_per_vbyte,
858 }),
859 MaxFee::NetworkRecommended {
860 leeway_sat_per_vbyte,
861 } => {
862 let recommended_fees = client.recommended_fees().await?;
863 let max_fee_rate = recommended_fees
864 .fastest_fee
865 .saturating_add(*leeway_sat_per_vbyte);
866 Ok(Fee::Rate {
867 sat_per_vbyte: max_fee_rate,
868 })
869 }
870 }
871 }
872}
873
874#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
875#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
876pub enum Fee {
877 Fixed { amount: u64 },
879 Rate { sat_per_vbyte: u64 },
881}
882
883impl Fee {
884 pub fn to_sats(&self, vbytes: u64) -> u64 {
885 match self {
886 Fee::Fixed { amount } => *amount,
887 Fee::Rate { sat_per_vbyte } => sat_per_vbyte.saturating_mul(vbytes),
888 }
889 }
890}
891
892#[derive(Debug, Clone, Serialize, Deserialize)]
893#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
894pub struct DepositInfo {
895 pub txid: String,
896 pub vout: u32,
897 pub amount_sats: u64,
898 pub is_mature: bool,
899 pub refund_tx: Option<String>,
900 pub refund_tx_id: Option<String>,
901 pub claim_error: Option<DepositClaimError>,
902}
903
904#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
905pub struct ClaimDepositRequest {
906 pub txid: String,
907 pub vout: u32,
908 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
909 pub max_fee: Option<MaxFee>,
910}
911
912#[derive(Debug, Clone, Serialize)]
913#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
914pub struct ClaimDepositResponse {
915 pub payment: Payment,
916}
917
918#[derive(Debug, Clone, Serialize)]
919#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
920pub struct RefundDepositRequest {
921 pub txid: String,
922 pub vout: u32,
923 pub destination_address: String,
924 pub fee: Fee,
925}
926
927#[derive(Debug, Clone, Serialize)]
928#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
929pub struct RefundDepositResponse {
930 pub tx_id: String,
931 pub tx_hex: String,
932}
933
934#[derive(Debug, Clone, Serialize)]
935#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
936pub struct ListUnclaimedDepositsRequest {}
937
938#[derive(Debug, Clone, Serialize)]
939#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
940pub struct ListUnclaimedDepositsResponse {
941 pub deposits: Vec<DepositInfo>,
942}
943
944#[derive(Debug, Clone)]
949#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
950pub enum BuyBitcoinRequest {
951 Moonpay {
954 locked_amount_sat: Option<u64>,
956 redirect_url: Option<String>,
958 },
959 CashApp {
963 amount_sats: Option<u64>,
965 },
966}
967
968impl Default for BuyBitcoinRequest {
969 fn default() -> Self {
970 Self::Moonpay {
971 locked_amount_sat: None,
972 redirect_url: None,
973 }
974 }
975}
976
977#[derive(Debug, Clone, Serialize)]
979#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
980pub struct BuyBitcoinResponse {
981 pub url: String,
983}
984
985impl std::fmt::Display for MaxFee {
986 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
987 match self {
988 MaxFee::Fixed { amount } => write!(f, "Fixed: {amount}"),
989 MaxFee::Rate { sat_per_vbyte } => write!(f, "Rate: {sat_per_vbyte}"),
990 MaxFee::NetworkRecommended {
991 leeway_sat_per_vbyte,
992 } => write!(f, "NetworkRecommended: {leeway_sat_per_vbyte}"),
993 }
994 }
995}
996
997#[derive(Debug, Clone)]
998#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
999pub struct Credentials {
1000 pub username: String,
1001 pub password: String,
1002}
1003
1004#[derive(Debug, Clone)]
1006#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1007pub struct GetInfoRequest {
1008 pub ensure_synced: Option<bool>,
1009}
1010
1011#[derive(Debug, Clone, Serialize)]
1013#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1014pub struct GetInfoResponse {
1015 pub identity_pubkey: String,
1017 pub balance_sats: u64,
1019 pub token_balances: HashMap<String, TokenBalance>,
1021}
1022
1023#[derive(Debug, Clone, Serialize, Deserialize)]
1024#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1025pub struct TokenBalance {
1026 pub balance: u128,
1027 pub token_metadata: TokenMetadata,
1028}
1029
1030#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1031#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1032pub struct TokenMetadata {
1033 pub identifier: String,
1034 pub issuer_public_key: String,
1036 pub name: String,
1037 pub ticker: String,
1038 pub decimals: u32,
1040 pub max_supply: u128,
1041 pub is_freezable: bool,
1042}
1043
1044#[derive(Debug, Clone)]
1046#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1047pub struct SyncWalletRequest {}
1048
1049#[derive(Debug, Clone, Serialize)]
1051#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1052pub struct SyncWalletResponse {}
1053
1054#[derive(Debug, Clone, Serialize)]
1055#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1056pub enum ReceivePaymentMethod {
1057 SparkAddress,
1058 SparkInvoice {
1059 amount: Option<u128>,
1061 token_identifier: Option<String>,
1064 expiry_time: Option<u64>,
1066 description: Option<String>,
1068 sender_public_key: Option<String>,
1070 },
1071 BitcoinAddress {
1072 new_address: Option<bool>,
1076 },
1077 Bolt11Invoice {
1078 description: String,
1079 amount_sats: Option<u64>,
1080 expiry_secs: Option<u32>,
1082 payment_hash: Option<String>,
1086 },
1087}
1088
1089#[derive(Debug, Clone, Serialize)]
1090#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1091pub enum SendPaymentMethod {
1092 BitcoinAddress {
1093 address: BitcoinAddressDetails,
1094 fee_quote: SendOnchainFeeQuote,
1095 },
1096 Bolt11Invoice {
1097 invoice_details: Bolt11InvoiceDetails,
1098 spark_transfer_fee_sats: Option<u64>,
1099 lightning_fee_sats: u64,
1100 }, SparkAddress {
1102 address: String,
1103 fee: u128,
1106 token_identifier: Option<String>,
1109 },
1110 SparkInvoice {
1111 spark_invoice_details: SparkInvoiceDetails,
1112 fee: u128,
1115 token_identifier: Option<String>,
1118 },
1119}
1120
1121#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1122#[derive(Debug, Clone, Serialize)]
1123pub struct SendOnchainFeeQuote {
1124 pub id: String,
1125 pub expires_at: u64,
1126 pub speed_fast: SendOnchainSpeedFeeQuote,
1127 pub speed_medium: SendOnchainSpeedFeeQuote,
1128 pub speed_slow: SendOnchainSpeedFeeQuote,
1129}
1130
1131#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1132#[derive(Debug, Clone, Serialize)]
1133pub struct SendOnchainSpeedFeeQuote {
1134 pub user_fee_sat: u64,
1135 pub l1_broadcast_fee_sat: u64,
1136}
1137
1138impl SendOnchainSpeedFeeQuote {
1139 pub fn total_fee_sat(&self) -> u64 {
1140 self.user_fee_sat.saturating_add(self.l1_broadcast_fee_sat)
1141 }
1142}
1143
1144#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1145pub struct ReceivePaymentRequest {
1146 pub payment_method: ReceivePaymentMethod,
1147}
1148
1149#[derive(Debug, Clone, Serialize)]
1150#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1151pub struct ReceivePaymentResponse {
1152 pub payment_request: String,
1153 pub fee: u128,
1156}
1157
1158#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1159pub struct PrepareLnurlPayRequest {
1160 pub amount: u128,
1163 pub pay_request: LnurlPayRequestDetails,
1164 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1165 pub comment: Option<String>,
1166 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1167 pub validate_success_action_url: Option<bool>,
1168 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1170 pub token_identifier: Option<String>,
1171 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1173 pub conversion_options: Option<ConversionOptions>,
1174 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1176 pub fee_policy: Option<FeePolicy>,
1177}
1178
1179#[derive(Debug, Clone)]
1180#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1181pub struct PrepareLnurlPayResponse {
1182 pub amount_sats: u64,
1187 pub comment: Option<String>,
1188 pub pay_request: LnurlPayRequestDetails,
1189 pub fee_sats: u64,
1192 pub invoice_details: Bolt11InvoiceDetails,
1193 pub success_action: Option<SuccessAction>,
1194 pub conversion_estimate: Option<ConversionEstimate>,
1196 pub fee_policy: FeePolicy,
1198}
1199
1200#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1201pub struct LnurlPayRequest {
1202 pub prepare_response: PrepareLnurlPayResponse,
1203 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1207 pub idempotency_key: Option<String>,
1208}
1209
1210#[derive(Debug, Serialize)]
1211#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1212pub struct LnurlPayResponse {
1213 pub payment: Payment,
1214 pub success_action: Option<SuccessActionProcessed>,
1215}
1216
1217#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1218pub struct LnurlWithdrawRequest {
1219 pub amount_sats: u64,
1222 pub withdraw_request: LnurlWithdrawRequestDetails,
1223 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1227 pub completion_timeout_secs: Option<u32>,
1228}
1229
1230#[derive(Debug, Serialize)]
1231#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1232pub struct LnurlWithdrawResponse {
1233 pub payment_request: String,
1235 pub payment: Option<Payment>,
1236}
1237
1238#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
1240#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1241pub struct LnurlPayInfo {
1242 pub ln_address: Option<String>,
1243 pub comment: Option<String>,
1244 pub domain: Option<String>,
1245 pub metadata: Option<String>,
1246 pub processed_success_action: Option<SuccessActionProcessed>,
1247 pub raw_success_action: Option<SuccessAction>,
1248}
1249
1250#[derive(Clone, Debug, Deserialize, Serialize)]
1252#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1253pub struct LnurlWithdrawInfo {
1254 pub withdraw_url: String,
1255}
1256
1257impl LnurlPayInfo {
1258 pub fn extract_description(&self) -> Option<String> {
1259 let Some(metadata) = &self.metadata else {
1260 return None;
1261 };
1262
1263 let Ok(metadata) = serde_json::from_str::<Vec<Vec<Value>>>(metadata) else {
1264 return None;
1265 };
1266
1267 for arr in metadata {
1268 if arr.len() != 2 {
1269 continue;
1270 }
1271 if let (Some(key), Some(value)) = (arr[0].as_str(), arr[1].as_str())
1272 && key == "text/plain"
1273 {
1274 return Some(value.to_string());
1275 }
1276 }
1277
1278 None
1279 }
1280}
1281
1282#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
1284#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1285pub enum FeePolicy {
1286 #[default]
1289 FeesExcluded,
1290 FeesIncluded,
1293}
1294
1295#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1296#[derive(Debug, Clone, Serialize)]
1297pub enum OnchainConfirmationSpeed {
1298 Fast,
1299 Medium,
1300 Slow,
1301}
1302
1303#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1304pub struct PrepareSendPaymentRequest {
1305 pub payment_request: String,
1306 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1311 pub amount: Option<u128>,
1312 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1315 pub token_identifier: Option<String>,
1316 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1318 pub conversion_options: Option<ConversionOptions>,
1319 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1321 pub fee_policy: Option<FeePolicy>,
1322}
1323
1324#[derive(Debug, Clone, Serialize)]
1325#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1326pub struct PrepareSendPaymentResponse {
1327 pub payment_method: SendPaymentMethod,
1328 pub amount: u128,
1333 pub token_identifier: Option<String>,
1336 pub conversion_estimate: Option<ConversionEstimate>,
1338 pub fee_policy: FeePolicy,
1340}
1341
1342#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1343pub enum SendPaymentOptions {
1344 BitcoinAddress {
1345 confirmation_speed: OnchainConfirmationSpeed,
1347 },
1348 Bolt11Invoice {
1349 prefer_spark: bool,
1350
1351 completion_timeout_secs: Option<u32>,
1354 },
1355 SparkAddress {
1356 htlc_options: Option<SparkHtlcOptions>,
1359 },
1360}
1361
1362#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1363pub struct SparkHtlcOptions {
1364 pub payment_hash: String,
1366 pub expiry_duration_secs: u64,
1369}
1370
1371#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1372pub struct SendPaymentRequest {
1373 pub prepare_response: PrepareSendPaymentResponse,
1374 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1375 pub options: Option<SendPaymentOptions>,
1376 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1381 pub idempotency_key: Option<String>,
1382}
1383
1384#[derive(Debug, Clone, Serialize)]
1385#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1386pub struct SendPaymentResponse {
1387 pub payment: Payment,
1388}
1389
1390#[derive(Debug, Clone)]
1391#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1392pub enum PaymentDetailsFilter {
1393 Spark {
1394 htlc_status: Option<Vec<SparkHtlcStatus>>,
1396 conversion_refund_needed: Option<bool>,
1398 },
1399 Token {
1400 conversion_refund_needed: Option<bool>,
1402 tx_hash: Option<String>,
1404 tx_type: Option<TokenTransactionType>,
1406 },
1407 Lightning {
1408 htlc_status: Option<Vec<SparkHtlcStatus>>,
1410 },
1411}
1412
1413#[derive(Debug, Clone, Default)]
1415#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1416pub struct ListPaymentsRequest {
1417 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1418 pub type_filter: Option<Vec<PaymentType>>,
1419 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1420 pub status_filter: Option<Vec<PaymentStatus>>,
1421 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1422 pub asset_filter: Option<AssetFilter>,
1423 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1425 pub payment_details_filter: Option<Vec<PaymentDetailsFilter>>,
1426 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1428 pub from_timestamp: Option<u64>,
1429 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1431 pub to_timestamp: Option<u64>,
1432 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1434 pub offset: Option<u32>,
1435 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1437 pub limit: Option<u32>,
1438 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1439 pub sort_ascending: Option<bool>,
1440}
1441
1442#[derive(Debug, Clone)]
1444#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1445pub enum AssetFilter {
1446 Bitcoin,
1447 Token {
1448 token_identifier: Option<String>,
1450 },
1451}
1452
1453impl FromStr for AssetFilter {
1454 type Err = String;
1455
1456 fn from_str(s: &str) -> Result<Self, Self::Err> {
1457 Ok(match s.to_lowercase().as_str() {
1458 "bitcoin" => AssetFilter::Bitcoin,
1459 "token" => AssetFilter::Token {
1460 token_identifier: None,
1461 },
1462 str if str.starts_with("token:") => AssetFilter::Token {
1463 token_identifier: Some(
1464 str.split_once(':')
1465 .ok_or(format!("Invalid asset filter '{s}'"))?
1466 .1
1467 .to_string(),
1468 ),
1469 },
1470 _ => return Err(format!("Invalid asset filter '{s}'")),
1471 })
1472 }
1473}
1474
1475#[derive(Debug, Clone, Serialize)]
1477#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1478pub struct ListPaymentsResponse {
1479 pub payments: Vec<Payment>,
1481}
1482
1483#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1484pub struct GetPaymentRequest {
1485 pub payment_id: String,
1486}
1487
1488#[derive(Debug, Clone, Serialize)]
1489#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1490pub struct GetPaymentResponse {
1491 pub payment: Payment,
1492}
1493
1494#[cfg_attr(feature = "uniffi", uniffi::export(callback_interface))]
1495pub trait Logger: Send + Sync {
1496 fn log(&self, l: LogEntry);
1497}
1498
1499#[derive(Debug, Clone, Serialize)]
1500#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1501pub struct LogEntry {
1502 pub line: String,
1503 pub level: String,
1504}
1505
1506#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1507#[derive(Debug, Clone, Serialize, Deserialize)]
1508pub struct CheckLightningAddressRequest {
1509 pub username: String,
1510}
1511
1512#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1513#[derive(Debug, Clone, Serialize, Deserialize)]
1514pub struct RegisterLightningAddressRequest {
1515 pub username: String,
1516 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1517 pub description: Option<String>,
1518}
1519
1520#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1521#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
1522pub struct LnurlInfo {
1523 pub url: String,
1524 pub bech32: String,
1525}
1526
1527impl LnurlInfo {
1528 pub fn new(url: String) -> Self {
1529 let bech32 =
1530 breez_sdk_common::lnurl::encode_lnurl_to_bech32(&url).unwrap_or_else(|_| url.clone());
1531 Self { url, bech32 }
1532 }
1533}
1534
1535#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1536#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
1537pub struct LightningAddressInfo {
1538 pub description: String,
1539 pub lightning_address: String,
1540 pub lnurl: LnurlInfo,
1541 pub username: String,
1542}
1543
1544impl From<RecoverLnurlPayResponse> for LightningAddressInfo {
1545 fn from(resp: RecoverLnurlPayResponse) -> Self {
1546 Self {
1547 description: resp.description,
1548 lightning_address: resp.lightning_address,
1549 lnurl: LnurlInfo::new(resp.lnurl),
1550 username: resp.username,
1551 }
1552 }
1553}
1554
1555#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1556#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1557pub enum KeySetType {
1558 #[default]
1559 Default,
1560 Taproot,
1561 NativeSegwit,
1562 WrappedSegwit,
1563 Legacy,
1564}
1565
1566impl From<spark_wallet::KeySetType> for KeySetType {
1567 fn from(value: spark_wallet::KeySetType) -> Self {
1568 match value {
1569 spark_wallet::KeySetType::Default => KeySetType::Default,
1570 spark_wallet::KeySetType::Taproot => KeySetType::Taproot,
1571 spark_wallet::KeySetType::NativeSegwit => KeySetType::NativeSegwit,
1572 spark_wallet::KeySetType::WrappedSegwit => KeySetType::WrappedSegwit,
1573 spark_wallet::KeySetType::Legacy => KeySetType::Legacy,
1574 }
1575 }
1576}
1577
1578impl From<KeySetType> for spark_wallet::KeySetType {
1579 fn from(value: KeySetType) -> Self {
1580 match value {
1581 KeySetType::Default => spark_wallet::KeySetType::Default,
1582 KeySetType::Taproot => spark_wallet::KeySetType::Taproot,
1583 KeySetType::NativeSegwit => spark_wallet::KeySetType::NativeSegwit,
1584 KeySetType::WrappedSegwit => spark_wallet::KeySetType::WrappedSegwit,
1585 KeySetType::Legacy => spark_wallet::KeySetType::Legacy,
1586 }
1587 }
1588}
1589
1590#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
1594#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1595pub struct KeySetConfig {
1596 pub key_set_type: KeySetType,
1598 pub use_address_index: bool,
1600 pub account_number: Option<u32>,
1602}
1603
1604impl Default for KeySetConfig {
1605 fn default() -> Self {
1606 Self {
1607 key_set_type: KeySetType::Default,
1608 use_address_index: false,
1609 account_number: None,
1610 }
1611 }
1612}
1613
1614#[derive(Debug, Clone, Serialize)]
1616#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1617pub struct ListFiatCurrenciesResponse {
1618 pub currencies: Vec<FiatCurrency>,
1620}
1621
1622#[derive(Debug, Clone, Serialize)]
1624#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1625pub struct ListFiatRatesResponse {
1626 pub rates: Vec<Rate>,
1628}
1629
1630#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
1632#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1633pub enum ServiceStatus {
1634 Operational,
1636 Degraded,
1638 Partial,
1640 Unknown,
1642 Major,
1644}
1645
1646#[derive(Debug, Clone, Serialize)]
1648#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1649pub struct SparkStatus {
1650 pub status: ServiceStatus,
1652 pub last_updated: u64,
1654}
1655
1656pub(crate) enum WaitForPaymentIdentifier {
1657 PaymentId(String),
1658 PaymentRequest(String),
1659}
1660
1661#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1662pub struct GetTokensMetadataRequest {
1663 pub token_identifiers: Vec<String>,
1664}
1665
1666#[derive(Debug, Clone, Serialize)]
1667#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1668pub struct GetTokensMetadataResponse {
1669 pub tokens_metadata: Vec<TokenMetadata>,
1670}
1671
1672#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1673pub struct SignMessageRequest {
1674 pub message: String,
1675 pub compact: bool,
1677}
1678
1679#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1680pub struct SignMessageResponse {
1681 pub pubkey: String,
1682 pub signature: String,
1684}
1685
1686#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1687pub struct CheckMessageRequest {
1688 pub message: String,
1690 pub pubkey: String,
1692 pub signature: String,
1694}
1695
1696#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1697pub struct CheckMessageResponse {
1698 pub is_valid: bool,
1699}
1700
1701#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1702#[derive(Debug, Clone, Serialize)]
1703pub struct UserSettings {
1704 pub spark_private_mode_enabled: bool,
1705
1706 pub stable_balance_active_label: Option<String>,
1708}
1709
1710#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1711pub struct UpdateUserSettingsRequest {
1712 pub spark_private_mode_enabled: Option<bool>,
1713
1714 #[cfg_attr(feature = "uniffi", uniffi(default = None))]
1716 pub stable_balance_active_label: Option<StableBalanceActiveLabel>,
1717}
1718
1719#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1720pub struct ClaimHtlcPaymentRequest {
1721 pub preimage: String,
1722}
1723
1724#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1725pub struct ClaimHtlcPaymentResponse {
1726 pub payment: Payment,
1727}
1728
1729#[derive(Debug, Clone, Deserialize, Serialize)]
1730#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1731pub struct LnurlReceiveMetadata {
1732 pub nostr_zap_request: Option<String>,
1733 pub nostr_zap_receipt: Option<String>,
1734 pub sender_comment: Option<String>,
1735}
1736
1737#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1738pub struct OptimizationProgress {
1739 pub is_running: bool,
1740 pub current_round: u32,
1741 pub total_rounds: u32,
1742}
1743
1744#[derive(Debug, Clone, Serialize, Deserialize)]
1746#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1747pub struct Contact {
1748 pub id: String,
1749 pub name: String,
1750 pub payment_identifier: String,
1752 pub created_at: u64,
1753 pub updated_at: u64,
1754}
1755
1756#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1758pub struct AddContactRequest {
1759 pub name: String,
1760 pub payment_identifier: String,
1762}
1763
1764#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1766pub struct UpdateContactRequest {
1767 pub id: String,
1768 pub name: String,
1769 pub payment_identifier: String,
1771}
1772
1773#[derive(Debug, Clone, Default)]
1775#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1776pub struct ListContactsRequest {
1777 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1778 pub offset: Option<u32>,
1779 #[cfg_attr(feature = "uniffi", uniffi(default=None))]
1780 pub limit: Option<u32>,
1781}
1782
1783#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
1785#[allow(clippy::enum_variant_names)]
1786#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
1787pub enum WebhookEventType {
1788 LightningReceiveFinished,
1790 LightningSendFinished,
1792 CoopExitFinished,
1794 StaticDepositFinished,
1796 Unknown(String),
1798}
1799
1800#[derive(Debug, Clone, Serialize)]
1802#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1803pub struct Webhook {
1804 pub id: String,
1806 pub url: String,
1808 pub event_types: Vec<WebhookEventType>,
1810}
1811
1812#[derive(Debug, Clone)]
1814#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1815pub struct RegisterWebhookRequest {
1816 pub url: String,
1818 pub secret: String,
1820 pub event_types: Vec<WebhookEventType>,
1822}
1823
1824#[derive(Debug, Clone, Serialize)]
1826#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1827pub struct RegisterWebhookResponse {
1828 pub webhook_id: String,
1830}
1831
1832#[derive(Debug, Clone)]
1834#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
1835pub struct UnregisterWebhookRequest {
1836 pub webhook_id: String,
1838}