84 lines
2.5 KiB
Go
84 lines
2.5 KiB
Go
package mysql
|
|
|
|
import (
|
|
"context"
|
|
"sort"
|
|
"strings"
|
|
|
|
"hyapp/pkg/appcode"
|
|
"hyapp/pkg/xerr"
|
|
"hyapp/services/wallet-service/internal/domain/ledger"
|
|
)
|
|
|
|
// GetBalances 读取用户多资产余额;指定资产不存在时返回 0 投影,便于客户端稳定渲染。
|
|
func (r *Repository) GetBalances(ctx context.Context, userID int64, assetTypes []string) ([]ledger.AssetBalance, error) {
|
|
if r == nil || r.db == nil {
|
|
return nil, xerr.New(xerr.Unavailable, "mysql repository is not configured")
|
|
}
|
|
assetTypes = normalizeAssetTypes(assetTypes)
|
|
appCode := appcode.FromContext(ctx)
|
|
|
|
query := `SELECT app_code, user_id, asset_type, available_amount, frozen_amount, version, updated_at_ms
|
|
FROM wallet_accounts WHERE app_code = ? AND user_id = ?`
|
|
args := []any{appCode, userID}
|
|
if len(assetTypes) > 0 {
|
|
placeholders := strings.TrimRight(strings.Repeat("?,", len(assetTypes)), ",")
|
|
query += " AND asset_type IN (" + placeholders + ")"
|
|
for _, assetType := range assetTypes {
|
|
args = append(args, assetType)
|
|
}
|
|
}
|
|
query += " ORDER BY asset_type"
|
|
|
|
rows, err := r.db.QueryContext(ctx, query, args...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
byAsset := make(map[string]ledger.AssetBalance)
|
|
for rows.Next() {
|
|
var balance ledger.AssetBalance
|
|
if err := rows.Scan(&balance.AppCode, &balance.UserID, &balance.AssetType, &balance.AvailableAmount, &balance.FrozenAmount, &balance.Version, &balance.UpdatedAtMs); err != nil {
|
|
return nil, err
|
|
}
|
|
byAsset[balance.AssetType] = balance
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(assetTypes) == 0 {
|
|
balances := make([]ledger.AssetBalance, 0, len(byAsset))
|
|
for _, balance := range byAsset {
|
|
balances = append(balances, balance)
|
|
}
|
|
sort.Slice(balances, func(i, j int) bool { return balances[i].AssetType < balances[j].AssetType })
|
|
return balances, nil
|
|
}
|
|
|
|
balances := make([]ledger.AssetBalance, 0, len(assetTypes))
|
|
for _, assetType := range assetTypes {
|
|
if balance, ok := byAsset[assetType]; ok {
|
|
balances = append(balances, balance)
|
|
continue
|
|
}
|
|
balances = append(balances, ledger.AssetBalance{AppCode: appCode, UserID: userID, AssetType: assetType})
|
|
}
|
|
return balances, nil
|
|
}
|
|
|
|
func normalizeAssetTypes(assetTypes []string) []string {
|
|
seen := make(map[string]bool, len(assetTypes))
|
|
result := make([]string, 0, len(assetTypes))
|
|
for _, assetType := range assetTypes {
|
|
assetType = strings.ToUpper(strings.TrimSpace(assetType))
|
|
if assetType == "" || seen[assetType] {
|
|
continue
|
|
}
|
|
seen[assetType] = true
|
|
result = append(result, assetType)
|
|
}
|
|
return result
|
|
}
|