package market import ( "fmt" "sync" "time" "git.mleku.dev/mleku/dendrite/pkg/axiom" ) // RevenueSource distinguishes where revenue came from. type RevenueSource int const ( ArbitrageRevenue RevenueSource = iota // from exploiting dislocations InfrastructureRevenue // from services (feeds, reputation, relay fees) ) func (rs RevenueSource) String() string { if rs == ArbitrageRevenue { return "arbitrage" } return "infrastructure" } // RevenueEntry records a single revenue event. type RevenueEntry struct { Source RevenueSource Amount float64 Asset string Note string Time time.Time } // RevenueAccounting tracks the split between extractive and corrective revenue. // The organism's health is measured not just by total revenue but by the ratio: // infrastructure revenue should grow while arbitrage revenue shrinks, indicating // the organism is building structure that eliminates the dislocations it fed on. type RevenueAccounting struct { mu sync.Mutex entries []RevenueEntry } // NewRevenueAccounting creates an empty revenue tracker. func NewRevenueAccounting() *RevenueAccounting { return &RevenueAccounting{} } // Record adds a revenue entry. func (ra *RevenueAccounting) Record(entry RevenueEntry) { ra.mu.Lock() defer ra.mu.Unlock() ra.entries = append(ra.entries, entry) } // Summary returns aggregate revenue by source. type RevenueSummary struct { Arbitrage float64 Infrastructure float64 Total float64 InfraRatio float64 // infrastructure / total; higher = healthier EntryCount int } // Summary computes the revenue split. func (ra *RevenueAccounting) Summary() RevenueSummary { ra.mu.Lock() defer ra.mu.Unlock() var s RevenueSummary for _, e := range ra.entries { switch e.Source { case ArbitrageRevenue: s.Arbitrage += e.Amount case InfrastructureRevenue: s.Infrastructure += e.Amount } } s.Total = s.Arbitrage + s.Infrastructure s.EntryCount = len(ra.entries) if s.Total > 0 { s.InfraRatio = s.Infrastructure / s.Total } return s } // IsTransitioning returns true when infrastructure revenue exceeds // arbitrage revenue — the organism has transitioned from parasite to symbiont. func (ra *RevenueAccounting) IsTransitioning() bool { s := ra.Summary() return s.Infrastructure > s.Arbitrage } // RevenueSummaryToElements decomposes the revenue split into lattice elements. func RevenueSummaryToElements(s *RevenueSummary) []axiom.Element { return []axiom.Element{ element{"revenue-arbitrage", s.Arbitrage}, element{"revenue-infrastructure", s.Infrastructure}, element{"revenue-total", s.Total}, element{"revenue-infra-ratio", s.InfraRatio}, element{"revenue-entry-count", s.EntryCount}, element{"timestamp", fmt.Sprintf("%d", time.Now().Unix())}, } }