feat: overhaul landing page and implement dashboard components#67
Merged
Conversation
Contributor
BigBen-7
commented
Mar 6, 2026
- Refactored the landing page to include new components: Nav, Hero, StatStrip, MockDashboard, FeatureOrbit, HowItWorks, OpenSourceCTA, and Footer.
- Created DashboardShell component to manage dashboard data fetching and state.
- Added FeeChart, PercentileRow, RollingAverages, StatCards, TopBar, and TrendPanel components for displaying fee data and trends.
- Implemented API utility functions for fetching current fees, fee history, fee trends, and insights.
- Defined TypeScript types for API responses to ensure type safety across components.
- Enhanced utility functions for formatting and styling data.
- Refactored the landing page to include new components: Nav, Hero, StatStrip, MockDashboard, FeatureOrbit, HowItWorks, OpenSourceCTA, and Footer. - Created DashboardShell component to manage dashboard data fetching and state. - Added FeeChart, PercentileRow, RollingAverages, StatCards, TopBar, and TrendPanel components for displaying fee data and trends. - Implemented API utility functions for fetching current fees, fee history, fee trends, and insights. - Defined TypeScript types for API responses to ensure type safety across components. - Enhanced utility functions for formatting and styling data.
Excludes target/, node_modules/, .next/, .env files, SQLite DBs, OS/editor noise, and proptest-regressions. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…caffold harness & simulation modules Closes StellarCommons#91 Closes StellarCommons#92 Closes StellarCommons#93 Closes StellarCommons#94 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… delay - ScenarioRotator cycles through a list of scenario names (StellarCommons#107) - HorizonMock::rotate() advances to the next scenario via the rotator (StellarCommons#107) - HorizonMock::with_delay_ms() / apply_delay() simulate network latency (StellarCommons#110) Closes StellarCommons#107, StellarCommons#110
…k server - log_request() prints timestamp, method, path, and active scenario name (StellarCommons#108) - health_payload() returns {"status":"ok","scenario":"<current>"} for GET /health (StellarCommons#109) Closes StellarCommons#108, StellarCommons#109
- Add analysis module with percentile, spike_classifier, rolling_window stubs (StellarCommons#95) - Add cli module with replay, export, benchmark stubs (StellarCommons#96) - Add shared types module with FeeRecord, Scenario, SimResult stubs (StellarCommons#97) - Add DevkitError enum using thiserror; add thiserror dep to Cargo.toml (StellarCommons#98) Closes StellarCommons#95, StellarCommons#96, StellarCommons#97, StellarCommons#98
… fixtures - congested.json: high-load, p95 > 100,000 stroops, multiple spikes (StellarCommons#103) - recovery.json: post-spike normalisation, fees declining to baseline (StellarCommons#104) - spike.json: single 10x spike ledger then normal (StellarCommons#105) Closes StellarCommons#103, StellarCommons#104, StellarCommons#105
…ons#106) - HorizonMock now accepts a scenario_path and exposes fee_stats_payload() - scenarios::load_from_file reads a JSON scenario from disk Closes StellarCommons#106
…all scenario JSONs - HorizonMock::with_error_rate() injects 500/503 at a configurable rate (StellarCommons#111) - tests/harness_normal.rs: asserts normal scenario p50 fee_charged == 100 (StellarCommons#112) - tests/harness_congested.rs: asserts congested p95 fee_charged > 100,000 (StellarCommons#113) - Add max_fee object to congested, normal, recovery, spike scenario JSONs (StellarCommons#114) Closes StellarCommons#111 Closes StellarCommons#112 Closes StellarCommons#113 Closes StellarCommons#114
- README.md: scope, boundary rules, module table, run instructions (StellarCommons#99) - CONTRIBUTING.md: PR requirements, test expectations, code style, boundary rules (StellarCommons#100) - horizon_mock.rs: HorizonMock serves canned GET /fee_stats response; add axum/tokio/serde_json deps (StellarCommons#101) - scenarios/normal.json: baseline fee scenario, p50 ≈ 100 stroops (StellarCommons#102) Closes StellarCommons#99 Closes StellarCommons#100 Closes StellarCommons#101 Closes StellarCommons#102
…lator, capacity pressure, and fee curve JSON serialisation Closes StellarCommons#119, StellarCommons#120, StellarCommons#121, StellarCommons#122
- Add optional seed to FeeModel and NetworkLoad for reproducible runs (StellarCommons#130) - Add timestamp field to FeePoint spaced by ledger_interval_secs (StellarCommons#129) - Unit tests for spike injection rate and fee values (StellarCommons#127) - Unit tests for all four CongestionPredictor tiers (StellarCommons#128) - Fix unclosed brace in scenarios/mod.rs - Rename ScenarioRotator::next -> advance (clippy)
- Implement Percentile::nearest_rank (StellarCommons#136) - Implement Percentile::linear_interpolation (StellarCommons#137) - Document simulation module in README (StellarCommons#135)
…mmons#153, StellarCommons#154 - StellarCommons#151: Add FeeDistributionSummary struct and fee_distribution_summary() to percentile.rs returning min/max/mean/median/std_dev/p10-p99 - StellarCommons#152: Add iqr_outliers() to spike_classifier.rs flagging fees outside 1.5x IQR as outlier indices - StellarCommons#153: Add benches/percentile_bench.rs benchmarking nearest_rank, linear_interpolation, and fee_distribution_summary on 1M samples - StellarCommons#154: Add benches/rolling_window_bench.rs benchmarking SMA/EMA/WMA on 100k samples; implement SMA/EMA/WMA in rolling_window.rs - Update Cargo.toml to register percentile_bench and rolling_window_bench
- Add RollingWindow::ema() with configurable alpha (StellarCommons#147) - Add RollingWindow::wma() with linear weighting (StellarCommons#148) - Add Benchmark::compare_spike() printing SMA/EMA/WMA table (StellarCommons#149) - Add integration tests for all three algorithms (StellarCommons#150)
- Implement SpikeSeverity enum and SpikeClassifier::classify() (StellarCommons#143) Thresholds: Low 2-5x, Medium 5-10x, High 10-50x, Critical >50x baseline - Implement SpikeClassifier::detect() with duration_ledgers tracking (StellarCommons#144) Consecutive spike ledgers grouped into one SpikeEvent with max severity - Implement RollingWindow::sma() and push() for configurable-window SMA (StellarCommons#146) - Add 11 unit tests covering all severity levels, duration, and edge cases (StellarCommons#145) Closes StellarCommons#143, StellarCommons#144, StellarCommons#145, StellarCommons#146
…larCommons#141 StellarCommons#142 - Define SpikeEvent struct with SpikeSeverity enum (closes StellarCommons#141) - Implement SpikeClassifier::detect() for fee spike detection (closes StellarCommons#142) - Write nearest-rank percentile tests p10/p50/p90/p95/p99 (closes StellarCommons#139) - Write interpolation percentile tests with boundary and midpoint cases (closes StellarCommons#140)
Correctness ----------- - horizon.rs: fix avg_fee field mapping — was reading Horizon 'mode' (statistical mode) instead of 'avg' (arithmetic mean); renamed serde rename to use actual avg - api/fees.rs: fix 1h_pct always returning 0 — now compares short_term vs medium_term and medium_term vs long_term instead of a window against itself - repository.rs: add "Moderate" to VALID_THRESHOLDS (was missing, breaking SpikeSeverity round-trips) Security -------- - api/alerts.rs: SSRF guard on webhook_url — rejects non-HTTPS URLs and loopback/private-range IPs (is_safe_webhook_url) - middleware/rate_limit.rs: XFF only trusted from loopback peers (reverse-proxy guard); direct connections always use the TCP peer address Performance / Reliability -------------------------- - api/fees.rs: eliminate thundering herd — hold Mutex across staleness check and cache write so concurrent requests share one upstream fetch - insights/horizon_adapter.rs: use pooled HorizonClient HTTP client instead of ephemeral reqwest::get() call; add http_client() getter on HorizonClient - alerts/mod.rs: prune seen_spikes to active congestion window entries, bounding the HashSet to recent_spikes.len() and preventing unbounded growth - middleware/rate_limit.rs: evict stale DashMap buckets when map exceeds 10k entries (120s cutoff) Infrastructure -------------- - main.rs: restructure router — /health outside rate limiter, /metrics outside API-key auth but still rate-limited, business routes get both - main.rs: replace panic on invalid ALLOWED_ORIGINS with warn-and-skip - api/headers.rs: replace non-stable DefaultHasher with FNV-1a for ETags so ETags survive server restarts with identical data - api/fees.rs + headers.rs: replace .expect() on Response/HeaderValue builders with .unwrap_or_else() fallbacks - metrics.rs: remove http_requests_total and http_request_duration (registered but never incremented — produced misleading zeros in Prometheus) Code Quality ------------ - main.rs: remove #![allow(dead_code)] blanket suppression - insights/mod.rs: remove #![allow(unused_imports)] blanket suppression - scheduler.rs: delete run_fee_polling (never called; only run_fee_polling_with_retry is used in production) - repository.rs: delete insert_snapshot (never called in production) - services/horizon.rs: delete HorizonTransaction, HorizonOperation, four wrapper structs, fetch_latest_transaction, fetch_operations — all dead; HorizonFeeDataProvider has its own deserialization - insights/tracker.rs: delete 6 unused methods (get_historical_extremes, get_all_historical_extremes, reset_current_period, has_current_data, historical_period_count, get_current_period_info) - insights/calculator.rs: delete 3 unused methods (get_average_for_window, get_sample_count, has_sufficient_data) - insights/detector.rs: delete get_historical_spikes - insights/engine.rs: delete reset() - repository.rs: replace silent filter_map ok()? drops with explicit tracing::error! logging for all three row-decode sites Tests ----- - Fix duplicate struct field initializers in api/fees.rs, services/horizon.rs, repository.rs tests (were compile errors masked by blanket allow) - Fix duplicate JSON keys in horizon.rs test strings - Update rate limit tests: different_ips_have_independent_buckets now uses ConnectInfo socket addresses; add xff_is_trusted_when_connection_is_from_loopback - Update insights/tests.rs: replace reset() call with get_last_update assertion; replace has_current_data() with get_current_extremes().is_err() - Update integration test: remove reference to deleted http_request_duration metric All 193 tests pass.
# Conflicts: # .gitignore # Cargo.lock # packages/core/src/api/fees.rs # packages/core/src/api/headers.rs # packages/core/src/insights/calculator.rs # packages/core/src/insights/detector.rs # packages/core/src/insights/engine.rs # packages/core/src/insights/horizon_adapter.rs # packages/core/src/insights/mod.rs # packages/core/src/insights/tests.rs # packages/core/src/insights/tracker.rs # packages/core/src/main.rs # packages/core/src/metrics.rs # packages/core/src/repository.rs # packages/core/src/services/horizon.rs # packages/devkit/Cargo.toml # packages/devkit/benches/fee_model_bench.rs # packages/devkit/benches/rolling_window_bench.rs # packages/devkit/src/analysis/percentile.rs # packages/devkit/src/analysis/rolling_window.rs # packages/devkit/src/analysis/spike_classifier.rs # packages/devkit/src/harness/horizon_mock.rs # packages/devkit/src/harness/scenarios/mod.rs # packages/devkit/src/simulation/congestion_predictor.rs # packages/devkit/src/simulation/fee_model.rs # packages/devkit/src/simulation/network_load.rs # packages/devkit/tests/fee_model.rs
# Conflicts: # .gitignore # packages/devkit/Cargo.toml # packages/devkit/benches/fee_model_bench.rs # packages/devkit/benches/rolling_window_bench.rs # packages/devkit/src/analysis/percentile.rs # packages/devkit/src/analysis/rolling_window.rs # packages/devkit/src/analysis/spike_classifier.rs # packages/devkit/src/harness/horizon_mock.rs # packages/devkit/src/harness/scenarios/mod.rs # packages/devkit/src/simulation/congestion_predictor.rs # packages/devkit/src/simulation/fee_model.rs # packages/devkit/src/simulation/network_load.rs # packages/devkit/tests/fee_model.rs
- cargo fmt --all: fix formatting across core and devkit files - clippy: remove unused imports in mod.rs and tests.rs - clippy: replace map_or(false) with is_some_and in rate_limit.rs - clippy: add dead_code allows on intentional public-API items - devkit lib.rs: wire up missing module declarations (analysis, cli, harness, simulation) - devkit Cargo.toml: add criterion dev-dep and bench targets Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.