973e25a7c9
web/handlers/stash.go: GET /stash/{holderID} renders balance in Grain +
Bread-scale conversion (x/bread/types.BreadScaleAll() + GrainsPerBread=10000,
D-073 code constants NOT docs) + 90-day maturity progress bar (ActiveDays/90
capped at 100%) + IsMature badge. stash_test.go: D-073 regression guard
(GrainsPerBread=10000, Crumb=100 Grain; would fail if docs 1000x values used),
mature vs immature fixture, 404 + G-026 error lexicon check. Coverage 83.5%
cumulative. Template FuncMap divGrain for the scale table.
---ci---
project: oy
phase: 2
milestone: v0.6
status: execute
---/ci---
69 lines
2.1 KiB
Go
69 lines
2.1 KiB
Go
package handlers
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
breadtypes "github.com/oy/openyield/x/bread/types"
|
|
stashtypes "github.com/oy/openyield/x/stash/types"
|
|
)
|
|
|
|
// registerStash wires the Stash dashboard route (REQ-041) into the mux.
|
|
func (s *Server) registerStash(mux *http.ServeMux) {
|
|
mux.HandleFunc("GET /stash/{holderID}", s.handleStashDashboard)
|
|
}
|
|
|
|
// stashViewData is the template data for the Stash dashboard. It carries the
|
|
// real x/*/types structs plus the Bread-scale conversion (computed from the
|
|
// x/bread/types code constants per D-073) and the maturity progress.
|
|
type stashViewData struct {
|
|
Stash stashtypes.Stash
|
|
Activity stashtypes.StashActivity
|
|
Found bool
|
|
BreadScale []breadtypes.BreadScale
|
|
BalanceBread int64
|
|
MaturityPct int
|
|
Mature bool
|
|
ThresholdDays uint32
|
|
MaxGapDays uint32
|
|
}
|
|
|
|
// handleStashDashboard renders the Stash dashboard (REQ-041): balance in Grain
|
|
// + Bread-scale conversion (using x/bread/types.BreadScaleAll() + GrainsPerBread
|
|
// per D-073 — code constants, NOT docs) + 90-day maturity progress bar
|
|
// (StashActivity.IsMature, MaturityThresholdDays=90).
|
|
func (s *Server) handleStashDashboard(w http.ResponseWriter, r *http.Request) {
|
|
holderID := r.PathValue("holderID")
|
|
stash, ok := s.Store.GetStash(holderID)
|
|
if !ok {
|
|
http.NotFound(w, r)
|
|
return
|
|
}
|
|
activity, _ := s.Store.GetStashActivity(stash.StashID)
|
|
|
|
// D-073: Bread-scale conversion from x/bread/types code constants.
|
|
scale := breadtypes.BreadScaleAll()
|
|
balanceBread := stash.BalanceGrain / breadtypes.GrainsPerBread
|
|
|
|
// Maturity progress: ActiveDays / MaturityThresholdDays, capped at 100%.
|
|
threshold := uint32(stashtypes.MaturityThresholdDays)
|
|
pct := int(float64(activity.ActiveDays) / float64(threshold) * 100)
|
|
if pct > 100 {
|
|
pct = 100
|
|
}
|
|
if pct < 0 {
|
|
pct = 0
|
|
}
|
|
|
|
s.render(w, "stash.html", stashViewData{
|
|
Stash: stash,
|
|
Activity: activity,
|
|
Found: true,
|
|
BreadScale: scale,
|
|
BalanceBread: balanceBread,
|
|
MaturityPct: pct,
|
|
Mature: activity.IsMature(),
|
|
ThresholdDays: threshold,
|
|
MaxGapDays: stashtypes.MaxGapForMaturity,
|
|
})
|
|
}
|