Skip to content

Commit

Permalink
Round amounts to 1 satoshi.
Browse files Browse the repository at this point in the history
bitcoin::Amount is not able to parse floating points with a high precision but just fails with : `amount has a too high precision`.
We fix this by rounding the f64 to the smallest satoshi before parsing it to bitcoin::Amount.

Signed-off-by: Philipp Hoenisch <[email protected]>
  • Loading branch information
bonomat committed Jul 29, 2021
1 parent 052878b commit b12dc9c
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 9 deletions.
20 changes: 19 additions & 1 deletion bobtimus/src/amounts.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use anyhow::{anyhow, Context, Result};
use elements::bitcoin::{Amount, Denomination};
use rust_decimal::{prelude::ToPrimitive, Decimal};
use rust_decimal::{
prelude::{FromPrimitive, ToPrimitive},
Decimal, RoundingStrategy,
};
use serde::{Deserialize, Serialize};
use std::{convert::TryFrom, fmt::Debug};

Expand Down Expand Up @@ -43,6 +46,10 @@ impl Rate {
let btc = Decimal::from(satodollars)
.checked_div(Decimal::from(self.ask.as_satodollar()))
.ok_or_else(|| anyhow!("division overflow"))?;

// we round to 1 satoshi
let btc = btc.round_dp_with_strategy(8, RoundingStrategy::MidpointAwayFromZero);

let btc = btc
.to_f64()
.ok_or_else(|| anyhow!("decimal cannot be represented as f64"))?;
Expand Down Expand Up @@ -109,6 +116,11 @@ impl TryFrom<f64> for LiquidUsdt {
type Error = anyhow::Error;

fn try_from(value: f64) -> Result<Self> {
let value = Decimal::from_f64(value)
.with_context(|| format!("LiquidUsdt amount cannot be parsed from float {}", value))?
.round_dp_with_strategy(8, RoundingStrategy::MidpointAwayFromZero)
.to_f64()
.unwrap();
Ok(LiquidUsdt(Amount::from_btc(value)?))
}
}
Expand Down Expand Up @@ -169,4 +181,10 @@ mod tests {

assert_eq!(serialized, "{\"ask\":19313.52,\"bid\":19213.53}")
}

#[test]
fn test_rounding_liquid_usdt() {
let amount = LiquidUsdt::try_from(0.0000000123).unwrap();
assert_eq!(amount.0, Amount::from_sat(1));
}
}
24 changes: 16 additions & 8 deletions extension/wallet/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ use std::str::FromStr;

use bip32::{Language, Mnemonic};
use conquer_once::Lazy;
use elements::{
bitcoin::util::amount::{Amount, Denomination},
Address, AddressParams, Txid,
};
use elements::{bitcoin::util::amount::Amount, Address, AddressParams, Txid};
use futures::lock::Mutex;
use js_sys::Promise;
use reqwest::Url;
use rust_decimal::{prelude::ToPrimitive, Decimal, RoundingStrategy};
use wasm_bindgen::{prelude::*, JsCast};
use web_sys::window;

Expand All @@ -22,7 +21,6 @@ mod storage;
mod wallet;

use crate::{storage::Storage, wallet::*};
use reqwest::Url;

// TODO: make this configurable through extension option UI
const DEFAULT_SAT_PER_VBYTE: u64 = 1;
Expand Down Expand Up @@ -190,7 +188,7 @@ pub async fn make_buy_create_swap_payload(
wallet_name: String,
usdt: String,
) -> Result<JsValue, JsValue> {
let usdt = map_err_from_anyhow!(Amount::from_str_in(&usdt, Denomination::Bitcoin))?;
let usdt = map_err_from_anyhow!(parse_to_bitcoin_amount(usdt))?;
let payload = map_err_from_anyhow!(
wallet::make_buy_create_swap_payload(wallet_name, &LOADED_WALLET, usdt).await
)?;
Expand All @@ -207,7 +205,7 @@ pub async fn make_sell_create_swap_payload(
wallet_name: String,
btc: String,
) -> Result<JsValue, JsValue> {
let btc = map_err_from_anyhow!(Amount::from_str_in(&btc, Denomination::Bitcoin))?;
let btc = map_err_from_anyhow!(parse_to_bitcoin_amount(btc))?;
let payload = map_err_from_anyhow!(
wallet::make_sell_create_swap_payload(wallet_name, &LOADED_WALLET, btc).await
)?;
Expand All @@ -228,7 +226,7 @@ pub async fn make_loan_request(
wallet_name: String,
collateral: String,
) -> Result<JsValue, JsValue> {
let collateral = map_err_from_anyhow!(Amount::from_str_in(&collateral, Denomination::Bitcoin))?;
let collateral = map_err_from_anyhow!(parse_to_bitcoin_amount(collateral))?;
let loan_request = map_err_from_anyhow!(
wallet::make_loan_request(wallet_name, &LOADED_WALLET, collateral).await
)?;
Expand Down Expand Up @@ -423,3 +421,13 @@ impl From<Transaction> for elements::Transaction {
from.inner
}
}

fn parse_to_bitcoin_amount(amount: String) -> anyhow::Result<Amount> {
let parsed = Decimal::from_str(amount.as_str())?;
let rounded = parsed
.round_dp_with_strategy(8, RoundingStrategy::MidpointAwayFromZero)
.to_f64()
.ok_or_else(|| anyhow::anyhow!("decimal cannot be represented as f64"))?;
let amount = Amount::from_btc(rounded)?;
Ok(amount)
}

0 comments on commit b12dc9c

Please sign in to comment.