175 lines
4.5 KiB
Markdown
175 lines
4.5 KiB
Markdown
|
|
# 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 包的实现独立但兼容。
|