package models import ( "time" ) // HolderSnapshot represents token holders data from blockchain type HolderSnapshot struct { ID uint `gorm:"primaryKey;autoIncrement" json:"id"` HolderAddress string `gorm:"size:42;not null;index:idx_holder_token" json:"holder_address"` TokenType string `gorm:"size:50;not null;index:idx_holder_token,idx_token_time" json:"token_type"` TokenAddress string `gorm:"size:42;not null" json:"token_address"` Balance string `gorm:"type:varchar(78);not null" json:"balance"` ChainID int `gorm:"not null" json:"chain_id"` FirstSeen int64 `gorm:"not null" json:"first_seen"` LastUpdated int64 `gorm:"not null;index:idx_token_time" json:"last_updated"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } func (HolderSnapshot) TableName() string { return "holder_snapshots" } // HolderStats represents aggregated statistics for each token type type HolderStats struct { TokenType string `json:"token_type"` HolderCount int `json:"holder_count"` TotalBalance string `json:"total_balance,omitempty"` } // ScannerState persists scanner progress so it can resume after restart type ScannerState struct { ID uint `gorm:"primaryKey;autoIncrement"` ScannerType string `gorm:"column:scanner_type;not null;default:'holder';uniqueIndex:idx_chain_scanner"` ChainID int `gorm:"column:chain_id;uniqueIndex:idx_chain_scanner;not null"` LastScannedBlock uint64 `gorm:"column:last_scanned_block;not null;default:0"` UpdatedAt time.Time `gorm:"column:updated_at"` } func (ScannerState) TableName() string { return "scanner_state" }