refactor: use TargetAmount

This commit is contained in:
thesimplekid
2024-05-26 21:33:03 +01:00
parent ea17895478
commit 0dce83bbb7
5 changed files with 94 additions and 34 deletions

View File

@@ -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, &quote_id)
.mint(mint_url, &quote_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, &quote_id)
.melt(&mint_url, &quote_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,
)

View File

@@ -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),
}

View File

@@ -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());

View File

@@ -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)?;

View File

@@ -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,
)