email reward

This commit is contained in:
lianghuanjie
2025-01-03 20:44:03 +08:00
parent bc0aeec1da
commit b098e50eb0
36 changed files with 1188 additions and 51 deletions

View File

@@ -21,13 +21,13 @@ init:
# 格式化api文件
api-format:
goctl api format --dir doc/api/
goctl api plugin -plugin goctl-swagger="swagger -filename nova-task.json" -api doc/api/nova-task.api -dir doc/swagger
goctl api plugin -plugin goctl-swagger="swagger -filename nova.json" -api doc/api/nova.api -dir doc/swagger
.PHONY: api
# 根据api文件生成代码
api:
make api-format
goctl api go -api doc/api/nova-task.api --dir . --style go_zero
goctl api go -api doc/api/nova.api --dir . --style go_zero
.PHONY: build
# 编译二进制可执行文件

23
doc/api/admin.api Normal file
View File

@@ -0,0 +1,23 @@
syntax = "v1"
@server (
prefix: /gapi/admin
middleware: AdminSecretCheck
group: admin
)
service novatask {
@doc "每日钱包签到任务"
@handler AddEmailReward
post /email_reward (EmailReward)
@doc "执行发放奖励操作"
@handler SendEmailReward
get /email_reward
}
type EmailReward {
Email string `json:"email"`
RewardType string `json:"reward_type"`
Value float64 `json:"value"`
}

50
doc/api/carv.api Normal file
View File

@@ -0,0 +1,50 @@
syntax = "v1"
@server (
prefix: /gapi/carv
middleware: ApiKeyCheck
group: carv
)
service novatask {
@doc "注册绑定钱包任务"
@handler BindWallet
get /bind_wallet (EmailKey) returns (CarvResult)
@doc "每日钱包签到任务"
@handler WalletCheckIn
get /check_in_wallet (EmailKey) returns (CarvResult)
@doc "下载并绑定Castile游戏角色"
@handler DownloadAndBindRole
get /bind_role (EmailKey) returns (CarvResult)
@doc "游戏主线解锁第x章节"
@handler UnlockChapter
get /unlock_chapter (UnlockChapterReq) returns (CarvResult)
}
type Result {
IsValid bool `json:"isValid"`
}
type Error {
Code int `json:"code"`
Message string `json:"message"`
}
type CarvResult {
Result *Result `json:"result"`
Error *Error `json:"error"`
}
type EmailKey {
Email string `form:"email"`
ApiKey string `Header:"x-api-key"`
}
type UnlockChapterReq {
Email string `form:"email"`
Chapter int `form:"chapter"`
ApiKey string `Header:"x-api-key"`
}

12
doc/api/nova.api Normal file
View File

@@ -0,0 +1,12 @@
syntax = "v1"
import "task.api"
import "carv.api"
import "admin.api"
info (
desc: "nova api"
author: "jager"
email: "lhj168os@gmail.com"
)

View File

@@ -132,7 +132,7 @@ type UserNftList {
// StakeNftList 质押请求参数NFT列表
type StakeNftList {
RoleId uint64 `json:"role_id"` // 角色id
RoleId uint64 `json:"role_id,optional"` // 角色id
TokenIds []string `json:"token_ids"` // nft列表
}

View File

@@ -39,31 +39,28 @@ CREATE TABLE `nh_nft_holder_change_log`
CREATE TABLE `nh_task_nft_stake`
(
`id` int unsigned NOT NULL AUTO_INCREMENT,
`uid` int unsigned NOT NULL COMMENT '用户钱包',
`id` int unsigned NOT NULL AUTO_INCREMENT,
`uid` int unsigned NOT NULL COMMENT '用户钱包',
`role_id` bigint unsigned NOT NULL COMMENT '角色id',
`token_id` varchar(32) NOT NULL COMMENT 'token id',
`state` tinyint NOT NULL DEFAULT 0 COMMENT '状态1质押中 0已取消质押',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
`token_id` varchar(32) NOT NULL COMMENT 'token id',
`state` tinyint NOT NULL DEFAULT 0 COMMENT '状态1质押中 0已取消质押',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY (`uid`, `token_id`)
UNIQUE KEY (`token_id`)
) COMMENT ='nft质押表';
CREATE TABLE `nh_task_nft_stake_log`
(
`id` int unsigned NOT NULL AUTO_INCREMENT,
`uid` int unsigned NOT NULL COMMENT '用户钱包',
`id` int unsigned NOT NULL AUTO_INCREMENT,
`uid` int unsigned NOT NULL COMMENT '用户钱包',
`role_id` bigint unsigned NOT NULL COMMENT '角色id',
`address` varchar(80) NOT NULL COMMENT '钱包地址',
`token_id` varchar(32) NOT NULL COMMENT 'token id',
`award_seq` int NOT NULL COMMENT '派奖序列号',
`balance` int(11) NOT NULL COMMENT '余额',
`stake` tinyint NOT NULL DEFAULT 0 COMMENT '状态1质押中 0未质押',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
`token_id` varchar(32) NOT NULL COMMENT 'token id',
`operate` tinyint NOT NULL DEFAULT 0 COMMENT '状态1质押 2取消质押, 3转出',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`)
) COMMENT ='派奖时nft质押日志表';
) COMMENT ='nft质押日志表';
CREATE TABLE `nh_task_nft_stake_reward`
(
@@ -79,4 +76,18 @@ CREATE TABLE `nh_task_nft_stake_reward`
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY (`uid`, `award_seq`)
) COMMENT ='nft质押派奖表';
) COMMENT ='nft质押派奖表';
CREATE TABLE `nh_email_reward`
(
`id` int unsigned NOT NULL AUTO_INCREMENT,
`email` varchar(80) NOT NULL COMMENT '邮箱',
`uid` int unsigned NOT NULL DEFAULT 0 COMMENT '用户id',
`reward_type` varchar(32) NOT NULL COMMENT '奖励类型:[points,elite_points,castile,keys]',
`value` decimal(18, 6) NOT NULL DEFAULT 0 COMMENT '需要发送的积分',
`remark` varchar(256) NOT NULL DEFAULT '' COMMENT '备注',
`sent_at` int NOT NULL DEFAULT 0 COMMENT '发放时间戳',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`)
) COMMENT ='需要发放积分的';

View File

