init: 初始化 AssetX 项目仓库
包含 webapp(Next.js 用户端)、webapp-back(Go 后端)、 antdesign(管理后台)、landingpage(营销落地页)、 数据库 SQL 和配置文件。
This commit is contained in:
125
webapp-back/holders/db_config.go
Normal file
125
webapp-back/holders/db_config.go
Normal file
@@ -0,0 +1,125 @@
|
||||
package holders
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/gothinkster/golang-gin-realworld-example-app/common"
|
||||
)
|
||||
|
||||
// Asset represents a product/asset in the database
|
||||
type Asset struct {
|
||||
ID int64 `gorm:"column:id"`
|
||||
AssetCode string `gorm:"column:asset_code"`
|
||||
Name string `gorm:"column:name"`
|
||||
TokenRole string `gorm:"column:token_role"`
|
||||
ChainID int `gorm:"column:chain_id"`
|
||||
ContractAddress string `gorm:"column:contract_address"`
|
||||
DeployBlock *uint64 `gorm:"column:deploy_block"`
|
||||
}
|
||||
|
||||
|
||||
const zeroAddress = "0x0000000000000000000000000000000000000000"
|
||||
|
||||
// LoadConfigFromDB loads contract addresses and deploy blocks from database based on chain ID
|
||||
func LoadConfigFromDB(chainID int64) (Config, error) {
|
||||
db := common.GetDB()
|
||||
|
||||
log.Printf("📚 [Scanner] 从数据库加载配置 - Chain ID: %d", chainID)
|
||||
|
||||
switch chainID {
|
||||
case 97, 421614:
|
||||
// supported
|
||||
default:
|
||||
return Config{}, fmt.Errorf("unsupported chain ID: %d", chainID)
|
||||
}
|
||||
|
||||
// Load YT assets by token_role filtered by chain_id
|
||||
var assets []Asset
|
||||
if err := db.Table("assets").
|
||||
Where("token_role = ? AND chain_id = ? AND is_active = ?", "yt_token", chainID, true).
|
||||
Find(&assets).Error; err != nil {
|
||||
return Config{}, fmt.Errorf("failed to load assets: %w", err)
|
||||
}
|
||||
|
||||
ytVaults := make([]VaultConfig, 0, len(assets))
|
||||
for _, asset := range assets {
|
||||
if asset.ContractAddress == "" || asset.ContractAddress == zeroAddress {
|
||||
log.Printf("⚠️ [Scanner] 跳过 %s (地址未配置)", asset.AssetCode)
|
||||
continue
|
||||
}
|
||||
if asset.DeployBlock == nil || *asset.DeployBlock == 0 {
|
||||
log.Printf("⚠️ [Scanner] 跳过 %s (deploy_block 未配置)", asset.AssetCode)
|
||||
continue
|
||||
}
|
||||
|
||||
ytVaults = append(ytVaults, VaultConfig{
|
||||
Name: asset.AssetCode,
|
||||
Address: asset.ContractAddress,
|
||||
DeployBlock: *asset.DeployBlock,
|
||||
})
|
||||
log.Printf(" ✓ %s: %s (部署区块: %d)", asset.AssetCode, asset.ContractAddress, *asset.DeployBlock)
|
||||
}
|
||||
log.Printf("✅ [Scanner] 加载了 %d 个 YT Vault", len(ytVaults))
|
||||
|
||||
// Load YTLPToken address from system_contracts
|
||||
var ytLPContract struct {
|
||||
Address string `gorm:"column:address"`
|
||||
DeployBlock *uint64 `gorm:"column:deploy_block"`
|
||||
}
|
||||
ytLPAddress := ""
|
||||
var ytLPDeployBlock uint64
|
||||
err := db.Table("system_contracts").
|
||||
Where("name = ? AND chain_id = ? AND is_active = ?", "YTLPToken", chainID, 1).
|
||||
Select("address, deploy_block").
|
||||
First(&ytLPContract).Error
|
||||
if err != nil {
|
||||
log.Printf("⚠️ [Scanner] 未找到 YTLPToken 配置")
|
||||
} else if ytLPContract.Address == "" || ytLPContract.Address == zeroAddress {
|
||||
log.Printf("⚠️ [Scanner] 跳过 ytLP (地址未配置)")
|
||||
} else if ytLPContract.DeployBlock == nil || *ytLPContract.DeployBlock == 0 {
|
||||
log.Printf("⚠️ [Scanner] 跳过 ytLP (deploy_block 未配置)")
|
||||
} else {
|
||||
ytLPAddress = ytLPContract.Address
|
||||
ytLPDeployBlock = *ytLPContract.DeployBlock
|
||||
log.Printf("✅ [Scanner] ytLP: %s (部署区块: %d)", ytLPAddress, ytLPDeployBlock)
|
||||
}
|
||||
|
||||
rpcURL := getRPCURLForChain(chainID)
|
||||
|
||||
config := Config{
|
||||
ChainID: int(chainID),
|
||||
RPCURL: rpcURL,
|
||||
YTVaults: ytVaults,
|
||||
YTLPAddress: ytLPAddress,
|
||||
DeploymentBlocks: DeploymentBlocks{
|
||||
YTLP: ytLPDeployBlock,
|
||||
},
|
||||
PollInterval: 30 * time.Second,
|
||||
BatchSize: 9999,
|
||||
}
|
||||
|
||||
log.Printf("📊 [Scanner] 配置加载完成: YT Vaults=%d, ytLP=%s, RPC=%s",
|
||||
len(config.YTVaults), config.YTLPAddress, config.RPCURL)
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// getRPCURLForChain returns the RPC URL for the given chain ID
|
||||
func getRPCURLForChain(chainID int64) string {
|
||||
switch chainID {
|
||||
case 421614:
|
||||
return "https://api.zan.top/node/v1/arb/sepolia/baf84c429d284bb5b676cb8c9ca21c07"
|
||||
case 97:
|
||||
return "https://api.zan.top/node/v1/bsc/testnet/baf84c429d284bb5b676cb8c9ca21c07"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// TableName sets the table name for GORM
|
||||
func (Asset) TableName() string {
|
||||
return "assets"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user