188 lines
5.6 KiB
TypeScript
188 lines
5.6 KiB
TypeScript
import { DEFAULT_GUILD } from 'common/Constants'
|
|
import logger from 'logger/logger'
|
|
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 sourceList = require('../../configs/partner_nft_list.json')
|
|
const nftList = sourceList.map(o => {
|
|
return {
|
|
contract: o['Contract'],
|
|
projectName: o['Project'],
|
|
link: o['Twitter'],
|
|
collection: o['Collection name'],
|
|
group: o['GROUP'],
|
|
guild: o['SERVER ID'] || DEFAULT_GUILD,
|
|
role: o['ROLE ID'],
|
|
tier: o['TIER'] == 'Tier 2' ? 2 : 1,
|
|
}
|
|
})
|
|
if (process.env.NODE_ENV !== 'production') {
|
|
nftList.unshift({
|
|
projectName: 'Test',
|
|
link: 'https://x.com/sparky-chain',
|
|
contract: '0x50a8e60041a206acaa5f844a1104896224be6f38',
|
|
collection: 'Test Group01',
|
|
guild: '1222509817411665920',
|
|
role: '1230421511735738409',
|
|
tier: 2,
|
|
})
|
|
nftList.unshift({
|
|
projectName: 'Test',
|
|
link: 'https://x.com/sparky-chain',
|
|
contract: '0x50a8e60041a206acaa5f844a1104896224be6f38',
|
|
collection: 'Test Group02',
|
|
guild: '1222509817411665920',
|
|
role: '1230421511735738409',
|
|
tier: 2,
|
|
})
|
|
nftList.unshift({
|
|
projectName: 'Test',
|
|
link: 'https://x.com/sparky-chain',
|
|
contract: '0x50a8e60041a206acaa5f844a1104896224be6f39',
|
|
collection: 'Test Collection',
|
|
guild: '1222509817411665920',
|
|
role: '1229658972793999391',
|
|
tier: 2,
|
|
})
|
|
}
|
|
const nftListStr = JSON.stringify(nftList)
|
|
const nftMap = new Map()
|
|
const groupMap = new Map()
|
|
for (let o of nftList) {
|
|
nftMap.set(o.contract.toLowerCase(), o)
|
|
if (o.group) {
|
|
if (!groupMap.has(o.group)) {
|
|
groupMap.set(o.group, [])
|
|
}
|
|
groupMap.get(o.group).push(o)
|
|
}
|
|
}
|
|
/**
|
|
* 合作伙伴相关接口
|
|
*/
|
|
class NftController extends BaseController {
|
|
/**
|
|
* NFT 列表
|
|
*/
|
|
@role(ROLE_ANON)
|
|
@router('get /api/partner/nfts')
|
|
async fetchNftList(req) {
|
|
const user = req.user
|
|
let list = JSON.parse(nftListStr)
|
|
list.forEach(o => {
|
|
o.status = 0
|
|
})
|
|
if (user) {
|
|
let records = await NFTHolderRecord.find({ user: user.id })
|
|
let recordSet = new Set()
|
|
let groupSet = new Set()
|
|
for (let record of records) {
|
|
recordSet.add(record.contract.toLowerCase())
|
|
if (record.group) {
|
|
groupSet.add(record.group)
|
|
}
|
|
}
|
|
for (let sub of list) {
|
|
sub.status = recordSet.has(sub.contract.toLowerCase()) || groupSet.has(sub.group) ? 1 : 0
|
|
}
|
|
}
|
|
return list
|
|
}
|
|
/**
|
|
* 领取合作伙伴nft holder奖励, 检查NFT
|
|
*/
|
|
// @router('post /api/partner/claim')
|
|
async claimNftHolderReward(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')
|
|
}
|
|
let rpcRes = await queryNftBalance(contract, user.address)
|
|
console.log('check result:', rpcRes)
|
|
if (rpcRes.error) {
|
|
throw new ZError(20, `check error: ${rpcRes.error.message}`)
|
|
}
|
|
let count = parseInt(rpcRes.result)
|
|
if (count === 0) {
|
|
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: count,
|
|
rewards: [chest.id],
|
|
})
|
|
await recordNew.save()
|
|
return { chests: [chest.toJson()] }
|
|
}
|
|
|
|
@router('post /api/partner/claim')
|
|
async claimNftHolderRewardDC(req) {
|
|
new SyncLocker().checkLock(req)
|
|
logger.db('claim_partner', req)
|
|
const user = req.user
|
|
if (!user.discordId) {
|
|
throw new ZError(10, 'need connect discord first')
|
|
}
|
|
let { contract } = req.params
|
|
if (!contract) {
|
|
throw new ZError(11, 'params error')
|
|
}
|
|
contract = contract.toLowerCase()
|
|
if (!nftMap.has(contract)) {
|
|
throw new ZError(12, 'cfg not found')
|
|
}
|
|
let record = await NFTHolderRecord.findOne({ user: user.id, contract })
|
|
if (record) {
|
|
throw new ZError(13, 'already claimed')
|
|
}
|
|
const cfg = nftMap.get(contract)
|
|
if (cfg.group) {
|
|
let groupRecord = await NFTHolderRecord.findOne({ user: user.id, group: cfg.group })
|
|
if (groupRecord) {
|
|
throw new ZError(16, 'already claimed')
|
|
}
|
|
}
|
|
const guild = cfg.guild || DEFAULT_GUILD
|
|
let rpcRes = await checkDiscordRole(user.address.toLowerCase(), guild, cfg.role)
|
|
console.log('check result:', rpcRes)
|
|
if (rpcRes.errcode) {
|
|
throw new ZError(rpcRes.errcode, `rpcRes.errmsg`)
|
|
}
|
|
if (!rpcRes.data.result) {
|
|
throw new ZError(14, 'had no role')
|
|
}
|
|
let chestLevel = cfg.tier || 1
|
|
let chest = generateNewChest(user.id, user.activity, chestLevel, ChestStatusEnum.NORMAL)
|
|
await chest.save()
|
|
let recordNew = new NFTHolderRecord({
|
|
user: user.id,
|
|
contract,
|
|
chain: nftMap.get(contract).chain,
|
|
holderNum: 1,
|
|
group: cfg.group,
|
|
rewards: [chest.id],
|
|
})
|
|
await recordNew.save()
|
|
return { chests: [chest.toJson()] }
|
|
}
|
|
}
|