Files
assetx/webapp-back/holders/db_config.go

126 lines
3.9 KiB
Go
Raw Normal View History

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"
}