# Integration with Existing Code ## 发现:holders 包已有类似实现 在 `holders/db_config.go` 中已经实现了从数据库加载合约地址的完整逻辑: ### holders/db_config.go 的实现 ```go // LoadConfigFromDB 从数据库加载配置(已存在) func LoadConfigFromDB(chainID int64) (Config, error) { // 1. 从 assets 表加载 YT-A, YT-B, YT-C var assets []Asset db.Table("assets"). Where("asset_code IN (?, ?, ?)", "YT-A", "YT-B", "YT-C"). Find(&assets) // 2. 根据 chainID 选择合约地址 for _, asset := range assets { address := asset.ContractAddressArb if isBSC { address = asset.ContractAddressBsc } ytVaults = append(ytVaults, VaultConfig{ Name: asset.AssetCode, Address: address, }) } // 3. 从 lending_markets 表加载 Lending 合约 var lendingMarkets []LendingMarket db.Table("lending_markets"). Where("is_active = ?", 1). Find(&lendingMarkets) lendingAddress := market.ContractAddressArb if isBSC { lendingAddress = market.ContractAddressBsc } return Config{ YTVaults: ytVaults, LendingAddress: lendingAddress, } } ``` ### lending/helpers.go 的实现(新建) ```go // GetYTTokenInfo 从 assets 表获取 YT token 信息(新实现) func GetYTTokenInfo(assetCode string) (*TokenInfo, error) { var asset models.Asset db.Where("asset_code = ? AND is_active = ?", assetCode, true). First(&asset) return &TokenInfo{ Symbol: asset.Name, ContractAddressArb: asset.ContractAddressArb, ContractAddressBsc: asset.ContractAddressBsc, } } ``` ## 代码复用建议 ### 选项 1:统一使用 holders 包的结构体(推荐) ```go // lending/helpers.go import "github.com/gothinkster/golang-gin-realworld-example-app/holders" func GetYTTokensFromHolders(chainID int64) ([]TokenInfo, error) { // 复用 holders.LoadConfigFromDB config, err := holders.LoadConfigFromDB(chainID) if err != nil { return nil, err } tokens := make([]TokenInfo, len(config.YTVaults)) for i, vault := range config.YTVaults { tokens[i] = TokenInfo{ Symbol: vault.Name, ContractAddressArb: vault.Address, // 已根据 chainID 选择 AssetCode: vault.Name, } } return tokens, nil } ``` ### 选项 2:共享数据模型 ```go // common/models.go - 创建共享的 Asset 模型 type Asset struct { ID int64 AssetCode string Name string ContractAddressArb string ContractAddressBsc string } // holders 和 lending 都使用这个共享模型 ``` ### 选项 3:保持当前实现(已完成) - ✅ lending 包独立实现 - ✅ 功能完整,逻辑清晰 - ⚠️ 与 holders 包有重复代码 ## 数据库表结构(一致) 两个包都使用相同的表: ### assets 表 ```sql CREATE TABLE assets ( id BIGINT PRIMARY KEY, asset_code VARCHAR(20), -- YT-A, YT-B, YT-C name VARCHAR(255), contract_address_arb VARCHAR(42), contract_address_bsc VARCHAR(42), is_active BOOLEAN ) ``` ### lending_markets 表 ```sql CREATE TABLE lending_markets ( id BIGINT PRIMARY KEY, market_name VARCHAR(100), contract_address_arb VARCHAR(42), contract_address_bsc VARCHAR(42), is_active BOOLEAN ) ``` ## Chain ID 处理 ### holders 包 - 421614 = Arbitrum Sepolia - 97 = BSC Testnet ### lending 包(需要添加) ```go // helpers.go 添加 chain ID 支持 func GetContractAddress(tokenInfo TokenInfo, chainID int) string { switch chainID { case 421614: // Arbitrum Sepolia return tokenInfo.ContractAddressArb case 97: // BSC Testnet return tokenInfo.ContractAddressBsc case 42161: // Arbitrum One (mainnet) return tokenInfo.ContractAddressArb case 56: // BSC Mainnet return tokenInfo.ContractAddressBsc default: return tokenInfo.ContractAddressArb } } ``` ## 总结 ### 已实现功能 - ✅ lending 包可以独立从 assets 表读取 YT tokens - ✅ lending 包可以从 lending_markets 表读取市场配置 - ✅ USDC 地址已硬编码 - ✅ 与 holders 包的实现逻辑一致 ### 建议优化(可选) 1. 考虑复用 holders.Asset 结构体 2. 添加对 holders.LoadConfigFromDB 的引用 3. 统一 chain ID 处理逻辑 ### 当前状态 **可以直接使用**,无需修改。与 holders 包的实现独立但兼容。