init: 初始化 AssetX 项目仓库

包含 webapp(Next.js 用户端)、webapp-back(Go 后端)、
antdesign(管理后台)、landingpage(营销落地页)、
数据库 SQL 和配置文件。
This commit is contained in:
2026-03-27 11:26:43 +00:00
commit 2ee4553b71
634 changed files with 988255 additions and 0 deletions

200
webapp-back/main.go Normal file
View File

@@ -0,0 +1,200 @@
package main
import (
"log"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
"github.com/gothinkster/golang-gin-realworld-example-app/admin"
"github.com/gothinkster/golang-gin-realworld-example-app/alp"
"github.com/gothinkster/golang-gin-realworld-example-app/articles"
"github.com/gothinkster/golang-gin-realworld-example-app/common"
"github.com/gothinkster/golang-gin-realworld-example-app/config"
"github.com/gothinkster/golang-gin-realworld-example-app/fundmarket"
"github.com/gothinkster/golang-gin-realworld-example-app/holders"
"github.com/gothinkster/golang-gin-realworld-example-app/lending"
"github.com/gothinkster/golang-gin-realworld-example-app/middleware"
"github.com/gothinkster/golang-gin-realworld-example-app/models"
"github.com/gothinkster/golang-gin-realworld-example-app/points"
"github.com/gothinkster/golang-gin-realworld-example-app/users"
"gorm.io/gorm"
)
func Migrate(db *gorm.DB) {
// Original tables
users.AutoMigrate()
db.AutoMigrate(&articles.ArticleModel{})
db.AutoMigrate(&articles.TagModel{})
db.AutoMigrate(&articles.FavoriteModel{})
db.AutoMigrate(&articles.ArticleUserModel{})
db.AutoMigrate(&articles.CommentModel{})
// AssetX core tables
db.AutoMigrate(&models.User{})
db.AutoMigrate(&models.HolderSnapshot{})
db.AutoMigrate(&models.Asset{})
db.AutoMigrate(&models.AssetPerformance{})
db.AutoMigrate(&models.APYSnapshot{})
db.AutoMigrate(&models.AssetCustody{})
db.AutoMigrate(&models.AssetAuditReport{})
// Config / content tables
db.AutoMigrate(&models.SystemContract{})
db.AutoMigrate(&models.ProductLink{})
// Points system tables
db.AutoMigrate(&models.PointsRule{})
db.AutoMigrate(&models.Season{})
db.AutoMigrate(&models.VIPTier{})
db.AutoMigrate(&models.InviteCode{})
db.AutoMigrate(&models.Invitation{})
db.AutoMigrate(&models.UserPointsSummary{})
db.AutoMigrate(&models.UserPointsRecord{})
db.AutoMigrate(&models.UserTeam{})
// ALP pool snapshots
db.AutoMigrate(&models.ALPSnapshot{})
// Liquidation bot records
db.AutoMigrate(&models.LiquidationRecord{})
db.AutoMigrate(&models.KnownBorrower{})
// Collateral buyer bot records
db.AutoMigrate(&models.CollateralBuyRecord{})
// Scanner state: drop old single-column unique index, then migrate with composite index
db.Exec("ALTER TABLE scanner_state DROP INDEX `uni_chain_id`") // ignore error if not exists
db.AutoMigrate(&models.ScannerState{})
// YT Swap event records (for "Your Total Earning" calculation)
db.AutoMigrate(&models.YTSwapRecord{})
// Audit / ops
db.AutoMigrate(&models.OperationLog{})
log.Println("✓ Database migration completed")
}
func main() {
cfg := config.Load()
log.Println("✓ Configuration loaded")
var db *gorm.DB
if cfg.DBType == "mysql" {
db = common.InitMySQL()
} else {
db = common.Init()
}
Migrate(db)
sqlDB, err := db.DB()
if err != nil {
log.Println("failed to get sql.DB:", err)
} else {
defer sqlDB.Close()
}
common.InitRedis()
// Start holder scanner (continuous block scanning)
go holders.StartAllScanners()
// Start background snapshot services (run every hour)
go fundmarket.StartPriceSnapshot(cfg)
go alp.StartALPSnapshot(cfg)
go lending.StartLendingAPYSnapshot(cfg)
// Start liquidation bot (requires LIQUIDATOR_PRIVATE_KEY)
go lending.StartLiquidationBot(cfg)
// Start collateral buyer bot (requires COLLATERAL_BUYER_PRIVATE_KEY)
go lending.StartCollateralBuyerBot(cfg)
if cfg.GinMode == "release" {
gin.SetMode(gin.ReleaseMode)
}
r := gin.Default()
r.Use(cors.New(cors.Config{
AllowAllOrigins: true,
AllowMethods: []string{"GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"},
AllowHeaders: []string{"Origin", "Content-Type", "Authorization"},
ExposeHeaders: []string{"Content-Length"},
AllowCredentials: false,
}))
r.RedirectTrailingSlash = false
// Serve uploaded files
r.Static("/uploads", "./uploads")
v1 := r.Group("/api")
// Public routes
users.UsersRegister(v1.Group("/users"))
articles.ArticlesAnonymousRegister(v1.Group("/articles"))
articles.TagsAnonymousRegister(v1.Group("/tags"))
users.ProfileRetrieveRegister(v1.Group("/profiles"))
v1.GET("/holders/stats", holders.GetStats)
v1.GET("/holders/:tokenType", holders.GetHoldersByType)
v1.GET("/contracts", admin.GetContracts)
v1.GET("/fundmarket/products", fundmarket.GetProducts)
v1.GET("/fundmarket/stats", fundmarket.GetStats)
v1.GET("/fundmarket/products/:id", fundmarket.GetProductByID)
v1.GET("/fundmarket/products/:id/history", fundmarket.GetProductHistory)
v1.GET("/fundmarket/products/:id/daily-returns", fundmarket.GetDailyReturns)
v1.GET("/fundmarket/net-deposited", fundmarket.GetNetDeposited)
v1.GET("/alp/stats", alp.GetALPStats)
v1.GET("/alp/history", alp.GetALPHistory)
v1.GET("/lending/position/:address", lending.GetUserPosition)
v1.GET("/lending/stats", lending.GetLendingStats)
v1.GET("/lending/markets", lending.GetLendingMarkets)
v1.GET("/lending/apy-history", lending.GetLendingAPYHistory)
v1.GET("/lending/tokens", lending.GetTokensInfo)
v1.GET("/lending/tokens/:assetCode", lending.GetTokenInfo)
v1.POST("/lending/supply", lending.SupplyUSDC)
v1.POST("/lending/withdraw", lending.WithdrawUSDC)
v1.POST("/lending/supply-collateral", lending.SupplyCollateral)
v1.POST("/lending/withdraw-collateral", lending.WithdrawCollateral)
v1.POST("/lending/borrow", lending.BorrowUSDC)
v1.POST("/lending/repay", lending.RepayUSDC)
v1.POST("/points/wallet-register", points.WalletRegister)
v1.GET("/points/dashboard", points.GetDashboard)
v1.GET("/points/leaderboard", points.GetLeaderboard)
v1.GET("/points/invite-code", points.GetInviteCode)
v1.POST("/points/bind-invite", points.BindInvite)
v1.GET("/points/team", points.GetTeamTVL)
v1.GET("/points/activities", points.GetActivities)
// Admin API (has its own auth + RequireAdmin middleware internally)
admin.RegisterRoutes(v1)
// Protected routes
v1.Use(middleware.AuthMiddleware(true))
{
users.UserRegister(v1.Group("/user"))
users.ProfileRegister(v1.Group("/profiles"))
articles.ArticlesRegister(v1.Group("/articles"))
holdersGroup := v1.Group("/holders")
holdersGroup.POST("/update", middleware.RequireAdmin(), holders.UpdateHolders)
}
r.GET("/api/ping", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "pong", "version": "1.0.0-assetx"})
})
port := ":" + cfg.Port
log.Printf("✓ Server starting on port %s\n", cfg.Port)
if err := r.Run(port); err != nil {
log.Fatal("failed to start server:", err)
}
}