Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions backend/src/app/api/user_api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package api

import (
"github.com/gin-gonic/gin"
"github.com/mumu/cryptoSwap/src/app/service"
"github.com/mumu/cryptoSwap/src/core/log"
"github.com/mumu/cryptoSwap/src/core/result"
"go.uber.org/zap"
)

type UserApi struct {
svc *service.UserService
}

func NewUserApi() *UserApi {
return &UserApi{
svc: service.NewUserService(),
}
}

// GetProfile godoc
// @Summary 获取用户资料
// @Description 根据钱包地址返回用户的积分、质押总量和活跃质押数量
// @Tags user
// @Accept json
// @Produce json
// @Param Authorization header string false "Bearer token"
// @Param walletAddress query string false "用户地址"
// @Success 200 {object} result.Response{data=service.UserProfile}
// @Router /api/v1/user/profile [get]
func (u *UserApi) GetProfile(c *gin.Context) {
addr := extractWalletAddress(c)
if addr == "" {
result.Error(c, result.InvalidParameter)
return
}

profile, err := u.svc.GetProfile(addr)
if err != nil {
log.Logger.Error("获取用户资料失败", zap.String("address", addr), zap.Error(err))
result.Error(c, result.DBQueryFailed)
return
}

result.OK(c, profile)
}
75 changes: 75 additions & 0 deletions backend/src/app/service/user_service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package service

import (
"fmt"
"strings"

"github.com/mumu/cryptoSwap/src/app/model"
"github.com/mumu/cryptoSwap/src/core/ctx"
"github.com/mumu/cryptoSwap/src/core/log"
"go.uber.org/zap"
)

// UserProfile 用户资料
type UserProfile struct {
Address string `json:"address"`
TotalStaked float64 `json:"totalStaked"`
Points float64 `json:"points"`
ActiveStakes int64 `json:"activeStakes"`
}

type UserService struct{}

func NewUserService() *UserService {
return &UserService{}
}

// GetProfile 获取用户资料
func (s *UserService) GetProfile(address string) (*UserProfile, error) {
addr := strings.ToLower(address)

// 查询用户记录(可能跨多条链,累计积分)
var users []model.Users
if err := ctx.Ctx.DB.Where("address = ?", addr).Find(&users).Error; err != nil {
return nil, fmt.Errorf("查询用户信息失败: %v", err)
}

// 汇总各链数据
var totalStaked float64
var totalPoints float64
for _, u := range users {
totalStaked += float64(u.TotalAmount) / 1e18
jf, exact := u.Jf.Float64()
if !exact {
log.Logger.Warn("积分精度丢失", zap.String("address", addr), zap.String("jf", u.Jf.String()))
}
totalPoints += jf
}

// 统计活跃质押数量:质押数减去已提取数
var stakedCount int64
if err := ctx.Ctx.DB.Model(&model.UserOperationRecord{}).
Where("address = ? AND event_type = ?", addr, "Staked").
Count(&stakedCount).Error; err != nil {
return nil, fmt.Errorf("统计质押记录失败: %v", err)
}

var withdrawnCount int64
if err := ctx.Ctx.DB.Model(&model.UserOperationRecord{}).
Where("address = ? AND event_type = ?", addr, "withdraw").
Count(&withdrawnCount).Error; err != nil {
return nil, fmt.Errorf("统计提取记录失败: %v", err)
}

activeStakes := stakedCount - withdrawnCount
if activeStakes < 0 {
activeStakes = 0
}

return &UserProfile{
Address: address,
TotalStaked: totalStaked,
Points: totalPoints,
ActiveStakes: activeStakes,
}, nil
}
4 changes: 4 additions & 0 deletions backend/src/core/gin/router/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ func ApiBind(r *gin.Engine, ctx *ctx.Context) {
// 管理员更新默克尔根(需要运维调用,后续可加鉴权)
v.POST("/airdrop/admin/updateMerkleRoot", airDropApi.AdminUpdateMerkleRoot)

// 用户资料接口
userApi := api.NewUserApi()
v.GET("/user/profile", userApi.GetProfile)

// 质押相关接口(需要验证)
stakeApi := api.NewStakeApi()
// 质押代币
Expand Down