修改合作伙伴nft holder claim规则
This commit is contained in:
parent
8a7b036bd9
commit
9513fab283
@ -5,7 +5,9 @@
|
||||
"contract": "0x20577896ea6113ed8c94b2f08f3893bdc08eba22",
|
||||
"collection": "l3e7 worlds",
|
||||
"remarks": "600 collection",
|
||||
"chain": 1
|
||||
"chain": 1,
|
||||
"guild": "1222509817411665920",
|
||||
"role": "1229658972793999391"
|
||||
},
|
||||
{
|
||||
"projectName": "Ultiverse",
|
||||
|
@ -22,7 +22,7 @@ export const STEP_SCORE_MIN = 40
|
||||
// 每一步能获得的最大分数
|
||||
export const STEP_SCORE_MAX = 50
|
||||
// 每一步能获得的宝箱的概率
|
||||
export const STEP_CHEST_RATE = 0.3
|
||||
export const STEP_CHEST_RATE = 1
|
||||
// 邀请用户得到额外分数
|
||||
export const INVITE_REBATE = 0.1
|
||||
|
||||
|
@ -2,6 +2,7 @@ import { ChestStatusEnum } from 'models/ActivityChest'
|
||||
import { NFTHolderRecord } from 'models/NFTHodlerRecord'
|
||||
import { queryNftBalance } from 'services/chain.svr'
|
||||
import { generateChestLevel, generateNewChest } from 'services/game.svr'
|
||||
import { checkDiscordRole } from 'services/oauth.svr'
|
||||
import { SyncLocker, BaseController, router, role, ROLE_ANON, ZError } from 'zutils'
|
||||
|
||||
const nftList = require('../../configs/partner_nft_list.json')
|
||||
@ -33,9 +34,9 @@ class NftController extends BaseController {
|
||||
return list
|
||||
}
|
||||
/**
|
||||
* 领取合作伙伴nft holder奖励
|
||||
* 领取合作伙伴nft holder奖励, 检查NFT
|
||||
*/
|
||||
@router('post /api/partner/claim')
|
||||
// @router('post /api/partner/claim')
|
||||
async claimNftHolderReward(req) {
|
||||
new SyncLocker().checkLock(req)
|
||||
const user = req.user
|
||||
@ -73,4 +74,43 @@ class NftController extends BaseController {
|
||||
await recordNew.save()
|
||||
return { chests: [chest.toJson()] }
|
||||
}
|
||||
|
||||
@router('post /api/partner/claim')
|
||||
async claimNftHolderRewardDC(req) {
|
||||
new SyncLocker().checkLock(req)
|
||||
const user = req.user
|
||||
let { contract } = req.params
|
||||
if (!contract) {
|
||||
throw new ZError(11, 'contract not found')
|
||||
}
|
||||
contract = contract.toLowerCase()
|
||||
if (!nftMap.has(contract)) {
|
||||
throw new ZError(12, 'contract not found')
|
||||
}
|
||||
let record = await NFTHolderRecord.findOne({ user: user.id, contract })
|
||||
if (record) {
|
||||
throw new ZError(13, 'already claimed')
|
||||
}
|
||||
const cfg = nftMap.get(contract)
|
||||
let rpcRes = await checkDiscordRole(user.address.toLowerCase(), cfg.guild, cfg.role)
|
||||
console.log('check result:', rpcRes)
|
||||
if (rpcRes.errcode) {
|
||||
throw new ZError(20, `check error: ${rpcRes.errmsg}`)
|
||||
}
|
||||
if (!rpcRes.data.result) {
|
||||
throw new ZError(14, 'not match claim condition')
|
||||
}
|
||||
let randomLevel = generateChestLevel()
|
||||
let chest = generateNewChest(user.id, user.activity, randomLevel, ChestStatusEnum.NORMAL)
|
||||
await chest.save()
|
||||
let recordNew = new NFTHolderRecord({
|
||||
user: user.id,
|
||||
contract,
|
||||
chain: nftMap.get(contract).chain,
|
||||
holderNum: 1,
|
||||
rewards: [chest.id],
|
||||
})
|
||||
await recordNew.save()
|
||||
return { chests: [chest.toJson()] }
|
||||
}
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ class SignController extends BaseController {
|
||||
discordName: user.discordName,
|
||||
scoreToday: formatNumShow(todayScore ? parseInt(todayScore + '') / RANK_SCORE_SCALE : 0),
|
||||
scoreTotal: formatNumShow(totalScore ? parseInt(totalScore + '') / RANK_SCORE_SCALE : 0),
|
||||
rankTotal: totalRank ? totalRank : '-',
|
||||
rankTotal: totalRank != undefined ? totalRank : '-',
|
||||
invite,
|
||||
inviteCount: records.length,
|
||||
inviteScore,
|
||||
|
@ -8,6 +8,7 @@ import { BASE_TASK_TICKET } from 'common/Constants'
|
||||
import { BASE_TASK_REWARD, SIGN_SEQ, TicketRecord } from 'models/TicketRecord'
|
||||
import { ActivityGame } from 'models/ActivityGame'
|
||||
import { formatNumShow } from 'common/Utils'
|
||||
import { fetchClaimStatus } from 'services/chain.svr'
|
||||
const fs = require('fs')
|
||||
|
||||
const prod = process.env.NODE_ENV === 'production'
|
||||
@ -205,6 +206,10 @@ export default class TasksController extends BaseController {
|
||||
if (!chainRecord) {
|
||||
throw new ZError(14, 'waiting for chain confirm')
|
||||
}
|
||||
// let result = await fetchClaimStatus(user.address.toLowerCase(), task)
|
||||
// if (!result) {
|
||||
// throw new ZError(15, 'waiting for chain confirm')
|
||||
// }
|
||||
}
|
||||
|
||||
const Task = require('../tasks/' + currentTask.task)
|
||||
|
@ -2,6 +2,10 @@ import { CheckIn } from 'models/chain/CheckIn'
|
||||
import { NftHolder } from 'models/chain/NftHolder'
|
||||
import { NftStake } from 'models/chain/NftStake'
|
||||
import { getMonthBegin, getNDayAgo } from 'utils/utcdate.util'
|
||||
import { timeoutFetch } from 'zutils/utils/net.util'
|
||||
import { numberToBN } from 'zutils/utils/number.util'
|
||||
const DEFAULT_TIMEOUT = 30000
|
||||
const ACTIVITY_RPC_URL = process.env.ACTIVITY_RPC_URL
|
||||
|
||||
export const queryCheckInList = async (address: string, days: string | number | string[], limit: number = 0) => {
|
||||
let query: any = { from: address.toLowerCase() }
|
||||
@ -69,23 +73,94 @@ export const queryStakeList = async (userAddress: string) => {
|
||||
return records
|
||||
}
|
||||
|
||||
const requestChain = async (rpc: string, method: string, params: any) => {
|
||||
const data = {
|
||||
id: Date.now(),
|
||||
jsonrpc: '2.0',
|
||||
method,
|
||||
params,
|
||||
}
|
||||
const options: any = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
}
|
||||
return timeoutFetch(rpc, options, DEFAULT_TIMEOUT).then(res => res.json())
|
||||
}
|
||||
|
||||
export const queryNftBalance = async (contract: string, address: string) => {
|
||||
const rpc = 'https://mainnet.infura.io/v3/b6bf7d3508c941499b10025c0776eaf8'
|
||||
const data = {
|
||||
id: (Date.now() / 1000) | 0,
|
||||
jsonrpc: '2.0',
|
||||
method: 'eth_call',
|
||||
params: [
|
||||
{
|
||||
data: `0x70a08231000000000000000000000000${address.replace('0x', '')}`,
|
||||
from: address,
|
||||
to: contract,
|
||||
},
|
||||
'latest',
|
||||
],
|
||||
}
|
||||
return fetch(rpc, {
|
||||
body: JSON.stringify(data),
|
||||
method: 'POST',
|
||||
}).then(res => res.json())
|
||||
const params = [
|
||||
{
|
||||
data: `0x70a08231000000000000000000000000${address.replace('0x', '')}`,
|
||||
from: address,
|
||||
to: contract,
|
||||
},
|
||||
'latest',
|
||||
]
|
||||
return requestChain(rpc, 'eth_call', params)
|
||||
}
|
||||
|
||||
export const fetchChainStatus = async (address: string, data: string) => {
|
||||
console.log(data)
|
||||
const params = [
|
||||
{
|
||||
data: data,
|
||||
from: address,
|
||||
to: process.env.ACTIVITY_CONTRACT,
|
||||
},
|
||||
'latest',
|
||||
]
|
||||
return requestChain(ACTIVITY_RPC_URL, 'eth_call', params)
|
||||
}
|
||||
|
||||
export const fetchCheckInStatus = async (address: string) => {
|
||||
const days = ((Date.now() / 1000 / 60 / 60 / 24) | 0) - 1
|
||||
const valStr = days.toString(16).padStart(64, '0')
|
||||
const addressStr = address.replace('0x', '').padStart(64, '0')
|
||||
const method = '86cd4926'
|
||||
return fetchChainStatus(address, `0x${method}${addressStr}${valStr}`)
|
||||
}
|
||||
|
||||
export const fetchExploreStatus = async (address: string, exploreId: string) => {
|
||||
const valStr = exploreId.toString().padStart(64, '0')
|
||||
const addressStr = address.replace('0x', '').padStart(64, '0')
|
||||
const method = '36028275'
|
||||
return fetchChainStatus(address, `0x${method}${addressStr}${valStr}`)
|
||||
}
|
||||
|
||||
export const fetchOpenBoxtatus = async (address: string, boxId: string) => {
|
||||
const valStr = boxId.padStart(64, '0')
|
||||
const addressStr = address.replace('0x', '').padStart(64, '0')
|
||||
const method = 'd869bb29'
|
||||
return fetchChainStatus(address, `0x${method}${addressStr}${valStr}`)
|
||||
}
|
||||
|
||||
export const fetchEnhanceStatus = async (address: string, shareCode: string) => {
|
||||
const shareCodeHex = shareCode
|
||||
.split('')
|
||||
.map(c => c.charCodeAt(0).toString(16).padStart(2, '0'))
|
||||
.join('')
|
||||
const valStr = shareCodeHex.padStart(64, '0')
|
||||
const addressStr = address.replace('0x', '').padStart(64, '0')
|
||||
const method = '9b68ea4c'
|
||||
let res = await fetchChainStatus(address, `0x${method}${addressStr}${valStr}`)
|
||||
if (res.error) {
|
||||
throw new Error(res.error.message)
|
||||
}
|
||||
let result = parseInt(res.result)
|
||||
return !!result
|
||||
}
|
||||
|
||||
export const fetchClaimStatus = async (address: string, taskId: string) => {
|
||||
const taskIdHex = taskId
|
||||
.split('')
|
||||
.map(c => c.charCodeAt(0).toString(16).padStart(2, '0'))
|
||||
.join('')
|
||||
const valStr = taskIdHex.padStart(64, '0')
|
||||
const addressStr = address.replace('0x', '').padStart(64, '0')
|
||||
const method = '4902f7e0'
|
||||
return fetchChainStatus(address, `0x${method}${addressStr}${valStr}`)
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { hmacSha256 } from 'zutils/utils/security.util'
|
||||
import { handleFetch } from 'zutils/utils/net.util'
|
||||
import { handleFetch, timeoutFetch } from 'zutils/utils/net.util'
|
||||
|
||||
const SECRET_KEY = process.env.HASH_SALT
|
||||
const DEFAULT_TIMEOUT = 30000
|
||||
|
||||
function createSign(address: string) {
|
||||
// address = address.toLowerCase();
|
||||
@ -9,14 +10,51 @@ function createSign(address: string) {
|
||||
return signCheck
|
||||
}
|
||||
|
||||
export function checkTwitter(address: string) {
|
||||
export async function checkTwitter(address: string) {
|
||||
let sign = createSign(address)
|
||||
const url = `${process.env.OAUTH_SVR_URL}/activity/twitter/${address}?sign=${sign}`
|
||||
return handleFetch(url)
|
||||
}
|
||||
|
||||
export function checkDiscord(address: string) {
|
||||
export async function checkDiscord(address: string) {
|
||||
let sign = createSign(address)
|
||||
const url = `${process.env.OAUTH_SVR_URL}/activity/discord/${address}?sign=${sign}`
|
||||
return handleFetch(url)
|
||||
}
|
||||
|
||||
export async function checkDiscordGuid(address: string, gid: string) {
|
||||
let sign = createSign(address)
|
||||
const data = {
|
||||
gid,
|
||||
address,
|
||||
sign,
|
||||
}
|
||||
const url = `${process.env.OAUTH_SVR_URL}/activity/discord/guild`
|
||||
const options: any = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
}
|
||||
return timeoutFetch(url, options, DEFAULT_TIMEOUT).then(res => res.json())
|
||||
}
|
||||
|
||||
export async function checkDiscordRole(address: string, gid: string, rid: string) {
|
||||
let sign = createSign(address)
|
||||
const data = {
|
||||
gid,
|
||||
address,
|
||||
rid,
|
||||
sign,
|
||||
}
|
||||
const url = `${process.env.OAUTH_SVR_URL}/activity/discord/role`
|
||||
const options: any = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
}
|
||||
return timeoutFetch(url, options, DEFAULT_TIMEOUT).then(res => res.json())
|
||||
}
|
||||
|
@ -91,7 +91,8 @@ export const rankKey = (activity: string, date?: Date) => {
|
||||
return `${activity}:score:${dateTag}`
|
||||
}
|
||||
|
||||
export const rankLevel = (rank: number) => {
|
||||
export const rankLevel = (rank: number | string) => {
|
||||
rank = parseInt(rank + '')
|
||||
const data = rankLevels.find(o => rank >= o.rankMin && rank <= o.rankMax)
|
||||
return data.level
|
||||
return data ? data.level : '-'
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user