riftenlabs-indexer/src/rpc/apy/mod.rs

86 lines
2.5 KiB
Rust
Raw Normal View History

// Copyright (C) 2024 Riften Labs AS
//
// This software is licensed under the GNU Affero General Public License (AGPL), version 3.0 or later.
// A copy of the license can be found in the LICENSE file or at https://www.gnu.org/licenses/agpl-3.0.html
use poolperiod::PoolPeriod;
use rocket::{get, http::Status, response::status::Custom, serde::json::Json, State};
use serde_json::Value;
use crate::{
db::{cauldron::pool::get_pool_period_snapshot, DB},
timeutil::time_now,
};
use serde_json::json;
pub mod apyaggregator;
pub mod poolperiod;
#[derive(Clone, Debug)]
pub struct PoolSnapshot {
pub pool_id: String,
pub timestamp: u64,
pub sats: u64,
pub token_amount: u64,
}
impl PoolSnapshot {
#[allow(dead_code)] // used in unit tests
pub fn dummy(timestamp: u64, sats: u64, token_amount: u64) -> Self {
Self {
pool_id: "dummy".to_string(),
timestamp,
sats,
token_amount,
}
}
}
#[get("/pool/aggregated_apy?<token>&<pkh>&<start>&<end>")]
pub fn aggregate_apy(
token: Option<&str>,
pkh: Option<&str>,
start: Option<i64>, // default 30 days before end
end: Option<i64>, // default now
db: &State<DB>,
) -> Result<Json<Value>, Custom<String>> {
let end = end.unwrap_or(time_now());
let start = start.unwrap_or(end - (3600 * 24 * 30)); // 30 days
if end < start {
return Err(Custom(
Status::BadRequest,
"end time cannot be less than start time".to_string(),
));
}
if start < 0 {
return Err(Custom(
Status::BadRequest,
"start time cannot be negative".to_string(),
));
}
let conn = db
.cauldron_r
.get()
.map_err(|e| Custom(Status::InternalServerError, format!("DB error: {}", e)))?;
let pools: anyhow::Result<Vec<PoolPeriod>> =
get_pool_period_snapshot(&conn, token, pkh, start, end)
.map_err(|e| Custom(Status::InternalServerError, format!("Error: {}", e)))?
.into_iter()
.map(|(start, end)| PoolPeriod::new(start, end))
.collect();
let pools = pools.map_err(|e| Custom(Status::InternalServerError, format!("Error: {}", e)))?;
let pools_count = pools.len();
let apy = apyaggregator::APYAggregator::aggregate_apy(pools.into_iter(), Some(start as u64))
.map_err(|e| Custom(Status::InternalServerError, format!("Error: {}", e)))?;
Ok(Json(json!({
"apy": apy.to_string(),
"pools": pools_count,
})))
}