Files
assetx/webapp-back/lending/INTEGRATION_NOTE.md
default 2ee4553b71 init: 初始化 AssetX 项目仓库
包含 webapp(Next.js 用户端)、webapp-back(Go 后端)、
antdesign(管理后台)、landingpage(营销落地页)、
数据库 SQL 和配置文件。
2026-03-27 11:26:43 +00:00

4.5 KiB
Raw Permalink Blame History

Integration with Existing Code

发现holders 包已有类似实现

holders/db_config.go 中已经实现了从数据库加载合约地址的完整逻辑:

holders/db_config.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 的实现(新建)

// 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 包的结构体(推荐)

// 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共享数据模型

// common/models.go - 创建共享的 Asset 模型
type Asset struct {
    ID                 int64
    AssetCode          string
    Name               string
    ContractAddressArb string
    ContractAddressBsc string
}

// holders 和 lending 都使用这个共享模型

选项 3保持当前实现已完成

  • lending 包独立实现
  • 功能完整,逻辑清晰
  • ⚠️ 与 holders 包有重复代码

数据库表结构(一致)

两个包都使用相同的表:

assets 表

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 表

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 包(需要添加)

// 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 包的实现独立但兼容。