Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[workspace]
members = ["packages/core"]
members = ["packages/core", "packages/devkit"]
resolver = "2"
4 changes: 2 additions & 2 deletions packages/core/src/alerts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,8 @@ mod tests {
use super::*;
use chrono::{DateTime, Duration, Utc};
use wiremock::{
Mock, MockServer, ResponseTemplate,
matchers::{method, path},
Mock, MockServer, ResponseTemplate,
};

use crate::insights::{
Expand Down Expand Up @@ -246,4 +246,4 @@ mod tests {
manager.check_and_dispatch(&update).await;
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
}
}
}
2 changes: 1 addition & 1 deletion packages/core/src/alerts/webhook.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ impl WebhookDelivery {
mod tests {
use super::*;
use wiremock::{
Mock, MockServer, ResponseTemplate,
matchers::{body_json, method, path},
Mock, MockServer, ResponseTemplate,
};

fn build_payload() -> AlertPayload {
Expand Down
28 changes: 20 additions & 8 deletions packages/core/src/api/alerts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,6 @@ pub async fn delete_alert(
}
}


// ---- Alert history ----

#[derive(Debug, Deserialize)]
Expand Down Expand Up @@ -241,8 +240,8 @@ mod tests {
use axum::{
body::Body,
http::{Method, Request},
Router,
routing::{delete, get, patch, post},
Router,
};
use http_body_util::BodyExt;
use tower::ServiceExt;
Expand Down Expand Up @@ -273,7 +272,9 @@ mod tests {
.method(Method::POST)
.uri("/alerts/config")
.header("content-type", "application/json")
.body(Body::from(r#"{"webhook_url":"https://example.com/hook","threshold":"Major"}"#))
.body(Body::from(
r#"{"webhook_url":"https://example.com/hook","threshold":"Major"}"#,
))
.unwrap();

let resp = app.oneshot(req).await.unwrap();
Expand All @@ -289,7 +290,9 @@ mod tests {
.method(Method::POST)
.uri("/alerts/config")
.header("content-type", "application/json")
.body(Body::from(r#"{"webhook_url":"https://example.com/hook","threshold":"Catastrophic"}"#))
.body(Body::from(
r#"{"webhook_url":"https://example.com/hook","threshold":"Catastrophic"}"#,
))
.unwrap();

let resp = app.oneshot(req).await.unwrap();
Expand Down Expand Up @@ -325,7 +328,10 @@ mod tests {
async fn patch_updates_alert_config() {
let pool = create_pool("sqlite::memory:").await.unwrap();
let repo = Arc::new(FeeRepository::new(pool));
let id = repo.insert_alert_config("https://example.com/hook", "Minor").await.unwrap();
let id = repo
.insert_alert_config("https://example.com/hook", "Minor")
.await
.unwrap();

let app = Router::new()
.route("/alerts/config/:id", patch(update_alert))
Expand All @@ -346,7 +352,10 @@ mod tests {
async fn patch_invalid_threshold_returns_400() {
let pool = create_pool("sqlite::memory:").await.unwrap();
let repo = Arc::new(FeeRepository::new(pool));
let id = repo.insert_alert_config("https://example.com/hook", "Minor").await.unwrap();
let id = repo
.insert_alert_config("https://example.com/hook", "Minor")
.await
.unwrap();

let app = Router::new()
.route("/alerts/config/:id", patch(update_alert))
Expand All @@ -367,7 +376,10 @@ mod tests {
async fn delete_soft_deletes_alert_config() {
let pool = create_pool("sqlite::memory:").await.unwrap();
let repo = Arc::new(FeeRepository::new(pool.clone()));
let id = repo.insert_alert_config("https://example.com/hook", "Major").await.unwrap();
let id = repo
.insert_alert_config("https://example.com/hook", "Major")
.await
.unwrap();

let app = Router::new()
.route("/alerts/config/:id", delete(delete_alert))
Expand Down Expand Up @@ -408,8 +420,8 @@ mod history_tests {
use axum::{
body::Body,
http::{Method, Request},
Router,
routing::get,
Router,
};
use http_body_util::BodyExt;
use tower::ServiceExt;
Expand Down
63 changes: 31 additions & 32 deletions packages/core/src/api/fees.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use async_trait::async_trait;
use axum::{
body::Body,
extract::{Query, State},
http::{HeaderMap, StatusCode, header},
http::{header, HeaderMap, StatusCode},
response::Response,
Json,
};
Expand All @@ -13,12 +13,12 @@ use serde::{Deserialize, Serialize};
use serde_json::{json, Value};
use tokio::sync::{Mutex, RwLock};

use super::headers::{cache_control, compute_etag, if_none_match_matches, last_modified};
use crate::cache::ResponseCache;
use crate::error::AppError;
use crate::insights::{FeeDataPoint, FeeInsightsEngine, TrendIndicator, TrendStrength};
use crate::services::horizon::HorizonClient;
use crate::store::FeeHistoryStore;
use super::headers::{cache_control, compute_etag, if_none_match_matches, last_modified};

/// Shared state type for the fees route.
pub type FeesState = Arc<FeesApiState>;
Expand All @@ -38,18 +38,18 @@ impl FeeStatsProvider for HorizonClient {
max_fee: stats.fee_charged.max,
avg_fee: stats.fee_charged.avg,
percentiles: PercentileFees {
p10: stats.fee_charged.p10,
p20: stats.fee_charged.p20,
p30: stats.fee_charged.p30,
p40: stats.fee_charged.p40,
p50: stats.fee_charged.p50,
p60: stats.fee_charged.p60,
p70: stats.fee_charged.p70,
p80: stats.fee_charged.p80,
p90: stats.fee_charged.p90,
p95: stats.fee_charged.p95,
p99: stats.fee_charged.p99,
},
p10: stats.fee_charged.p10,
p20: stats.fee_charged.p20,
p30: stats.fee_charged.p30,
p40: stats.fee_charged.p40,
p50: stats.fee_charged.p50,
p60: stats.fee_charged.p60,
p70: stats.fee_charged.p70,
p80: stats.fee_charged.p80,
p90: stats.fee_charged.p90,
p95: stats.fee_charged.p95,
p99: stats.fee_charged.p99,
},
})
}
}
Expand Down Expand Up @@ -324,9 +324,7 @@ pub struct FeeTrendResponse {
pub last_updated: DateTime<Utc>,
}

pub async fn fee_trend(
State(state): State<FeesState>,
) -> Result<Json<FeeTrendResponse>, AppError> {
pub async fn fee_trend(State(state): State<FeesState>) -> Result<Json<FeeTrendResponse>, AppError> {
let engine = state
.insights_engine
.as_ref()
Expand Down Expand Up @@ -389,13 +387,13 @@ mod tests {
use std::sync::Mutex as StdMutex;
use std::time::Duration as StdDuration;

use crate::insights::InsightsConfig;
use axum::{
body::{to_bytes, Body},
http::{Request, StatusCode},
routing::get,
Router,
};
use crate::insights::InsightsConfig;
use chrono::Duration as ChronoDuration;
use tower::ServiceExt;

Expand Down Expand Up @@ -477,19 +475,19 @@ mod tests {
min_fee: "100".to_string(),
max_fee: "5000".to_string(),
avg_fee: "213".to_string(),
percentiles: PercentileFees {
p10: "100".to_string(),
p20: "100".to_string(),
p30: "100".to_string(),
p40: "100".to_string(),
p50: "150".to_string(),
p60: "200".to_string(),
p70: "250".to_string(),
p80: "300".to_string(),
p90: "500".to_string(),
p95: "800".to_string(),
p99: "1000".to_string(),
},
percentiles: PercentileFees {
p10: "100".to_string(),
p20: "100".to_string(),
p30: "100".to_string(),
p40: "100".to_string(),
p50: "150".to_string(),
p60: "200".to_string(),
p70: "250".to_string(),
p80: "300".to_string(),
p90: "500".to_string(),
p95: "800".to_string(),
p99: "1000".to_string(),
},
}
}

Expand Down Expand Up @@ -551,7 +549,8 @@ mod tests {
make_current_fee_response("100"),
make_current_fee_response("200"),
]);
let state = make_fee_state_with_provider(Arc::new(mock.clone()), StdDuration::from_secs(60));
let state =
make_fee_state_with_provider(Arc::new(mock.clone()), StdDuration::from_secs(60));

let app = Router::new()
.route("/fees/current", get(current_fees))
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/api/headers.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};

use axum::http::{HeaderMap, HeaderValue, header};
use axum::http::{header, HeaderMap, HeaderValue};
use chrono::{DateTime, Utc};

/// Compute a weakly-stable quoted ETag from response bytes.
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/api/health.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use axum::{
body::Body,
http::{HeaderValue, StatusCode, header},
http::{header, HeaderValue, StatusCode},
response::{IntoResponse, Response},
};

Expand Down
8 changes: 4 additions & 4 deletions packages/core/src/api/insights.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use axum::{
body::Body,
extract::State,
http::{HeaderMap, StatusCode, header},
http::{header, HeaderMap, StatusCode},
response::{Json, Response},
routing::get,
Router,
Expand All @@ -12,8 +12,8 @@ use serde_json::Value;
use std::sync::Arc;
use tokio::sync::RwLock;

use crate::insights::{CongestionTrends, FeeExtremes, FeeInsightsEngine, RollingAverages};
use super::headers::{cache_control, compute_etag, if_none_match_matches, last_modified};
use crate::insights::{CongestionTrends, FeeExtremes, FeeInsightsEngine, RollingAverages};

/// Shared state for the insights API
pub type InsightsState = Arc<RwLock<FeeInsightsEngine>>;
Expand Down Expand Up @@ -97,7 +97,7 @@ async fn get_insights_health(
State(engine): State<InsightsState>,
) -> Result<Json<Value>, (StatusCode, Json<Value>)> {
let engine = engine.read().await;

let health_info = serde_json::json!({
"status": "healthy",
"last_update": engine.get_last_update(),
Expand All @@ -107,6 +107,6 @@ async fn get_insights_health(
"spike_threshold": engine.get_config().spike_detection.threshold_multiplier
}
});

Ok(Json(health_info))
}
7 changes: 3 additions & 4 deletions packages/core/src/api/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
pub mod health;
pub mod fees;
pub mod insights;
pub mod alerts;
pub mod fees;
pub mod headers;

pub mod health;
pub mod insights;
18 changes: 10 additions & 8 deletions packages/core/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,8 @@ impl Config {
.unwrap_or(1000);

// -------- Database URL --------
let database_url = get("DATABASE_URL")
.unwrap_or_else(|| "sqlite://stellar_fees.db".to_string());
let database_url =
get("DATABASE_URL").unwrap_or_else(|| "sqlite://stellar_fees.db".to_string());

// -------- Storage retention --------
let storage_retention_days = get("STORAGE_RETENTION_DAYS")
Expand Down Expand Up @@ -369,9 +369,10 @@ mod tests {
#[test]
fn allowed_origins_parses_comma_separated_list() {
let cli = make_cli("testnet", None);
let env = HashMap::from([
("ALLOWED_ORIGINS", "http://localhost:3000,https://app.example.com"),
]);
let env = HashMap::from([(
"ALLOWED_ORIGINS",
"http://localhost:3000,https://app.example.com",
)]);
let config = Config::from_sources_with_overrides(&cli, &env).unwrap();
assert_eq!(
config.allowed_origins,
Expand All @@ -382,9 +383,10 @@ mod tests {
#[test]
fn allowed_origins_trims_whitespace() {
let cli = make_cli("testnet", None);
let env = HashMap::from([
("ALLOWED_ORIGINS", "http://localhost:3000 , https://app.example.com "),
]);
let env = HashMap::from([(
"ALLOWED_ORIGINS",
"http://localhost:3000 , https://app.example.com ",
)]);
let config = Config::from_sources_with_overrides(&cli, &env).unwrap();
assert_eq!(
config.allowed_origins,
Expand Down
8 changes: 6 additions & 2 deletions packages/core/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,11 @@ mod tests {

// Run migrations a second time explicitly
let result = sqlx::migrate!("./migrations").run(&pool).await;
assert!(result.is_ok(), "Second migration run failed: {:?}", result.err());
assert!(
result.is_ok(),
"Second migration run failed: {:?}",
result.err()
);
}

#[tokio::test]
Expand Down Expand Up @@ -69,4 +73,4 @@ mod tests {

assert!(result.is_ok(), "Insert failed: {:?}", result.err());
}
}
}
4 changes: 2 additions & 2 deletions packages/core/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::fmt;
use std::error::Error;
use std::fmt;

use axum::{
http::StatusCode,
Expand Down Expand Up @@ -109,4 +109,4 @@ mod tests {
"Unknown error: ???"
);
}
}
}
Loading
Loading