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
71 changes: 71 additions & 0 deletions Cargo.lock

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

11 changes: 8 additions & 3 deletions packages/devkit/src/cli/benchmark.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/// Runs benchmarks against the fee tracker pipeline.
/// Runs benchmarks against the fee tracker pipeline.
pub struct Benchmark;

impl Benchmark {
Expand Down Expand Up @@ -27,7 +27,12 @@ impl Benchmark {
/// Run all analysis benchmarks and print a summary table.
pub fn run_all(fees: &[f64], window: usize, alpha: f64) {
println!("=== Benchmark Results ===");
println!("Input: {} data points, window={}, alpha={}", fees.len(), window, alpha);
println!(
"Input: {} data points, window={}, alpha={}",
fees.len(),
window,
alpha
);
println!();
Self::compare_spike(fees, window, alpha);
}
Expand All @@ -42,4 +47,4 @@ mod tests {
let fees: Vec<f64> = (1..=10).map(|x| x as f64 * 100.0).collect();
Benchmark::run_all(&fees, 3, 0.3);
}
}
}
33 changes: 24 additions & 9 deletions packages/devkit/src/cli/export.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use crate::simulation::fee_model::FeePoint;
use crate::simulation::fee_model::FeePoint;
use std::fmt::Write as FmtWrite;
use std::path::{Path, PathBuf};

use crate::simulation::fee_model::FeePoint;

/// Arguments for the `export` subcommand.
pub struct ExportArgs {
/// Source SQLite database path.
Expand Down Expand Up @@ -32,7 +30,7 @@ pub enum Window {
}

impl Window {
pub fn from_str(s: &str) -> Option<Self> {
pub fn parse(s: &str) -> Option<Self> {
match s {
"1h" => Some(Self::OneHour),
"6h" => Some(Self::SixHours),
Expand All @@ -58,7 +56,7 @@ pub struct Export;
impl Export {
/// Serialize fee points to CSV.
/// Filter points by window relative to the latest timestamp.
pub fn filter_window<'a>(points: &'a [FeePoint], window: Window) -> &'a [FeePoint] {
pub fn filter_window(points: &[FeePoint], window: Window) -> &[FeePoint] {
match window.cutoff_seconds() {
None => points,
Some(secs) => {
Expand Down Expand Up @@ -111,8 +109,18 @@ mod tests {

fn pts() -> Vec<FeePoint> {
vec![
FeePoint { timestamp: 0, fee: 100, ledger: 1, is_spike: false },
FeePoint { timestamp: 7200, fee: 200, ledger: 2, is_spike: true },
FeePoint {
timestamp: 0,
fee: 100,
ledger: 1,
is_spike: false,
},
FeePoint {
timestamp: 7200,
fee: 200,
ledger: 2,
is_spike: true,
},
]
}

Expand All @@ -128,8 +136,15 @@ mod tests {
fn window_all_keeps_all() {
let p = pts();
assert_eq!(Export::filter_window(&p, Window::All).len(), 2);
}

fn sample() -> Vec<FeePoint> {
vec![FeePoint { timestamp: 1000, fee: 100, ledger: 1, is_spike: false }]
vec![FeePoint {
timestamp: 1000,
fee: 100,
ledger: 1,
is_spike: false,
}]
}

#[test]
Expand All @@ -144,4 +159,4 @@ mod tests {
assert!(json.starts_with('['));
assert!(json.ends_with(']'));
}
}
}
6 changes: 5 additions & 1 deletion packages/devkit/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ pub mod benchmark;
pub mod export;
pub mod replay;

use clap::{Parser, Subcommand};

/// Arguments for the `simulate` subcommand.
pub struct SimulateArgs {
/// Base fee floor in stroops.
Expand Down Expand Up @@ -30,6 +32,8 @@ impl SimulateArgs {
self.duration, self.base_fee, self.spike_prob
);
}
}

/// Arguments for the `mock` subcommand.
pub struct MockArgs {
/// Scenario to load (e.g. "normal", "congested", "spike").
Expand All @@ -55,7 +59,7 @@ impl MockArgs {
self.port, self.scenario
);
}
use clap::{Parser, Subcommand};
}

/// Developer toolkit for the Stellar fee tracker.
#[derive(Parser)]
Expand Down
59 changes: 22 additions & 37 deletions packages/devkit/src/cli/replay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,24 @@ pub struct ReplayArgs {
pub db: PathBuf,
/// Show a progress bar during replay.
pub progress: bool,
/// Playback speed multiplier (1.0 = real-time).
pub speed: f32,
/// Start of the replay window (ISO-8601 timestamp).
pub from: Option<String>,
/// End of the replay window (ISO-8601 timestamp).
pub to: Option<String>,
}

impl Default for ReplayArgs {
fn default() -> Self {
Self {
db: PathBuf::from("stellar_fees.db"),
progress: false,
speed: 1.0,
from: None,
to: None,
}
}
}

impl ReplayArgs {
Expand All @@ -27,54 +45,21 @@ impl ReplayArgs {
bar.inc(1);
}
bar.finish_with_message("replay complete");
use clap::Args;

/// Arguments for the `replay` subcommand.
#[derive(Args)]
pub struct ReplayArgs {
/// Path to the SQLite database file.
pub db: PathBuf,
/// Playback speed multiplier (1.0 = real-time).
#[arg(long, default_value = "1.0")]
pub speed: f32,
/// Start of the replay window (ISO-8601 timestamp).
#[arg(long)]
pub from: Option<String>,
/// End of the replay window (ISO-8601 timestamp).
#[arg(long)]
pub to: Option<String>,
}
}

impl ReplayArgs {
/// Replays fee records filtered by the given time window.
pub fn run(&self) {
pub fn run_windowed(&self) {
eprintln!(
"Replaying from {} at {:.1}x speed, window {:?}..{:?}",
self.db.display(),
self.speed,
self.from,
self.to
);
/// Path to the SQLite database file containing recorded fee data.
pub db: PathBuf,
/// Playback speed multiplier (1.0 = real-time, 10.0 = 10x faster).
#[arg(long, default_value = "1.0")]
pub speed: f32,
}

impl ReplayArgs {
/// Replays fee records at the specified speed multiplier.
pub fn run(&self) {
eprintln!(
"Replaying from {} at {:.1}x speed",
self.db.display(),
self.speed
);
}
}

impl ReplayArgs {
/// Replays fee records from the database to stdout as a JSON stream.
pub fn run(&self) {
pub fn run_json(&self) {
eprintln!("Replaying fee records from {}", self.db.display());
println!("[]");
}
Expand Down
Loading
Loading