@@ -5,4 +5,6 @@ const (
DailyPayConf = "daily_pay_conf"
NftStakeTaskDate = "nft_stake_task_date"
NftStakeTaskConf = "nft_stake_task_conf"
CarvApiKey = "carv_api_key"
AdminSecret = "admin_secret"
)

View File

@@ -0,0 +1,29 @@
package admin
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"nova_task/internal/logic/admin"
"nova_task/internal/svc"
"nova_task/internal/types"
)
// 每日钱包签到任务
func AddEmailRewardHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.EmailReward
if err := httpx.Parse(r, &req); err != nil {
httpx.ErrorCtx(r.Context(), w, err)
return
}
l := admin.NewAddEmailRewardLogic(r.Context(), svcCtx)
err := l.AddEmailReward(&req)
if err != nil {
httpx.ErrorCtx(r.Context(), w, err)
} else {
httpx.Ok(w)
}
}
}

View File

@@ -0,0 +1,29 @@
package admin
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"nova_task/internal/logic/admin"
"nova_task/internal/svc"
"nova_task/internal/types"
)
// 每日钱包签到任务
func AddEmialRewardHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.EmailReward
if err := httpx.Parse(r, &req); err != nil {
httpx.ErrorCtx(r.Context(), w, err)
return
}
l := admin.NewAddEmialRewardLogic(r.Context(), svcCtx)
err := l.AddEmialReward(&req)
if err != nil {
httpx.ErrorCtx(r.Context(), w, err)
} else {
httpx.Ok(w)
}
}
}

View File

@@ -0,0 +1,22 @@
package admin
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"nova_task/internal/logic/admin"
"nova_task/internal/svc"
)
// 执行发放奖励操作
func SendEmailRewardHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
l := admin.NewSendEmailRewardLogic(r.Context(), svcCtx)
err := l.SendEmailReward()
if err != nil {
httpx.ErrorCtx(r.Context(), w, err)
} else {
httpx.Ok(w)
}
}
}

View File

@@ -0,0 +1,29 @@
package carv
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"nova_task/internal/logic/carv"
"nova_task/internal/svc"
"nova_task/internal/types"
)
// 注册绑定钱包任务
func BindWalletHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.EmailKey
if err := httpx.Parse(r, &req); err != nil {
httpx.ErrorCtx(r.Context(), w, err)
return
}
l := carv.NewBindWalletLogic(r.Context(), svcCtx)
resp, err := l.BindWallet(&req)
if err != nil {
httpx.ErrorCtx(r.Context(), w, err)
} else {
httpx.OkJsonCtx(r.Context(), w, resp)
}
}
}

View File

@@ -0,0 +1,29 @@
package carv
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"nova_task/internal/logic/carv"
"nova_task/internal/svc"
"nova_task/internal/types"
)
// 下载并绑定Castile游戏角色
func DownloadAndBindRoleHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.EmailKey
if err := httpx.Parse(r, &req); err != nil {
httpx.ErrorCtx(r.Context(), w, err)
return
}
l := carv.NewDownloadAndBindRoleLogic(r.Context(), svcCtx)
resp, err := l.DownloadAndBindRole(&req)
if err != nil {
httpx.ErrorCtx(r.Context(), w, err)
} else {
httpx.OkJsonCtx(r.Context(), w, resp)
}
}
}

View File

@@ -0,0 +1,29 @@
package carv
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"nova_task/internal/logic/carv"
"nova_task/internal/svc"
"nova_task/internal/types"
)
// 游戏主线解锁第x章节
func UnlockChapterHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.UnlockChapterReq
if err := httpx.Parse(r, &req); err != nil {
httpx.ErrorCtx(r.Context(), w, err)
return
}
l := carv.NewUnlockChapterLogic(r.Context(), svcCtx)
resp, err := l.UnlockChapter(&req)
if err != nil {
httpx.ErrorCtx(r.Context(), w, err)
} else {
httpx.OkJsonCtx(r.Context(), w, resp)
}
}
}

View File

@@ -0,0 +1,29 @@
package carv
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"nova_task/internal/logic/carv"
"nova_task/internal/svc"
"nova_task/internal/types"
)
// 每日钱包签到任务
func WalletCheckInHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.EmailKey
if err := httpx.Parse(r, &req); err != nil {
httpx.ErrorCtx(r.Context(), w, err)
return
}
l := carv.NewWalletCheckInLogic(r.Context(), svcCtx)
resp, err := l.WalletCheckIn(&req)
if err != nil {
httpx.ErrorCtx(r.Context(), w, err)
} else {
httpx.OkJsonCtx(r.Context(), w, resp)
}
}
}

View File

