增加软质押手动结算测试接口

This commit is contained in:
lianghuanjie
2025-01-08 11:41:11 +08:00
parent 9aae8bd4dd
commit e7a802efdb
24 changed files with 634 additions and 330 deletions

View File

@@ -13,6 +13,14 @@ service novatask {
@doc "执行发放奖励操作" @doc "执行发放奖励操作"
@handler SendEmailReward @handler SendEmailReward
get /email_reward get /email_reward
@doc "软质压手动结算"
@handler StakeSettle
get /stake_settle
@doc "NFT持有者更新"
@handler NftHolderUpdate
get /nft_holder_update
} }
type EmailReward { type EmailReward {

View File

@@ -43,6 +43,7 @@ CREATE TABLE `nh_task_nft_stake`
`uid` int unsigned NOT NULL COMMENT '用户钱包', `uid` int unsigned NOT NULL COMMENT '用户钱包',
`role_id` bigint unsigned NOT NULL COMMENT '角色id', `role_id` bigint unsigned NOT NULL COMMENT '角色id',
`token_id` varchar(32) NOT NULL COMMENT 'token id', `token_id` varchar(32) NOT NULL COMMENT 'token id',
`type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '类型0=小塔罗1=大塔罗',
`state` tinyint NOT NULL DEFAULT 0 COMMENT '状态1质押中 0已取消质押', `state` tinyint NOT NULL DEFAULT 0 COMMENT '状态1质押中 0已取消质押',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
@@ -52,14 +53,19 @@ CREATE TABLE `nh_task_nft_stake`
CREATE TABLE `nh_task_nft_stake_log` CREATE TABLE `nh_task_nft_stake_log`
( (
`id` int unsigned NOT NULL AUTO_INCREMENT, `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`uid` int unsigned NOT NULL COMMENT '用户钱包', `uid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '用户钱包',
`role_id` bigint unsigned NOT NULL COMMENT '角色id', `role_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '角色id',
`token_id` varchar(32) NOT NULL COMMENT 'token id', `token_id` varchar(32) NOT NULL COMMENT 'token id',
`operate` tinyint NOT NULL DEFAULT 0 COMMENT '状态1质押 2取消质押, 3转出', `operate` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态1质押 2取消质押, 3转出',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `callback_status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '下发通知状态:0未通知,1已通知,2通知异常',
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', `callback_num` int(10) NOT NULL DEFAULT '0' COMMENT '发送通知次数',
PRIMARY KEY (`id`) `callback_at` timestamp NULL DEFAULT NULL COMMENT '发送通知最新时间',
`callback_remark` varchar(255) NOT NULL DEFAULT '' 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`),
KEY `callback_status` (`callback_status`) USING BTREE
) COMMENT ='nft质押日志表'; ) COMMENT ='nft质押日志表';
CREATE TABLE `nh_task_nft_stake_reward` CREATE TABLE `nh_task_nft_stake_reward`

View File

@@ -54,6 +54,36 @@
] ]
} }
}, },
"/gapi/admin/nft_holder_update": {
"get": {
"summary": "NFT持有者更新",
"operationId": "NftHolderUpdate",
"responses": {
"200": {
"description": "A successful response.",
"schema": {}
}
},
"tags": [
"admin"
]
}
},
"/gapi/admin/stake_settle": {
"get": {
"summary": "软质压手动结算",
"operationId": "StakeSettle",
"responses": {
"200": {
"description": "A successful response.",
"schema": {}
}
},
"tags": [
"admin"
]
}
},
"/gapi/carv/bind_role": { "/gapi/carv/bind_role": {
"get": { "get": {
"summary": "下载并绑定Castile游戏角色", "summary": "下载并绑定Castile游戏角色",

View File

@@ -7,4 +7,5 @@ const (
NftStakeTaskConf = "nft_stake_task_conf" NftStakeTaskConf = "nft_stake_task_conf"
CarvApiKey = "carv_api_key" CarvApiKey = "carv_api_key"
AdminSecret = "admin_secret" AdminSecret = "admin_secret"
NftHolderApiConf = "nft_holder_api_conf"
) )

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"
)
// NFT持有者更新
func NftHolderUpdateHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
l := admin.NewNftHolderUpdateLogic(r.Context(), svcCtx)
err := l.NftHolderUpdate()
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 StakeSettleHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
l := admin.NewStakeSettleLogic(r.Context(), svcCtx)
err := l.StakeSettle()
if err != nil {
httpx.ErrorCtx(r.Context(), w, err)
} else {
httpx.Ok(w)
}
}
}

View File

@@ -31,6 +31,18 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/email_reward", Path: "/email_reward",
Handler: admin.SendEmailRewardHandler(serverCtx), Handler: admin.SendEmailRewardHandler(serverCtx),
}, },
{
// NFT持有者更新
Method: http.MethodGet,
Path: "/nft_holder_update",
Handler: admin.NftHolderUpdateHandler(serverCtx),
},
{
// 软质压手动结算
Method: http.MethodGet,
Path: "/stake_settle",
Handler: admin.StakeSettleHandler(serverCtx),
},
}..., }...,
), ),
rest.WithPrefix("/gapi/admin"), rest.WithPrefix("/gapi/admin"),

View File

@@ -2,11 +2,11 @@ package earn
import ( import (
"context" "context"
ea "github.com/earn-alliance/earnalliance-go"
"github.com/robfig/cron/v3" "github.com/robfig/cron/v3"
"github.com/spf13/cast" "github.com/spf13/cast"
"github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
"nova_task/internal/consts" "nova_task/internal/consts"
"nova_task/internal/logic/earn"
"nova_task/internal/svc" "nova_task/internal/svc"
) )
@@ -35,56 +35,8 @@ func (c *Cron) Run() {
logx.Errorw("find earn alliance inviter id failed", logx.Field("err", err)) logx.Errorw("find earn alliance inviter id failed", logx.Field("err", err))
return return
} }
c.pushUserInfo(cast.ToUint(conf.Value)) shareId := cast.ToUint(conf.Value)
c.pushUserBind(cast.ToUint(conf.Value)) lg := earn.NewDataReportLogic(c.ctx, c.svcCtx)
} lg.PushUserInfo(shareId)
lg.PushUserBind(shareId)
func (c *Cron) pushUserInfo(shareId uint) {
us, err := c.svcCtx.PromoteBindModel.FindRequirePushUser(c.ctx, shareId)
if err != nil {
logx.Errorw("find require push user failed", logx.Field("err", err), logx.Field("share_id", shareId))
return
}
logx.Debugw("find require push user", logx.Field("count", len(us)))
for _, u := range us {
ui, err := c.svcCtx.UserModel.FindOne(c.ctx, u.InvitedUid)
if err != nil {
logx.Errorw("find user failed", logx.Field("err", err), logx.Field("uid", u.InvitedUid))
continue
}
var twitterId string
ut, err := c.svcCtx.TwitterModel.FindOne(c.ctx, u.InvitedUid)
if err == nil {
twitterId = ut.TwitterId
}
err = c.svcCtx.PromoteBindModel.UpdatePushUser(c.ctx, u.Id)
if err != nil {
logx.Errorw("update push user failed", logx.Field("err", err), logx.Field("uid", u.InvitedUid), logx.Field("twitter_id", twitterId), logx.Field("email", ui.Email))
} else {
c.svcCtx.Earn.SetIdentifiers(cast.ToString(ui.Id), &ea.Identifiers{
Email: ea.IdentifierFrom(ui.Email),
TwitterId: ea.IdentifierFrom(twitterId),
})
logx.Infow("push user info success", logx.Field("uid", u.InvitedUid), logx.Field("twitter_id", twitterId), logx.Field("email", ui.Email))
}
}
}
func (c *Cron) pushUserBind(shareId uint) {
us, err := c.svcCtx.TouristBindModel.FindRequirePushUser(c.ctx, shareId)
if err != nil {
logx.Errorw("find require push bind role user failed", logx.Field("err", err), logx.Field("share_id", shareId))
return
}
logx.Debugw("find require push bind role user", logx.Field("count", len(us)))
for _, u := range us {
err = c.svcCtx.PromoteBindModel.UpdatePushRole(c.ctx, u.Id)
if err != nil {
logx.Errorw("update push user failed", logx.Field("err", err), logx.Field("uid", u.Uid))
} else {
c.svcCtx.Earn.Track(cast.ToString(u.Uid), "BIND_ROLE", nil, nil)
logx.Infow("push user info success", logx.Field("uid", u.Uid))
}
}
} }

View File

@@ -2,13 +2,10 @@ package holder
import ( import (
"context" "context"
"errors"
"github.com/robfig/cron/v3" "github.com/robfig/cron/v3"
"github.com/spf13/cast"
"github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
"nova_task/internal/model" "nova_task/internal/logic/nft"
"nova_task/internal/svc" "nova_task/internal/svc"
"time"
) )
type Cron struct { type Cron struct {
@@ -33,93 +30,6 @@ func (c *Cron) Spec() string {
func (c *Cron) Run() { func (c *Cron) Run() {
logx.Debugw("run Cron cron task") logx.Debugw("run Cron cron task")
ols, err := GetOwnerList() lg := nft.NewHolderUpdateLogic(c.ctx, c.svcCtx)
if err != nil { lg.HolderUpdate()
logx.Errorw("get owner list error", logx.Field("error", err))
return
}
updateSeq := int(time.Now().Unix())
for _, o := range ols.Owners {
for _, tk := range o.TokenBalances {
balance := cast.ToInt(tk.Balance)
logx.Debugw("owner token", logx.Field("address", o.OwnerAddress), logx.Field("token", tk.TokenID), logx.Field("balance", tk.Balance))
nft, err := c.svcCtx.NftHolderModel.FindOneByTokenId(c.ctx, tk.TokenID)
if err != nil {
if errors.Is(err, model.ErrNotFound) {
nft = &model.NhNftHolder{
Address: o.OwnerAddress,
TokenId: tk.TokenID,
Balance: balance,
UpdateSeq: updateSeq,
}
} else {
logx.Errorw("find nft holder error", logx.Field("error", err), logx.Field("address", o.OwnerAddress), logx.Field("token", tk.TokenID))
continue
}
}
var value int
if nft.Id == 0 {
// 新增
_, err = c.svcCtx.NftHolderModel.Insert(c.ctx, nft)
value = balance
} else {
// 持有数量变化
value = balance - nft.Balance
if value != 0 {
nft.Balance = balance
nft.UpdateSeq = updateSeq
err = c.svcCtx.NftHolderModel.Update(c.ctx, nft)
}
}
if err != nil {
logx.Errorw("insert or update nft holder error", logx.Field("error", err), logx.Field("address", o.OwnerAddress), logx.Field("token", tk.TokenID), logx.Field("balance", balance))
}
// 余额有变化,记录变化日志
if value != 0 {
_, err = c.svcCtx.NftHolderChangeLogModel.Insert(c.ctx, &model.NhNftHolderChangeLog{
Address: o.OwnerAddress,
TokenId: tk.TokenID,
Value: balance,
Balance: balance,
})
if err != nil {
logx.Errorw("insert nft holder change log error", logx.Field("error", err), logx.Field("address", o.OwnerAddress), logx.Field("token", tk.TokenID))
}
}
}
}
// 删除已经不持有的地址,且添加变化日志
nfts, err := c.svcCtx.NftHolderModel.FindOtherUpdateSeq(c.ctx, updateSeq)
if err != nil {
logx.Errorw("find other update seq error", logx.Field("error", err))
return
}
for _, nft := range nfts {
_, err = c.svcCtx.NftHolderChangeLogModel.Insert(c.ctx, &model.NhNftHolderChangeLog{
Address: nft.Address,
TokenId: nft.TokenId,
Value: -nft.Balance,
Balance: 0,
})
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 {
logx.Errorw("delete other update seq error", logx.Field("error", err), logx.Field("update_seq", updateSeq))
}
} }

View File

@@ -1,31 +0,0 @@
package holder
import (
"encoding/json"
"fmt"
"net/http"
)
type OwnerList struct {
Owners []struct {
OwnerAddress string `json:"ownerAddress"`
TokenBalances []struct {
TokenID string `json:"tokenId"`
Balance string `json:"balance"`
} `json:"tokenBalances"`
} `json:"owners"`
PageKey string `json:"pageKey"`
}
func GetOwnerList() (*OwnerList, error) {
contractAddress := "0x89B8D549feA2eBd2aA0b375ce0DCaBba79e7e636"
url := fmt.Sprintf("https://eth-mainnet.g.alchemy.com/nft/v3/alcht_1a183fAsPqF9upfTfp3AC1l0iedGLo/getOwnersForContract?contractAddress=%s&withTokenBalances=true", contractAddress)
resp, err := http.Get(url)
if err != nil {
return nil, err
}
defer resp.Body.Close()
result := new(OwnerList)
err = json.NewDecoder(resp.Body).Decode(result)
return result, err
}

View File

@@ -3,13 +3,9 @@ package stake_settle
import ( import (
"context" "context"
"github.com/robfig/cron/v3" "github.com/robfig/cron/v3"
"github.com/shopspring/decimal"
"github.com/spf13/cast"
"github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
"nova_task/internal/model" "nova_task/internal/logic/nft"
"nova_task/internal/pkg/utils"
"nova_task/internal/svc" "nova_task/internal/svc"
"time"
) )
type Cron struct { type Cron struct {
@@ -30,91 +26,6 @@ func (c *Cron) Spec() string {
func (c *Cron) Run() { func (c *Cron) Run() {
logx.Debugw("run settle cron task") logx.Debugw("run settle cron task")
start, end, err := c.svcCtx.ConfigModel.GetNftStakeTaskOpenDate(c.ctx) lg := nft.NewStakeSettleLogic(c.ctx, c.svcCtx)
if err != nil { lg.StakeSettle()
logx.Errorw("get nft stake task open date failed", logx.Field("err", err))
return
}
end = end.AddDate(0, 0, 1).Add(-time.Second)
now := time.Now()
if now.Before(start) || now.After(end) {
logx.Debugw("now is not in the date range", logx.Field("now", now), logx.Field("start", start), logx.Field("end", end))
return
}
taskConf, err := c.svcCtx.ConfigModel.GetNftStakeTaskConf(c.ctx)
if err != nil {
logx.Errorw("get nft stake task conf failed", logx.Field("err", err))
return
}
stakes, err := c.svcCtx.StakeNftModel.AllStakeNft(c.ctx)
if err != nil {
logx.Errorw("get all stake nft failed", logx.Field("err", err))
return
}
uid2tokens := map[uint]float64{}
for _, s := range stakes {
if s.State != 1 {
continue
}
nftHolder, err := c.svcCtx.NftHolderModel.FindOneByTokenId(c.ctx, s.TokenId)
if err != nil {
logx.Errorw("find nft holder failed", logx.Field("err", err), logx.Field("tokenId", s.TokenId))
continue
}
uid, err := c.svcCtx.WalletModel.FindUidByAddress(c.ctx, nftHolder.Address)
if err != nil {
logx.Errorw("find uid by address failed", logx.Field("err", err), logx.Field("address", nftHolder.Address))
continue
}
if uid != s.Uid {
logx.Errorw("uid not match", logx.Field("uid", s.Uid), logx.Field("nftHolderUid", uid))
continue
}
if utils.IsBigTarot(s.TokenId) {
uid2tokens[s.Uid] += float64(taskConf.GreatTarot)
} else {
uid2tokens[s.Uid] += float64(taskConf.LittleTarot)
}
}
awardSeq := cast.ToInt(time.Now().AddDate(0, 0, -1).Format("20060102"))
for uid, tokens := range uid2tokens {
coefficient, err := c.svcCtx.StakeRewardModel.GetRandomCoefficientByUid(c.ctx, uid, awardSeq, taskConf.MinCoefficient, taskConf.MaxCoefficient)
if err != nil {
logx.Errorw("get random coefficient failed", logx.Field("err", err), logx.Field("uid", uid), logx.Field("awardSeq", awardSeq))
continue
}
tokensDecimal := decimal.NewFromFloat(tokens)
reward := tokensDecimal.Mul(decimal.NewFromFloat(coefficient))
err = c.svcCtx.StakeRewardModel.SetReward(c.ctx, uid, awardSeq, taskConf.OccupyPercent, tokensDecimal, reward)
if err != nil {
logx.Errorw("set reward failed", logx.Field("err", err), logx.Field("uid", uid), logx.Field("awardSeq", awardSeq), logx.Field("coefficient", coefficient), logx.Field("tokens", tokens), logx.Field("reward", reward))
continue
}
// 加资产
err = c.svcCtx.TaskAssetModel.AddCastile(c.ctx, uid, reward)
if err != nil {
logx.Errorw("add castile failed", logx.Field("err", err), logx.Field("uid", uid), logx.Field("awardSeq", awardSeq), logx.Field("reward", reward))
continue
}
// 加资产记录表
_, err = c.svcCtx.TaskAssetRecordModel.Insert(c.ctx, &model.NhTaskAssetRecord{
Uid: int(uid),
EventId: 0,
AssetField: "castile",
Count: reward.InexactFloat64(),
Remark: "nft软质押奖励",
ProvideUid: 0,
CreateTime: int(now.Unix()),
})
if err != nil {
logx.Errorw("insert task asset record failed", logx.Field("err", err), logx.Field("uid", uid), logx.Field("awardSeq", awardSeq), logx.Field("reward", reward))
}
}
} }

View File

@@ -0,0 +1,31 @@
package admin
import (
"context"
"nova_task/internal/logic/nft"
"nova_task/internal/pkg/errs"
"github.com/zeromicro/go-zero/core/logx"
"nova_task/internal/svc"
)
type NftHolderUpdateLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
// NFT持有者更新
func NewNftHolderUpdateLogic(ctx context.Context, svcCtx *svc.ServiceContext) *NftHolderUpdateLogic {
return &NftHolderUpdateLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *NftHolderUpdateLogic) NftHolderUpdate() error {
lg := nft.NewHolderUpdateLogic(l.ctx, l.svcCtx)
lg.HolderUpdate()
return errs.Success()
}

View File

@@ -0,0 +1,30 @@
package admin
import (
"context"
"github.com/zeromicro/go-zero/core/logx"
"nova_task/internal/logic/nft"
"nova_task/internal/pkg/errs"
"nova_task/internal/svc"
)
type StakeSettleLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
// 软质压手动结算
func NewStakeSettleLogic(ctx context.Context, svcCtx *svc.ServiceContext) *StakeSettleLogic {
return &StakeSettleLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *StakeSettleLogic) StakeSettle() error {
lg := nft.NewStakeSettleLogic(l.ctx, l.svcCtx)
lg.StakeSettle()
return errs.Success()
}

View File

@@ -2,6 +2,9 @@ package carv
import ( import (
"context" "context"
"errors"
"nova_task/internal/model"
"nova_task/internal/pkg/errs"
"nova_task/internal/svc" "nova_task/internal/svc"
"nova_task/internal/types" "nova_task/internal/types"
@@ -24,8 +27,40 @@ func NewBindWalletLogic(ctx context.Context, svcCtx *svc.ServiceContext) *BindWa
} }
} }
func (l *BindWalletLogic) BindWallet(req *types.EmailKey) (resp *types.CarvResult, err error) { func (l *BindWalletLogic) BindWallet(req *types.EmailKey) (*types.CarvResult, error) {
l.svcCtx.UserModel.FindOneByEmail(l.ctx, req.Email) u, err := l.svcCtx.UserModel.FindOneByEmail(l.ctx, req.Email)
if err != nil {
if !errors.Is(err, model.ErrNotFound) {
return &types.CarvResult{
Error: &types.Error{
Code: int(errs.ErrDatabaseOperate),
Message: "system error",
},
}, nil
}
return &types.CarvResult{
Error: &types.Error{
Code: int(errs.ErrUserNotFound),
Message: "email not exist",
},
}, nil
}
return _, err = l.svcCtx.WalletModel.FindAddressByUid(l.ctx, u.Id)
if err != nil {
if !errors.Is(err, model.ErrNotFound) {
return &types.CarvResult{
Error: &types.Error{
Code: int(errs.ErrDatabaseOperate),
Message: "system error",
},
}, nil
}
return &types.CarvResult{
Result: &types.Result{IsValid: false},
}, nil
}
return &types.CarvResult{
Result: &types.Result{IsValid: true},
}, nil
} }

View File

@@ -0,0 +1,71 @@
package earn
import (
"context"
ea "github.com/earn-alliance/earnalliance-go"
"github.com/spf13/cast"
"github.com/zeromicro/go-zero/core/logx"
"nova_task/internal/svc"
)
type DataReportLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewDataReportLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DataReportLogic {
return &DataReportLogic{
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *DataReportLogic) PushUserInfo(shareId uint) {
us, err := l.svcCtx.PromoteBindModel.FindRequirePushUser(l.ctx, shareId)
if err != nil {
logx.Errorw("find require push user failed", logx.Field("err", err), logx.Field("share_id", shareId))
return
}
logx.Debugw("find require push user", logx.Field("count", len(us)))
for _, u := range us {
ui, err := l.svcCtx.UserModel.FindOne(l.ctx, u.InvitedUid)
if err != nil {
logx.Errorw("find user failed", logx.Field("err", err), logx.Field("uid", u.InvitedUid))
continue
}
var twitterId string
ut, err := l.svcCtx.TwitterModel.FindOne(l.ctx, u.InvitedUid)
if err == nil {
twitterId = ut.TwitterId
}
err = l.svcCtx.PromoteBindModel.UpdatePushUser(l.ctx, u.Id)
if err != nil {
logx.Errorw("update push user failed", logx.Field("err", err), logx.Field("uid", u.InvitedUid), logx.Field("twitter_id", twitterId), logx.Field("email", ui.Email))
} else {
l.svcCtx.Earn.SetIdentifiers(cast.ToString(ui.Id), &ea.Identifiers{
Email: ea.IdentifierFrom(ui.Email),
TwitterId: ea.IdentifierFrom(twitterId),
})
logx.Infow("push user info success", logx.Field("uid", u.InvitedUid), logx.Field("twitter_id", twitterId), logx.Field("email", ui.Email))
}
}
}
func (l *DataReportLogic) PushUserBind(shareId uint) {
us, err := l.svcCtx.TouristBindModel.FindRequirePushUser(l.ctx, shareId)
if err != nil {
logx.Errorw("find require push bind role user failed", logx.Field("err", err), logx.Field("share_id", shareId))
return
}
logx.Debugw("find require push bind role user", logx.Field("count", len(us)))
for _, u := range us {
err = l.svcCtx.PromoteBindModel.UpdatePushRole(l.ctx, u.Id)
if err != nil {
logx.Errorw("update push user failed", logx.Field("err", err), logx.Field("uid", u.Uid))
} else {
l.svcCtx.Earn.Track(cast.ToString(u.Uid), "BIND_ROLE", nil, nil)
logx.Infow("push user info success", logx.Field("uid", u.Uid))
}
}
}

View File

@@ -0,0 +1,158 @@
package nft
import (
"context"
"encoding/json"
"errors"
"fmt"
"github.com/spf13/cast"
"github.com/zeromicro/go-zero/core/logx"
"net/http"
"nova_task/internal/consts"
"nova_task/internal/model"
"nova_task/internal/svc"
"time"
)
type HolderUpdateLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewHolderUpdateLogic(ctx context.Context, svcCtx *svc.ServiceContext) *HolderUpdateLogic {
return &HolderUpdateLogic{
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *HolderUpdateLogic) HolderUpdate() {
conf := struct {
Network string `json:"network"`
Contract string `json:"contract"`
}{}
cf, err := l.svcCtx.ConfigModel.FindOneByName(l.ctx, consts.NftHolderApiConf)
if err != nil {
logx.Errorw("find nft holder api conf error", logx.Field("error", err))
return
}
err = json.Unmarshal([]byte(cf.Value), &conf)
if err != nil {
logx.Errorw("unmarshal nft holder api conf error", logx.Field("error", err), logx.Field("value", cf.Value))
return
}
ols, err := l.GetOwnerList(conf.Network, conf.Contract)
if err != nil {
logx.Errorw("get owner list error", logx.Field("error", err))
return
}
updateSeq := int(time.Now().Unix())
for _, o := range ols.Owners {
for _, tk := range o.TokenBalances {
balance := cast.ToInt(tk.Balance)
logx.Debugw("owner token", logx.Field("address", o.OwnerAddress), logx.Field("token", tk.TokenID), logx.Field("balance", tk.Balance))
nft, err := l.svcCtx.NftHolderModel.FindOneByTokenId(l.ctx, tk.TokenID)
if err != nil {
if errors.Is(err, model.ErrNotFound) {
nft = &model.NhNftHolder{
Address: o.OwnerAddress,
TokenId: tk.TokenID,
Balance: balance,
UpdateSeq: updateSeq,
}
} else {
logx.Errorw("find nft holder error", logx.Field("error", err), logx.Field("address", o.OwnerAddress), logx.Field("token", tk.TokenID))
continue
}
}
var value int
if nft.Id == 0 {
// 新增
_, err = l.svcCtx.NftHolderModel.Insert(l.ctx, nft)
value = balance
} else {
// 持有数量变化
value = balance - nft.Balance
if value != 0 {
nft.Balance = balance
nft.UpdateSeq = updateSeq
err = l.svcCtx.NftHolderModel.Update(l.ctx, nft)
}
}
if err != nil {
logx.Errorw("insert or update nft holder error", logx.Field("error", err), logx.Field("address", o.OwnerAddress), logx.Field("token", tk.TokenID), logx.Field("balance", balance))
}
// 余额有变化,记录变化日志
if value != 0 {
_, err = l.svcCtx.NftHolderChangeLogModel.Insert(l.ctx, &model.NhNftHolderChangeLog{
Address: o.OwnerAddress,
TokenId: tk.TokenID,
Value: balance,
Balance: balance,
})
if err != nil {
logx.Errorw("insert nft holder change log error", logx.Field("error", err), logx.Field("address", o.OwnerAddress), logx.Field("token", tk.TokenID))
}
}
}
}
// 删除已经不持有的地址,且添加变化日志
nfts, err := l.svcCtx.NftHolderModel.FindOtherUpdateSeq(l.ctx, updateSeq)
if err != nil {
logx.Errorw("find other update seq error", logx.Field("error", err))
return
}
for _, nft := range nfts {
_, err = l.svcCtx.NftHolderChangeLogModel.Insert(l.ctx, &model.NhNftHolderChangeLog{
Address: nft.Address,
TokenId: nft.TokenId,
Value: -nft.Balance,
Balance: 0,
})
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 := l.svcCtx.WalletModel.FindUidByAddress(l.ctx, nft.Address)
if err != nil {
logx.Errorw("find uid by address error", logx.Field("error", err), logx.Field("address", nft.Address))
continue
}
err = l.svcCtx.StakeNftModel.UnStakeNft(l.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 = l.svcCtx.NftHolderModel.DeleteOtherUpdateSeq(l.ctx, updateSeq)
if err != nil {
logx.Errorw("delete other update seq error", logx.Field("error", err), logx.Field("update_seq", updateSeq))
}
}
type OwnerList struct {
Owners []struct {
OwnerAddress string `json:"ownerAddress"`
TokenBalances []struct {
TokenID string `json:"tokenId"`
Balance string `json:"balance"`
} `json:"tokenBalances"`
} `json:"owners"`
PageKey string `json:"pageKey"`
}
func (l *HolderUpdateLogic) GetOwnerList(network, contractAddress string) (*OwnerList, error) {
url := fmt.Sprintf("https://eth-%s.g.alchemy.com/nft/v3/alcht_1a183fAsPqF9upfTfp3AC1l0iedGLo/getOwnersForContract?contractAddress=%s&withTokenBalances=true", network, contractAddress)
resp, err := http.Get(url)
if err != nil {
return nil, err
}
defer resp.Body.Close()
result := new(OwnerList)
err = json.NewDecoder(resp.Body).Decode(result)
return result, err
}

View File

@@ -0,0 +1,114 @@
package nft
import (
"context"
"github.com/shopspring/decimal"
"github.com/spf13/cast"
"github.com/zeromicro/go-zero/core/logx"
"nova_task/internal/model"
"nova_task/internal/pkg/utils"
"nova_task/internal/svc"
"time"
)
type StakeSettleLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewStakeSettleLogic(ctx context.Context, svcCtx *svc.ServiceContext) *StakeSettleLogic {
return &StakeSettleLogic{
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *StakeSettleLogic) StakeSettle() {
start, end, err := l.svcCtx.ConfigModel.GetNftStakeTaskOpenDate(l.ctx)
if err != nil {
logx.Errorw("get nft stake task open date failed", logx.Field("err", err))
return
}
end = end.AddDate(0, 0, 1).Add(-time.Second)
now := time.Now()
if now.Before(start) || now.After(end) {
logx.Infow("now is not in the date range", logx.Field("now", now), logx.Field("start", start), logx.Field("end", end))
return
}
taskConf, err := l.svcCtx.ConfigModel.GetNftStakeTaskConf(l.ctx)
if err != nil {
logx.Errorw("get nft stake task conf failed", logx.Field("err", err))
return
}
stakes, err := l.svcCtx.StakeNftModel.AllStakeNft(l.ctx)
if err != nil {
logx.Errorw("get all stake nft failed", logx.Field("err", err))
return
}
uid2tokens := map[uint]float64{}
for _, s := range stakes {
if s.State != 1 {
continue
}
nftHolder, err := l.svcCtx.NftHolderModel.FindOneByTokenId(l.ctx, s.TokenId)
if err != nil {
logx.Errorw("find nft holder failed", logx.Field("err", err), logx.Field("tokenId", s.TokenId))
continue
}
uid, err := l.svcCtx.WalletModel.FindUidByAddress(l.ctx, nftHolder.Address)
if err != nil {
logx.Errorw("find uid by address failed", logx.Field("err", err), logx.Field("address", nftHolder.Address))
continue
}
if uid != s.Uid {
logx.Errorw("uid not match", logx.Field("uid", s.Uid), logx.Field("nftHolderUid", uid))
continue
}
if utils.IsBigTarot(s.TokenId) {
uid2tokens[s.Uid] += float64(taskConf.GreatTarot)
} else {
uid2tokens[s.Uid] += float64(taskConf.LittleTarot)
}
}
awardSeq := cast.ToInt(time.Now().AddDate(0, 0, -1).Format("20060102"))
for uid, tokens := range uid2tokens {
coefficient, err := l.svcCtx.StakeRewardModel.GetRandomCoefficientByUid(l.ctx, uid, awardSeq, taskConf.MinCoefficient, taskConf.MaxCoefficient)
if err != nil {
logx.Errorw("get random coefficient failed", logx.Field("err", err), logx.Field("uid", uid), logx.Field("awardSeq", awardSeq))
continue
}
tokensDecimal := decimal.NewFromFloat(tokens)
reward := tokensDecimal.Mul(decimal.NewFromFloat(coefficient))
err = l.svcCtx.StakeRewardModel.SetReward(l.ctx, uid, awardSeq, taskConf.OccupyPercent, tokensDecimal, reward)
if err != nil {
logx.Errorw("set reward failed", logx.Field("err", err), logx.Field("uid", uid), logx.Field("awardSeq", awardSeq), logx.Field("coefficient", coefficient), logx.Field("tokens", tokens), logx.Field("reward", reward))
continue
}
// 加资产
err = l.svcCtx.TaskAssetModel.AddCastile(l.ctx, uid, reward)
if err != nil {
logx.Errorw("add castile failed", logx.Field("err", err), logx.Field("uid", uid), logx.Field("awardSeq", awardSeq), logx.Field("reward", reward))
continue
}
// 加资产记录表
_, err = l.svcCtx.TaskAssetRecordModel.Insert(l.ctx, &model.NhTaskAssetRecord{
Uid: int(uid),
EventId: 0,
AssetField: "castile",
Count: reward.InexactFloat64(),
Remark: "nft软质押奖励",
ProvideUid: 0,
CreateTime: int(now.Unix()),
})
if err != nil {
logx.Errorw("insert task asset record failed", logx.Field("err", err), logx.Field("uid", uid), logx.Field("awardSeq", awardSeq), logx.Field("reward", reward))
}
}
}

View File

@@ -48,7 +48,7 @@ func (l *GetNftListLogic) GetNftList(req *types.GetNftListReq) (*types.UserNftLi
var hasStake bool var hasStake bool
var stakeAt string var stakeAt string
var roleId uint64 var roleId uint64
nft, err := l.svcCtx.StakeNftModel.FindOneByUidTokenId(l.ctx, uid, token) nft, err := l.svcCtx.StakeNftModel.FindOneByTokenId(l.ctx, token)
if err == nil { if err == nil {
hasStake = nft.State == 1 hasStake = nft.State == 1
if hasStake { if hasStake {

View File

@@ -40,37 +40,52 @@ func (l *StakeNftLogic) StakeNft(req *types.StakeNftList) error {
l.Errorw("find nft holder failed", logx.Field("err", err), logx.Field("uid", uid), logx.Field("tokenId", tokenId)) l.Errorw("find nft holder failed", logx.Field("err", err), logx.Field("uid", uid), logx.Field("tokenId", tokenId))
return errs.New(errs.ErrDatabaseOperate, err) return errs.New(errs.ErrDatabaseOperate, err)
} }
l.svcCtx.WalletModel.FindUidByAddress(l.ctx, tkHolder.Address) wUid, err := l.svcCtx.WalletModel.FindUidByAddress(l.ctx, tkHolder.Address)
err = l.svcCtx.StakeNftModel.StakeNft(l.ctx, uid, req.RoleId, tokenId) if err != nil {
if !errors.Is(err, model.ErrNotFound) {
l.Errorw("find wallet by address failed", logx.Field("err", err), logx.Field("uid", uid), logx.Field("address", tkHolder.Address))
return errs.New(errs.ErrDatabaseOperate, err)
}
return errs.New(errs.ErrNftNotBelongToUser, "nft not belong to user")
}
if wUid != uid {
l.Errorw("nft not belong to user", logx.Field("uid", uid), logx.Field("address", tkHolder.Address))
return errs.New(errs.ErrNftNotBelongToUser, "nft not belong to user")
}
var sns []int8
var propertyId string
var tarotType int8
if utils.IsBigTarot(tokenId) {
sns = []int8{1, 2}
propertyId = "402505"
tarotType = 1
} else {
sns = []int8{1}
propertyId = "402605"
}
err = l.svcCtx.StakeNftModel.StakeNft(l.ctx, uid, req.RoleId, tokenId, tarotType)
if err != nil { if err != nil {
l.Errorw("stake nft failed", logx.Field("err", err), logx.Field("uid", uid), logx.Field("tokenIds", req.TokenIds)) l.Errorw("stake nft failed", logx.Field("err", err), logx.Field("uid", uid), logx.Field("tokenIds", req.TokenIds))
return errs.New(errs.ErrDatabaseOperate, err) return errs.New(errs.ErrDatabaseOperate, err)
} }
var sns []int8 if req.RoleId > 0 {
var propertyId string for _, sn := range sns {
if utils.IsBigTarot(tokenId) { _, err = l.svcCtx.StakePropertyModel.Insert(l.ctx, &model.NhNftStakeProperty{
sns = []int8{1, 2} Uid: uid,
propertyId = "402505" RoleId: int64(req.RoleId),
} else { TokenId: cast.ToUint(tokenId),
sns = []int8{1} PropertyId: propertyId,
propertyId = "402605" Sn: sn,
} })
for _, sn := range sns { if err != nil {
_, err = l.svcCtx.StakePropertyModel.Insert(l.ctx, &model.NhNftStakeProperty{ errMySQL := new(mysql.MySQLError)
Uid: uid, if errors.As(err, &errMySQL) {
RoleId: int64(req.RoleId), switch errMySQL.Number {
TokenId: cast.ToUint(tokenId), case 1062:
PropertyId: propertyId, default:
Sn: sn, l.Errorw("insert stake property failed", logx.Field("err", err), logx.Field("uid", uid), logx.Field("tokenId", tokenId), logx.Field("propertyId", propertyId))
}) }
if err != nil {
errMySQL := new(mysql.MySQLError)
if errors.As(err, &errMySQL) {
switch errMySQL.Number {
case 1062:
default:
l.Errorw("insert stake property failed", logx.Field("err", err), logx.Field("uid", uid), logx.Field("tokenId", tokenId), logx.Field("propertyId", propertyId))
} }
} }
} }

View File

@@ -37,13 +37,17 @@ type (
} }
NhTaskNftStakeLog struct { NhTaskNftStakeLog struct {
Id uint `db:"id"` Id uint `db:"id"`
Uid uint `db:"uid"` // 用户钱包 Uid uint `db:"uid"` // 用户钱包
RoleId uint64 `db:"role_id"` // 角色id RoleId uint64 `db:"role_id"` // 角色id
TokenId string `db:"token_id"` // token id TokenId string `db:"token_id"` // token id
Operate int8 `db:"operate"` // 状态1质押 2取消质押, 3转出 Operate int8 `db:"operate"` // 状态1质押 2取消质押, 3转出
CreatedAt time.Time `db:"created_at"` // 创建时间 CallbackStatus int8 `db:"callback_status"` // 下发通知状态:0未通知,1已通知,2通知异常
UpdatedAt time.Time `db:"updated_at"` // 修改时间 CallbackNum int `db:"callback_num"` // 发送通知次数
CallbackAt sql.NullTime `db:"callback_at"` // 发送通知最新时间
CallbackRemark string `db:"callback_remark"` // 通知回调备注
CreatedAt time.Time `db:"created_at"` // 创建时间
UpdatedAt time.Time `db:"updated_at"` // 修改时间
} }
) )
@@ -75,14 +79,14 @@ func (m *defaultNhTaskNftStakeLogModel) FindOne(ctx context.Context, id uint) (*
} }
func (m *defaultNhTaskNftStakeLogModel) Insert(ctx context.Context, data *NhTaskNftStakeLog) (sql.Result, error) { func (m *defaultNhTaskNftStakeLogModel) Insert(ctx context.Context, data *NhTaskNftStakeLog) (sql.Result, error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?)", m.table, nhTaskNftStakeLogRowsExpectAutoSet) 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) ret, err := m.conn.ExecCtx(ctx, query, data.Uid, data.RoleId, data.TokenId, data.Operate, data.CallbackStatus, data.CallbackNum, data.CallbackAt, data.CallbackRemark)
return ret, err return ret, err
} }
func (m *defaultNhTaskNftStakeLogModel) Update(ctx context.Context, data *NhTaskNftStakeLog) error { func (m *defaultNhTaskNftStakeLogModel) Update(ctx context.Context, data *NhTaskNftStakeLog) error {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, nhTaskNftStakeLogRowsWithPlaceHolder) query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, nhTaskNftStakeLogRowsWithPlaceHolder)
_, err := m.conn.ExecCtx(ctx, query, data.Uid, data.RoleId, data.TokenId, data.Operate, data.Id) _, err := m.conn.ExecCtx(ctx, query, data.Uid, data.RoleId, data.TokenId, data.Operate, data.CallbackStatus, data.CallbackNum, data.CallbackAt, data.CallbackRemark, data.Id)
return err return err
} }

View File

@@ -16,7 +16,7 @@ type (
NhTaskNftStakeModel interface { NhTaskNftStakeModel interface {
nhTaskNftStakeModel nhTaskNftStakeModel
withSession(session sqlx.Session) NhTaskNftStakeModel withSession(session sqlx.Session) NhTaskNftStakeModel
StakeNft(ctx context.Context, uid uint, roleId uint64, tokenId string) error StakeNft(ctx context.Context, uid uint, roleId uint64, tokenId string, tarotType int8) error
UnStakeNft(ctx context.Context, uid uint, token string, isTransferOut bool) error UnStakeNft(ctx context.Context, uid uint, token string, isTransferOut bool) error
FindByUid(ctx context.Context, uid uint) ([]NhTaskNftStake, error) FindByUid(ctx context.Context, uid uint) ([]NhTaskNftStake, error)
AllStakeNft(ctx context.Context) ([]NhTaskNftStake, error) AllStakeNft(ctx context.Context) ([]NhTaskNftStake, error)
@@ -49,7 +49,7 @@ func (m *customNhTaskNftStakeModel) FindByUid(ctx context.Context, uid uint) ([]
} }
func (m *customNhTaskNftStakeModel) UnStakeNft(ctx context.Context, uid uint, token string, isTransferOut bool) 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) update := fmt.Sprintf("UPDATE %s SET `state` = 0 WHERE `token_id` = ?", m.table)
result, err := m.conn.ExecCtx(ctx, update, uid, token) result, err := m.conn.ExecCtx(ctx, update, uid, token)
if err != nil { if err != nil {
return err return err
@@ -74,9 +74,9 @@ func (m *customNhTaskNftStakeModel) UnStakeNft(ctx context.Context, uid uint, to
return err return err
} }
func (m *customNhTaskNftStakeModel) StakeNft(ctx context.Context, uid uint, roleId uint64, tokenId string) error { func (m *customNhTaskNftStakeModel) StakeNft(ctx context.Context, uid uint, roleId uint64, tokenId string, tarotType int8) 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) insertOrUpdate := fmt.Sprintf("INSERT INTO %s (`uid`, `token_id`, `role_id`, `type`, `state`) VALUES (?, ?, ?, ?, 1) ON DUPLICATE KEY UPDATE `uid` = ?, `role_id` = ?, `state` = 1", m.table)
_, err := m.conn.ExecCtx(ctx, insertOrUpdate, uid, tokenId, roleId, roleId) _, err := m.conn.ExecCtx(ctx, insertOrUpdate, uid, tokenId, roleId, tarotType, uid, roleId)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -27,7 +27,7 @@ type (
nhTaskNftStakeModel interface { nhTaskNftStakeModel interface {
Insert(ctx context.Context, data *NhTaskNftStake) (sql.Result, error) Insert(ctx context.Context, data *NhTaskNftStake) (sql.Result, error)
FindOne(ctx context.Context, id uint) (*NhTaskNftStake, error) FindOne(ctx context.Context, id uint) (*NhTaskNftStake, error)
FindOneByUidTokenId(ctx context.Context, uid uint, tokenId string) (*NhTaskNftStake, error) FindOneByTokenId(ctx context.Context, tokenId string) (*NhTaskNftStake, error)
Update(ctx context.Context, data *NhTaskNftStake) error Update(ctx context.Context, data *NhTaskNftStake) error
Delete(ctx context.Context, id uint) error Delete(ctx context.Context, id uint) error
} }
@@ -41,6 +41,7 @@ type (
Id uint `db:"id"` Id uint `db:"id"`
Uid uint `db:"uid"` // 用户钱包 Uid uint `db:"uid"` // 用户钱包
RoleId uint64 `db:"role_id"` // 角色id RoleId uint64 `db:"role_id"` // 角色id
Type int8 `db:"type"` // 类型0=小塔罗1=大塔罗
TokenId string `db:"token_id"` // token id TokenId string `db:"token_id"` // token id
State int8 `db:"state"` // 状态1质押中 0已取消质押 State int8 `db:"state"` // 状态1质押中 0已取消质押
CreatedAt time.Time `db:"created_at"` // 创建时间 CreatedAt time.Time `db:"created_at"` // 创建时间
@@ -75,10 +76,10 @@ func (m *defaultNhTaskNftStakeModel) FindOne(ctx context.Context, id uint) (*NhT
} }
} }
func (m *defaultNhTaskNftStakeModel) FindOneByUidTokenId(ctx context.Context, uid uint, tokenId string) (*NhTaskNftStake, error) { func (m *defaultNhTaskNftStakeModel) FindOneByTokenId(ctx context.Context, tokenId string) (*NhTaskNftStake, error) {
var resp NhTaskNftStake var resp NhTaskNftStake
query := fmt.Sprintf("select %s from %s where `uid` = ? and `token_id` = ? limit 1", nhTaskNftStakeRows, m.table) query := fmt.Sprintf("select %s from %s where `token_id` = ? limit 1", nhTaskNftStakeRows, m.table)
err := m.conn.QueryRowCtx(ctx, &resp, query, uid, tokenId) err := m.conn.QueryRowCtx(ctx, &resp, query, tokenId)
switch err { switch err {
case nil: case nil:
return &resp, nil return &resp, nil
@@ -90,14 +91,14 @@ func (m *defaultNhTaskNftStakeModel) FindOneByUidTokenId(ctx context.Context, ui
} }
func (m *defaultNhTaskNftStakeModel) Insert(ctx context.Context, data *NhTaskNftStake) (sql.Result, error) { func (m *defaultNhTaskNftStakeModel) Insert(ctx context.Context, data *NhTaskNftStake) (sql.Result, error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?)", m.table, nhTaskNftStakeRowsExpectAutoSet) query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?)", m.table, nhTaskNftStakeRowsExpectAutoSet)
ret, err := m.conn.ExecCtx(ctx, query, data.Uid, data.RoleId, data.TokenId, data.State) ret, err := m.conn.ExecCtx(ctx, query, data.Uid, data.RoleId, data.Type, data.TokenId, data.State)
return ret, err return ret, err
} }
func (m *defaultNhTaskNftStakeModel) Update(ctx context.Context, newData *NhTaskNftStake) error { func (m *defaultNhTaskNftStakeModel) Update(ctx context.Context, newData *NhTaskNftStake) error {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, nhTaskNftStakeRowsWithPlaceHolder) query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, nhTaskNftStakeRowsWithPlaceHolder)
_, err := m.conn.ExecCtx(ctx, query, newData.Uid, newData.RoleId, newData.TokenId, newData.State, newData.Id) _, err := m.conn.ExecCtx(ctx, query, newData.Uid, newData.RoleId, newData.Type, newData.TokenId, newData.State, newData.Id)
return err return err
} }

View File

@@ -28,7 +28,7 @@ type (
// SetReward 对未发送奖励的用户发送奖励,支持并发,且不会重发 // SetReward 对未发送奖励的用户发送奖励,支持并发,且不会重发
func (m *customNhTaskNftStakeRewardModel) SetReward(ctx context.Context, uid uint, awardSeq, occupyPercent int, pledgeOutput, reward decimal.Decimal) error { func (m *customNhTaskNftStakeRewardModel) SetReward(ctx context.Context, uid uint, awardSeq, occupyPercent int, pledgeOutput, reward decimal.Decimal) error {
update := fmt.Sprintf("UPDATE %s SET `occupy_percent` = ?, `pledge_output` = ?, `reward` = ?, `sent` = 1 WHERE `uid` = ? AND `award_seq` = ?, `sent` = 0", m.table) update := fmt.Sprintf("UPDATE %s SET `occupy_percent` = ?, `pledge_output` = ?, `reward` = ?, `sent` = 1 WHERE `uid` = ? AND `award_seq` = ? AND `sent` = 0", m.table)
result, err := m.conn.ExecCtx(ctx, update, occupyPercent, pledgeOutput, reward, uid, awardSeq) result, err := m.conn.ExecCtx(ctx, update, occupyPercent, pledgeOutput, reward, uid, awardSeq)
if err != nil { if err != nil {
return err return err

View File

@@ -25,4 +25,6 @@ const (
ErrNotBindWallet Reason = 20004 // 未绑定钱包 ErrNotBindWallet Reason = 20004 // 未绑定钱包
ErrTaskOpenDateNotSet Reason = 20005 // 任务开放时间未设置 ErrTaskOpenDateNotSet Reason = 20005 // 任务开放时间未设置
ErrTaskConfNotSet Reason = 20006 // 任务配置未设置 ErrTaskConfNotSet Reason = 20006 // 任务配置未设置
ErrUserNotFound Reason = 20007 // 用户不存在
ErrNftNotBelongToUser Reason = 20008 // NFT不属于用户
) )