Skip to content

Commit

Permalink
add sat conversion for bill payment link and add timestamps to light … (
Browse files Browse the repository at this point in the history
#396)

* add sat conversion for bill payment link and add timestamps to light bill

* fix lint and add to full bill

* remove check from payment
  • Loading branch information
zupzup authored Feb 14, 2025
1 parent 7ba1b32 commit d4c484a
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 26 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ lettre = { version = "0.11.10", features = [
"tokio1-native-tls",
"file-transport",
] }
rust_decimal = { version = "1.35.0", default-features = false, features = ["std"] }
nostr-sdk = { version = "0.38.0", features = ["nip59"] }
uuid = { version = "1.11.0", features = ["v4"] }
infer = { version = "0.16", default-features = false }
Expand Down
3 changes: 3 additions & 0 deletions src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ pub const PAYMENT_DEADLINE_SECONDS: u64 = 86400 * 2; // 2 days
pub const ACCEPT_DEADLINE_SECONDS: u64 = 86400 * 2; // 2 days
pub const RECOURSE_DEADLINE_SECONDS: u64 = 86400 * 2; // 2 days

// Currency
pub const SAT_TO_BTC_RATE: i64 = 100_000_000;

// Validation
pub const MAX_FILE_SIZE_BYTES: usize = 1_000_000; // ~1 MB
pub const MAX_FILE_NAME_CHARACTERS: usize = 200;
Expand Down
5 changes: 3 additions & 2 deletions src/external/bitcoin.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::CONFIG;
use crate::{util, CONFIG};
use async_trait::async_trait;
use bitcoin::{secp256k1::Scalar, Network};
use serde::Deserialize;
Expand Down Expand Up @@ -167,7 +167,8 @@ impl BitcoinClientApi for BitcoinClient {
}

fn generate_link_to_pay(&self, address: &str, sum: u64, message: &str) -> String {
let link = format!("bitcoin:{}?amount={}&message={}", address, sum, message);
let btc_sum = util::currency::sat_to_btc(sum);
let link = format!("bitcoin:{}?amount={}&message={}", address, btc_sum, message);
link
}

Expand Down
43 changes: 21 additions & 22 deletions src/service/bill_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1076,6 +1076,8 @@ impl BillService {
Ok(BitcreditBillToReturn {
id: bill.id,
time_of_drawing,
time_of_maturity: util::date::date_string_to_i64_timestamp(&bill.maturity_date, None)
.unwrap_or(0) as u64,
country_of_issuing: bill.country_of_issuing,
city_of_issuing: bill.city_of_issuing,
drawee: bill.drawee,
Expand Down Expand Up @@ -1121,29 +1123,20 @@ impl BillService {
.get_last_version_bill(&chain, &bill_keys, identity)
.await?;

// We only check payment, if the maturity date hasn't expired
if let Some(maturity_date_timestamp) =
util::date::date_string_to_i64_timestamp(&bill.maturity_date, None)
let holder_public_key = match bill.endorsee {
None => &bill.payee.node_id,
Some(ref endorsee) => &endorsee.node_id,
};
let address_to_pay = self
.bitcoin_client
.get_address_to_pay(&bill_keys.public_key, holder_public_key)?;
if let Ok((paid, sum)) = self
.bitcoin_client
.check_if_paid(&address_to_pay, bill.sum)
.await
{
if maturity_date_timestamp
> (util::date::now().timestamp() - PAYMENT_DEADLINE_SECONDS as i64)
{
let holder_public_key = match bill.endorsee {
None => &bill.payee.node_id,
Some(ref endorsee) => &endorsee.node_id,
};
let address_to_pay = self
.bitcoin_client
.get_address_to_pay(&bill_keys.public_key, holder_public_key)?;
if let Ok((paid, sum)) = self
.bitcoin_client
.check_if_paid(&address_to_pay, bill.sum)
.await
{
if paid && sum > 0 {
self.store.set_to_paid(bill_id, &address_to_pay).await?;
}
}
if paid && sum > 0 {
self.store.set_to_paid(bill_id, &address_to_pay).await?;
}
}
Ok(())
Expand Down Expand Up @@ -3221,6 +3214,8 @@ pub struct LightBitcreditBillToReturn {
pub sum: String,
pub currency: String,
pub issue_date: String,
pub time_of_drawing: u64,
pub time_of_maturity: u64,
}

impl From<BitcreditBillToReturn> for LightBitcreditBillToReturn {
Expand All @@ -3235,6 +3230,9 @@ impl From<BitcreditBillToReturn> for LightBitcreditBillToReturn {
sum: value.sum,
currency: value.currency,
issue_date: value.issue_date,
time_of_drawing: value.time_of_drawing,
time_of_maturity: util::date::date_string_to_i64_timestamp(&value.maturity_date, None)
.unwrap_or(0) as u64,
}
}
}
Expand All @@ -3243,6 +3241,7 @@ impl From<BitcreditBillToReturn> for LightBitcreditBillToReturn {
pub struct BitcreditBillToReturn {
pub id: String,
pub time_of_drawing: u64,
pub time_of_maturity: u64,
pub country_of_issuing: String,
pub city_of_issuing: String,
/// The party obliged to pay a Bill
Expand Down
25 changes: 24 additions & 1 deletion src/util/currency.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
use crate::service::{Error, Result};
use crate::{
constants::SAT_TO_BTC_RATE,
service::{Error, Result},
};
use rust_decimal::Decimal;

pub fn parse_sum(sum: &str) -> Result<u64> {
match sum.parse::<u64>() {
Expand All @@ -10,3 +14,22 @@ pub fn parse_sum(sum: &str) -> Result<u64> {
pub fn sum_to_string(sum: u64) -> String {
sum.to_string()
}

pub fn sat_to_btc(val: u64) -> String {
let conversion_factor = Decimal::new(1, 0) / Decimal::new(SAT_TO_BTC_RATE, 0);
let sat_dec = Decimal::from(val);
let btc_dec = sat_dec * conversion_factor;
btc_dec.to_string()
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn sat_to_btc_test() {
assert_eq!(sat_to_btc(1000), String::from("0.00001000"));
assert_eq!(sat_to_btc(10000), String::from("0.00010000"));
assert_eq!(sat_to_btc(1), String::from("0.00000001"));
}
}
2 changes: 1 addition & 1 deletion src/web/handlers/quotes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub async fn return_quote(
let bill_id_hex = hex::encode(bill_id_u8);
let copy_id_hex = bill_id_hex.clone();

let local_node_id = get_current_identity_node_id(&state).await;
let local_node_id = get_current_identity_node_id(state).await;
if !quote.bill_id.is_empty() && quote.quote_id.is_empty() {
// Usage of thread::spawn is necessary here, because we spawn a new tokio runtime in the
// thread, but this logic will be replaced soon
Expand Down

0 comments on commit d4c484a

Please sign in to comment.