use cdk::nuts::CurrencyUnit as CdkCurrencyUnit;
use cdk::Amount as CdkAmount;
use serde::{Deserialize, Serialize};
use crate::error::FfiError;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, uniffi::Record)]
#[serde(transparent)]
pub struct Amount {
pub value: u64,
}
impl Amount {
pub fn new(value: u64) -> Self {
Self { value }
}
pub fn zero() -> Self {
Self { value: 0 }
}
pub fn is_zero(&self) -> bool {
self.value == 0
}
pub fn convert_unit(
&self,
current_unit: CurrencyUnit,
target_unit: CurrencyUnit,
) -> Result<Amount, FfiError> {
Ok(CdkAmount::from(self.value)
.convert_unit(¤t_unit.into(), &target_unit.into())
.map(Into::into)?)
}
pub fn add(&self, other: Amount) -> Result<Amount, FfiError> {
let self_amount = CdkAmount::from(self.value);
let other_amount = CdkAmount::from(other.value);
self_amount
.checked_add(other_amount)
.map(Into::into)
.ok_or_else(|| FfiError::internal("Amount overflow"))
}
pub fn subtract(&self, other: Amount) -> Result<Amount, FfiError> {
let self_amount = CdkAmount::from(self.value);
let other_amount = CdkAmount::from(other.value);
self_amount
.checked_sub(other_amount)
.map(Into::into)
.ok_or_else(|| FfiError::internal("Amount overflow"))
}
pub fn multiply(&self, factor: u64) -> Result<Amount, FfiError> {
let self_amount = CdkAmount::from(self.value);
let factor_amount = CdkAmount::from(factor);
self_amount
.checked_mul(factor_amount)
.map(Into::into)
.ok_or_else(|| FfiError::internal("Amount overflow"))
}
pub fn divide(&self, divisor: u64) -> Result<Amount, FfiError> {
if divisor == 0 {
return Err(FfiError::internal("Division by zero"));
}
let self_amount = CdkAmount::from(self.value);
let divisor_amount = CdkAmount::from(divisor);
self_amount
.checked_div(divisor_amount)
.map(Into::into)
.ok_or_else(|| FfiError::internal("Amount overflow"))
}
}
impl From<CdkAmount> for Amount {
fn from(amount: CdkAmount) -> Self {
Self {
value: u64::from(amount),
}
}
}
impl From<Amount> for CdkAmount {
fn from(amount: Amount) -> Self {
CdkAmount::from(amount.value)
}
}
#[derive(Debug, Clone, Serialize, Deserialize, uniffi::Record)]
pub struct FeeAndAmounts {
pub fee: u64,
pub amounts: Vec<u64>,
}
impl From<cdk_common::amount::FeeAndAmounts> for FeeAndAmounts {
fn from(fa: cdk_common::amount::FeeAndAmounts) -> Self {
Self {
fee: fa.fee(),
amounts: fa.amounts().to_vec(),
}
}
}
#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, uniffi::Enum)]
pub enum CurrencyUnit {
Sat,
Msat,
Usd,
Eur,
Auth,
Custom { unit: String },
}
impl From<CdkCurrencyUnit> for CurrencyUnit {
fn from(unit: CdkCurrencyUnit) -> Self {
match unit {
CdkCurrencyUnit::Sat => CurrencyUnit::Sat,
CdkCurrencyUnit::Msat => CurrencyUnit::Msat,
CdkCurrencyUnit::Usd => CurrencyUnit::Usd,
CdkCurrencyUnit::Eur => CurrencyUnit::Eur,
CdkCurrencyUnit::Auth => CurrencyUnit::Auth,
CdkCurrencyUnit::Custom(s) => CurrencyUnit::Custom { unit: s },
_ => CurrencyUnit::Sat, }
}
}
impl From<CurrencyUnit> for CdkCurrencyUnit {
fn from(unit: CurrencyUnit) -> Self {
match unit {
CurrencyUnit::Sat => CdkCurrencyUnit::Sat,
CurrencyUnit::Msat => CdkCurrencyUnit::Msat,
CurrencyUnit::Usd => CdkCurrencyUnit::Usd,
CurrencyUnit::Eur => CdkCurrencyUnit::Eur,
CurrencyUnit::Auth => CdkCurrencyUnit::Auth,
CurrencyUnit::Custom { unit } => CdkCurrencyUnit::Custom(unit),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, uniffi::Enum)]
pub enum SplitTarget {
None,
Value { amount: Amount },
Values { amounts: Vec<Amount> },
}
impl From<SplitTarget> for cdk::amount::SplitTarget {
fn from(target: SplitTarget) -> Self {
match target {
SplitTarget::None => cdk::amount::SplitTarget::None,
SplitTarget::Value { amount } => cdk::amount::SplitTarget::Value(amount.into()),
SplitTarget::Values { amounts } => {
cdk::amount::SplitTarget::Values(amounts.into_iter().map(Into::into).collect())
}
}
}
}
impl From<cdk::amount::SplitTarget> for SplitTarget {
fn from(target: cdk::amount::SplitTarget) -> Self {
match target {
cdk::amount::SplitTarget::None => SplitTarget::None,
cdk::amount::SplitTarget::Value(amount) => SplitTarget::Value {
amount: amount.into(),
},
cdk::amount::SplitTarget::Values(amounts) => SplitTarget::Values {
amounts: amounts.into_iter().map(Into::into).collect(),
},
}
}
}