mirror of
https://github.com/aljazceru/cdk.git
synced 2025-12-22 15:14:51 +01:00
feat: try_sum for amounts
This commit is contained in:
@@ -51,13 +51,13 @@ impl JsSwapRequest {
|
||||
/// Proofs Amount
|
||||
#[wasm_bindgen(js_name = proofsAmount)]
|
||||
pub fn proofs_amount(&self) -> JsAmount {
|
||||
self.inner.input_amount().into()
|
||||
self.inner.input_amount().expect("Amount overflow").into()
|
||||
}
|
||||
|
||||
/// Output Amount
|
||||
#[wasm_bindgen(js_name = outputAmount)]
|
||||
pub fn output_amount(&self) -> JsAmount {
|
||||
self.inner.output_amount().into()
|
||||
self.inner.output_amount().expect("Amount overflow").into()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,6 +99,9 @@ impl JsSwapResponse {
|
||||
/// Promises Amount
|
||||
#[wasm_bindgen(js_name = promisesAmount)]
|
||||
pub fn promises_amount(&self) -> JsAmount {
|
||||
self.inner.promises_amount().into()
|
||||
self.inner
|
||||
.promises_amount()
|
||||
.expect("Amount overflow")
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ impl JsMintBolt11Request {
|
||||
|
||||
#[wasm_bindgen(js_name = totalAmount)]
|
||||
pub fn total_amount(&self) -> JsAmount {
|
||||
self.inner.total_amount().into()
|
||||
self.inner.total_amount().expect("Amount overflow").into()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -223,7 +223,10 @@ pub async fn post_melt_bolt11(
|
||||
}
|
||||
};
|
||||
|
||||
let inputs_amount_quote_unit = payload.proofs_amount();
|
||||
let inputs_amount_quote_unit = payload.proofs_amount().map_err(|_| {
|
||||
tracing::error!("Proof inputs in melt quote overflowed");
|
||||
into_response(Error::AmountOverflow)
|
||||
})?;
|
||||
|
||||
let (preimage, amount_spent_quote_unit) = match mint_quote {
|
||||
Some(mint_quote) => {
|
||||
|
||||
@@ -37,8 +37,7 @@ async fn attempt_to_swap_by_overflowing() -> Result<()> {
|
||||
sleep(Duration::from_secs(2)).await;
|
||||
}
|
||||
|
||||
let premint_secrets =
|
||||
PreMintSecrets::random(keyset_id.clone(), 1.into(), &SplitTarget::default())?;
|
||||
let premint_secrets = PreMintSecrets::random(keyset_id, 1.into(), &SplitTarget::default())?;
|
||||
|
||||
let mint_response = wallet_client
|
||||
.post_mint(
|
||||
@@ -60,12 +59,11 @@ async fn attempt_to_swap_by_overflowing() -> Result<()> {
|
||||
let amount = 2_u64.pow(63);
|
||||
|
||||
let pre_mint_amount =
|
||||
PreMintSecrets::random(keyset_id.clone(), amount.into(), &SplitTarget::default())?;
|
||||
PreMintSecrets::random(keyset_id, amount.into(), &SplitTarget::default())?;
|
||||
let pre_mint_amount_two =
|
||||
PreMintSecrets::random(keyset_id.clone(), amount.into(), &SplitTarget::default())?;
|
||||
PreMintSecrets::random(keyset_id, amount.into(), &SplitTarget::default())?;
|
||||
|
||||
let mut pre_mint =
|
||||
PreMintSecrets::random(keyset_id.clone(), 1.into(), &SplitTarget::default())?;
|
||||
let mut pre_mint = PreMintSecrets::random(keyset_id, 1.into(), &SplitTarget::default())?;
|
||||
|
||||
pre_mint.combine(pre_mint_amount);
|
||||
pre_mint.combine(pre_mint_amount_two);
|
||||
@@ -91,11 +89,11 @@ async fn attempt_to_swap_by_overflowing() -> Result<()> {
|
||||
|
||||
println!(
|
||||
"Pre swap amount: {:?}",
|
||||
pre_swap_proofs.iter().map(|p| p.amount).sum::<Amount>()
|
||||
Amount::try_sum(pre_swap_proofs.iter().map(|p| p.amount)).expect("Amount overflowed")
|
||||
);
|
||||
println!(
|
||||
"Post swap amount: {:?}",
|
||||
post_swap_proofs.iter().map(|p| p.amount).sum::<Amount>()
|
||||
Amount::try_sum(post_swap_proofs.iter().map(|p| p.amount)).expect("Amount Overflowed")
|
||||
);
|
||||
|
||||
println!(
|
||||
|
||||
@@ -54,7 +54,7 @@ impl Amount {
|
||||
parts.extend(amount_left.split());
|
||||
}
|
||||
|
||||
parts_total = parts.clone().iter().copied().sum::<Amount>();
|
||||
parts_total = Amount::try_sum(parts.clone().iter().copied())?;
|
||||
|
||||
if parts_total.eq(self) {
|
||||
break;
|
||||
@@ -65,7 +65,7 @@ impl Amount {
|
||||
parts
|
||||
}
|
||||
SplitTarget::Values(values) => {
|
||||
let values_total: Amount = values.clone().into_iter().sum();
|
||||
let values_total: Amount = Amount::try_sum(values.clone().into_iter())?;
|
||||
|
||||
match self.cmp(&values_total) {
|
||||
Ordering::Equal => values.clone(),
|
||||
@@ -190,15 +190,6 @@ impl std::ops::Div for Amount {
|
||||
}
|
||||
}
|
||||
|
||||
impl core::iter::Sum for Amount {
|
||||
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
|
||||
iter.fold(Amount::ZERO, |acc, x| {
|
||||
acc.checked_add(x)
|
||||
.unwrap_or_else(|| panic!("Addition overflow"))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Kinds of targeting that are supported
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Default, Serialize, Deserialize)]
|
||||
pub enum SplitTarget {
|
||||
@@ -314,7 +305,7 @@ mod tests {
|
||||
|
||||
let amounts = vec![amount_one, amount_two];
|
||||
|
||||
let _total: Amount = amounts.into_iter().sum();
|
||||
let _total: Amount = Amount::try_sum(amounts).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -20,6 +20,9 @@ pub enum Error {
|
||||
/// Amount is not what is expected
|
||||
#[error("Amount")]
|
||||
Amount,
|
||||
/// Amount overflow
|
||||
#[error("Amount Overflow")]
|
||||
AmountOverflow,
|
||||
/// Not engough inputs provided
|
||||
#[error("Inputs: `{0}`, Outputs: `{0}`, Fee: `{0}`")]
|
||||
InsufficientInputs(u64, u64, u64),
|
||||
@@ -89,6 +92,12 @@ pub enum Error {
|
||||
/// NUT00 Error
|
||||
#[error(transparent)]
|
||||
NUT00(#[from] crate::nuts::nut00::Error),
|
||||
/// NUT04 Error
|
||||
#[error(transparent)]
|
||||
NUT04(#[from] crate::nuts::nut04::Error),
|
||||
/// NUT05 Error
|
||||
#[error(transparent)]
|
||||
NUT05(#[from] crate::nuts::nut05::Error),
|
||||
/// NUT11 Error
|
||||
#[error(transparent)]
|
||||
NUT11(#[from] crate::nuts::nut11::Error),
|
||||
|
||||
@@ -705,13 +705,13 @@ impl Mint {
|
||||
return Err(Error::BlindedMessageAlreadySigned);
|
||||
}
|
||||
|
||||
let proofs_total = swap_request.input_amount();
|
||||
let proofs_total = swap_request.input_amount()?;
|
||||
|
||||
let output_total = swap_request.output_amount();
|
||||
let output_total = swap_request.output_amount()?;
|
||||
|
||||
let fee = self.get_proofs_fee(&swap_request.inputs).await?;
|
||||
|
||||
if proofs_total < output_total + fee {
|
||||
if proofs_total < output_total.checked_add(fee).ok_or(Error::AmountOverflow)? {
|
||||
tracing::info!(
|
||||
"Swap request without enough inputs: {}, outputs {}, fee {}",
|
||||
proofs_total,
|
||||
@@ -989,7 +989,7 @@ impl Mint {
|
||||
.await?
|
||||
.ok_or(Error::UnknownQuote)?;
|
||||
|
||||
let proofs_total = melt_request.proofs_amount();
|
||||
let proofs_total = melt_request.proofs_amount()?;
|
||||
|
||||
let fee = self.get_proofs_fee(&melt_request.inputs).await?;
|
||||
|
||||
@@ -1121,7 +1121,7 @@ impl Mint {
|
||||
let mut change = None;
|
||||
|
||||
// Check if there is change to return
|
||||
if melt_request.proofs_amount() > total_spent {
|
||||
if melt_request.proofs_amount()? > total_spent {
|
||||
// Check if wallet provided change outputs
|
||||
if let Some(outputs) = melt_request.outputs.clone() {
|
||||
let blinded_messages: Vec<PublicKey> =
|
||||
@@ -1141,7 +1141,7 @@ impl Mint {
|
||||
return Err(Error::BlindedMessageAlreadySigned);
|
||||
}
|
||||
|
||||
let change_target = melt_request.proofs_amount() - total_spent;
|
||||
let change_target = melt_request.proofs_amount()? - total_spent;
|
||||
let mut amounts = change_target.split();
|
||||
let mut change_sigs = Vec::with_capacity(amounts.len());
|
||||
|
||||
@@ -1271,7 +1271,7 @@ impl Mint {
|
||||
.get_blind_signatures_for_keyset(&keyset.id)
|
||||
.await?;
|
||||
|
||||
let total = blinded.iter().map(|b| b.amount).sum();
|
||||
let total = Amount::try_sum(blinded.iter().map(|b| b.amount))?;
|
||||
|
||||
total_issued.insert(keyset.id, total);
|
||||
}
|
||||
@@ -1289,14 +1289,13 @@ impl Mint {
|
||||
for keyset in keysets {
|
||||
let (proofs, state) = self.localstore.get_proofs_by_keyset_id(&keyset.id).await?;
|
||||
|
||||
let total_spent = proofs
|
||||
.iter()
|
||||
.zip(state)
|
||||
.filter_map(|(p, s)| match s == Some(State::Spent) {
|
||||
let total_spent =
|
||||
Amount::try_sum(proofs.iter().zip(state).filter_map(|(p, s)| {
|
||||
match s == Some(State::Spent) {
|
||||
true => Some(p.amount),
|
||||
false => None,
|
||||
})
|
||||
.sum();
|
||||
}
|
||||
}))?;
|
||||
|
||||
total_redeemed.insert(keyset.id, total_spent);
|
||||
}
|
||||
|
||||
@@ -609,11 +609,10 @@ impl PreMintSecrets {
|
||||
}
|
||||
|
||||
/// Totoal amount of secrets
|
||||
pub fn total_amount(&self) -> Amount {
|
||||
self.secrets
|
||||
.iter()
|
||||
.map(|PreMint { amount, .. }| *amount)
|
||||
.sum()
|
||||
pub fn total_amount(&self) -> Result<Amount, Error> {
|
||||
Ok(Amount::try_sum(
|
||||
self.secrets.iter().map(|PreMint { amount, .. }| *amount),
|
||||
)?)
|
||||
}
|
||||
|
||||
/// [`BlindedMessage`]s from [`PreMintSecrets`]
|
||||
|
||||
@@ -74,7 +74,7 @@ impl Token {
|
||||
}
|
||||
|
||||
/// Total value of [`Token`]
|
||||
pub fn value(&self) -> Amount {
|
||||
pub fn value(&self) -> Result<Amount, Error> {
|
||||
match self {
|
||||
Self::TokenV3(token) => token.value(),
|
||||
Self::TokenV4(token) => token.value(),
|
||||
@@ -207,11 +207,13 @@ impl TokenV3 {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn value(&self) -> Amount {
|
||||
fn value(&self) -> Result<Amount, Error> {
|
||||
Ok(Amount::try_sum(
|
||||
self.token
|
||||
.iter()
|
||||
.map(|t| t.proofs.iter().map(|p| p.amount).sum())
|
||||
.sum()
|
||||
.map(|t| Amount::try_sum(t.proofs.iter().map(|p| p.amount)))
|
||||
.collect::<Result<Vec<Amount>, _>>()?,
|
||||
)?)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -305,11 +307,13 @@ impl TokenV4 {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn value(&self) -> Amount {
|
||||
fn value(&self) -> Result<Amount, Error> {
|
||||
Ok(Amount::try_sum(
|
||||
self.token
|
||||
.iter()
|
||||
.map(|t| t.proofs.iter().map(|p| p.amount).sum())
|
||||
.sum()
|
||||
.map(|t| Amount::try_sum(t.proofs.iter().map(|p| p.amount)))
|
||||
.collect::<Result<Vec<Amount>, _>>()?,
|
||||
)?)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -464,7 +468,7 @@ mod tests {
|
||||
let token_str_multi_keysets = "cashuBo2F0gqJhaUgA_9SLj17PgGFwgaNhYQFhc3hAYWNjMTI0MzVlN2I4NDg0YzNjZjE4NTAxNDkyMThhZjkwZjcxNmE1MmJmNGE1ZWQzNDdlNDhlY2MxM2Y3NzM4OGFjWCECRFODGd5IXVW-07KaZCvuWHk3WrnnpiDhHki6SCQh88-iYWlIAK0mjE0fWCZhcIKjYWECYXN4QDEzMjNkM2Q0NzA3YTU4YWQyZTIzYWRhNGU5ZjFmNDlmNWE1YjRhYzdiNzA4ZWIwZDYxZjczOGY0ODMwN2U4ZWVhY1ghAjRWqhENhLSsdHrr2Cw7AFrKUL9Ffr1XN6RBT6w659lNo2FhAWFzeEA1NmJjYmNiYjdjYzY0MDZiM2ZhNWQ1N2QyMTc0ZjRlZmY4YjQ0MDJiMTc2OTI2ZDNhNTdkM2MzZGNiYjU5ZDU3YWNYIQJzEpxXGeWZN5qXSmJjY8MzxWyvwObQGr5G1YCCgHicY2FtdWh0dHA6Ly9sb2NhbGhvc3Q6MzMzOGF1Y3NhdA==";
|
||||
|
||||
let token = Token::from_str(token_str_multi_keysets).unwrap();
|
||||
let amount = token.value();
|
||||
let amount = token.value()?;
|
||||
|
||||
assert_eq!(amount, Amount::from(4));
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::nut00::{BlindSignature, BlindedMessage, PreMintSecrets, Proofs};
|
||||
use crate::Amount;
|
||||
use crate::{error::Error, Amount};
|
||||
|
||||
/// Preswap information
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
|
||||
@@ -36,13 +36,13 @@ impl SwapRequest {
|
||||
}
|
||||
|
||||
/// Total value of proofs in [`SwapRequest`]
|
||||
pub fn input_amount(&self) -> Amount {
|
||||
self.inputs.iter().map(|proof| proof.amount).sum()
|
||||
pub fn input_amount(&self) -> Result<Amount, Error> {
|
||||
Amount::try_sum(self.inputs.iter().map(|proof| proof.amount))
|
||||
}
|
||||
|
||||
/// Total value of outputs in [`SwapRequest`]
|
||||
pub fn output_amount(&self) -> Amount {
|
||||
self.outputs.iter().map(|proof| proof.amount).sum()
|
||||
pub fn output_amount(&self) -> Result<Amount, Error> {
|
||||
Amount::try_sum(self.outputs.iter().map(|proof| proof.amount))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,10 +62,11 @@ impl SwapResponse {
|
||||
}
|
||||
|
||||
/// Total [`Amount`] of promises
|
||||
pub fn promises_amount(&self) -> Amount {
|
||||
pub fn promises_amount(&self) -> Result<Amount, Error> {
|
||||
Amount::try_sum(
|
||||
self.signatures
|
||||
.iter()
|
||||
.map(|BlindSignature { amount, .. }| *amount)
|
||||
.sum()
|
||||
.map(|BlindSignature { amount, .. }| *amount),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,9 @@ pub enum Error {
|
||||
/// Unknown Quote State
|
||||
#[error("Unknown Quote State")]
|
||||
UnknownState,
|
||||
/// Amount overflow
|
||||
#[error("Amount overflow")]
|
||||
AmountOverflow,
|
||||
}
|
||||
|
||||
/// Mint quote request [NUT-04]
|
||||
@@ -179,11 +182,13 @@ pub struct MintBolt11Request {
|
||||
|
||||
impl MintBolt11Request {
|
||||
/// Total [`Amount`] of outputs
|
||||
pub fn total_amount(&self) -> Amount {
|
||||
pub fn total_amount(&self) -> Result<Amount, Error> {
|
||||
Amount::try_sum(
|
||||
self.outputs
|
||||
.iter()
|
||||
.map(|BlindedMessage { amount, .. }| *amount)
|
||||
.sum()
|
||||
.map(|BlindedMessage { amount, .. }| *amount),
|
||||
)
|
||||
.map_err(|_| Error::AmountOverflow)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,9 @@ pub enum Error {
|
||||
/// Unknown Quote State
|
||||
#[error("Unknown quote state")]
|
||||
UnknownState,
|
||||
/// Amount overflow
|
||||
#[error("Amount Overflow")]
|
||||
AmountOverflow,
|
||||
}
|
||||
|
||||
/// Melt quote request [NUT-05]
|
||||
@@ -210,8 +213,9 @@ pub struct MeltBolt11Request {
|
||||
|
||||
impl MeltBolt11Request {
|
||||
/// Total [`Amount`] of [`Proofs`]
|
||||
pub fn proofs_amount(&self) -> Amount {
|
||||
self.inputs.iter().map(|proof| proof.amount).sum()
|
||||
pub fn proofs_amount(&self) -> Result<Amount, Error> {
|
||||
Amount::try_sum(self.inputs.iter().map(|proof| proof.amount))
|
||||
.map_err(|_| Error::AmountOverflow)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ impl MeltBolt11Request {
|
||||
pub fn output_amount(&self) -> Option<Amount> {
|
||||
self.outputs
|
||||
.as_ref()
|
||||
.map(|o| o.iter().map(|proof| proof.amount).sum())
|
||||
.and_then(|o| Amount::try_sum(o.iter().map(|proof| proof.amount)).ok())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,6 @@ impl MeltQuoteBolt11Response {
|
||||
pub fn change_amount(&self) -> Option<Amount> {
|
||||
self.change
|
||||
.as_ref()
|
||||
.map(|c| c.iter().map(|b| b.amount).sum())
|
||||
.and_then(|o| Amount::try_sum(o.iter().map(|proof| proof.amount)).ok())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,9 @@ pub enum Error {
|
||||
/// Unknown Key
|
||||
#[error("Unknown key")]
|
||||
UnknownKey,
|
||||
/// Amount overflow
|
||||
#[error("Amount Overflow")]
|
||||
AmountOverflow,
|
||||
/// Spending Locktime not provided
|
||||
#[error("Spending condition locktime not provided")]
|
||||
LocktimeNotProvided,
|
||||
|
||||
@@ -145,7 +145,7 @@ impl Wallet {
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
let balance = proofs.iter().map(|p| p.proof.amount).sum::<Amount>();
|
||||
let balance = Amount::try_sum(proofs.iter().map(|p| p.proof.amount))?;
|
||||
|
||||
Ok(balance)
|
||||
}
|
||||
@@ -457,7 +457,7 @@ impl Wallet {
|
||||
.into_iter()
|
||||
.partition(|p| pending_states.contains(&p.y));
|
||||
|
||||
let amount = pending_proofs.iter().map(|p| p.proof.amount).sum();
|
||||
let amount = Amount::try_sum(pending_proofs.iter().map(|p| p.proof.amount))?;
|
||||
|
||||
self.localstore
|
||||
.update_proofs(
|
||||
@@ -678,7 +678,7 @@ impl Wallet {
|
||||
&keys,
|
||||
)?;
|
||||
|
||||
let minted_amount = proofs.iter().map(|p| p.amount).sum();
|
||||
let minted_amount = Amount::try_sum(proofs.iter().map(|p| p.amount))?;
|
||||
|
||||
// Remove filled quote from store
|
||||
self.localstore.remove_mint_quote("e_info.id).await?;
|
||||
@@ -754,7 +754,7 @@ impl Wallet {
|
||||
let mut values = Vec::new();
|
||||
|
||||
for amount in amounts_needed_refill {
|
||||
let values_sum: Amount = values.clone().into_iter().sum();
|
||||
let values_sum = Amount::try_sum(values.clone().into_iter())?;
|
||||
if values_sum + amount <= change_amount {
|
||||
values.push(amount);
|
||||
}
|
||||
@@ -776,7 +776,7 @@ impl Wallet {
|
||||
let active_keyset_id = self.get_active_mint_keyset().await?.id;
|
||||
|
||||
// Desired amount is either amount passed or value of all proof
|
||||
let proofs_total: Amount = proofs.iter().map(|p| p.amount).sum();
|
||||
let proofs_total = Amount::try_sum(proofs.iter().map(|p| p.amount))?;
|
||||
|
||||
let ys: Vec<PublicKey> = proofs.iter().map(|p| p.y()).collect::<Result<_, _>>()?;
|
||||
self.localstore.set_pending_proofs(ys).await?;
|
||||
@@ -953,7 +953,7 @@ impl Wallet {
|
||||
|
||||
for proof in all_proofs {
|
||||
let proofs_to_send_amount =
|
||||
proofs_to_send.iter().map(|p| p.amount).sum::<Amount>();
|
||||
Amount::try_sum(proofs_to_send.iter().map(|p| p.amount))?;
|
||||
if proof.amount + proofs_to_send_amount <= amount + pre_swap.fee {
|
||||
proofs_to_send.push(proof);
|
||||
} else {
|
||||
@@ -965,7 +965,7 @@ impl Wallet {
|
||||
}
|
||||
};
|
||||
|
||||
let send_amount: Amount = proofs_to_send.iter().map(|p| p.amount).sum();
|
||||
let send_amount = Amount::try_sum(proofs_to_send.iter().map(|p| p.amount))?;
|
||||
|
||||
if send_amount.ne(&(amount + pre_swap.fee)) {
|
||||
tracing::warn!(
|
||||
@@ -1158,7 +1158,7 @@ impl Wallet {
|
||||
// Handle exact matches offline
|
||||
(SendKind::OfflineExact, Ok(selected_proofs), _) => {
|
||||
let selected_proofs_amount =
|
||||
selected_proofs.iter().map(|p| p.amount).sum::<Amount>();
|
||||
Amount::try_sum(selected_proofs.iter().map(|p| p.amount))?;
|
||||
|
||||
let amount_to_send = match include_fees {
|
||||
true => amount + self.get_proofs_fee(&selected_proofs).await?,
|
||||
@@ -1175,7 +1175,7 @@ impl Wallet {
|
||||
// Handle exact matches
|
||||
(SendKind::OnlineExact, Ok(selected_proofs), _) => {
|
||||
let selected_proofs_amount =
|
||||
selected_proofs.iter().map(|p| p.amount).sum::<Amount>();
|
||||
Amount::try_sum(selected_proofs.iter().map(|p| p.amount))?;
|
||||
|
||||
let amount_to_send = match include_fees {
|
||||
true => amount + self.get_proofs_fee(&selected_proofs).await?,
|
||||
@@ -1196,7 +1196,7 @@ impl Wallet {
|
||||
// Handle offline tolerance
|
||||
(SendKind::OfflineTolerance(tolerance), Ok(selected_proofs), _) => {
|
||||
let selected_proofs_amount =
|
||||
selected_proofs.iter().map(|p| p.amount).sum::<Amount>();
|
||||
Amount::try_sum(selected_proofs.iter().map(|p| p.amount))?;
|
||||
|
||||
let amount_to_send = match include_fees {
|
||||
true => amount + self.get_proofs_fee(&selected_proofs).await?,
|
||||
@@ -1222,7 +1222,7 @@ impl Wallet {
|
||||
// Handle online tolerance with successful selection
|
||||
(SendKind::OnlineTolerance(tolerance), Ok(selected_proofs), _) => {
|
||||
let selected_proofs_amount =
|
||||
selected_proofs.iter().map(|p| p.amount).sum::<Amount>();
|
||||
Amount::try_sum(selected_proofs.iter().map(|p| p.amount))?;
|
||||
let amount_to_send = match include_fees {
|
||||
true => amount + self.get_proofs_fee(&selected_proofs).await?,
|
||||
false => amount,
|
||||
@@ -1435,7 +1435,7 @@ impl Wallet {
|
||||
Some(change_proofs) => {
|
||||
tracing::debug!(
|
||||
"Change amount returned from melt: {}",
|
||||
change_proofs.iter().map(|p| p.amount).sum::<Amount>()
|
||||
Amount::try_sum(change_proofs.iter().map(|p| p.amount))?
|
||||
);
|
||||
|
||||
// Update counter for keyset
|
||||
@@ -1532,7 +1532,7 @@ impl Wallet {
|
||||
) -> Result<Proofs, Error> {
|
||||
// TODO: Check all proofs are same unit
|
||||
|
||||
if proofs.iter().map(|p| p.amount).sum::<Amount>() < amount {
|
||||
if Amount::try_sum(proofs.iter().map(|p| p.amount))? < amount {
|
||||
return Err(Error::InsufficientFunds);
|
||||
}
|
||||
|
||||
@@ -1571,8 +1571,8 @@ impl Wallet {
|
||||
break;
|
||||
}
|
||||
|
||||
remaining_amount =
|
||||
amount + fees - selected_proofs.iter().map(|p| p.amount).sum::<Amount>();
|
||||
remaining_amount = amount.checked_add(fees).ok_or(Error::AmountOverflow)?
|
||||
- Amount::try_sum(selected_proofs.iter().map(|p| p.amount))?;
|
||||
(proofs_larger, proofs_smaller) = proofs_smaller
|
||||
.into_iter()
|
||||
.skip(1)
|
||||
@@ -1608,7 +1608,7 @@ impl Wallet {
|
||||
|
||||
for inactive_proof in inactive_proofs {
|
||||
selected_proofs.push(inactive_proof);
|
||||
let selected_total = selected_proofs.iter().map(|p| p.amount).sum::<Amount>();
|
||||
let selected_total = Amount::try_sum(selected_proofs.iter().map(|p| p.amount))?;
|
||||
let fees = self.get_proofs_fee(&selected_proofs).await?;
|
||||
|
||||
if selected_total >= amount + fees {
|
||||
@@ -1620,7 +1620,7 @@ impl Wallet {
|
||||
|
||||
for active_proof in active_proofs {
|
||||
selected_proofs.push(active_proof);
|
||||
let selected_total = selected_proofs.iter().map(|p| p.amount).sum::<Amount>();
|
||||
let selected_total = Amount::try_sum(selected_proofs.iter().map(|p| p.amount))?;
|
||||
let fees = self.get_proofs_fee(&selected_proofs).await?;
|
||||
|
||||
if selected_total >= amount + fees {
|
||||
@@ -1767,7 +1767,7 @@ impl Wallet {
|
||||
|
||||
let mut total_amount = Amount::ZERO;
|
||||
for (mint, proofs) in received_proofs {
|
||||
total_amount += proofs.iter().map(|p| p.amount).sum();
|
||||
total_amount += Amount::try_sum(proofs.iter().map(|p| p.amount))?;
|
||||
let proofs = proofs
|
||||
.into_iter()
|
||||
.map(|proof| ProofInfo::new(proof, mint.clone(), State::Unspent, self.unit))
|
||||
@@ -1927,7 +1927,7 @@ impl Wallet {
|
||||
.cloned()
|
||||
.collect();
|
||||
|
||||
restored_value += unspent_proofs.iter().map(|p| p.amount).sum();
|
||||
restored_value += Amount::try_sum(unspent_proofs.iter().map(|p| p.amount))?;
|
||||
|
||||
let unspent_proofs = unspent_proofs
|
||||
.into_iter()
|
||||
|
||||
Reference in New Issue
Block a user