Reputation Score Explorer
The score explorer provides transparency into how FairScore is calculated.
Overview
Located at /score, the explorer shows:
- Overall FairScore with tier badge
- Breakdown of 7 scoring factors
- Earned badges
- Tips for improving score
Scoring Factors
| Factor | Weight | Description |
|---|---|---|
| Active Days | 25% | Days with on-chain activity |
| Transaction Count | 20% | Total transactions made |
| LST Holdings | 15% | Liquid Staking Token percentile |
| Native SOL | 15% | SOL holdings percentile |
| Stablecoin Holdings | 10% | Stablecoin holdings percentile |
| Wallet Age | 10% | How long wallet existed |
| Activity Consistency | 5% | Regular transaction pattern |
Implementation
Component Usage
import { ReputationScoreExplorer } from '@/components/score/ReputationScoreExplorer'
<ReputationScoreExplorer />Data Source
Uses the useFairScore hook:
const { data: scoreData, loading } = useFairScore()
// scoreData.features contains factor values
interface FairScoreFeatures {
active_days?: number
tx_count?: number
lst_percentile_score?: number
native_sol_percentile?: number
stable_percentile_score?: number
wallet_age_days?: number
median_gap_hours?: number
}Score Calculation
Formula
FairScore = Base Score + Social Score
Base Score = Σ (Factor Value / Max Value) × WeightFactor Details
Active Days (25%)
// Your Value: scoreData.features.active_days
// Max Value: 100
// Score = (active_days / 100) × 25
if (active_days > 100) return 25 // Max score
return (active_days / 100) * 25Transaction Count (20%)
// Your Value: scoreData.features.tx_count
// Max Value: 1000
// Score = (tx_count / 1000) × 20LST Holdings (15%)
// Your Value: scoreData.features.lst_percentile_score
// Percentile 0-100
// Score = (percentile / 100) × 15Native SOL (15%)
// Your Value: scoreData.features.native_sol_percentile
// Percentile 0-100
// Score = (percentile / 100) × 15Stablecoin Holdings (10%)
// Your Value: scoreData.features.stable_percentile_score
// Percentile 0-100
// Score = (percentile / 100) × 10Wallet Age (10%)
// Your Value: scoreData.features.wallet_age_days
// Max Value: 730 (2 years)
// Score = (wallet_age_days / 730) × 10Activity Consistency (5%)
// Your Value: scoreData.features.median_gap_hours
// Lower is better (regular activity)
// Max Value: 720 hours (30 days gap)
// Score = (1 - median_gap_hours / 720) × 5Tier Thresholds
| Tier | Score Range | Voting Multiplier |
|---|---|---|
| Platinum | 80-100 | 3.0x |
| Gold | 60-79 | 2.2x |
| Silver | 40-59 | 1.8x |
| Bronze | 20-39 | 1.4x |
| Unscored | 0-19 | 1.0x |
UI Components
Score Header
<div className="bg-gradient-to-br from-indigo-500 to-purple-600 rounded-xl p-6">
<div className="text-5xl font-bold">{fairscore}</div>
<span className="px-3 py-1 rounded-full">{tier} Tier</span>
<div className="text-sm">{badges.length} badges earned</div>
</div>Factor Breakdown
Each factor shows as an expandable card:
<div className="bg-white border rounded-lg">
<button onClick={() => setExpanded(!expanded)}>
<div className="flex items-center gap-4">
<Icon />
<div className="flex-1">
<span>{factor.name}</span>
<div className="h-2 bg-slate-100 rounded-full">
<div className="h-full bg-indigo-500" style={{ width: `${percentage}%` }} />
</div>
</div>
<span>{score} / {weight} pts</span>
</div>
</button>
{expanded && (
<div className="bg-slate-50 rounded-lg p-3">
<p>{factor.description}</p>
<div className="flex justify-between">
<span>Your Value: {value}</span>
<span>Max: {maxValue}</span>
</div>
</div>
)}
</div>Badges Display
<div className="grid grid-cols-2 sm:grid-cols-3 gap-3">
{badges.map(badge => (
<div key={badge.id} className="bg-white border rounded-lg p-3">
<div className="flex items-center gap-2">
<div className={`w-6 h-6 rounded-full ${getBadgeColor(badge.tier)}`} />
<span>{badge.label}</span>
</div>
<p className="text-xs text-slate-500">{badge.description}</p>
</div>
))}
</div>Improving Your Score
The explorer includes actionable tips:
<div className="bg-slate-50 rounded-lg p-4">
<h4>How to Improve Your Score</h4>
<ul>
<li>Stay active - transact regularly</li>
<li>Hold LSTs - stake your SOL</li>
<li>Maintain consistency - regular activity over bursts</li>
<li>Build history - older wallets score higher</li>
</ul>
</div>Integration
Navigation Link
Added to main navigation:
const navLinks = [
{ href: '/', label: 'Dashboard' },
{ href: '/proposals', label: 'Proposals' },
{ href: '/delegates', label: 'Delegates' },
{ href: '/score', label: 'My Score' },
{ href: '/analytics', label: 'Analytics' },
]Page Route
// app/score/page.tsx
export default function ScoreExplorerPage() {
return (
<div className="min-h-screen bg-slate-50">
<Navigation />
<main className="max-w-3xl mx-auto px-4 py-8">
<h1>Reputation Score Explorer</h1>
<ReputationScoreExplorer />
</main>
</div>
)
}Privacy Considerations
- Scores are public on-chain data
- Factor details may reveal financial positions
- Users should understand implications before sharing
Future Enhancements
- Historical score tracking over time
- Score comparison with similar wallets
- Projected score with suggested actions
- Export score report as PDF