263 lines
11 KiB
Go
263 lines
11 KiB
Go
|
|
package models
|
||
|
|
|
||
|
|
import (
|
||
|
|
"time"
|
||
|
|
)
|
||
|
|
|
||
|
|
// Season represents the seasons table
|
||
|
|
type Season struct {
|
||
|
|
ID uint `gorm:"primaryKey;autoIncrement" json:"id"`
|
||
|
|
SeasonNumber int `gorm:"not null;unique;index" json:"season_number"`
|
||
|
|
SeasonName string `gorm:"size:100;not null" json:"season_name"`
|
||
|
|
StartTime time.Time `gorm:"not null" json:"start_time"`
|
||
|
|
EndTime time.Time `gorm:"not null" json:"end_time"`
|
||
|
|
Status string `gorm:"size:20;default:'upcoming'" json:"status"` // upcoming, active, ended
|
||
|
|
TotalRewards float64 `gorm:"type:decimal(30,2)" json:"total_rewards"`
|
||
|
|
Multiplier float64 `gorm:"type:decimal(10,4);default:1.0000" json:"multiplier"`
|
||
|
|
Description string `gorm:"type:text" json:"description"`
|
||
|
|
IsActive bool `gorm:"default:true" json:"is_active"`
|
||
|
|
CreatedAt time.Time `json:"created_at"`
|
||
|
|
UpdatedAt time.Time `json:"updated_at"`
|
||
|
|
}
|
||
|
|
|
||
|
|
func (Season) TableName() string {
|
||
|
|
return "seasons"
|
||
|
|
}
|
||
|
|
|
||
|
|
// VIPTier represents the vip_tiers table
|
||
|
|
type VIPTier struct {
|
||
|
|
ID uint `gorm:"primaryKey;autoIncrement" json:"id"`
|
||
|
|
TierName string `gorm:"size:50;not null" json:"tier_name"`
|
||
|
|
TierLevel int `gorm:"not null;unique;index" json:"tier_level"`
|
||
|
|
MinPoints int64 `gorm:"not null;index" json:"min_points"`
|
||
|
|
MaxPoints *int64 `json:"max_points"`
|
||
|
|
Multiplier float64 `gorm:"type:decimal(10,4);default:1.0000" json:"multiplier"`
|
||
|
|
Perks string `gorm:"type:json" json:"perks"`
|
||
|
|
Icon string `gorm:"size:255" json:"icon"`
|
||
|
|
Color string `gorm:"size:50" json:"color"`
|
||
|
|
DisplayOrder int `gorm:"default:0" json:"display_order"`
|
||
|
|
IsActive bool `gorm:"default:true" json:"is_active"`
|
||
|
|
CreatedAt time.Time `json:"created_at"`
|
||
|
|
UpdatedAt time.Time `json:"updated_at"`
|
||
|
|
}
|
||
|
|
|
||
|
|
func (VIPTier) TableName() string {
|
||
|
|
return "vip_tiers"
|
||
|
|
}
|
||
|
|
|
||
|
|
// UserTeam represents the user_teams table
|
||
|
|
type UserTeam struct {
|
||
|
|
WalletAddress string `gorm:"primaryKey;size:42" json:"wallet_address"`
|
||
|
|
TeamTVLUSD float64 `gorm:"type:decimal(30,2);default:0.00" json:"team_tvl_usd"`
|
||
|
|
TeamTargetTVLUSD float64 `gorm:"type:decimal(30,2);default:10000000.00" json:"team_target_tvl_usd"`
|
||
|
|
TeamMembersCount int `gorm:"default:0" json:"team_members_count"`
|
||
|
|
WhalesCount int `gorm:"default:0" json:"whales_count"`
|
||
|
|
WhalesTarget int `gorm:"default:3" json:"whales_target"`
|
||
|
|
TradersCount int `gorm:"default:0" json:"traders_count"`
|
||
|
|
TradersTarget int `gorm:"default:3" json:"traders_target"`
|
||
|
|
UsersCount int `gorm:"default:0" json:"users_count"`
|
||
|
|
UsersTarget int `gorm:"default:3" json:"users_target"`
|
||
|
|
LastCalculatedAt *time.Time `json:"last_calculated_at"`
|
||
|
|
CreatedAt time.Time `json:"created_at"`
|
||
|
|
UpdatedAt time.Time `json:"updated_at"`
|
||
|
|
}
|
||
|
|
|
||
|
|
func (UserTeam) TableName() string {
|
||
|
|
return "user_teams"
|
||
|
|
}
|
||
|
|
|
||
|
|
// UserPointsSummary represents the user_points_summary table
|
||
|
|
type UserPointsSummary struct {
|
||
|
|
WalletAddress string `gorm:"primaryKey;size:42" json:"wallet_address"`
|
||
|
|
TotalPoints int64 `gorm:"default:0" json:"total_points"`
|
||
|
|
HoldingPoints int64 `gorm:"default:0" json:"holding_points"`
|
||
|
|
LpPoints int64 `gorm:"default:0" json:"lp_points"`
|
||
|
|
LendingPoints int64 `gorm:"default:0" json:"lending_points"`
|
||
|
|
TradingPoints int64 `gorm:"default:0" json:"trading_points"`
|
||
|
|
InvitationPoints int64 `gorm:"default:0" json:"invitation_points"`
|
||
|
|
BonusPoints int64 `gorm:"default:0" json:"bonus_points"`
|
||
|
|
GlobalRank *int `json:"global_rank"`
|
||
|
|
SeasonRank *int `json:"season_rank"`
|
||
|
|
CurrentSeason int `gorm:"default:1" json:"current_season"`
|
||
|
|
TotalTrades int `gorm:"default:0" json:"total_trades"`
|
||
|
|
TotalHoldingDays int `gorm:"default:0" json:"total_holding_days"`
|
||
|
|
TotalInvites int `gorm:"default:0" json:"total_invites"`
|
||
|
|
LastCalculatedAt *time.Time `json:"last_calculated_at"`
|
||
|
|
UpdatedAt time.Time `json:"updated_at"`
|
||
|
|
}
|
||
|
|
|
||
|
|
func (UserPointsSummary) TableName() string {
|
||
|
|
return "user_points_summary"
|
||
|
|
}
|
||
|
|
|
||
|
|
// UserPointsRecord represents the user_points_records table
|
||
|
|
type UserPointsRecord struct {
|
||
|
|
ID uint `gorm:"primaryKey;autoIncrement" json:"id"`
|
||
|
|
WalletAddress string `gorm:"size:42;not null;index" json:"wallet_address"`
|
||
|
|
PointsChange int `gorm:"not null" json:"points_change"`
|
||
|
|
PointsBefore int `gorm:"not null" json:"points_before"`
|
||
|
|
PointsAfter int `gorm:"not null" json:"points_after"`
|
||
|
|
SourceType string `gorm:"size:50;not null" json:"source_type"`
|
||
|
|
MultiplierApplied float64 `gorm:"type:decimal(10,4);default:1.0000" json:"multiplier_applied"`
|
||
|
|
SourceID *uint `json:"source_id"`
|
||
|
|
RuleID *uint `json:"rule_id"`
|
||
|
|
Description string `gorm:"type:text" json:"description"`
|
||
|
|
Metadata string `gorm:"type:json" json:"metadata"`
|
||
|
|
CreatedAt time.Time `json:"created_at"`
|
||
|
|
}
|
||
|
|
|
||
|
|
func (UserPointsRecord) TableName() string {
|
||
|
|
return "user_points_records"
|
||
|
|
}
|
||
|
|
|
||
|
|
// Invitation represents the invitations table
|
||
|
|
type Invitation struct {
|
||
|
|
ID uint `gorm:"primaryKey;autoIncrement" json:"id"`
|
||
|
|
ReferrerWallet string `gorm:"size:42;not null;index" json:"referrer_wallet"`
|
||
|
|
RefereeWallet string `gorm:"size:42;not null;unique;index" json:"referee_wallet"`
|
||
|
|
InviteCode string `gorm:"size:20;not null" json:"invite_code"`
|
||
|
|
BindSignature string `gorm:"type:text" json:"bind_signature"`
|
||
|
|
BindHash string `gorm:"size:66" json:"bind_hash"`
|
||
|
|
Status string `gorm:"size:50;default:'active'" json:"status"`
|
||
|
|
ReferrerRewardPoints int `gorm:"default:0" json:"referrer_reward_points"`
|
||
|
|
RefereeRewardPoints int `gorm:"default:0" json:"referee_reward_points"`
|
||
|
|
BoundAt time.Time `gorm:"not null" json:"bound_at"`
|
||
|
|
CreatedAt time.Time `json:"created_at"`
|
||
|
|
}
|
||
|
|
|
||
|
|
func (Invitation) TableName() string {
|
||
|
|
return "invitations"
|
||
|
|
}
|
||
|
|
|
||
|
|
// InviteCode represents the invite_codes table
|
||
|
|
type InviteCode struct {
|
||
|
|
ID uint `gorm:"primaryKey;autoIncrement" json:"id"`
|
||
|
|
WalletAddress string `gorm:"size:42;not null;unique;index" json:"wallet_address"`
|
||
|
|
Code string `gorm:"size:20;not null;unique;index" json:"code"`
|
||
|
|
MaxUses int `gorm:"default:-1" json:"max_uses"` // -1 = unlimited
|
||
|
|
UsedCount int `gorm:"default:0" json:"used_count"`
|
||
|
|
ExpiresAt NullTime `json:"expires_at"`
|
||
|
|
IsActive bool `gorm:"default:true" json:"is_active"`
|
||
|
|
CreatedAt time.Time `json:"created_at"`
|
||
|
|
}
|
||
|
|
|
||
|
|
func (InviteCode) TableName() string {
|
||
|
|
return "invite_codes"
|
||
|
|
}
|
||
|
|
|
||
|
|
// =====================
|
||
|
|
// Response DTOs
|
||
|
|
// =====================
|
||
|
|
|
||
|
|
// DashboardResponse is the response for GET /api/points/dashboard
|
||
|
|
type DashboardResponse struct {
|
||
|
|
TotalPoints int64 `json:"totalPoints"`
|
||
|
|
GlobalRank int `json:"globalRank"`
|
||
|
|
TopPercentage string `json:"topPercentage"`
|
||
|
|
MemberTier string `json:"memberTier"`
|
||
|
|
VIPLevel int `json:"vipLevel"`
|
||
|
|
PointsToNextTier int64 `json:"pointsToNextTier"`
|
||
|
|
NextTier string `json:"nextTier"`
|
||
|
|
Season SeasonInfo `json:"season"`
|
||
|
|
}
|
||
|
|
|
||
|
|
// SeasonInfo contains season information
|
||
|
|
type SeasonInfo struct {
|
||
|
|
SeasonNumber int `json:"seasonNumber"`
|
||
|
|
SeasonName string `json:"seasonName"`
|
||
|
|
IsLive bool `json:"isLive"`
|
||
|
|
EndTime time.Time `json:"endTime"`
|
||
|
|
DaysRemaining int `json:"daysRemaining"`
|
||
|
|
HoursRemaining int `json:"hoursRemaining"`
|
||
|
|
}
|
||
|
|
|
||
|
|
// LeaderboardResponse is the response for GET /api/points/leaderboard
|
||
|
|
type LeaderboardResponse struct {
|
||
|
|
TopUsers []LeaderboardUser `json:"topUsers"`
|
||
|
|
MyRank int `json:"myRank"`
|
||
|
|
MyPoints int64 `json:"myPoints"`
|
||
|
|
}
|
||
|
|
|
||
|
|
// LeaderboardUser represents a user in the leaderboard
|
||
|
|
type LeaderboardUser struct {
|
||
|
|
Rank int `json:"rank"`
|
||
|
|
WalletAddress string `json:"address"`
|
||
|
|
Points int64 `json:"points"`
|
||
|
|
}
|
||
|
|
|
||
|
|
// InviteCodeResponse is the response for GET /api/points/invite-code
|
||
|
|
type InviteCodeResponse struct {
|
||
|
|
Code string `json:"code"`
|
||
|
|
UsedCount int `json:"usedCount"`
|
||
|
|
MaxUses int `json:"maxUses"`
|
||
|
|
}
|
||
|
|
|
||
|
|
// TeamTVLResponse is the response for GET /api/points/team
|
||
|
|
type TeamTVLResponse struct {
|
||
|
|
CurrentTVL string `json:"currentTVL"`
|
||
|
|
TargetTVL string `json:"targetTVL"`
|
||
|
|
ProgressPercent float64 `json:"progressPercent"`
|
||
|
|
TotalMembers int `json:"totalMembers"`
|
||
|
|
Roles []RoleCount `json:"roles"`
|
||
|
|
}
|
||
|
|
|
||
|
|
// RoleCount represents count for each role
|
||
|
|
type RoleCount struct {
|
||
|
|
Icon string `json:"icon"`
|
||
|
|
Label string `json:"label"`
|
||
|
|
Current int `json:"current"`
|
||
|
|
Target int `json:"target"`
|
||
|
|
}
|
||
|
|
|
||
|
|
// ActivitiesResponse is the response for GET /api/points/activities
|
||
|
|
type ActivitiesResponse struct {
|
||
|
|
Activities []ActivityRecord `json:"activities"`
|
||
|
|
Pagination PaginationInfo `json:"pagination"`
|
||
|
|
}
|
||
|
|
|
||
|
|
// ActivityRecord represents a single activity
|
||
|
|
type ActivityRecord struct {
|
||
|
|
Type string `json:"type"`
|
||
|
|
UserAddress string `json:"userAddress"`
|
||
|
|
FriendAddress string `json:"friendAddress,omitempty"`
|
||
|
|
InviteCode string `json:"inviteCode,omitempty"`
|
||
|
|
Points int `json:"points"`
|
||
|
|
CreatedAt time.Time `json:"createdAt"`
|
||
|
|
}
|
||
|
|
|
||
|
|
// PaginationInfo contains pagination metadata
|
||
|
|
type PaginationInfo struct {
|
||
|
|
Page int `json:"page"`
|
||
|
|
PageSize int `json:"pageSize"`
|
||
|
|
Total int `json:"total"`
|
||
|
|
TotalPage int `json:"totalPage"`
|
||
|
|
}
|
||
|
|
|
||
|
|
// BindInviteRequest is the request body for POST /api/points/bind-invite
|
||
|
|
type BindInviteRequest struct {
|
||
|
|
Code string `json:"code" binding:"required"`
|
||
|
|
Signature string `json:"signature" binding:"required"`
|
||
|
|
}
|
||
|
|
|
||
|
|
// HoldersSnapshot represents the holders_snapshots table
|
||
|
|
// 每小时快照:记录用户持有 YT/LP/Lending 代币的余额及积分计算结果
|
||
|
|
type HoldersSnapshot struct {
|
||
|
|
ID uint `gorm:"primaryKey;autoIncrement" json:"id"`
|
||
|
|
WalletAddress string `gorm:"size:42;not null;index" json:"wallet_address"`
|
||
|
|
TokenType string `gorm:"size:20;not null" json:"token_type"`
|
||
|
|
TokenAddress string `gorm:"size:42;not null" json:"token_address"`
|
||
|
|
ChainID int `gorm:"not null" json:"chain_id"`
|
||
|
|
Balance float64 `gorm:"type:decimal(30,18);not null" json:"balance"`
|
||
|
|
BalanceUSD float64 `gorm:"type:decimal(30,2)" json:"balance_usd"`
|
||
|
|
HoldingDurationHours int `json:"holding_duration_hours"`
|
||
|
|
PointsMultiplier float64 `gorm:"type:decimal(10,4);default:1.0000" json:"points_multiplier"`
|
||
|
|
EarnedPoints int `json:"earned_points"`
|
||
|
|
SnapshotTime time.Time `gorm:"not null;index" json:"snapshot_time"`
|
||
|
|
SeasonID *uint `gorm:"index" json:"season_id"`
|
||
|
|
CreatedAt time.Time `json:"created_at"`
|
||
|
|
}
|
||
|
|
|
||
|
|
func (HoldersSnapshot) TableName() string {
|
||
|
|
return "holders_snapshots"
|
||
|
|
}
|