Skip to content

Commit

Permalink
Introduces a in-memory price cache (#329)
Browse files Browse the repository at this point in the history
  • Loading branch information
bilthon authored Jul 17, 2024
1 parent 8588a23 commit 9a4c466
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 4 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 @@ -45,3 +45,4 @@ config = "0.14.0"
clap = { version = "4.5.3", features = ["derive"] }
lnurl-rs = "0.5.0"
openssl = { version = "0.10", features = ["vendored"] }
once_cell = "1.19.0"
11 changes: 7 additions & 4 deletions src/app/order.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::cli::settings::Settings;
use crate::lightning::invoice::decode_invoice;
use crate::util::{get_market_quote, publish_order, send_cant_do_msg};
use crate::util::{get_bitcoin_price, publish_order, send_cant_do_msg};

use anyhow::Result;
use mostro_core::message::Message;
Expand Down Expand Up @@ -54,10 +54,13 @@ pub async fn order_action(
}
}

for fiat_amount in amount_vec {
for (_, fiat_amount) in amount_vec.iter().enumerate() {
let quote = match order.amount {
0 => match get_market_quote(&fiat_amount, &order.fiat_code, 0).await {
Ok(amount) => amount,
0 => match get_bitcoin_price(&order.fiat_code) {
Ok(price) => {
let quote = *fiat_amount as f64 / price;
(quote * 1E8) as i64
},
Err(e) => {
error!("{:?}", e.to_string());
return Ok(());
Expand Down
38 changes: 38 additions & 0 deletions src/bitcoin_price.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use std::collections::HashMap;
use std::sync::RwLock;
use serde::Deserialize;
use anyhow::Result;
use tracing::info;
use once_cell::sync::Lazy;

const YADIO_API_URL: &str = "https://api.yadio.io/exrates/BTC";

#[derive(Debug, Deserialize)]
struct YadioResponse {
#[serde(rename = "BTC")]
btc: HashMap<String, f64>,
}

static BITCOIN_PRICES: Lazy<RwLock<HashMap<String, f64>>> = Lazy::new(|| RwLock::new(HashMap::new()));

pub struct BitcoinPriceManager;

impl BitcoinPriceManager {
pub async fn update_prices() -> Result<()> {
let response = reqwest::get(YADIO_API_URL).await?;
let yadio_response: YadioResponse = response.json().await?;
info!(
"Bitcoin prices updated. Got BTC price in {} fiat currencies",
yadio_response.btc.keys().collect::<Vec<&String>>().len()
);

let mut prices_write = BITCOIN_PRICES.write().unwrap();
*prices_write = yadio_response.btc;
Ok(())
}

pub fn get_price(currency: &str) -> Option<f64> {
let prices_read = BITCOIN_PRICES.read().unwrap();
prices_read.get(currency).cloned()
}
}
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub mod models;
pub mod nip33;
pub mod scheduler;
pub mod util;
mod bitcoin_price;

use crate::app::run;
use crate::cli::settings::{init_global_settings, Settings};
Expand Down
14 changes: 14 additions & 0 deletions src/scheduler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::db::*;
use crate::lightning::LndConnector;
use crate::util;
use crate::NOSTR_CLIENT;
use crate::bitcoin_price::BitcoinPriceManager;

use chrono::{TimeDelta, Utc};
use mostro_core::order::{Kind, Status};
Expand All @@ -25,6 +26,7 @@ pub async fn start_scheduler(rate_list: Arc<Mutex<Vec<Event>>>) {
job_retry_failed_payments().await;
job_info_event_send().await;
job_relay_list().await;
job_update_bitcoin_prices().await;

info!("Scheduler Started");
}
Expand Down Expand Up @@ -334,3 +336,15 @@ async fn job_expire_pending_older_orders() {
}
});
}

async fn job_update_bitcoin_prices() {
tokio::spawn(async {
loop {
info!("Updating Bitcoin prices");
if let Err(e) = BitcoinPriceManager::update_prices().await {
error!("Failed to update Bitcoin prices: {}", e);
}
tokio::time::sleep(tokio::time::Duration::from_secs(300)).await;
}
});
}
6 changes: 6 additions & 0 deletions src/util.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::app::rate_user::get_user_reputation;
use crate::bitcoin_price::BitcoinPriceManager;
use crate::cli::settings::Settings;
use crate::db;
use crate::error::MostroError;
Expand Down Expand Up @@ -55,6 +56,11 @@ pub async fn retries_yadio_request(
Ok((Some(res), fiat_list_check))
}

pub fn get_bitcoin_price(fiat_code: &str) -> Result<f64> {
BitcoinPriceManager::get_price(fiat_code)
.ok_or_else(|| anyhow::anyhow!("Failed to get Bitcoin price"))
}

/// Request market quote from Yadio to have sats amount at actual market price
pub async fn get_market_quote(
fiat_amount: &i64,
Expand Down

0 comments on commit 9a4c466

Please sign in to comment.