From ea86ab71e8af3bd11cb8c246b946a82eae01f8fa Mon Sep 17 00:00:00 2001 From: lianghuanjie Date: Tue, 31 Dec 2024 20:39:02 +0800 Subject: [PATCH] nft task reward --- Makefile | 2 +- doc/api/nova-task.api | 9 +- doc/sql/novatask.sql | 158 ++--- doc/swagger/nova-task.json | 42 +- etc/novatask.yaml | 15 +- internal/handler/task/get_nft_list_handler.go | 9 +- internal/job/holder/cron.go | 2 +- internal/job/stake_settle/cron.go | 50 ++ internal/logic/task/get_nft_list_logic.go | 30 +- .../logic/task/get_stake_task_detail_logic.go | 10 + internal/logic/task/stake_nft_logic.go | 2 +- internal/model/nh_nft_holder_model_gen.go | 8 +- .../model/nh_task_nft_stake_log_model_gen.go | 7 +- internal/model/nh_task_nft_stake_model.go | 8 +- internal/model/nh_task_nft_stake_model_gen.go | 7 +- .../model/nh_task_nft_stake_reward_model.go | 48 +- .../nh_task_nft_stake_reward_model_gen.go | 42 +- internal/pkg/utils/big_tarot.go | 38 -- internal/pkg/utils/tarot.go | 621 ++++++++++++++++++ internal/types/types.go | 7 + 20 files changed, 945 insertions(+), 170 deletions(-) delete mode 100644 internal/pkg/utils/big_tarot.go create mode 100644 internal/pkg/utils/tarot.go diff --git a/Makefile b/Makefile index 05860ce..3dca6a9 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -host ?= 192.168.2.108:3306 +host ?= 192.168.20.101:3306 user ?= huangjie pwd ?= jMDqPQM^a6hsAR table ?= diff --git a/doc/api/nova-task.api b/doc/api/nova-task.api index 985fd97..9f30a87 100644 --- a/doc/api/nova-task.api +++ b/doc/api/nova-task.api @@ -30,7 +30,7 @@ service novatask { @doc "拉取玩家持有的nft列表" @handler GetNftList - get /nfts returns (UserNftList) + get /nfts (GetNftListReq) returns (UserNftList) @doc "质押任务详情" @handler GetStakeTaskDetail @@ -115,8 +115,14 @@ type StakeTaskDetail { // UserNft 用户NFT type UserNft { TokenId string `json:"token_id"` // nftID + Image string `json:"image"` // nft图片 HasStake bool `json:"has_stake"` // 是否已质押 StakeAt string `json:"stake_at"` // 质押时间 + RoleId uint64 `json:"role_id"` // 角色id +} + +type GetNftListReq { + WalletAddress string `form:"wallet_address"` } // UserNftList 用户NFT列表 @@ -126,6 +132,7 @@ type UserNftList { // StakeNftList 质押请求参数NFT列表 type StakeNftList { + RoleId uint64 `json:"role_id"` // 角色id TokenIds []string `json:"token_ids"` // nft列表 } diff --git a/doc/sql/novatask.sql b/doc/sql/novatask.sql index ffd0524..031fac5 100644 --- a/doc/sql/novatask.sql +++ b/doc/sql/novatask.sql @@ -1,78 +1,82 @@ -CREATE TABLE `nh_task_progress` -( - `id` int(11) unsigned NOT NULL AUTO_INCREMENT, - `uid` int(11) unsigned NOT NULL, - `task_id` int(11) unsigned NOT NULL COMMENT '任务id', - `task_seq` int(11) NOT NULL COMMENT '用于可重复任务的序列号', - `stage` tinyint NOT NULL DEFAULT 0 COMMENT '任务的阶段, 0:未完成 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`), - UNIQUE KEY `uid_task_id_seq` (`uid`, `task_id`, `task_seq`) -) COMMENT ='用户任务节点'; - -CREATE TABLE `nh_nft_holder` -( - `id` int unsigned NOT NULL AUTO_INCREMENT, - `address` varchar(80) NOT NULL COMMENT '钱包地址', - `token_id` varchar(32) NOT NULL COMMENT 'token id', - `balance` int(11) NOT NULL DEFAULT 0 COMMENT '余额', - `update_seq` int NOT NULL 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`), - UNIQUE KEY (`address`, `token_id`), - INDEX (`update_seq`) -) COMMENT ='nft 持有表'; - -CREATE TABLE `nh_nft_holder_change_log` -( - `id` int unsigned NOT NULL AUTO_INCREMENT, - `address` varchar(80) NOT NULL COMMENT '钱包地址', - `token_id` varchar(32) NOT NULL COMMENT 'token id', - `value` int(11) NOT NULL COMMENT '变化数量', - `balance` int(11) NOT NULL 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 ='nft 持有表变化日志'; - -CREATE TABLE `nh_task_nft_stake` -( - `id` int unsigned NOT NULL AUTO_INCREMENT, - `uid` int unsigned NOT NULL 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`) -) COMMENT ='nft质押表'; - -CREATE TABLE `nh_task_nft_stake_log` -( - `id` int unsigned NOT NULL AUTO_INCREMENT, - `uid` int unsigned NOT NULL COMMENT '用户钱包', - `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 '修改时间', - PRIMARY KEY (`id`) -) COMMENT ='派奖时nft质押日志表'; - -CREATE TABLE `nh_task_nft_stake_reward` -( - `id` int unsigned NOT NULL AUTO_INCREMENT, - `uid` int unsigned NOT NULL COMMENT '用户钱包', - `award_seq` int NOT NULL COMMENT '派奖序列号', - `pledge_output` decimal(40, 8) DEFAULT NULL COMMENT '质押产出代币', - `random_coefficient` float NOT NULL COMMENT '随机系数', - `occupy_percent` int NOT NULL DEFAULT 100 COMMENT '占领百分比', - `reward` decimal(40, 8) DEFAULT NULL 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`) +CREATE TABLE `nh_task_progress` +( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `uid` int(11) unsigned NOT NULL, + `task_id` int(11) unsigned NOT NULL COMMENT '任务id', + `task_seq` int(11) NOT NULL COMMENT '用于可重复任务的序列号', + `stage` tinyint NOT NULL DEFAULT 0 COMMENT '任务的阶段, 0:未完成 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`), + UNIQUE KEY `uid_task_id_seq` (`uid`, `task_id`, `task_seq`) +) COMMENT ='用户任务节点'; + +CREATE TABLE `nh_nft_holder` +( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `address` varchar(80) NOT NULL COMMENT '钱包地址', + `token_id` varchar(32) NOT NULL COMMENT 'token id', + `balance` int(11) NOT NULL DEFAULT 0 COMMENT '余额', + `update_seq` int NOT NULL 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`), + UNIQUE KEY (`token_id`), + INDEX (`update_seq`) +) COMMENT ='nft 持有表'; + +CREATE TABLE `nh_nft_holder_change_log` +( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `address` varchar(80) NOT NULL COMMENT '钱包地址', + `token_id` varchar(32) NOT NULL COMMENT 'token id', + `value` int(11) NOT NULL COMMENT '变化数量', + `balance` int(11) NOT NULL 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 ='nft 持有表变化日志'; + +CREATE TABLE `nh_task_nft_stake` +( + `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 '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY (`uid`, `token_id`) +) COMMENT ='nft质押表'; + +CREATE TABLE `nh_task_nft_stake_log` +( + `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 '修改时间', + PRIMARY KEY (`id`) +) COMMENT ='派奖时nft质押日志表'; + +CREATE TABLE `nh_task_nft_stake_reward` +( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `uid` int unsigned NOT NULL COMMENT '用户钱包', + `award_seq` int NOT NULL COMMENT '派奖序列号', + `pledge_output` decimal(18, 6) NOT NULL DEFAULT 0 COMMENT '质押产出代币', + `random_coefficient` float NOT NULL COMMENT '随机系数', + `occupy_percent` int NOT NULL DEFAULT 100 COMMENT '占领百分比', + `reward` decimal(18, 6) NOT NULL DEFAULT 0 COMMENT '奖励金额', + `sent` bool NOT NULL DEFAULT false 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`), + UNIQUE KEY (`uid`, `award_seq`) ) COMMENT ='nft质押派奖表'; \ No newline at end of file diff --git a/doc/swagger/nova-task.json b/doc/swagger/nova-task.json index 77bd0b3..a589b12 100644 --- a/doc/swagger/nova-task.json +++ b/doc/swagger/nova-task.json @@ -106,9 +106,20 @@ } } }, + "parameters": [ + { + "name": "wallet_address", + "in": "query", + "required": true, + "type": "string" + } + ], "tags": [ "task" ], + "consumes": [ + "multipart/form-data" + ], "security": [ { "apiKey": [] @@ -299,6 +310,18 @@ "community_list" ] }, + "GetNftListReq": { + "type": "object", + "properties": { + "wallet_address": { + "type": "string" + } + }, + "title": "GetNftListReq", + "required": [ + "wallet_address" + ] + }, "GetTaskListReq": { "type": "object", "properties": { @@ -342,6 +365,11 @@ "StakeNftList": { "type": "object", "properties": { + "role_id": { + "type": "integer", + "format": "int64", + "description": " 角色id" + }, "token_ids": { "type": "array", "items": { @@ -352,6 +380,7 @@ }, "title": "StakeNftList", "required": [ + "role_id", "token_ids" ] }, @@ -517,6 +546,10 @@ "type": "string", "description": " nftID" }, + "image": { + "type": "string", + "description": " nft图片" + }, "has_stake": { "type": "boolean", "format": "boolean", @@ -525,13 +558,20 @@ "stake_at": { "type": "string", "description": " 质押时间" + }, + "role_id": { + "type": "integer", + "format": "int64", + "description": " 角色id" } }, "title": "UserNft", "required": [ "token_id", + "image", "has_stake", - "stake_at" + "stake_at", + "role_id" ] }, "UserNftList": { diff --git a/etc/novatask.yaml b/etc/novatask.yaml index a4033ad..4efea51 100644 --- a/etc/novatask.yaml +++ b/etc/novatask.yaml @@ -1,8 +1,9 @@ Name: novatask Host: 0.0.0.0 -Port: 443 -CertFile: "etc/cert/saas.crt" -KeyFile: "etc/cert/saas.key" +Port: 8888 +Timeout: 30000 +#CertFile: "etc/cert/saas.crt" +#KeyFile: "etc/cert/saas.key" Log: # Mode: "file" @@ -18,7 +19,7 @@ Auth: # js-sdk鉴权相关配置 AccessSecret: "Mj2G%szYe&$MP@ytNv8JktQN1n5^cPq%" # 鉴权token密钥 MySql: # mysql相关配置 - Addr: "192.168.2.108:3306" # mysql地址 + Addr: "192.168.20.101:3306" # mysql地址 User: "huangjie" # mysql用户 Password: "jMDqPQM^a6hsAR" # mysql密码 Database: "nova_home" # 数据库名 @@ -35,10 +36,10 @@ Earn: GameId: "c0deda99-bb15-47a2-a3be-f1fe2983cde2" EarnCorn: - Spec: "@every 5m" - RunOnStart : true + Spec: "" #"@every 5m" + RunOnStart : false NftTaskCron: - HolderSpec: "@every 30m" + HolderSpec: "" #"@every 30m" SettleSpec: "5 0 0 * * ?" # 每天凌晨0点5秒执行质押结算 HolderCheckRunOnStart : false \ No newline at end of file diff --git a/internal/handler/task/get_nft_list_handler.go b/internal/handler/task/get_nft_list_handler.go index 93833cb..34fa6b5 100644 --- a/internal/handler/task/get_nft_list_handler.go +++ b/internal/handler/task/get_nft_list_handler.go @@ -6,13 +6,20 @@ import ( "github.com/zeromicro/go-zero/rest/httpx" "nova_task/internal/logic/task" "nova_task/internal/svc" + "nova_task/internal/types" ) // 拉取玩家持有的nft列表 func GetNftListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { + var req types.GetNftListReq + if err := httpx.Parse(r, &req); err != nil { + httpx.ErrorCtx(r.Context(), w, err) + return + } + l := task.NewGetNftListLogic(r.Context(), svcCtx) - resp, err := l.GetNftList() + resp, err := l.GetNftList(&req) if err != nil { httpx.ErrorCtx(r.Context(), w, err) } else { diff --git a/internal/job/holder/cron.go b/internal/job/holder/cron.go index ac1bb06..e316786 100644 --- a/internal/job/holder/cron.go +++ b/internal/job/holder/cron.go @@ -43,7 +43,7 @@ func (c *Cron) Run() { 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.FindOneByAddressTokenId(c.ctx, o.OwnerAddress, tk.TokenID) + nft, err := c.svcCtx.NftHolderModel.FindOneByTokenId(c.ctx, tk.TokenID) if err != nil { if errors.Is(err, model.ErrNotFound) { nft = &model.NhNftHolder{ diff --git a/internal/job/stake_settle/cron.go b/internal/job/stake_settle/cron.go index 3ad2fb8..3c941fe 100644 --- a/internal/job/stake_settle/cron.go +++ b/internal/job/stake_settle/cron.go @@ -3,7 +3,10 @@ package stake_settle import ( "context" "github.com/robfig/cron/v3" + "github.com/shopspring/decimal" + "github.com/spf13/cast" "github.com/zeromicro/go-zero/core/logx" + "nova_task/internal/pkg/utils" "nova_task/internal/svc" "time" ) @@ -37,16 +40,63 @@ func (c *Cron) Run() { 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 + } + + // todo: 增加资产 + //c.svcCtx.TaskAssetModel.AddUserPoint() } logx.Debugw("run settle cron task") diff --git a/internal/logic/task/get_nft_list_logic.go b/internal/logic/task/get_nft_list_logic.go index ce288ba..fb84d8b 100644 --- a/internal/logic/task/get_nft_list_logic.go +++ b/internal/logic/task/get_nft_list_logic.go @@ -2,8 +2,6 @@ package task import ( "context" - "errors" - "nova_task/internal/model" "nova_task/internal/pkg/errs" "nova_task/internal/pkg/utils" "nova_task/internal/svc" @@ -19,7 +17,7 @@ type GetNftListLogic struct { svcCtx *svc.ServiceContext } -// 拉取玩家持有的nft列表 +// NewGetNftListLogic 拉取玩家持有的nft列表 func NewGetNftListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetNftListLogic { return &GetNftListLogic{ Logger: logx.WithContext(ctx), @@ -28,20 +26,20 @@ func NewGetNftListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetNft } } -func (l *GetNftListLogic) GetNftList() (*types.UserNftList, error) { +func (l *GetNftListLogic) GetNftList(req *types.GetNftListReq) (*types.UserNftList, error) { uid := utils.GetUidUint(l.ctx) - address, err := l.svcCtx.WalletModel.FindAddressByUid(l.ctx, uid) - if err != nil { - if errors.Is(err, model.ErrNotFound) { - return nil, errs.New(errs.ErrNotBindWallet, "") - } - l.Errorw("find address by uid failed", logx.Field("err", err), logx.Field("uid", uid)) - return nil, errs.New(errs.ErrDatabaseOperate, err) - } + //address, err := l.svcCtx.WalletModel.FindAddressByUid(l.ctx, uid) + //if err != nil { + // if errors.Is(err, model.ErrNotFound) { + // return nil, errs.New(errs.ErrNotBindWallet, "") + // } + // l.Errorw("find address by uid failed", logx.Field("err", err), logx.Field("uid", uid)) + // return nil, errs.New(errs.ErrDatabaseOperate, err) + //} - tokens, err := l.svcCtx.NftHolderModel.FindTokensByAddress(l.ctx, address) + tokens, err := l.svcCtx.NftHolderModel.FindTokensByAddress(l.ctx, req.WalletAddress) if err != nil { - l.Errorw("find tokens by address failed", logx.Field("err", err), logx.Field("address", address), logx.Field("uid", uid)) + l.Errorw("find tokens by address failed", logx.Field("err", err), logx.Field("address", req.WalletAddress), logx.Field("uid", uid)) return nil, errs.New(errs.ErrDatabaseOperate, err) } @@ -49,17 +47,21 @@ func (l *GetNftListLogic) GetNftList() (*types.UserNftList, error) { for _, token := range tokens { var hasStake bool var stakeAt string + var roleId uint64 nft, err := l.svcCtx.StakeNftModel.FindOneByUidTokenId(l.ctx, uid, token) if err == nil { hasStake = nft.State == 1 if hasStake { stakeAt = nft.UpdatedAt.Format(time.DateOnly) + roleId = nft.RoleId } } nftList = append(nftList, types.UserNft{ TokenId: token, + Image: utils.TarotImg(token), HasStake: hasStake, StakeAt: stakeAt, + RoleId: roleId, }) } diff --git a/internal/logic/task/get_stake_task_detail_logic.go b/internal/logic/task/get_stake_task_detail_logic.go index a48c6bd..4433cb5 100644 --- a/internal/logic/task/get_stake_task_detail_logic.go +++ b/internal/logic/task/get_stake_task_detail_logic.go @@ -3,6 +3,7 @@ package task import ( "context" "errors" + "github.com/spf13/cast" "nova_task/internal/model" "nova_task/internal/pkg/errs" "nova_task/internal/pkg/utils" @@ -76,6 +77,15 @@ func (l *GetStakeTaskDetailLogic) GetStakeTaskDetail() (*types.StakeTaskDetail, canReceiveTokens = produceTokensToday } + awardSeq := cast.ToInt(time.Now().Format("20060102")) + coefficient, err := l.svcCtx.StakeRewardModel.GetRandomCoefficientByUid(l.ctx, uid, awardSeq, taskConf.MinCoefficient, taskConf.MaxCoefficient) + if err != nil { + l.Errorw("get random coefficient failed", logx.Field("err", err), logx.Field("uid", uid), logx.Field("awardSeq", awardSeq)) + return nil, errs.New(errs.ErrDatabaseOperate, err) + } + + canReceiveTokens *= coefficient + return &types.StakeTaskDetail{ StartDate: start.Format(time.DateOnly), EndDate: end.Format(time.DateOnly), diff --git a/internal/logic/task/stake_nft_logic.go b/internal/logic/task/stake_nft_logic.go index c0cc35f..0be666a 100644 --- a/internal/logic/task/stake_nft_logic.go +++ b/internal/logic/task/stake_nft_logic.go @@ -26,7 +26,7 @@ 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.TokenIds) + 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) diff --git a/internal/model/nh_nft_holder_model_gen.go b/internal/model/nh_nft_holder_model_gen.go index 05bf4d7..3e1289f 100755 --- a/internal/model/nh_nft_holder_model_gen.go +++ b/internal/model/nh_nft_holder_model_gen.go @@ -27,7 +27,7 @@ type ( nhNftHolderModel interface { Insert(ctx context.Context, data *NhNftHolder) (sql.Result, error) FindOne(ctx context.Context, id uint) (*NhNftHolder, error) - FindOneByAddressTokenId(ctx context.Context, address string, tokenId string) (*NhNftHolder, error) + FindOneByTokenId(ctx context.Context, tokenId string) (*NhNftHolder, error) Update(ctx context.Context, data *NhNftHolder) error Delete(ctx context.Context, id uint) error } @@ -75,10 +75,10 @@ func (m *defaultNhNftHolderModel) FindOne(ctx context.Context, id uint) (*NhNftH } } -func (m *defaultNhNftHolderModel) FindOneByAddressTokenId(ctx context.Context, address string, tokenId string) (*NhNftHolder, error) { +func (m *defaultNhNftHolderModel) FindOneByTokenId(ctx context.Context, tokenId string) (*NhNftHolder, error) { var resp NhNftHolder - query := fmt.Sprintf("select %s from %s where `address` = ? and `token_id` = ? limit 1", nhNftHolderRows, m.table) - err := m.conn.QueryRowCtx(ctx, &resp, query, address, tokenId) + query := fmt.Sprintf("select %s from %s where `token_id` = ? limit 1", nhNftHolderRows, m.table) + err := m.conn.QueryRowCtx(ctx, &resp, query, tokenId) switch err { case nil: return &resp, nil diff --git a/internal/model/nh_task_nft_stake_log_model_gen.go b/internal/model/nh_task_nft_stake_log_model_gen.go index 02f6c44..6a0a961 100755 --- a/internal/model/nh_task_nft_stake_log_model_gen.go +++ b/internal/model/nh_task_nft_stake_log_model_gen.go @@ -39,6 +39,7 @@ type ( NhTaskNftStakeLog struct { 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"` // 派奖序列号 @@ -77,14 +78,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.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.Address, data.TokenId, data.AwardSeq, data.Balance, data.Stake) 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.Address, data.TokenId, data.AwardSeq, data.Balance, data.Stake, data.Id) + _, err := m.conn.ExecCtx(ctx, query, data.Uid, data.RoleId, data.Address, data.TokenId, data.AwardSeq, data.Balance, data.Stake, data.Id) return err } diff --git a/internal/model/nh_task_nft_stake_model.go b/internal/model/nh_task_nft_stake_model.go index 4879786..3a53e9f 100755 --- a/internal/model/nh_task_nft_stake_model.go +++ b/internal/model/nh_task_nft_stake_model.go @@ -15,7 +15,7 @@ type ( NhTaskNftStakeModel interface { nhTaskNftStakeModel withSession(session sqlx.Session) NhTaskNftStakeModel - StakeNft(ctx context.Context, uid uint, tokens []string) error + StakeNft(ctx context.Context, uid uint, roleId uint64, tokens []string) error UnStakeNft(ctx context.Context, uid uint, token string) error FindByUid(ctx context.Context, uid uint) ([]NhTaskNftStake, error) AllStakeNft(ctx context.Context) ([]NhTaskNftStake, error) @@ -52,10 +52,10 @@ func (m *customNhTaskNftStakeModel) UnStakeNft(ctx context.Context, uid uint, to return err } -func (m *customNhTaskNftStakeModel) StakeNft(ctx context.Context, uid uint, tokens []string) error { - insertOrUpdate := fmt.Sprintf("INSERT INTO %s (`uid`, `token_id`, `state`) VALUES (?, ?, 1) ON DUPLICATE KEY UPDATE `state` = 1", m.table) +func (m *customNhTaskNftStakeModel) StakeNft(ctx context.Context, uid uint, roleId uint64, tokens []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) + _, err := m.conn.ExecCtx(ctx, insertOrUpdate, uid, token, roleId, roleId) if err != nil { return err } diff --git a/internal/model/nh_task_nft_stake_model_gen.go b/internal/model/nh_task_nft_stake_model_gen.go index f3042a9..1ada95c 100755 --- a/internal/model/nh_task_nft_stake_model_gen.go +++ b/internal/model/nh_task_nft_stake_model_gen.go @@ -40,6 +40,7 @@ type ( NhTaskNftStake struct { Id uint `db:"id"` Uid uint `db:"uid"` // 用户钱包 + RoleId uint64 `db:"role_id"` // 角色id TokenId string `db:"token_id"` // token id State int8 `db:"state"` // 状态:1质押中, 0已取消质押 CreatedAt time.Time `db:"created_at"` // 创建时间 @@ -89,14 +90,14 @@ func (m *defaultNhTaskNftStakeModel) FindOneByUidTokenId(ctx context.Context, ui } func (m *defaultNhTaskNftStakeModel) Insert(ctx context.Context, data *NhTaskNftStake) (sql.Result, error) { - query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?)", m.table, nhTaskNftStakeRowsExpectAutoSet) - ret, err := m.conn.ExecCtx(ctx, query, data.Uid, data.TokenId, data.State) + 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) return ret, err } func (m *defaultNhTaskNftStakeModel) Update(ctx context.Context, newData *NhTaskNftStake) error { query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, nhTaskNftStakeRowsWithPlaceHolder) - _, err := m.conn.ExecCtx(ctx, query, newData.Uid, newData.TokenId, newData.State, newData.Id) + _, err := m.conn.ExecCtx(ctx, query, newData.Uid, newData.RoleId, newData.TokenId, newData.State, newData.Id) return err } diff --git a/internal/model/nh_task_nft_stake_reward_model.go b/internal/model/nh_task_nft_stake_reward_model.go index bab07e7..c3e4cd0 100755 --- a/internal/model/nh_task_nft_stake_reward_model.go +++ b/internal/model/nh_task_nft_stake_reward_model.go @@ -1,6 +1,13 @@ package model -import "github.com/zeromicro/go-zero/core/stores/sqlx" +import ( + "context" + "errors" + "fmt" + "github.com/shopspring/decimal" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "math/rand" +) var _ NhTaskNftStakeRewardModel = (*customNhTaskNftStakeRewardModel)(nil) @@ -10,6 +17,8 @@ type ( NhTaskNftStakeRewardModel interface { nhTaskNftStakeRewardModel withSession(session sqlx.Session) NhTaskNftStakeRewardModel + GetRandomCoefficientByUid(ctx context.Context, uid uint, awardSeq int, min, max float64) (float64, error) + SetReward(ctx context.Context, uid uint, awardSeq, occupyPercent int, pledgeOutput, reward decimal.Decimal) error } customNhTaskNftStakeRewardModel struct { @@ -17,6 +26,43 @@ type ( } ) +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` = ? WHERE `uid` = ? AND `award_seq` = ?", m.table) + result, err := m.conn.ExecCtx(ctx, update, occupyPercent, pledgeOutput, reward, uid, awardSeq) + if err != nil { + return err + } + rowsAffected, err := result.RowsAffected() + if err != nil { + return err + } + if rowsAffected == 0 { + return ErrNoRowUpdate + } + return nil +} + +func (m *customNhTaskNftStakeRewardModel) GetRandomCoefficientByUid(ctx context.Context, uid uint, awardSeq int, min, max float64) (float64, error) { + query := fmt.Sprintf("SELECT `random_coefficient` FROM %s WHERE `uid` = ? AND `award_seq` = ?", m.table) + var randomCoefficient float64 + err := m.conn.QueryRowCtx(ctx, &randomCoefficient, query, uid, awardSeq) + if err == nil { + return randomCoefficient, nil + } + + if !errors.Is(err, sqlx.ErrNotFound) { + return 0, err + } + + randomCoefficient = float64(int(min*100)+rand.Intn(int(max*100-min*100))) / 100 + _, err = m.Insert(ctx, &NhTaskNftStakeReward{ + Uid: uid, + AwardSeq: awardSeq, + RandomCoefficient: randomCoefficient, + }) + return randomCoefficient, err +} + // NewNhTaskNftStakeRewardModel returns a model for the database table. func NewNhTaskNftStakeRewardModel(conn sqlx.SqlConn) NhTaskNftStakeRewardModel { return &customNhTaskNftStakeRewardModel{ diff --git a/internal/model/nh_task_nft_stake_reward_model_gen.go b/internal/model/nh_task_nft_stake_reward_model_gen.go index b6ddf75..e9e5e7e 100755 --- a/internal/model/nh_task_nft_stake_reward_model_gen.go +++ b/internal/model/nh_task_nft_stake_reward_model_gen.go @@ -29,6 +29,7 @@ type ( nhTaskNftStakeRewardModel interface { Insert(ctx context.Context, data *NhTaskNftStakeReward) (sql.Result, error) FindOne(ctx context.Context, id uint) (*NhTaskNftStakeReward, error) + FindOneByUidAwardSeq(ctx context.Context, uid uint, awardSeq int) (*NhTaskNftStakeReward, error) Update(ctx context.Context, data *NhTaskNftStakeReward) error Delete(ctx context.Context, id uint) error } @@ -39,15 +40,16 @@ type ( } NhTaskNftStakeReward struct { - Id uint `db:"id"` - Uid uint `db:"uid"` // 用户钱包 - AwardSeq int `db:"award_seq"` // 派奖序列号 - PledgeOutput decimal.NullDecimal `db:"pledge_output"` // 质押产出代币 - RandomCoefficient float64 `db:"random_coefficient"` // 随机系数 - OccupyPercent int `db:"occupy_percent"` // 占领百分比 - Reward decimal.NullDecimal `db:"reward"` // 奖励金额 - CreatedAt time.Time `db:"created_at"` // 创建时间 - UpdatedAt time.Time `db:"updated_at"` // 修改时间 + Id uint `db:"id"` + Uid uint `db:"uid"` // 用户钱包 + AwardSeq int `db:"award_seq"` // 派奖序列号 + PledgeOutput decimal.Decimal `db:"pledge_output"` // 质押产出代币 + RandomCoefficient float64 `db:"random_coefficient"` // 随机系数 + OccupyPercent int `db:"occupy_percent"` // 占领百分比 + Reward decimal.Decimal `db:"reward"` // 奖励金额 + Sent int8 `db:"sent"` // 是否已发放 + CreatedAt time.Time `db:"created_at"` // 创建时间 + UpdatedAt time.Time `db:"updated_at"` // 修改时间 } ) @@ -78,15 +80,29 @@ func (m *defaultNhTaskNftStakeRewardModel) FindOne(ctx context.Context, id uint) } } +func (m *defaultNhTaskNftStakeRewardModel) FindOneByUidAwardSeq(ctx context.Context, uid uint, awardSeq int) (*NhTaskNftStakeReward, error) { + var resp NhTaskNftStakeReward + query := fmt.Sprintf("select %s from %s where `uid` = ? and `award_seq` = ? limit 1", nhTaskNftStakeRewardRows, m.table) + err := m.conn.QueryRowCtx(ctx, &resp, query, uid, awardSeq) + switch err { + case nil: + return &resp, nil + case sqlx.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + func (m *defaultNhTaskNftStakeRewardModel) Insert(ctx context.Context, data *NhTaskNftStakeReward) (sql.Result, error) { - query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?)", m.table, nhTaskNftStakeRewardRowsExpectAutoSet) - ret, err := m.conn.ExecCtx(ctx, query, data.Uid, data.AwardSeq, data.PledgeOutput, data.RandomCoefficient, data.OccupyPercent, data.Reward) + query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?)", m.table, nhTaskNftStakeRewardRowsExpectAutoSet) + ret, err := m.conn.ExecCtx(ctx, query, data.Uid, data.AwardSeq, data.PledgeOutput, data.RandomCoefficient, data.OccupyPercent, data.Reward, data.Sent) return ret, err } -func (m *defaultNhTaskNftStakeRewardModel) Update(ctx context.Context, data *NhTaskNftStakeReward) error { +func (m *defaultNhTaskNftStakeRewardModel) Update(ctx context.Context, newData *NhTaskNftStakeReward) error { query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, nhTaskNftStakeRewardRowsWithPlaceHolder) - _, err := m.conn.ExecCtx(ctx, query, data.Uid, data.AwardSeq, data.PledgeOutput, data.RandomCoefficient, data.OccupyPercent, data.Reward, data.Id) + _, err := m.conn.ExecCtx(ctx, query, newData.Uid, newData.AwardSeq, newData.PledgeOutput, newData.RandomCoefficient, newData.OccupyPercent, newData.Reward, newData.Sent, newData.Id) return err } diff --git a/internal/pkg/utils/big_tarot.go b/internal/pkg/utils/big_tarot.go deleted file mode 100644 index 7237c9e..0000000 --- a/internal/pkg/utils/big_tarot.go +++ /dev/null @@ -1,38 +0,0 @@ -package utils - -var bitTarot = map[string]bool{ - "288": true, - "297": true, - "298": true, - "300": true, - "308": true, - "311": true, - "333": true, - "336": true, - "349": true, - "357": true, - "366": true, - "367": true, - "388": true, - "396": true, - "406": true, - "409": true, - "418": true, - "419": true, - "436": true, - "456": true, - "503": true, - "564": true, - "58": true, - "26": true, - "82": true, - "152": true, - "186": true, - "379": true, - "500": true, - "523": true, -} - -func IsBigTarot(tarotId string) bool { - return bitTarot[tarotId] -} diff --git a/internal/pkg/utils/tarot.go b/internal/pkg/utils/tarot.go new file mode 100644 index 0000000..d7f70ad --- /dev/null +++ b/internal/pkg/utils/tarot.go @@ -0,0 +1,621 @@ +package utils + +var ( + bigTarot = map[string]string{ + "288": "Card_Tower.png", + "297": "Card_Justice.png", + "298": "Card_Thehangedman.png", + "300": "Card_Magician.png", + "308": "Card_Emperor.png", + "311": "Card_Judgement.png", + "333": "Card_Temperance.png", + "336": "Card_Chariot.png", + "349": "Card_Wheel.png", + "357": "Card_Empress.png", + "366": "Card_Star.png", + "367": "Card_Vault.png", + "388": "Card_Judgement.png", + "396": "Card_Lover.png", + "406": "Card_Moon.png", + "409": "Card_Sun.png", + "418": "Card_Moon.png", + "419": "Card_World.png", + "436": "Card_Hierophant.png", + "456": "Card_Death.png", + "503": "Card_Devil.png", + "564": "Card_World.png", + "58": "Card_Priestess.png", + "26": "Card_Devil.png", + "82": "Card_Star.png", + "152": "Card_Hermit.png", + "186": "Card_Sun.png", + "379": "Card_Strength.png", + "500": "Card_Tower.png", + "523": "Card_Fools.png", + } + smallTarot = map[string]string{ + "1": "Three_Of_Pentacles.png", + "2": "Queen_Of_Wands.png", + "3": "Seven_Of_Wands.png", + "4": "Nine_Of_Pentacles.png", + "5": "Queen_Of_Pentacles.png", + "6": "Eight_Of_Wands.png", + "7": "Ace_Of_Pentacles.png", + "8": "Three_Of_Cups.png", + "9": "Seven_Of_Cups.png", + "10": "Three_Of_Cups.png", + "11": "Ace_Of_Swords.png", + "12": "Ten_Of_Cups.png", + "13": "Eight_Of_Cups.png", + "14": "Ten_Of_Swords.png", + "15": "Nine_Of_Swords.png", + "16": "Page_Of_Pentacles.png", + "17": "Queen_Of_Swords.png", + "18": "Six_Of_Swords.png", + "19": "Three_Of_Wands.png", + "20": "Page_Of_Pentacles.png", + "21": "Queen_Of_Pentacles.png", + "22": "Four_Of_Wands.png", + "23": "Six_Of_Wands.png", + "24": "Queen_Of_Swords.png", + "25": "Eight_Of_Cups.png", + "27": "Three_Of_Wands.png", + "28": "Five_Of_Wands.png", + "29": "Seven_Of_Swords.png", + "30": "Eight_Of_Swords.png", + "31": "Ace_Of_Wands.png", + "32": "King_Of_Wands.png", + "33": "Eight_Of_Wands.png", + "34": "Three_Of_Swords.png", + "35": "Eight_Of_Wands.png", + "36": "Nine_Of_Wands.png", + "37": "Three_Of_Wands.png", + "38": "Two_Of_Cups.png", + "39": "Ten_Of_Cups.png", + "40": "Six_Of_Wands.png", + "41": "Two_Of_Wands.png", + "42": "King_Of_Swords.png", + "43": "Four_Of_Pentacles.png", + "44": "Eight_Of_Pentacles.png", + "45": "Nine_Of_Cups.png", + "46": "Seven_Of_Pentacles.png", + "47": "Nine_Of_Swords.png", + "48": "Four_Of_Wands.png", + "49": "Ten_Of_Wands.png", + "50": "Four_Of_Swords.png", + "51": "Ace_Of_Pentacles.png", + "52": "King_Of_Pentacles.png", + "53": "Five_Of_Cups.png", + "54": "Page_Of_Swords.png", + "55": "Five_Of_Cups.png", + "56": "Nine_Of_Swords.png", + "57": "Three_Of_Wands.png", + "59": "Four_Of_Cups.png", + "60": "Two_Of_Cups.png", + "61": "Two_Of_Wands.png", + "62": "Ace_Of_Cups.png", + "63": "Ten_Of_Wands.png", + "64": "Ace_Of_Pentacles.png", + "65": "Seven_Of_Cups.png", + "66": "Nine_Of_Wands.png", + "67": "Page_Of_Wands.png", + "68": "Two_Of_Cups.png", + "69": "Knight_Of_Cups.png", + "70": "Five_Of_Wands.png", + "71": "Eight_Of_Cups.png", + "72": "Nine_Of_Pentacles.png", + "73": "Nine_Of_Pentacles.png", + "74": "Ace_Of_Wands.png", + "75": "Five_Of_Pentacles.png", + "76": "Eight_Of_Cups.png", + "77": "Knight_Of_Wands.png", + "78": "Eight_Of_Swords.png", + "79": "Ace_Of_Swords.png", + "80": "King_Of_Swords.png", + "81": "Four_Of_Pentacles.png", + "83": "Seven_Of_Cups.png", + "84": "Eight_Of_Pentacles.png", + "85": "Seven_Of_Wands.png", + "86": "Five_Of_Swords.png", + "87": "Five_Of_Swords.png", + "88": "Six_Of_Cups.png", + "89": "Ace_Of_Wands.png", + "90": "King_Of_Wands.png", + "91": "King_Of_Pentacles.png", + "92": "Four_Of_Pentacles.png", + "93": "Six_Of_Cups.png", + "94": "Four_Of_Swords.png", + "95": "Ten_Of_Pentacles.png", + "96": "Four_Of_Cups.png", + "97": "Eight_Of_Pentacles.png", + "98": "Eight_Of_Swords.png", + "99": "Nine_Of_Cups.png", + "100": "Knight_Of_Swords.png", + "101": "Four_Of_Cups.png", + "102": "Eight_Of_Wands.png", + "103": "Two_Of_Swords.png", + "104": "Seven_Of_Swords.png", + "105": "Six_Of_Pentacles.png", + "106": "Two_Of_Swords.png", + "107": "Ace_Of_Cups.png", + "108": "Page_Of_Swords.png", + "109": "Page_Of_Swords.png", + "110": "Queen_Of_Pentacles.png", + "111": "Page_Of_Pentacles.png", + "112": "Two_Of_Pentacles.png", + "113": "King_Of_Pentacles.png", + "114": "Seven_Of_Wands.png", + "115": "Two_Of_Swords.png", + "116": "Eight_Of_Cups.png", + "117": "Queen_Of_Pentacles.png", + "118": "Five_Of_Wands.png", + "119": "Queen_Of_Swords.png", + "120": "Nine_Of_Swords.png", + "121": "King_Of_Swords.png", + "122": "Six_Of_Pentacles.png", + "123": "Six_Of_Cups.png", + "124": "Ace_Of_Cups.png", + "125": "Five_Of_Cups.png", + "126": "Page_Of_Cups.png", + "127": "Eight_Of_Swords.png", + "128": "Six_Of_Wands.png", + "129": "Eight_Of_Swords.png", + "130": "Five_Of_Wands.png", + "131": "Knight_Of_Cups.png", + "132": "Four_Of_Cups.png", + "133": "Three_Of_Wands.png", + "134": "Nine_Of_Swords.png", + "135": "Knight_Of_Pentacles.png", + "136": "Seven_Of_Cups.png", + "137": "Two_Of_Pentacles.png", + "138": "Two_Of_Cups.png", + "139": "Four_Of_Wands.png", + "140": "Nine_Of_Wands.png", + "141": "Seven_Of_Cups.png", + "142": "Knight_Of_Pentacles.png", + "143": "Two_Of_Pentacles.png", + "144": "Eight_Of_Cups.png", + "145": "Two_Of_Wands.png", + "146": "Ace_Of_Cups.png", + "147": "Page_Of_Swords.png", + "148": "Seven_Of_Cups.png", + "149": "Seven_Of_Wands.png", + "150": "King_Of_Cups.png", + "151": "Four_Of_Wands.png", + "153": "Queen_Of_Wands.png", + "154": "King_Of_Wands.png", + "155": "Six_Of_Swords.png", + "156": "Queen_Of_Cups.png", + "157": "Page_Of_Wands.png", + "158": "Six_Of_Cups.png", + "159": "Three_Of_Pentacles.png", + "160": "Six_Of_Cups.png", + "161": "Six_Of_Pentacles.png", + "162": "Five_Of_Cups.png", + "163": "Ten_Of_Pentacles.png", + "164": "Two_Of_Wands.png", + "165": "Ten_Of_Cups.png", + "166": "Two_Of_Wands.png", + "167": "Page_Of_Wands.png", + "168": "Ten_Of_Pentacles.png", + "169": "Two_Of_Cups.png", + "170": "Nine_Of_Swords.png", + "171": "King_Of_Pentacles.png", + "172": "Ten_Of_Wands.png", + "173": "Three_Of_Cups.png", + "174": "Eight_Of_Pentacles.png", + "175": "Two_Of_Swords.png", + "176": "Four_Of_Wands.png", + "177": "Ten_Of_Cups.png", + "178": "Nine_Of_Cups.png", + "179": "Eight_Of_Wands.png", + "180": "Eight_Of_Cups.png", + "181": "Knight_Of_Swords.png", + "182": "Page_Of_Swords.png", + "183": "Knight_Of_Cups.png", + "184": "King_Of_Wands.png", + "185": "Seven_Of_Cups.png", + "187": "Queen_Of_Swords.png", + "188": "King_Of_Cups.png", + "189": "Seven_Of_Pentacles.png", + "190": "Queen_Of_Wands.png", + "191": "King_Of_Swords.png", + "192": "Ten_Of_Pentacles.png", + "193": "Four_Of_Cups.png", + "194": "Five_Of_Pentacles.png", + "195": "Two_Of_Cups.png", + "196": "Four_Of_Wands.png", + "197": "Ace_Of_Pentacles.png", + "198": "Three_Of_Cups.png", + "199": "Six_Of_Pentacles.png", + "200": "Ten_Of_Cups.png", + "201": "Page_Of_Wands.png", + "202": "Ace_Of_Swords.png", + "203": "Knight_Of_Swords.png", + "204": "Knight_Of_Cups.png", + "205": "Eight_Of_Swords.png", + "206": "Four_Of_Cups.png", + "207": "Ten_Of_Swords.png", + "208": "Ace_Of_Pentacles.png", + "209": "Nine_Of_Swords.png", + "210": "Ten_Of_Pentacles.png", + "211": "Five_Of_Wands.png", + "212": "Queen_Of_Swords.png", + "213": "Nine_Of_Pentacles.png", + "214": "Knight_Of_Pentacles.png", + "215": "Queen_Of_Wands.png", + "216": "Eight_Of_Pentacles.png", + "217": "Seven_Of_Swords.png", + "218": "Five_Of_Wands.png", + "219": "Eight_Of_Wands.png", + "220": "Knight_Of_Cups.png", + "221": "Two_Of_Cups.png", + "222": "Page_Of_Pentacles.png", + "223": "King_Of_Wands.png", + "224": "Page_Of_Swords.png", + "225": "Knight_Of_Pentacles.png", + "226": "King_Of_Wands.png", + "227": "Three_Of_Pentacles.png", + "228": "Knight_Of_Swords.png", + "229": "Four_Of_Cups.png", + "230": "Three_Of_Pentacles.png", + "231": "Ace_Of_Wands.png", + "232": "Ace_Of_Cups.png", + "233": "Two_Of_Cups.png", + "234": "Four_Of_Pentacles.png", + "235": "Ace_Of_Cups.png", + "236": "Two_Of_Pentacles.png", + "237": "Five_Of_Swords.png", + "238": "Three_Of_Swords.png", + "239": "Nine_Of_Cups.png", + "240": "Five_Of_Swords.png", + "241": "Nine_Of_Pentacles.png", + "242": "Ten_Of_Swords.png", + "243": "Page_Of_Swords.png", + "244": "Eight_Of_Wands.png", + "245": "Four_Of_Cups.png", + "246": "Four_Of_Wands.png", + "247": "Seven_Of_Wands.png", + "248": "King_Of_Cups.png", + "249": "Page_Of_Swords.png", + "250": "Queen_Of_Wands.png", + "251": "Page_Of_Cups.png", + "252": "Six_Of_Swords.png", + "253": "Page_Of_Pentacles.png", + "254": "Knight_Of_Cups.png", + "255": "Knight_Of_Wands.png", + "256": "King_Of_Pentacles.png", + "257": "Ace_Of_Wands.png", + "258": "Page_Of_Cups.png", + "259": "Three_Of_Cups.png", + "260": "Five_Of_Wands.png", + "261": "Ten_Of_Swords.png", + "262": "Six_Of_Wands.png", + "263": "Six_Of_Swords.png", + "264": "Two_Of_Pentacles.png", + "265": "Queen_Of_Pentacles.png", + "266": "Three_Of_Pentacles.png", + "267": "Six_Of_Pentacles.png", + "268": "Six_Of_Wands.png", + "269": "Knight_Of_Pentacles.png", + "270": "King_Of_Cups.png", + "271": "Six_Of_Wands.png", + "272": "King_Of_Pentacles.png", + "273": "Page_Of_Wands.png", + "274": "Seven_Of_Pentacles.png", + "275": "Knight_Of_Pentacles.png", + "276": "Five_Of_Wands.png", + "277": "Ace_Of_Swords.png", + "278": "Four_Of_Swords.png", + "279": "Two_Of_Wands.png", + "280": "Page_Of_Wands.png", + "281": "Knight_Of_Cups.png", + "282": "Six_Of_Cups.png", + "283": "Eight_Of_Wands.png", + "284": "Two_Of_Pentacles.png", + "285": "Page_Of_Pentacles.png", + "286": "Queen_Of_Wands.png", + "287": "Seven_Of_Swords.png", + "289": "Nine_Of_Cups.png", + "290": "Page_Of_Pentacles.png", + "291": "Seven_Of_Pentacles.png", + "292": "Six_Of_Pentacles.png", + "293": "Ace_Of_Wands.png", + "294": "Knight_Of_Swords.png", + "295": "Four_Of_Cups.png", + "296": "Two_Of_Swords.png", + "299": "Ten_Of_Wands.png", + "301": "Queen_Of_Wands.png", + "302": "Seven_Of_Pentacles.png", + "303": "Ace_Of_Wands.png", + "304": "Seven_Of_Wands.png", + "305": "Eight_Of_Swords.png", + "306": "Seven_Of_Wands.png", + "307": "Three_Of_Swords.png", + "309": "Two_Of_Wands.png", + "310": "Five_Of_Cups.png", + "312": "Three_Of_Swords.png", + "313": "Queen_Of_Cups.png", + "314": "Seven_Of_Pentacles.png", + "315": "Five_Of_Swords.png", + "316": "Ace_Of_Swords.png", + "317": "Ace_Of_Swords.png", + "318": "Five_Of_Swords.png", + "319": "Eight_Of_Pentacles.png", + "320": "Knight_Of_Wands.png", + "321": "Three_Of_Cups.png", + "322": "Five_Of_Pentacles.png", + "323": "Ace_Of_Pentacles.png", + "324": "Four_Of_Wands.png", + "325": "Knight_Of_Wands.png", + "326": "Knight_Of_Swords.png", + "327": "Queen_Of_Pentacles.png", + "328": "Nine_Of_Pentacles.png", + "329": "Queen_Of_Cups.png", + "330": "Nine_Of_Wands.png", + "331": "Queen_Of_Wands.png", + "332": "Three_Of_Swords.png", + "334": "King_Of_Pentacles.png", + "335": "Page_Of_Wands.png", + "337": "King_Of_Swords.png", + "338": "Three_Of_Pentacles.png", + "339": "Five_Of_Swords.png", + "340": "Two_Of_Wands.png", + "341": "Eight_Of_Wands.png", + "342": "Queen_Of_Pentacles.png", + "343": "Seven_Of_Pentacles.png", + "344": "Three_Of_Wands.png", + "345": "Three_Of_Wands.png", + "346": "Three_Of_Wands.png", + "347": "Eight_Of_Cups.png", + "348": "Seven_Of_Cups.png", + "350": "Ace_Of_Pentacles.png", + "351": "Five_Of_Swords.png", + "352": "Two_Of_Pentacles.png", + "353": "Six_Of_Pentacles.png", + "354": "Five_Of_Swords.png", + "355": "Nine_Of_Swords.png", + "356": "King_Of_Pentacles.png", + "358": "Queen_Of_Swords.png", + "359": "Queen_Of_Wands.png", + "360": "Queen_Of_Cups.png", + "361": "Ace_Of_Wands.png", + "362": "Queen_Of_Cups.png", + "363": "Six_Of_Swords.png", + "364": "Ten_Of_Pentacles.png", + "365": "Three_Of_Swords.png", + "368": "Six_Of_Cups.png", + "369": "Nine_Of_Pentacles.png", + "370": "King_Of_Swords.png", + "371": "Four_Of_Pentacles.png", + "372": "Eight_Of_Pentacles.png", + "373": "Page_Of_Wands.png", + "374": "Queen_Of_Swords.png", + "375": "Ace_Of_Cups.png", + "376": "Three_Of_Swords.png", + "377": "Ten_Of_Wands.png", + "378": "Five_Of_Wands.png", + "380": "Eight_Of_Wands.png", + "381": "Five_Of_Cups.png", + "382": "Ace_Of_Pentacles.png", + "383": "King_Of_Swords.png", + "384": "Ace_Of_Wands.png", + "385": "Knight_Of_Pentacles.png", + "386": "Nine_Of_Swords.png", + "387": "Ace_Of_Cups.png", + "389": "Queen_Of_Swords.png", + "390": "King_Of_Wands.png", + "391": "Page_Of_Cups.png", + "392": "Nine_Of_Pentacles.png", + "393": "Six_Of_Wands.png", + "394": "Six_Of_Cups.png", + "395": "Three_Of_Cups.png", + "397": "Queen_Of_Cups.png", + "398": "Ten_Of_Wands.png", + "399": "Ace_Of_Pentacles.png", + "400": "Six_Of_Swords.png", + "401": "Eight_Of_Swords.png", + "402": "Nine_Of_Cups.png", + "403": "Four_Of_Pentacles.png", + "404": "Nine_Of_Wands.png", + "405": "Seven_Of_Cups.png", + "407": "King_Of_Cups.png", + "408": "Three_Of_Pentacles.png", + "410": "Nine_Of_Cups.png", + "411": "King_Of_Swords.png", + "412": "Queen_Of_Pentacles.png", + "413": "Seven_Of_Swords.png", + "414": "Nine_Of_Wands.png", + "415": "Ten_Of_Wands.png", + "416": "Ten_Of_Swords.png", + "417": "Six_Of_Pentacles.png", + "420": "King_Of_Cups.png", + "421": "Ace_Of_Cups.png", + "422": "Eight_Of_Pentacles.png", + "423": "Nine_Of_Wands.png", + "424": "Three_Of_Swords.png", + "425": "Ace_Of_Swords.png", + "426": "Knight_Of_Pentacles.png", + "427": "Five_Of_Swords.png", + "428": "Queen_Of_Cups.png", + "429": "Ten_Of_Cups.png", + "430": "Seven_Of_Cups.png", + "431": "Three_Of_Pentacles.png", + "432": "Eight_Of_Cups.png", + "433": "Ten_Of_Swords.png", + "434": "Six_Of_Swords.png", + "435": "Nine_Of_Wands.png", + "437": "Seven_Of_Swords.png", + "438": "King_Of_Pentacles.png", + "439": "Eight_Of_Wands.png", + "440": "Page_Of_Pentacles.png", + "441": "Two_Of_Pentacles.png", + "442": "Four_Of_Wands.png", + "443": "King_Of_Cups.png", + "444": "Five_Of_Pentacles.png", + "445": "Five_Of_Pentacles.png", + "446": "Nine_Of_Cups.png", + "447": "Ten_Of_Swords.png", + "448": "Four_Of_Swords.png", + "449": "Three_Of_Pentacles.png", + "450": "Knight_Of_Cups.png", + "451": "Ten_Of_Pentacles.png", + "452": "Ten_Of_Swords.png", + "453": "Nine_Of_Wands.png", + "454": "Four_Of_Swords.png", + "455": "Seven_Of_Wands.png", + "457": "Seven_Of_Swords.png", + "458": "Two_Of_Swords.png", + "459": "Seven_Of_Swords.png", + "460": "Four_Of_Pentacles.png", + "461": "Ace_Of_Swords.png", + "462": "Five_Of_Cups.png", + "463": "Ace_Of_Pentacles.png", + "464": "Ten_Of_Wands.png", + "465": "Two_Of_Pentacles.png", + "466": "Two_Of_Swords.png", + "467": "Six_Of_Swords.png", + "468": "Four_Of_Pentacles.png", + "469": "Six_Of_Pentacles.png", + "470": "Page_Of_Cups.png", + "471": "Two_Of_Wands.png", + "472": "Five_Of_Cups.png", + "473": "Three_Of_Wands.png", + "474": "Seven_Of_Wands.png", + "475": "Queen_Of_Cups.png", + "476": "Five_Of_Cups.png", + "477": "Four_Of_Swords.png", + "478": "Two_Of_Swords.png", + "479": "Knight_Of_Wands.png", + "480": "Page_Of_Cups.png", + "481": "Two_Of_Swords.png", + "482": "Ten_Of_Swords.png", + "483": "Three_Of_Swords.png", + "484": "Page_Of_Cups.png", + "485": "Six_Of_Wands.png", + "486": "Knight_Of_Cups.png", + "487": "Knight_Of_Swords.png", + "488": "Page_Of_Pentacles.png", + "489": "Three_Of_Pentacles.png", + "490": "Eight_Of_Swords.png", + "491": "King_Of_Wands.png", + "492": "Six_Of_Cups.png", + "493": "Queen_Of_Pentacles.png", + "494": "Six_Of_Swords.png", + "495": "Six_Of_Pentacles.png", + "496": "Knight_Of_Wands.png", + "497": "King_Of_Swords.png", + "498": "Queen_Of_Cups.png", + "499": "King_Of_Wands.png", + "501": "Knight_Of_Pentacles.png", + "502": "Nine_Of_Pentacles.png", + "504": "Five_Of_Cups.png", + "505": "Ten_Of_Wands.png", + "506": "Ten_Of_Swords.png", + "507": "Five_Of_Pentacles.png", + "508": "Page_Of_Cups.png", + "509": "Two_Of_Wands.png", + "510": "King_Of_Swords.png", + "511": "Six_Of_Swords.png", + "512": "Four_Of_Swords.png", + "513": "Ace_Of_Swords.png", + "514": "Knight_Of_Cups.png", + "515": "Six_Of_Cups.png", + "516": "Five_Of_Pentacles.png", + "517": "King_Of_Cups.png", + "518": "Nine_Of_Pentacles.png", + "519": "Seven_Of_Swords.png", + "520": "Four_Of_Wands.png", + "521": "Queen_Of_Cups.png", + "522": "Six_Of_Wands.png", + "524": "Knight_Of_Wands.png", + "525": "Eight_Of_Pentacles.png", + "526": "Three_Of_Cups.png", + "527": "Ten_Of_Pentacles.png", + "528": "Page_Of_Swords.png", + "529": "Ten_Of_Pentacles.png", + "530": "Knight_Of_Swords.png", + "531": "Five_Of_Pentacles.png", + "532": "Eight_Of_Pentacles.png", + "533": "Three_Of_Cups.png", + "534": "Nine_Of_Cups.png", + "535": "Five_Of_Wands.png", + "536": "Two_Of_Cups.png", + "537": "Four_Of_Swords.png", + "538": "Four_Of_Pentacles.png", + "539": "Ten_Of_Cups.png", + "540": "Nine_Of_Wands.png", + "541": "Four_Of_Pentacles.png", + "542": "Five_Of_Pentacles.png", + "543": "Seven_Of_Pentacles.png", + "544": "Ten_Of_Cups.png", + "545": "Ten_Of_Cups.png", + "546": "Three_Of_Wands.png", + "547": "Nine_Of_Wands.png", + "548": "Two_Of_Wands.png", + "549": "Seven_Of_Wands.png", + "550": "Page_Of_Cups.png", + "551": "Ace_Of_Wands.png", + "552": "Ace_Of_Cups.png", + "553": "Queen_Of_Swords.png", + "554": "Page_Of_Pentacles.png", + "555": "Page_Of_Wands.png", + "556": "Two_Of_Swords.png", + "557": "Six_Of_Wands.png", + "558": "Four_Of_Wands.png", + "559": "Four_Of_Swords.png", + "560": "Three_Of_Cups.png", + "561": "Knight_Of_Wands.png", + "562": "Page_Of_Cups.png", + "563": "King_Of_Wands.png", + "565": "Page_Of_Swords.png", + "566": "King_Of_Cups.png", + "567": "Ten_Of_Wands.png", + "568": "Two_Of_Pentacles.png", + "569": "Ten_Of_Wands.png", + "570": "Eight_Of_Swords.png", + "571": "Page_Of_Wands.png", + "572": "Queen_Of_Pentacles.png", + "573": "Four_Of_Cups.png", + "574": "Two_Of_Cups.png", + "575": "Five_Of_Pentacles.png", + "576": "Three_Of_Swords.png", + "577": "Queen_Of_Wands.png", + "578": "Five_Of_Wands.png", + "579": "Four_Of_Swords.png", + "580": "Knight_Of_Swords.png", + "581": "King_Of_Pentacles.png", + "582": "Ace_Of_Swords.png", + "583": "Six_Of_Wands.png", + "584": "Knight_Of_Swords.png", + "585": "Ten_Of_Pentacles.png", + "586": "Eight_Of_Cups.png", + "587": "Ten_Of_Cups.png", + "588": "Queen_Of_Swords.png", + "589": "Nine_Of_Cups.png", + "590": "Nine_Of_Swords.png", + "591": "Seven_Of_Pentacles.png", + "592": "Seven_Of_Swords.png", + "593": "Knight_Of_Wands.png", + "594": "Three_Of_Wands.png", + "595": "Seven_Of_Wands.png", + "596": "Seven_Of_Pentacles.png", + "597": "Knight_Of_Wands.png", + "598": "Ace_Of_Wands.png", + "599": "King_Of_Cups.png", + "600": "Knight_Of_Pentacles.png", + } +) + +func IsBigTarot(tarotId string) bool { + _, ok := bigTarot[tarotId] + return ok +} + +func TarotImg(tarotId string) string { + if img, ok := bigTarot[tarotId]; ok { + return img + } + img, _ := smallTarot[tarotId] + return img +} diff --git a/internal/types/types.go b/internal/types/types.go index d8fb043..51cb98c 100644 --- a/internal/types/types.go +++ b/internal/types/types.go @@ -16,6 +16,10 @@ type GetCommunityListResp struct { CommunityList []Community `json:"community_list"` // 社区列表 } +type GetNftListReq struct { + WalletAddress string `form:"wallet_address"` +} + type GetTaskListReq struct { CommunityId uint `form:"community_id,optional"` // 所属社区ID } @@ -29,6 +33,7 @@ type GetTaskRewardResp struct { } type StakeNftList struct { + RoleId uint64 `json:"role_id"` // 角色id TokenIds []string `json:"token_ids"` // nft列表 } @@ -70,8 +75,10 @@ type UnStakeNftReq struct { type UserNft struct { TokenId string `json:"token_id"` // nftID + Image string `json:"image"` // nft图片 HasStake bool `json:"has_stake"` // 是否已质押 StakeAt string `json:"stake_at"` // 质押时间 + RoleId uint64 `json:"role_id"` // 角色id } type UserNftList struct {