1use cdk::nuts::CurrencyUnit as CdkCurrencyUnit;
4use cdk::Amount as CdkAmount;
5use serde::{Deserialize, Serialize};
6
7use crate::error::FfiError;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, uniffi::Record)]
11#[serde(transparent)]
12pub struct Amount {
13 pub value: u64,
14}
15
16impl Amount {
17 pub fn new(value: u64) -> Self {
18 Self { value }
19 }
20
21 pub fn zero() -> Self {
22 Self { value: 0 }
23 }
24
25 pub fn is_zero(&self) -> bool {
26 self.value == 0
27 }
28
29 pub fn convert_unit(
30 &self,
31 current_unit: CurrencyUnit,
32 target_unit: CurrencyUnit,
33 ) -> Result<Amount, FfiError> {
34 Ok(CdkAmount::from(self.value)
35 .convert_unit(¤t_unit.into(), &target_unit.into())
36 .map(Into::into)?)
37 }
38
39 pub fn add(&self, other: Amount) -> Result<Amount, FfiError> {
40 let self_amount = CdkAmount::from(self.value);
41 let other_amount = CdkAmount::from(other.value);
42 self_amount
43 .checked_add(other_amount)
44 .map(Into::into)
45 .ok_or_else(|| FfiError::internal("Amount overflow"))
46 }
47
48 pub fn subtract(&self, other: Amount) -> Result<Amount, FfiError> {
49 let self_amount = CdkAmount::from(self.value);
50 let other_amount = CdkAmount::from(other.value);
51 self_amount
52 .checked_sub(other_amount)
53 .map(Into::into)
54 .ok_or_else(|| FfiError::internal("Amount overflow"))
55 }
56
57 pub fn multiply(&self, factor: u64) -> Result<Amount, FfiError> {
58 let self_amount = CdkAmount::from(self.value);
59 let factor_amount = CdkAmount::from(factor);
60 self_amount
61 .checked_mul(factor_amount)
62 .map(Into::into)
63 .ok_or_else(|| FfiError::internal("Amount overflow"))
64 }
65
66 pub fn divide(&self, divisor: u64) -> Result<Amount, FfiError> {
67 if divisor == 0 {
68 return Err(FfiError::internal("Division by zero"));
69 }
70 let self_amount = CdkAmount::from(self.value);
71 let divisor_amount = CdkAmount::from(divisor);
72 self_amount
73 .checked_div(divisor_amount)
74 .map(Into::into)
75 .ok_or_else(|| FfiError::internal("Amount overflow"))
76 }
77}
78
79impl From<CdkAmount> for Amount {
80 fn from(amount: CdkAmount) -> Self {
81 Self {
82 value: u64::from(amount),
83 }
84 }
85}
86
87impl From<Amount> for CdkAmount {
88 fn from(amount: Amount) -> Self {
89 CdkAmount::from(amount.value)
90 }
91}
92
93#[derive(Debug, Clone, Serialize, Deserialize, uniffi::Record)]
95pub struct FeeAndAmounts {
96 pub fee: u64,
98 pub amounts: Vec<u64>,
100}
101
102impl From<cdk_common::amount::FeeAndAmounts> for FeeAndAmounts {
103 fn from(fa: cdk_common::amount::FeeAndAmounts) -> Self {
104 Self {
105 fee: fa.fee(),
106 amounts: fa.amounts().to_vec(),
107 }
108 }
109}
110
111#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, uniffi::Enum)]
113pub enum CurrencyUnit {
114 Sat,
115 Msat,
116 Usd,
117 Eur,
118 Auth,
119 Custom { unit: String },
120}
121
122impl From<CdkCurrencyUnit> for CurrencyUnit {
123 fn from(unit: CdkCurrencyUnit) -> Self {
124 match unit {
125 CdkCurrencyUnit::Sat => CurrencyUnit::Sat,
126 CdkCurrencyUnit::Msat => CurrencyUnit::Msat,
127 CdkCurrencyUnit::Usd => CurrencyUnit::Usd,
128 CdkCurrencyUnit::Eur => CurrencyUnit::Eur,
129 CdkCurrencyUnit::Auth => CurrencyUnit::Auth,
130 CdkCurrencyUnit::Custom(s) => CurrencyUnit::Custom { unit: s },
131 _ => CurrencyUnit::Sat, }
133 }
134}
135
136impl From<CurrencyUnit> for CdkCurrencyUnit {
137 fn from(unit: CurrencyUnit) -> Self {
138 match unit {
139 CurrencyUnit::Sat => CdkCurrencyUnit::Sat,
140 CurrencyUnit::Msat => CdkCurrencyUnit::Msat,
141 CurrencyUnit::Usd => CdkCurrencyUnit::Usd,
142 CurrencyUnit::Eur => CdkCurrencyUnit::Eur,
143 CurrencyUnit::Auth => CdkCurrencyUnit::Auth,
144 CurrencyUnit::Custom { unit } => CdkCurrencyUnit::Custom(unit),
145 }
146 }
147}
148
149#[derive(Debug, Clone, Serialize, Deserialize, uniffi::Enum)]
151pub enum SplitTarget {
152 None,
154 Value { amount: Amount },
156 Values { amounts: Vec<Amount> },
158}
159
160impl From<SplitTarget> for cdk::amount::SplitTarget {
161 fn from(target: SplitTarget) -> Self {
162 match target {
163 SplitTarget::None => cdk::amount::SplitTarget::None,
164 SplitTarget::Value { amount } => cdk::amount::SplitTarget::Value(amount.into()),
165 SplitTarget::Values { amounts } => {
166 cdk::amount::SplitTarget::Values(amounts.into_iter().map(Into::into).collect())
167 }
168 }
169 }
170}
171
172impl From<cdk::amount::SplitTarget> for SplitTarget {
173 fn from(target: cdk::amount::SplitTarget) -> Self {
174 match target {
175 cdk::amount::SplitTarget::None => SplitTarget::None,
176 cdk::amount::SplitTarget::Value(amount) => SplitTarget::Value {
177 amount: amount.into(),
178 },
179 cdk::amount::SplitTarget::Values(amounts) => SplitTarget::Values {
180 amounts: amounts.into_iter().map(Into::into).collect(),
181 },
182 }
183 }
184}