Overview
Add a GET /api/fees/transaction/:hash endpoint that proxies to Horizon's transaction endpoint, retrieves the fee charged for a specific transaction, and enriches it with historical context from our SQLite store.
Horizon Source
Horizon endpoint: GET https://horizon-testnet.stellar.org/transactions/:hash
Key field from response: fee_charged
Response Shape
{
"hash": "abc123...",
"fee_charged": 150,
"ledger": 1234567,
"created_at": "2026-03-21T10:00:00Z",
"context": {
"network_avg_fee": 110,
"network_base_fee": 100,
"percentile_rank": "p60",
"verdict": "FAIR"
}
}
Verdict Logic
Compare fee_charged against the network stats stored for the closest timestamp in SQLite:
fee_charged <= base_fee * 1.1 → `"OPTIMAL"
fee_charged <= avg_fee * 3 → `"OVERPAID"
Acceptance Criteria
Notes
- Related frontend issue:
[Phase 2] feat(ui): dashboard — transaction lookup page
Overview
Add a
GET /api/fees/transaction/:hashendpoint that proxies to Horizon's transaction endpoint, retrieves the fee charged for a specific transaction, and enriches it with historical context from our SQLite store.Horizon Source
Horizon endpoint:
GET https://horizon-testnet.stellar.org/transactions/:hashKey field from response:
fee_chargedResponse Shape
{ "hash": "abc123...", "fee_charged": 150, "ledger": 1234567, "created_at": "2026-03-21T10:00:00Z", "context": { "network_avg_fee": 110, "network_base_fee": 100, "percentile_rank": "p60", "verdict": "FAIR" } }Verdict Logic
Compare
fee_chargedagainst the network stats stored for the closest timestamp in SQLite:fee_charged <= base_fee * 1.1→ `"OPTIMAL"fee_charged <= avg_fee * 3→ `"OVERPAID"Acceptance Criteria
GET /api/fees/transaction/:hashreturns the above response shapefee_chargedpercentile_rankby comparingfee_chargedagainst stored percentile values404with a clear error message if the transaction hash is not found on Horizon400if the hash format is clearly invalid (not 64 hex chars)Notes
[Phase 2] feat(ui): dashboard — transaction lookup page