@@ -6,6 +6,8 @@ package handler
import (
"net/http"
admin "nova_task/internal/handler/admin"
carv "nova_task/internal/handler/carv"
task "nova_task/internal/handler/task"
"nova_task/internal/svc"
@@ -13,6 +15,60 @@ import (
)
func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
server.AddRoutes(
rest.WithMiddlewares(
[]rest.Middleware{serverCtx.AdminSecretCheck},
[]rest.Route{
{
// 每日钱包签到任务
Method: http.MethodPost,
Path: "/email_reward",
Handler: admin.AddEmailRewardHandler(serverCtx),
},
{
// 执行发放奖励操作
Method: http.MethodGet,
Path: "/email_reward",
Handler: admin.SendEmailRewardHandler(serverCtx),
},
}...,
),
rest.WithPrefix("/gapi/admin"),
)
server.AddRoutes(
rest.WithMiddlewares(
[]rest.Middleware{serverCtx.ApiKeyCheck},
[]rest.Route{
{
// 下载并绑定Castile游戏角色
Method: http.MethodGet,
Path: "/bind_role",
Handler: carv.DownloadAndBindRoleHandler(serverCtx),
},
{
// 注册绑定钱包任务
Method: http.MethodGet,
Path: "/bind_wallet",
Handler: carv.BindWalletHandler(serverCtx),
},
{
// 每日钱包签到任务
Method: http.MethodGet,
Path: "/check_in_wallet",
Handler: carv.WalletCheckInHandler(serverCtx),
},
{
// 游戏主线解锁第x章节
Method: http.MethodGet,
Path: "/unlock_chapter",
Handler: carv.UnlockChapterHandler(serverCtx),
},
}...,
),
rest.WithPrefix("/gapi/carv"),
)
server.AddRoutes(
[]rest.Route{
{

View File

@@ -108,6 +108,15 @@ func (c *Cron) Run() {
if err != nil {
logx.Errorw("delete nft holder error", logx.Field("error", err), logx.Field("address", nft.Address), logx.Field("token", nft.TokenId))
}
uid, err := c.svcCtx.WalletModel.FindUidByAddress(c.ctx, nft.Address)
if err != nil {
logx.Errorw("find uid by address error", logx.Field("error", err), logx.Field("address", nft.Address))
continue
}
err = c.svcCtx.StakeNftModel.UnStakeNft(c.ctx, uid, nft.TokenId, true)
if err != nil {
logx.Errorw("un stake nft error", logx.Field("error", err), logx.Field("address", nft.Address), logx.Field("token", nft.TokenId))
}
}
err = c.svcCtx.NftHolderModel.DeleteOtherUpdateSeq(c.ctx, updateSeq)
if err != nil {

View File

@@ -0,0 +1,42 @@
package admin
import (
"context"
"github.com/shopspring/decimal"
"nova_task/internal/model"
"nova_task/internal/pkg/errs"
"nova_task/internal/svc"
"nova_task/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type AddEmailRewardLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
// 每日钱包签到任务
func NewAddEmailRewardLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AddEmailRewardLogic {
return &AddEmailRewardLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AddEmailRewardLogic) AddEmailReward(req *types.EmailReward) error {
_, err := l.svcCtx.EmailRewardModel.Insert(l.ctx, &model.NhEmailReward{
Email: req.Email,
RewardType: req.RewardType,
Value: decimal.NewFromFloat(req.Value),
})
if err != nil {
l.Errorw("add email reward failed", logx.Field("err", err), logx.Field("email", req.Email))
return errs.New(errs.ErrDatabaseOperate, err)
}
return errs.Success()
}

View File

@@ -0,0 +1,84 @@
package admin
import (
"context"
"github.com/zeromicro/go-zero/core/threading"
"nova_task/internal/model"
"nova_task/internal/pkg/errs"
"strings"
"time"
"github.com/zeromicro/go-zero/core/logx"
"nova_task/internal/svc"
)
type SendEmailRewardLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
// 执行发放奖励操作
func NewSendEmailRewardLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SendEmailRewardLogic {
return &SendEmailRewardLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *SendEmailRewardLogic) SendEmailReward() error {
rewards, err := l.svcCtx.EmailRewardModel.AllRequireSend(l.ctx)
if err != nil {
l.Errorw("get email reward failed", logx.Field("err", err))
return errs.New(errs.ErrDatabaseOperate, err)
}
if len(rewards) <= 0 {
return errs.Success()
}
threading.GoSafe(func() {
ctx := context.Background()
for _, rw := range rewards {
u, err := l.svcCtx.UserModel.FindOneByEmail(ctx, rw.Email)
if err != nil {
l.Errorw("find user failed", logx.Field("err", err), logx.Field("email", rw.Email))
continue
}
err = l.svcCtx.EmailRewardModel.SetSent(ctx, rw.Id, u.Id)
if err != nil {
l.Errorw("set sent failed", logx.Field("err", err), logx.Field("id", rw.Id), logx.Field("uid", u.Id))
continue
}
// points,elite_points,castile,keys
switch strings.ToLower(rw.RewardType) {
case "points":
err = l.svcCtx.TaskAssetModel.AddPoint(ctx, u.Id, rw.Value)
case "elite_points":
err = l.svcCtx.TaskAssetModel.AddElitePoints(ctx, u.Id, rw.Value)
case "castile":
err = l.svcCtx.TaskAssetModel.AddCastile(ctx, u.Id, rw.Value)
case "keys":
err = l.svcCtx.TaskAssetModel.AddKeys(ctx, u.Id, int(rw.Value.IntPart()))
}
if err != nil {
l.Errorw("add asset failed", logx.Field("err", err), logx.Field("uid", u.Id), logx.Field("rewardType", rw.RewardType), logx.Field("value", rw.Value))
}
_, err = l.svcCtx.TaskAssetRecordModel.Insert(ctx, &model.NhTaskAssetRecord{
Uid: int(u.Id),
AssetField: rw.RewardType,
Count: rw.Value.InexactFloat64(),
Remark: rw.Remark,
CreateTime: int(time.Now().Unix()),
})
if err != nil {
l.Errorw("insert task asset record failed", logx.Field("err", err), logx.Field("uid", u.Id), logx.Field("rewardType", rw.RewardType), logx.Field("value", rw.Value))
}
}
})
return nil
}

View File

@@ -0,0 +1,31 @@
package carv
import (
"context"
"nova_task/internal/svc"
"nova_task/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type BindWalletLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
// 注册绑定钱包任务
func NewBindWalletLogic(ctx context.Context, svcCtx *svc.ServiceContext) *BindWalletLogic {
return &BindWalletLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *BindWalletLogic) BindWallet(req *types.EmailKey) (resp *types.CarvResult, err error) {
// todo: add your logic here and delete this line
return
}

View File

@@ -0,0 +1,31 @@
package carv
import (
"context"
"nova_task/internal/svc"
"nova_task/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type DownloadAndBindRoleLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
// 下载并绑定Castile游戏角色
func NewDownloadAndBindRoleLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DownloadAndBindRoleLogic {
return &DownloadAndBindRoleLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *DownloadAndBindRoleLogic) DownloadAndBindRole(req *types.EmailKey) (resp *types.CarvResult, err error) {
// todo: add your logic here and delete this line
return
}

View File

@@ -0,0 +1,31 @@
package carv
import (
"context"
"nova_task/internal/svc"
"nova_task/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type UnlockChapterLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
// 游戏主线解锁第x章节
func NewUnlockChapterLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UnlockChapterLogic {
return &UnlockChapterLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *UnlockChapterLogic) UnlockChapter(req *types.UnlockChapterReq) (resp *types.CarvResult, err error) {
// todo: add your logic here and delete this line
return
}

View File

@@ -0,0 +1,31 @@
package carv
import (
"context"
"nova_task/internal/svc"
"nova_task/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type WalletCheckInLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
// 每日钱包签到任务
func NewWalletCheckInLogic(ctx context.Context, svcCtx *svc.ServiceContext) *WalletCheckInLogic {
return &WalletCheckInLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *WalletCheckInLogic) WalletCheckIn(req *types.EmailKey) (resp *types.CarvResult, err error) {
// todo: add your logic here and delete this line
return
}

View File

@@ -29,13 +29,24 @@ func NewStakeNftLogic(ctx context.Context, svcCtx *svc.ServiceContext) *StakeNft
func (l *StakeNftLogic) StakeNft(req *types.StakeNftList) error {
uid := utils.GetUidUint(l.ctx)
err := l.svcCtx.StakeNftModel.StakeNft(l.ctx, uid, req.RoleId, req.TokenIds)
if err != nil {
l.Errorw("stake nft failed", logx.Field("err", err), logx.Field("uid", uid), logx.Field("tokenIds", req.TokenIds))
return errs.New(errs.ErrDatabaseOperate, err)
}
for _, tokenId := range req.TokenIds {
tkHolder, err := l.svcCtx.NftHolderModel.FindOneByTokenId(l.ctx, tokenId)
if err != nil {
if errors.Is(err, model.ErrNotFound) {
l.Errorw("find nft holder not exist", logx.Field("err", err), logx.Field("uid", uid), logx.Field("tokenId", tokenId))
continue
}
l.Errorw("find nft holder failed", logx.Field("err", err), logx.Field("uid", uid), logx.Field("tokenId", tokenId))
return errs.New(errs.ErrDatabaseOperate, err)
}
l.svcCtx.WalletModel.FindUidByAddress(l.ctx, tkHolder.Address)
err = l.svcCtx.StakeNftModel.StakeNft(l.ctx, uid, req.RoleId, tokenId)
if err != nil {
l.Errorw("stake nft failed", logx.Field("err", err), logx.Field("uid", uid), logx.Field("tokenIds", req.TokenIds))
return errs.New(errs.ErrDatabaseOperate, err)
}
var sns []int8
var propertyId string
if utils.IsBigTarot(tokenId) {
@@ -50,7 +61,7 @@ func (l *StakeNftLogic) StakeNft(req *types.StakeNftList) error {
Uid: uid,
RoleId: int64(req.RoleId),
TokenId: cast.ToUint(tokenId),
PropertyId: "",
PropertyId: propertyId,
Sn: sn,
})
if err != nil {

View File

@@ -27,7 +27,7 @@ func NewUnStakeNftLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UnStak
func (l *UnStakeNftLogic) UnStakeNft(req *types.UnStakeNftReq) error {
uid := utils.GetUidUint(l.ctx)
err := l.svcCtx.StakeNftModel.UnStakeNft(l.ctx, uid, req.TokenId)
err := l.svcCtx.StakeNftModel.UnStakeNft(l.ctx, uid, req.TokenId, false)
if err != nil {
l.Errorw("unstake nft failed", logx.Field("err", err), logx.Field("uid", uid), logx.Field("tokenIds", req.TokenId))
return errs.New(errs.ErrDatabaseOperate, err)

View File

@@ -0,0 +1,33 @@
package middleware
import (
"errors"
"net/http"
"nova_task/internal/model"
)
type AdminSecretCheckMiddleware struct {
conf model.NhSystemConfigModel
}
func NewAdminSecretCheckMiddleware(conf model.NhSystemConfigModel) *AdminSecretCheckMiddleware {
return &AdminSecretCheckMiddleware{conf: conf}
}
func (m *AdminSecretCheckMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if key, err := m.conf.GetAdminSecret(r.Context()); err != nil {
if !errors.Is(err, model.ErrNotFound) {
http.Error(w, "system error", http.StatusInternalServerError)
return
}
} else {
apiKey := r.Header.Get("x-admin-secret")
if apiKey != key {
http.Error(w, "Invalid API key", http.StatusUnauthorized)
return
}
}
next(w, r)
}
}

View File

@@ -0,0 +1,34 @@
package middleware
import (
"errors"
"net/http"
"nova_task/internal/model"
)
type ApiKeyCheckMiddleware struct {
conf model.NhSystemConfigModel
}
func NewApiKeyCheckMiddleware(conf model.NhSystemConfigModel) *ApiKeyCheckMiddleware {
return &ApiKeyCheckMiddleware{conf: conf}
}
func (m *ApiKeyCheckMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if key, err := m.conf.GetCarvApiKey(r.Context()); err != nil {
if !errors.Is(err, model.ErrNotFound) {
http.Error(w, "system error", http.StatusInternalServerError)
return
}
} else {
apiKey := r.Header.Get("x-api-key")
if apiKey != key {
http.Error(w, "Invalid API key", http.StatusUnauthorized)
return
}
}
next(w, r)
}
}

View File

@@ -0,0 +1,63 @@
package model
import (
"context"
"errors"
"fmt"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"time"
)
var _ NhEmailRewardModel = (*customNhEmailRewardModel)(nil)
type (
// NhEmailRewardModel is an interface to be customized, add more methods here,
// and implement the added methods in customNhEmailRewardModel.
NhEmailRewardModel interface {
nhEmailRewardModel
withSession(session sqlx.Session) NhEmailRewardModel
AllRequireSend(ctx context.Context) ([]NhEmailReward, error)
SetSent(ctx context.Context, id, uid uint) error
}
customNhEmailRewardModel struct {
*defaultNhEmailRewardModel
}
)
func (m *customNhEmailRewardModel) SetSent(ctx context.Context, id, uid uint) error {
upate := fmt.Sprintf("update %s set `uid` = ?, `sent_at` = ? where `id` = ? and `sent_at` = 0", m.table)
result, err := m.conn.ExecCtx(ctx, upate, uid, time.Now().Unix(), id)
if err != nil {
return err
}
rows, err := result.RowsAffected()
if err != nil {
return err
}
if rows == 0 {
return ErrNoRowUpdate
}
return nil
}
func (m *customNhEmailRewardModel) AllRequireSend(ctx context.Context) ([]NhEmailReward, error) {
query := fmt.Sprintf("select %s from %s where `sent_at` = 0", nhEmailRewardRows, m.table)
var result []NhEmailReward
err := m.conn.QueryRowsCtx(ctx, &result, query)
if err != nil && !errors.Is(err, sqlx.ErrNotFound) {
return nil, err
}
return result, nil
}
// NewNhEmailRewardModel returns a model for the database table.
func NewNhEmailRewardModel(conn sqlx.SqlConn) NhEmailRewardModel {
return &customNhEmailRewardModel{
defaultNhEmailRewardModel: newNhEmailRewardModel(conn),
}
}
func (m *customNhEmailRewardModel) withSession(session sqlx.Session) NhEmailRewardModel {
return NewNhEmailRewardModel(sqlx.NewSqlConnFromSession(session))
}

View File

@@ -0,0 +1,95 @@
// Code generated by goctl. DO NOT EDIT.
// versions:
// goctl version: 1.7.3
package model
import (
"context"
"database/sql"
"fmt"
"strings"
"time"
"github.com/zeromicro/go-zero/core/stores/builder"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/stringx"
"github.com/shopspring/decimal"
)
var (
nhEmailRewardFieldNames = builder.RawFieldNames(&NhEmailReward{})
nhEmailRewardRows = strings.Join(nhEmailRewardFieldNames, ",")
nhEmailRewardRowsExpectAutoSet = strings.Join(stringx.Remove(nhEmailRewardFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
nhEmailRewardRowsWithPlaceHolder = strings.Join(stringx.Remove(nhEmailRewardFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
)
type (
nhEmailRewardModel interface {
Insert(ctx context.Context, data *NhEmailReward) (sql.Result, error)
FindOne(ctx context.Context, id uint) (*NhEmailReward, error)
Update(ctx context.Context, data *NhEmailReward) error
Delete(ctx context.Context, id uint) error
}
defaultNhEmailRewardModel struct {
conn sqlx.SqlConn
table string
}
NhEmailReward struct {
Id uint `db:"id"`
Email string `db:"email"` // 邮箱
Uid uint `db:"uid"` // 用户id
RewardType string `db:"reward_type"` // 奖励类型:[points,elite_points,castile,keys]
Value decimal.Decimal `db:"value"` // 需要发送的积分
Remark string `db:"remark"` // 备注
SentAt int `db:"sent_at"` // 发放时间戳
CreatedAt time.Time `db:"created_at"` // 创建时间
UpdatedAt time.Time `db:"updated_at"` // 修改时间
}
)
func newNhEmailRewardModel(conn sqlx.SqlConn) *defaultNhEmailRewardModel {
return &defaultNhEmailRewardModel{
conn: conn,
table: "`nh_email_reward`",
}
}
func (m *defaultNhEmailRewardModel) Delete(ctx context.Context, id uint) error {
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
_, err := m.conn.ExecCtx(ctx, query, id)
return err
}
func (m *defaultNhEmailRewardModel) FindOne(ctx context.Context, id uint) (*NhEmailReward, error) {
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", nhEmailRewardRows, m.table)
var resp NhEmailReward
err := m.conn.QueryRowCtx(ctx, &resp, query, id)
switch err {
case nil:
return &resp, nil
case sqlx.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultNhEmailRewardModel) Insert(ctx context.Context, data *NhEmailReward) (sql.Result, error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?)", m.table, nhEmailRewardRowsExpectAutoSet)
ret, err := m.conn.ExecCtx(ctx, query, data.Email, data.Uid, data.RewardType, data.Value, data.Remark, data.SentAt)
return ret, err
}
func (m *defaultNhEmailRewardModel) Update(ctx context.Context, data *NhEmailReward) error {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, nhEmailRewardRowsWithPlaceHolder)
_, err := m.conn.ExecCtx(ctx, query, data.Email, data.Uid, data.RewardType, data.Value, data.Remark, data.SentAt, data.Id)
return err
}
func (m *defaultNhEmailRewardModel) tableName() string {
return m.table
}

View File

@@ -0,0 +1,44 @@
package model
import (
"context"
"errors"
"github.com/zeromicro/go-zero/core/stores/sqlx"
)
var _ NhNftStakeModel = (*customNhNftStakeModel)(nil)
type (
// NhNftStakeModel is an interface to be customized, add more methods here,
// and implement the added methods in customNhNftStakeModel.
NhNftStakeModel interface {
nhNftStakeModel
withSession(session sqlx.Session) NhNftStakeModel
AllStakeNft(ctx context.Context) ([]NhNftStake, error)
}
customNhNftStakeModel struct {
*defaultNhNftStakeModel
}
)
func (m *customNhNftStakeModel) AllStakeNft(ctx context.Context) ([]NhNftStake, error) {
query := "SELECT * FROM `nh_nft_stake` WHERE `status` = 'staked'"
var result []NhNftStake
err := m.conn.QueryRowsCtx(ctx, &result, query)
if err != nil && !errors.Is(err, sqlx.ErrNotFound) {
return nil, err
}
return result, nil
}
// NewNhNftStakeModel returns a model for the database table.
func NewNhNftStakeModel(conn sqlx.SqlConn) NhNftStakeModel {
return &customNhNftStakeModel{
defaultNhNftStakeModel: newNhNftStakeModel(conn),
}
}
func (m *customNhNftStakeModel) withSession(session sqlx.Session) NhNftStakeModel {
return NewNhNftStakeModel(sqlx.NewSqlConnFromSession(session))
}

View File

@@ -0,0 +1,139 @@
// Code generated by goctl. DO NOT EDIT.
// versions:
// goctl version: 1.7.3
package model
import (
"context"
"database/sql"
"fmt"
"strings"
"time"
"github.com/zeromicro/go-zero/core/stores/builder"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/stringx"
)
var (
nhNftStakeFieldNames = builder.RawFieldNames(&NhNftStake{})
nhNftStakeRows = strings.Join(nhNftStakeFieldNames, ",")
nhNftStakeRowsExpectAutoSet = strings.Join(stringx.Remove(nhNftStakeFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
nhNftStakeRowsWithPlaceHolder = strings.Join(stringx.Remove(nhNftStakeFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
)
type (
nhNftStakeModel interface {
Insert(ctx context.Context, data *NhNftStake) (sql.Result, error)
FindOne(ctx context.Context, id uint) (*NhNftStake, error)
FindOneByStakeHashTokenId(ctx context.Context, stakeHash string, tokenId uint) (*NhNftStake, error)
FindOneByUnstakeHashTokenId(ctx context.Context, unstakeHash string, tokenId uint) (*NhNftStake, error)
Update(ctx context.Context, data *NhNftStake) error
Delete(ctx context.Context, id uint) error
}
defaultNhNftStakeModel struct {
conn sqlx.SqlConn
table string
}
NhNftStake struct {
Id uint `db:"id"`
UserId uint `db:"user_id"` // 用户ID
RoleId uint64 `db:"role_id"` // 角色ID
Email string `db:"email"` // email
UserAddress string `db:"user_address"` // 用户地址
NftAddress string `db:"nft_address"` // nft合约地址
TokenId uint `db:"token_id"` // NFT tokenid
TarotType int8 `db:"tarot_type"` // 塔罗类型1=大塔罗2=小塔罗
LockedGoodsId uint `db:"locked_goods_id"` // 提取前锁定游戏内的道具ID
StakeHash string `db:"stake_hash"` // 质押hash
UnstakeHash string `db:"unstake_hash"` // 提取hash
Status string `db:"status"` // 质押状态:pending待质押staked已质押unstaking提取中unstaked已提取
StakeTime sql.NullTime `db:"stake_time"` // 质押时间
UnstakeTime sql.NullTime `db:"unstake_time"` // 提取时间
Remark sql.NullString `db:"remark"` // 备注
CallbackStatus int8 `db:"callback_status"` // 质押成功通知状态:0未通知,1已通知,2通知异常
CallbackNum int `db:"callback_num"` // 质押成功发送通知次数
CallbackAt sql.NullTime `db:"callback_at"` // 质押通知最新时间
CallbackRemark string `db:"callback_remark"` // 质押通知回调备注
CallbackStatus2 int8 `db:"callback_status2"` // 提取成功通知状态:0未通知,1已通知,2通知异常
CallbackNum2 int `db:"callback_num2"` // 提取成功发送通知次数
CallbackAt2 sql.NullTime `db:"callback_at2"` // 提取发送通知最新时间
CallbackRemark2 string `db:"callback_remark2"` // 提取通知回调备注
CreatedAt time.Time `db:"created_at"` // 创建时间
UpdatedAt time.Time `db:"updated_at"` // 修改时间
}
)
func newNhNftStakeModel(conn sqlx.SqlConn) *defaultNhNftStakeModel {
return &defaultNhNftStakeModel{
conn: conn,
table: "`nh_nft_stake`",
}
}
func (m *defaultNhNftStakeModel) Delete(ctx context.Context, id uint) error {
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
_, err := m.conn.ExecCtx(ctx, query, id)
return err
}
func (m *defaultNhNftStakeModel) FindOne(ctx context.Context, id uint) (*NhNftStake, error) {
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", nhNftStakeRows, m.table)
var resp NhNftStake
err := m.conn.QueryRowCtx(ctx, &resp, query, id)
switch err {
case nil:
return &resp, nil
case sqlx.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultNhNftStakeModel) FindOneByStakeHashTokenId(ctx context.Context, stakeHash string, tokenId uint) (*NhNftStake, error) {
var resp NhNftStake
query := fmt.Sprintf("select %s from %s where `stake_hash` = ? and `token_id` = ? limit 1", nhNftStakeRows, m.table)
err := m.conn.QueryRowCtx(ctx, &resp, query, stakeHash, tokenId)
switch err {
case nil:
return &resp, nil
case sqlx.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultNhNftStakeModel) FindOneByUnstakeHashTokenId(ctx context.Context, unstakeHash string, tokenId uint) (*NhNftStake, error) {
var resp NhNftStake
query := fmt.Sprintf("select %s from %s where `unstake_hash` = ? and `token_id` = ? limit 1", nhNftStakeRows, m.table)
err := m.conn.QueryRowCtx(ctx, &resp, query, unstakeHash, tokenId)
switch err {
case nil:
return &resp, nil
case sqlx.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultNhNftStakeModel) Insert(ctx context.Context, data *NhNftStake) (sql.Result, error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, nhNftStakeRowsExpectAutoSet)
ret, err := m.conn.ExecCtx(ctx, query, data.UserId, data.RoleId, data.Email, data.UserAddress, data.NftAddress, data.TokenId, data.TarotType, data.LockedGoodsId, data.StakeHash, data.UnstakeHash, data.Status, data.StakeTime, data.UnstakeTime, data.Remark, data.CallbackStatus, data.CallbackNum, data.CallbackAt, data.CallbackRemark, data.CallbackStatus2, data.CallbackNum2, data.CallbackAt2, data.CallbackRemark2)
return ret, err
}
func (m *defaultNhNftStakeModel) Update(ctx context.Context, newData *NhNftStake) error {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, nhNftStakeRowsWithPlaceHolder)
_, err := m.conn.ExecCtx(ctx, query, newData.UserId, newData.RoleId, newData.Email, newData.UserAddress, newData.NftAddress, newData.TokenId, newData.TarotType, newData.LockedGoodsId, newData.StakeHash, newData.UnstakeHash, newData.Status, newData.StakeTime, newData.UnstakeTime, newData.Remark, newData.CallbackStatus, newData.CallbackNum, newData.CallbackAt, newData.CallbackRemark, newData.CallbackStatus2, newData.CallbackNum2, newData.CallbackAt2, newData.CallbackRemark2, newData.Id)
return err
}
func (m *defaultNhNftStakeModel) tableName() string {
return m.table
}

View File

@@ -3,6 +3,7 @@ package model
import (
"context"
"encoding/json"
"errors"
"github.com/zeromicro/go-zero/core/stores/cache"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"nova_task/internal/consts"
@@ -18,6 +19,8 @@ type (
nhSystemConfigModel
GetNftStakeTaskOpenDate(ctx context.Context) (start, end time.Time, err error)
GetNftStakeTaskConf(ctx context.Context) (conf NftStakeTaskConf, err error)
GetCarvApiKey(ctx context.Context) (apiKey string, err error)
GetAdminSecret(ctx context.Context) (secret string, err error)
}
customNhSystemConfigModel struct {
@@ -25,6 +28,28 @@ type (
}
)
func (m *customNhSystemConfigModel) GetAdminSecret(ctx context.Context) (secret string, err error) {
cf, err := m.FindOneByName(ctx, consts.CarvApiKey)
if err != nil {
if !errors.Is(err, sqlx.ErrNotFound) {
return "", err
}
return "", nil
}
return cf.Value, nil
}
func (m *customNhSystemConfigModel) GetCarvApiKey(ctx context.Context) (string, error) {
cf, err := m.FindOneByName(ctx, consts.CarvApiKey)
if err != nil {
if !errors.Is(err, sqlx.ErrNotFound) {
return "", err
}
return "", nil
}
return cf.Value, nil
}
// NewNhSystemConfigModel returns a model for the database table.
func NewNhSystemConfigModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) NhSystemConfigModel {
return &customNhSystemConfigModel{

View File

@@ -16,8 +16,10 @@ type (
NhTaskAssetModel interface {
nhTaskAssetModel
WithSession(session sqlx.Session) NhTaskAssetModel
AddPoint(ctx context.Context, uid int, points int) error
AddPoint(ctx context.Context, uid uint, points decimal.Decimal) error
AddCastile(ctx context.Context, uid uint, castile decimal.Decimal) error
AddElitePoints(ctx context.Context, uid uint, points decimal.Decimal) error
AddKeys(ctx context.Context, uid uint, keys int) error
}
customNhTaskAssetModel struct {
@@ -25,6 +27,18 @@ type (
}
)
func (m *customNhTaskAssetModel) AddKeys(ctx context.Context, uid uint, keys int) error {
insertOrUpdate := fmt.Sprintf("INSERT INTO %s (`uid`, `keys`, `create_time`) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE `keys` = `keys` + ?", m.table)
_, err := m.conn.ExecCtx(ctx, insertOrUpdate, uid, keys, time.Now().Unix(), keys)
return err
}
func (m *customNhTaskAssetModel) AddElitePoints(ctx context.Context, uid uint, elitePoints decimal.Decimal) error {
insertOrUpdate := fmt.Sprintf("INSERT INTO %s (`uid`, `elite_points`, `create_time`) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE `elite_points` = `elite_points` + ?", m.table)
_, err := m.conn.ExecCtx(ctx, insertOrUpdate, uid, elitePoints, time.Now().Unix(), elitePoints)
return err
}
func (m *customNhTaskAssetModel) AddCastile(ctx context.Context, uid uint, castile decimal.Decimal) error {
insertOrUpdate := fmt.Sprintf("INSERT INTO %s (`uid`, `castile`, `create_time`) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE `castile` = `castile` + ?", m.table)
_, err := m.conn.ExecCtx(ctx, insertOrUpdate, uid, castile, time.Now().Unix(), castile)
@@ -42,7 +56,7 @@ func (m *customNhTaskAssetModel) WithSession(session sqlx.Session) NhTaskAssetMo
return NewNhTaskAssetModel(sqlx.NewSqlConnFromSession(session))
}
func (m *customNhTaskAssetModel) AddPoint(ctx context.Context, uid int, points int) error {
func (m *customNhTaskAssetModel) AddPoint(ctx context.Context, uid uint, points decimal.Decimal) error {
insertOrUpdate := fmt.Sprintf("INSERT INTO %s (`uid`, `points`, `create_time`) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE `points` = `points` + ?", m.table)
_, err := m.conn.ExecCtx(ctx, insertOrUpdate, uid, points, time.Now().Unix(), points)
return err

View File

@@ -40,11 +40,8 @@ type (
Id uint `db:"id"`
Uid uint `db:"uid"` // 用户钱包
RoleId uint64 `db:"role_id"` // 角色id
Address string `db:"address"` // 钱包地址
TokenId string `db:"token_id"` // token id
AwardSeq int `db:"award_seq"` // 派奖序列号
Balance int `db:"balance"` // 余额
Stake int8 `db:"stake"` // 状态1质押中 0未质押
Operate int8 `db:"operate"` // 状态1质押 2取消质押, 3转出
CreatedAt time.Time `db:"created_at"` // 创建时间
UpdatedAt time.Time `db:"updated_at"` // 修改时间
}
@@ -78,14 +75,14 @@ func (m *defaultNhTaskNftStakeLogModel) FindOne(ctx context.Context, id uint) (*
}
func (m *defaultNhTaskNftStakeLogModel) Insert(ctx context.Context, data *NhTaskNftStakeLog) (sql.Result, error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?)", m.table, nhTaskNftStakeLogRowsExpectAutoSet)
ret, err := m.conn.ExecCtx(ctx, query, data.Uid, data.RoleId, data.Address, data.TokenId, data.AwardSeq, data.Balance, data.Stake)
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?)", m.table, nhTaskNftStakeLogRowsExpectAutoSet)
ret, err := m.conn.ExecCtx(ctx, query, data.Uid, data.RoleId, data.TokenId, data.Operate)
return ret, err
}
func (m *defaultNhTaskNftStakeLogModel) Update(ctx context.Context, data *NhTaskNftStakeLog) error {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, nhTaskNftStakeLogRowsWithPlaceHolder)
_, err := m.conn.ExecCtx(ctx, query, data.Uid, data.RoleId, data.Address, data.TokenId, data.AwardSeq, data.Balance, data.Stake, data.Id)
_, err := m.conn.ExecCtx(ctx, query, data.Uid, data.RoleId, data.TokenId, data.Operate, data.Id)
return err
}

View File

@@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stores/sqlx"
)
@@ -15,14 +16,15 @@ type (
NhTaskNftStakeModel interface {
nhTaskNftStakeModel
withSession(session sqlx.Session) NhTaskNftStakeModel
StakeNft(ctx context.Context, uid uint, roleId uint64, tokens []string) error
UnStakeNft(ctx context.Context, uid uint, token string) error
StakeNft(ctx context.Context, uid uint, roleId uint64, tokenId string) error
UnStakeNft(ctx context.Context, uid uint, token string, isTransferOut bool) error
FindByUid(ctx context.Context, uid uint) ([]NhTaskNftStake, error)
AllStakeNft(ctx context.Context) ([]NhTaskNftStake, error)
}
customNhTaskNftStakeModel struct {
*defaultNhTaskNftStakeModel
log NhTaskNftStakeLogModel
}
)
@@ -46,19 +48,46 @@ func (m *customNhTaskNftStakeModel) FindByUid(ctx context.Context, uid uint) ([]
return list, nil
}
func (m *customNhTaskNftStakeModel) UnStakeNft(ctx context.Context, uid uint, token string) error {
func (m *customNhTaskNftStakeModel) UnStakeNft(ctx context.Context, uid uint, token string, isTransferOut bool) error {
update := fmt.Sprintf("UPDATE %s SET `state` = 0 WHERE `uid` = ? AND `token_id` = ?", m.table)
_, err := m.conn.ExecCtx(ctx, update, uid, token)
result, err := m.conn.ExecCtx(ctx, update, uid, token)
if err != nil {
return err
}
row, err := result.RowsAffected()
if err != nil {
return err
}
if row > 0 {
var operate int8
if isTransferOut {
operate = 3
} else {
operate = 2
}
_, err = m.log.Insert(ctx, &NhTaskNftStakeLog{
Uid: uid,
TokenId: token,
Operate: operate,
})
}
return err
}
func (m *customNhTaskNftStakeModel) StakeNft(ctx context.Context, uid uint, roleId uint64, tokens []string) error {
func (m *customNhTaskNftStakeModel) StakeNft(ctx context.Context, uid uint, roleId uint64, tokenId string) error {
insertOrUpdate := fmt.Sprintf("INSERT INTO %s (`uid`, `token_id`, `role_id`, `state`) VALUES (?, ?, ?, 1) ON DUPLICATE KEY UPDATE `role_id` = ?, `state` = 1", m.table)
for _, token := range tokens {
_, err := m.conn.ExecCtx(ctx, insertOrUpdate, uid, token, roleId, roleId)
if err != nil {
return err
}
_, err := m.conn.ExecCtx(ctx, insertOrUpdate, uid, tokenId, roleId, roleId)
if err != nil {
return err
}
_, err = m.log.Insert(ctx, &NhTaskNftStakeLog{
Uid: uid,
RoleId: roleId,
TokenId: tokenId,
Operate: 1,
})
if err != nil {
logx.Errorw("insert stake log failed", logx.Field("err", err), logx.Field("uid", uid), logx.Field("tokenId", token), logx.Field("role", roleId))
}
return nil
}
@@ -67,6 +96,7 @@ func (m *customNhTaskNftStakeModel) StakeNft(ctx context.Context, uid uint, role
func NewNhTaskNftStakeModel(conn sqlx.SqlConn) NhTaskNftStakeModel {
return &customNhTaskNftStakeModel{
defaultNhTaskNftStakeModel: newNhTaskNftStakeModel(conn),
log: NewNhTaskNftStakeLogModel(conn),
}
}

View File

@@ -5,7 +5,9 @@ import (
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stores/redis"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/rest"
"nova_task/internal/config"
"nova_task/internal/middleware"
"nova_task/internal/model"
)
@@ -26,10 +28,15 @@ type ServiceContext struct {
NftHolderModel model.NhNftHolderModel
NftHolderChangeLogModel model.NhNftHolderChangeLogModel
StakeNftModel model.NhTaskNftStakeModel
OldStakeNftModel model.NhNftStakeModel
StakeNftLogModel model.NhTaskNftStakeLogModel
StakeRewardModel model.NhTaskNftStakeRewardModel
GamePitModel model.NhGamePitModel
StakePropertyModel model.NhNftStakePropertyModel
EmailRewardModel model.NhEmailRewardModel
ApiKeyCheck rest.Middleware
AdminSecretCheck rest.Middleware
Earn *ea.Client
DBConn sqlx.SqlConn
@@ -38,6 +45,7 @@ type ServiceContext struct {
func NewServiceContext(c config.Config) *ServiceContext {
dbConn := c.MySql.Conn()
configModel := model.NewNhSystemConfigModel(dbConn, c.Cache)
return &ServiceContext{
Config: c,
@@ -51,14 +59,18 @@ func NewServiceContext(c config.Config) *ServiceContext {
UserModel: model.NewNhUserModel(dbConn),
TouristBindModel: model.NewNhTouristBindModel(dbConn),
WalletModel: model.NewNhWalletModel(dbConn),
ConfigModel: model.NewNhSystemConfigModel(dbConn, c.Cache),
ConfigModel: configModel,
NftHolderModel: model.NewNhNftHolderModel(dbConn),
NftHolderChangeLogModel: model.NewNhNftHolderChangeLogModel(dbConn),
StakeNftModel: model.NewNhTaskNftStakeModel(dbConn),
StakeNftLogModel: model.NewNhTaskNftStakeLogModel(dbConn),
OldStakeNftModel: model.NewNhNftStakeModel(dbConn),
StakeRewardModel: model.NewNhTaskNftStakeRewardModel(dbConn),
GamePitModel: model.NewNhGamePitModel(dbConn),
StakePropertyModel: model.NewNhNftStakePropertyModel(dbConn),
EmailRewardModel: model.NewNhEmailRewardModel(dbConn),
ApiKeyCheck: middleware.NewApiKeyCheckMiddleware(configModel).Handle,
AdminSecretCheck: middleware.NewAdminSecretCheckMiddleware(configModel).Handle,
Earn: c.Earn.BuildEarnClient(),
DBConn: dbConn,

View File

@@ -3,6 +3,11 @@
package types
type CarvResult struct {
Result *Result `json:"result"`
Error *Error `json:"error"`
}
type Community struct {
Id uint `json:"id"` // 社区ID
Title string `json:"title"` // 社区标题
@@ -12,6 +17,22 @@ type Community struct {
EndAt int64 `json:"end_at"` // 结束时间
}
type EmailKey struct {
Email string `form:"email"`
ApiKey string `Header:"x-api-key"`
}
type EmailReward struct {
Email string `json:"email"`
RewardType string `json:"reward_type"`
Value float64 `json:"value"`
}
type Error struct {
Code int `json:"code"`
Message string `json:"message"`
}
type GetCommunityListResp struct {
CommunityList []Community `json:"community_list"` // 社区列表
}
@@ -32,9 +53,13 @@ type GetTaskRewardResp struct {
Points int `json:"points"` // 积分
}
type Result struct {
IsValid bool `json:"isValid"`
}
type StakeNftList struct {
RoleId uint64 `json:"role_id"` // 角色id
TokenIds []string `json:"token_ids"` // nft列表
RoleId uint64 `json:"role_id,optional"` // 角色id
TokenIds []string `json:"token_ids"` // nft列表
}
type StakeTaskDetail struct {
@@ -73,6 +98,12 @@ type UnStakeNftReq struct {
TokenId string `json:"token_id"` // nftID
}
type UnlockChapterReq struct {
Email string `form:"email"`
Chapter int `form:"chapter"`
ApiKey string `Header:"x-api-key"`
}
type UserNft struct {
TokenId string `json:"token_id"` // nftID
Image string `json:"image"` // nft图片