mirror of
https://github.com/aljazceru/cdk.git
synced 2026-01-12 09:25:57 +01:00
refactor: use TargetAmount
This commit is contained in:
@@ -2,6 +2,7 @@ use std::ops::Deref;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use cdk::amount::SplitTarget;
|
||||
use cdk::nuts::{Proofs, SecretKey};
|
||||
use cdk::url::UncheckedUrl;
|
||||
use cdk::wallet::Wallet;
|
||||
@@ -146,12 +147,20 @@ impl JsWallet {
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = mint)]
|
||||
pub async fn mint(&mut self, mint_url: String, quote_id: String) -> Result<JsAmount> {
|
||||
pub async fn mint(
|
||||
&mut self,
|
||||
mint_url: String,
|
||||
quote_id: String,
|
||||
split_target_amount: Option<JsAmount>,
|
||||
) -> Result<JsAmount> {
|
||||
let target = split_target_amount
|
||||
.map(|a| SplitTarget::Value(*a.deref()))
|
||||
.unwrap_or_default();
|
||||
let mint_url = UncheckedUrl::from_str(&mint_url).map_err(into_err)?;
|
||||
|
||||
Ok(self
|
||||
.inner
|
||||
.mint(mint_url, "e_id)
|
||||
.mint(mint_url, "e_id, target)
|
||||
.await
|
||||
.map_err(into_err)?
|
||||
.into())
|
||||
@@ -192,12 +201,20 @@ impl JsWallet {
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = melt)]
|
||||
pub async fn melt(&mut self, mint_url: String, quote_id: String) -> Result<JsMelted> {
|
||||
pub async fn melt(
|
||||
&mut self,
|
||||
mint_url: String,
|
||||
quote_id: String,
|
||||
split_target_amount: Option<JsAmount>,
|
||||
) -> Result<JsMelted> {
|
||||
let target = split_target_amount
|
||||
.map(|a| SplitTarget::Value(*a.deref()))
|
||||
.unwrap_or_default();
|
||||
let mint_url = UncheckedUrl::from_str(&mint_url).map_err(into_err)?;
|
||||
|
||||
let melted = self
|
||||
.inner
|
||||
.melt(&mint_url, "e_id)
|
||||
.melt(&mint_url, "e_id, target)
|
||||
.await
|
||||
.map_err(into_err)?;
|
||||
|
||||
@@ -216,12 +233,18 @@ impl JsWallet {
|
||||
|
||||
Ok(self
|
||||
.inner
|
||||
.receive(&encoded_token, None, signing_keys, preimages)
|
||||
.receive(
|
||||
&encoded_token,
|
||||
&SplitTarget::default(),
|
||||
signing_keys,
|
||||
preimages,
|
||||
)
|
||||
.await
|
||||
.map_err(into_err)?
|
||||
.into())
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
#[wasm_bindgen(js_name = send)]
|
||||
pub async fn send(
|
||||
&mut self,
|
||||
@@ -231,6 +254,7 @@ impl JsWallet {
|
||||
amount: u64,
|
||||
p2pk_condition: Option<JsP2PKSpendingConditions>,
|
||||
htlc_condition: Option<JsHTLCSpendingConditions>,
|
||||
split_target_amount: Option<JsAmount>,
|
||||
) -> Result<String> {
|
||||
let conditions = match (p2pk_condition, htlc_condition) {
|
||||
(Some(_), Some(_)) => {
|
||||
@@ -245,19 +269,23 @@ impl JsWallet {
|
||||
|
||||
let mint_url = UncheckedUrl::from_str(&mint_url).map_err(into_err)?;
|
||||
|
||||
let target = split_target_amount
|
||||
.map(|a| SplitTarget::Value(*a.deref()))
|
||||
.unwrap_or_default();
|
||||
self.inner
|
||||
.send(
|
||||
&mint_url,
|
||||
&unit.into(),
|
||||
memo,
|
||||
Amount::from(amount),
|
||||
None,
|
||||
&target,
|
||||
conditions,
|
||||
)
|
||||
.await
|
||||
.map_err(into_err)
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
#[wasm_bindgen(js_name = swap)]
|
||||
pub async fn swap(
|
||||
&mut self,
|
||||
@@ -267,6 +295,7 @@ impl JsWallet {
|
||||
input_proofs: Vec<JsProof>,
|
||||
p2pk_condition: Option<JsP2PKSpendingConditions>,
|
||||
htlc_condition: Option<JsHTLCSpendingConditions>,
|
||||
split_target_amount: Option<JsAmount>,
|
||||
) -> Result<JsValue> {
|
||||
let conditions = match (p2pk_condition, htlc_condition) {
|
||||
(Some(_), Some(_)) => {
|
||||
@@ -283,13 +312,16 @@ impl JsWallet {
|
||||
|
||||
let proofs: Proofs = input_proofs.iter().map(|p| p.deref()).cloned().collect();
|
||||
|
||||
let target = split_target_amount
|
||||
.map(|a| SplitTarget::Value(*a.deref()))
|
||||
.unwrap_or_default();
|
||||
let post_swap_proofs = self
|
||||
.inner
|
||||
.swap(
|
||||
&mint_url,
|
||||
&unit.into(),
|
||||
Some(Amount::from(amount)),
|
||||
None,
|
||||
&target,
|
||||
proofs,
|
||||
conditions,
|
||||
)
|
||||
|
||||
@@ -24,18 +24,16 @@ impl Amount {
|
||||
|
||||
/// Split into parts that are powers of two by target
|
||||
pub fn split_targeted(&self, target: &SplitTarget) -> Vec<Self> {
|
||||
let mut parts = vec![];
|
||||
let mut parts_total = Amount::ZERO;
|
||||
|
||||
match *target {
|
||||
SplitTarget::None => {
|
||||
parts = self.split();
|
||||
}
|
||||
let mut parts = match *target {
|
||||
SplitTarget::None => self.split(),
|
||||
SplitTarget::Value(amount) => {
|
||||
if self.le(&amount) {
|
||||
return self.split();
|
||||
}
|
||||
|
||||
let mut parts_total = Amount::ZERO;
|
||||
let mut parts = Vec::new();
|
||||
|
||||
// The powers of two that are need to create target value
|
||||
let parts_of_value = amount.split();
|
||||
|
||||
@@ -55,8 +53,10 @@ impl Amount {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parts
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
parts.sort();
|
||||
parts
|
||||
@@ -68,10 +68,10 @@ impl Amount {
|
||||
Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default, Serialize, Deserialize,
|
||||
)]
|
||||
pub enum SplitTarget {
|
||||
/// Default target least amount of proofs
|
||||
/// Default target; least amount of proofs
|
||||
#[default]
|
||||
None,
|
||||
/// Tagrget amount for wallet to have most proofs that add up to value
|
||||
/// Target amount for wallet to have most proofs that add up to value
|
||||
Value(Amount),
|
||||
}
|
||||
|
||||
|
||||
@@ -356,8 +356,12 @@ pub struct PreMintSecrets {
|
||||
|
||||
impl PreMintSecrets {
|
||||
/// Outputs for speceifed amount with random secret
|
||||
pub fn random(keyset_id: Id, amount: Amount) -> Result<Self, Error> {
|
||||
let amount_split = amount.split();
|
||||
pub fn random(
|
||||
keyset_id: Id,
|
||||
amount: Amount,
|
||||
amount_split_target: &SplitTarget,
|
||||
) -> Result<Self, Error> {
|
||||
let amount_split = amount.split_targeted(amount_split_target);
|
||||
|
||||
let mut output = Vec::with_capacity(amount_split.len());
|
||||
|
||||
@@ -427,10 +431,10 @@ impl PreMintSecrets {
|
||||
pub fn with_conditions(
|
||||
keyset_id: Id,
|
||||
amount: Amount,
|
||||
amount_split_target: SplitTarget,
|
||||
amount_split_target: &SplitTarget,
|
||||
conditions: SpendingConditions,
|
||||
) -> Result<Self, Error> {
|
||||
let amount_split = amount.split_targeted(&amount_split_target);
|
||||
let amount_split = amount.split_targeted(amount_split_target);
|
||||
|
||||
let mut output = Vec::with_capacity(amount_split.len());
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ use bitcoin::bip32::{ChildNumber, DerivationPath, ExtendedPrivKey};
|
||||
use super::nut00::{BlindedMessage, PreMint, PreMintSecrets};
|
||||
use super::nut01::SecretKey;
|
||||
use super::nut02::Id;
|
||||
use crate::amount::SplitTarget;
|
||||
use crate::dhke::blind_message;
|
||||
use crate::error::Error;
|
||||
use crate::secret::Secret;
|
||||
@@ -46,12 +47,13 @@ impl PreMintSecrets {
|
||||
xpriv: ExtendedPrivKey,
|
||||
amount: Amount,
|
||||
zero_amount: bool,
|
||||
amount_split_target: &SplitTarget,
|
||||
) -> Result<Self, Error> {
|
||||
let mut pre_mint_secrets = PreMintSecrets::default();
|
||||
|
||||
let mut counter = counter;
|
||||
|
||||
for amount in amount.split() {
|
||||
for amount in amount.split_targeted(amount_split_target) {
|
||||
let secret = Secret::from_xpriv(xpriv, keyset_id, counter)?;
|
||||
let blinding_factor = SecretKey::from_xpriv(xpriv, keyset_id, counter)?;
|
||||
|
||||
|
||||
@@ -444,7 +444,9 @@ impl Wallet {
|
||||
.await?;
|
||||
|
||||
if mint_quote_response.paid {
|
||||
let amount = self.mint(mint_quote.mint_url, &mint_quote.id).await?;
|
||||
let amount = self
|
||||
.mint(mint_quote.mint_url, &mint_quote.id, SplitTarget::default())
|
||||
.await?;
|
||||
total_amount += amount;
|
||||
} else if mint_quote.expiry.le(&unix_time()) {
|
||||
self.localstore.remove_mint_quote(&mint_quote.id).await?;
|
||||
@@ -511,7 +513,12 @@ impl Wallet {
|
||||
|
||||
/// Mint
|
||||
#[instrument(skip(self, quote_id), fields(mint_url = %mint_url))]
|
||||
pub async fn mint(&self, mint_url: UncheckedUrl, quote_id: &str) -> Result<Amount, Error> {
|
||||
pub async fn mint(
|
||||
&self,
|
||||
mint_url: UncheckedUrl,
|
||||
quote_id: &str,
|
||||
amount_split_target: SplitTarget,
|
||||
) -> Result<Amount, Error> {
|
||||
// Check that mint is in store of mints
|
||||
if self.localstore.get_mint(mint_url.clone()).await?.is_none() {
|
||||
self.add_mint(mint_url.clone()).await?;
|
||||
@@ -544,6 +551,7 @@ impl Wallet {
|
||||
self.xpriv,
|
||||
quote_info.amount,
|
||||
false,
|
||||
&amount_split_target,
|
||||
)?;
|
||||
|
||||
let mint_res = self
|
||||
@@ -599,7 +607,7 @@ impl Wallet {
|
||||
mint_url: &UncheckedUrl,
|
||||
unit: &CurrencyUnit,
|
||||
amount: Option<Amount>,
|
||||
amount_split_target: Option<SplitTarget>,
|
||||
amount_split_target: &SplitTarget,
|
||||
input_proofs: Proofs,
|
||||
spending_conditions: Option<SpendingConditions>,
|
||||
) -> Result<Option<Proofs>, Error> {
|
||||
@@ -706,7 +714,7 @@ impl Wallet {
|
||||
mint_url: &UncheckedUrl,
|
||||
unit: &CurrencyUnit,
|
||||
amount: Option<Amount>,
|
||||
amount_split_target: Option<SplitTarget>,
|
||||
amount_split_target: &SplitTarget,
|
||||
proofs: Proofs,
|
||||
spending_conditions: Option<SpendingConditions>,
|
||||
) -> Result<PreSwap, Error> {
|
||||
@@ -733,13 +741,14 @@ impl Wallet {
|
||||
self.xpriv,
|
||||
change_amount,
|
||||
false,
|
||||
amount_split_target,
|
||||
)?;
|
||||
|
||||
(
|
||||
PreMintSecrets::with_conditions(
|
||||
active_keyset_id,
|
||||
desired_amount,
|
||||
amount_split_target.unwrap_or_default(),
|
||||
amount_split_target,
|
||||
conditions,
|
||||
)?,
|
||||
change_premint_secrets,
|
||||
@@ -759,6 +768,7 @@ impl Wallet {
|
||||
self.xpriv,
|
||||
desired_amount,
|
||||
false,
|
||||
amount_split_target,
|
||||
)?;
|
||||
|
||||
count += premint_secrets.len() as u32;
|
||||
@@ -769,6 +779,7 @@ impl Wallet {
|
||||
self.xpriv,
|
||||
change_amount,
|
||||
false,
|
||||
amount_split_target,
|
||||
)?;
|
||||
|
||||
(premint_secrets, change_premint_secrets)
|
||||
@@ -796,7 +807,7 @@ impl Wallet {
|
||||
unit: &CurrencyUnit,
|
||||
memo: Option<String>,
|
||||
amount: Amount,
|
||||
amount_split_target: Option<SplitTarget>,
|
||||
amount_split_target: &SplitTarget,
|
||||
conditions: Option<SpendingConditions>,
|
||||
) -> Result<String, Error> {
|
||||
let input_proofs = self.select_proofs(mint_url.clone(), unit, amount).await?;
|
||||
@@ -955,7 +966,12 @@ impl Wallet {
|
||||
|
||||
/// Melt
|
||||
#[instrument(skip(self, quote_id), fields(mint_url = %mint_url))]
|
||||
pub async fn melt(&mut self, mint_url: &UncheckedUrl, quote_id: &str) -> Result<Melted, Error> {
|
||||
pub async fn melt(
|
||||
&mut self,
|
||||
mint_url: &UncheckedUrl,
|
||||
quote_id: &str,
|
||||
amount_split_target: SplitTarget,
|
||||
) -> Result<Melted, Error> {
|
||||
let quote_info = self.localstore.get_melt_quote(quote_id).await?;
|
||||
|
||||
let quote_info = if let Some(quote) = quote_info {
|
||||
@@ -983,8 +999,14 @@ impl Wallet {
|
||||
|
||||
let count = count.map_or(0, |c| c + 1);
|
||||
|
||||
let premint_secrets =
|
||||
PreMintSecrets::from_xpriv(active_keyset_id, count, self.xpriv, proofs_amount, true)?;
|
||||
let premint_secrets = PreMintSecrets::from_xpriv(
|
||||
active_keyset_id,
|
||||
count,
|
||||
self.xpriv,
|
||||
proofs_amount,
|
||||
true,
|
||||
&amount_split_target,
|
||||
)?;
|
||||
|
||||
let melt_response = self
|
||||
.client
|
||||
@@ -1045,7 +1067,7 @@ impl Wallet {
|
||||
pub async fn receive(
|
||||
&self,
|
||||
encoded_token: &str,
|
||||
amount_split_target: Option<SplitTarget>,
|
||||
amount_split_target: &SplitTarget,
|
||||
signing_keys: Option<Vec<SecretKey>>,
|
||||
preimages: Option<Vec<String>>,
|
||||
) -> Result<Amount, Error> {
|
||||
@@ -1198,7 +1220,7 @@ impl Wallet {
|
||||
pub async fn nostr_receive(
|
||||
&self,
|
||||
nostr_signing_key: SecretKey,
|
||||
amount_split_target: Option<SplitTarget>,
|
||||
amount_split_target: SplitTarget,
|
||||
) -> Result<Amount, Error> {
|
||||
use nostr_sdk::{Keys, Kind};
|
||||
|
||||
@@ -1247,7 +1269,7 @@ impl Wallet {
|
||||
match self
|
||||
.receive(
|
||||
token,
|
||||
amount_split_target,
|
||||
&amount_split_target,
|
||||
Some(vec![nostr_signing_key.clone()]),
|
||||
None,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user