根据最新需求修改cec claim相关接口
This commit is contained in:
parent
fa64a84b15
commit
49fa01ce7e
@ -11,27 +11,14 @@
|
|||||||
```js
|
```js
|
||||||
|
|
||||||
{
|
{
|
||||||
|
"stage": 0, // 当前所处阶段, 0: 预充值阶段, 1, 2: 对应的阶段
|
||||||
"total": "200000000000000000000", // 总量
|
"total": "200000000000000000000", // 总量
|
||||||
"available": "100000000000000000000", // 当前可获取的数量
|
"available": "100000000000000000000", // 当前可获取的数量
|
||||||
"claimed": "0", // 已领取的数量
|
"claimed": "0", // 已领取的数量
|
||||||
"outerAccount": 0, // 是否已绑定交易所账号
|
"unavailable": "100000000000000000000", // 不可领取的数量
|
||||||
"stages": [ // 阶段信息
|
"bindUid": "1231****3333", // 绑定了的交易所账号
|
||||||
{
|
"bindAddress": "0x44****3333", // 绑定了的交易所钱包地址
|
||||||
"stage": 1,
|
|
||||||
"amount": "100000000000000000000", // 当前阶段可获取的数量
|
|
||||||
"status": 0, // 领取状态, 0: 未领取, 1: 领取中, 9: 已领取
|
|
||||||
"unlocked": true, // 是否已解锁
|
|
||||||
"claimTime": 1720685893000, // 领取时间
|
|
||||||
"unlockTime": 1720685893000 // 解锁时间
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"stage": 2,
|
|
||||||
"amount": "100000000000000000000",
|
|
||||||
"status": 0,
|
|
||||||
"unlocked": false,
|
|
||||||
"unlockTime": 1720772293000
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"records": [
|
"records": [
|
||||||
{
|
{
|
||||||
"address": "0x50a8e60041a206acaa5f844a1104896224be6f39",
|
"address": "0x50a8e60041a206acaa5f844a1104896224be6f39",
|
||||||
@ -103,7 +90,8 @@ body:
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
{
|
{
|
||||||
"accid": "bitget交易所账号id"
|
"accid": "bitget交易所账号id",
|
||||||
|
"address": "bitget交易所账号绑定的钱包地址"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -75,3 +75,12 @@ export const randomSign = () => {
|
|||||||
hex += Math.random() > 0.5 ? '1b' : '1c'
|
hex += Math.random() > 0.5 ? '1b' : '1c'
|
||||||
return hex
|
return hex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const hidePartString = (str: string, showNum: number = 8) => {
|
||||||
|
if (str.length <= showNum) {
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
let len = str.length
|
||||||
|
let half = Math.floor(showNum / 2)
|
||||||
|
return str.slice(0, half) + '...' + str.slice(len - half)
|
||||||
|
}
|
@ -5,14 +5,16 @@ import { CECRecord } from 'models/CECRecord'
|
|||||||
import { ethers } from 'ethers'
|
import { ethers } from 'ethers'
|
||||||
import { CECClaimHistory, CECClaimStatus } from 'models/CECClaimHistory'
|
import { CECClaimHistory, CECClaimStatus } from 'models/CECClaimHistory'
|
||||||
import { SyncLocker } from 'common/SyncLocker'
|
import { SyncLocker } from 'common/SyncLocker'
|
||||||
import { CECRecordTotal, CECStatusEnum } from 'models/CECRecordTotal'
|
import { CECRecordTotal, CECStatusEnum, ClaimStatus, ClaimStatusEnum } from 'models/CECRecordTotal'
|
||||||
import { buildTokenClaimData } from 'services/chain.svr'
|
import { buildTokenClaimData, updateClaimStatus } from 'services/chain.svr'
|
||||||
import { Wallet } from 'models/Wallet'
|
import { Wallet } from 'models/Wallet'
|
||||||
import { PlatEnum } from 'enums/PlatEnum'
|
import { PlatEnum } from 'enums/PlatEnum'
|
||||||
import { BitgetBindInfo } from 'models/BitgitBindInfo'
|
import { BitgetBindInfo } from 'models/BitgitBindInfo'
|
||||||
|
import { hidePartString } from 'common/Utils'
|
||||||
|
|
||||||
const STAGE1_UNLOCK_TIME = Number(process.env.CEC_CLAIM_STAGE1)
|
const STAGE1_UNLOCK_TIME = Number(process.env.CEC_CLAIM_STAGE1)
|
||||||
const STAGE2_UNLOCK_TIME = Number(process.env.CEC_CLAIM_STAGE2)
|
const STAGE2_UNLOCK_TIME = Number(process.env.CEC_CLAIM_STAGE2)
|
||||||
|
const CEC_CLAIM_STAGE = Number(process.env.CEC_CLAIM_STAGE)
|
||||||
const CEC_ADDRESS = process.env.CEC_CONTRACT
|
const CEC_ADDRESS = process.env.CEC_CONTRACT
|
||||||
|
|
||||||
const checkAddress = (address: string) => {
|
const checkAddress = (address: string) => {
|
||||||
@ -24,6 +26,52 @@ const checkAddress = (address: string) => {
|
|||||||
}
|
}
|
||||||
return ethers.utils.getAddress(address).toLowerCase()
|
return ethers.utils.getAddress(address).toLowerCase()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询cec claim状态
|
||||||
|
* 第一期是比较特殊的记录, 在预售阶段, 需要展示第一期可领取的数量, 所以要特殊处理
|
||||||
|
* @param address 有资格的钱包地址
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
const queryCECClaimStatus = async (address: string) => {
|
||||||
|
let total = 0n
|
||||||
|
let available = 0n
|
||||||
|
let claimed = 0n
|
||||||
|
let unavailable = 0n
|
||||||
|
const records = await CECRecordTotal.find({ address })
|
||||||
|
const bindRecord = await BitgetBindInfo.findOne({ wallet: address })
|
||||||
|
let bit = 0n
|
||||||
|
for (const record of records) {
|
||||||
|
let currentTotal = BigInt(record.amount)
|
||||||
|
total += currentTotal
|
||||||
|
// fetch status from claimStatus
|
||||||
|
for (const [key, val] of record.claimStatus.entries()) {
|
||||||
|
const stage = parseInt(key)
|
||||||
|
// 预充值阶段, 需要展示第一期可领取的数量
|
||||||
|
if (stage === 1) {
|
||||||
|
if (CEC_CLAIM_STAGE === 0) {
|
||||||
|
available += (currentTotal * BigInt(val.rate)) / 100n
|
||||||
|
} else {
|
||||||
|
if (bindRecord && !bindRecord.invalid) {
|
||||||
|
claimed += (currentTotal * BigInt(val.rate)) / 100n
|
||||||
|
} else if (val.status === ClaimStatusEnum.NORMAL){
|
||||||
|
available += (currentTotal * BigInt(val.rate)) / 100n
|
||||||
|
bit = bit | 1n << BigInt(val.bit)
|
||||||
|
} else if ( val.status === ClaimStatusEnum.CLAIMED) {
|
||||||
|
claimed += (currentTotal * BigInt(val.rate)) / 100n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (stage <= CEC_CLAIM_STAGE && val.status === ClaimStatusEnum.NORMAL) {
|
||||||
|
available += (currentTotal * BigInt(val.rate)) / 100n
|
||||||
|
bit = bit | 1n << BigInt(val.bit)
|
||||||
|
} else if ( val.status === ClaimStatusEnum.CLAIMED) {
|
||||||
|
claimed += (currentTotal * BigInt(val.rate)) / 100n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unavailable = total - available - claimed
|
||||||
|
return { total, available, claimed, unavailable, bit, records, bindRecord }
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* CEC领取相关接口
|
* CEC领取相关接口
|
||||||
*/
|
*/
|
||||||
@ -48,6 +96,8 @@ class CECController extends BaseController {
|
|||||||
let available = 0n
|
let available = 0n
|
||||||
let claimed = 0n
|
let claimed = 0n
|
||||||
const records = await CECRecord.find({ address })
|
const records = await CECRecord.find({ address })
|
||||||
|
//@ts-ignore
|
||||||
|
await updateClaimStatus({ address, token: CEC_ADDRESS, records})
|
||||||
const now = Date.now()
|
const now = Date.now()
|
||||||
const stages = []
|
const stages = []
|
||||||
const lists = []
|
const lists = []
|
||||||
@ -106,59 +156,16 @@ class CECController extends BaseController {
|
|||||||
async scoreInfoTotal(req: any) {
|
async scoreInfoTotal(req: any) {
|
||||||
let { address } = req.params
|
let { address } = req.params
|
||||||
address = checkAddress(address)
|
address = checkAddress(address)
|
||||||
let total = 0n
|
const { total, available, claimed, unavailable, records, bindRecord } = await queryCECClaimStatus(address)
|
||||||
let available = 0n
|
|
||||||
let claimed = 0n
|
|
||||||
const records = await CECRecordTotal.find({ address })
|
|
||||||
const now = Date.now()
|
|
||||||
const stages = []
|
|
||||||
const lists = []
|
|
||||||
let firstTotal = 0n
|
|
||||||
let firstAvailable = 0n
|
|
||||||
let secondAvailable = 0n
|
|
||||||
for (const record of records) {
|
|
||||||
let currentTotal = BigInt(record.amount)
|
|
||||||
total += currentTotal
|
|
||||||
let firstRate = record.firstRate || 50
|
|
||||||
let firstAmount = currentTotal * BigInt(firstRate) / 100n
|
|
||||||
firstTotal += firstAmount
|
|
||||||
if (STAGE1_UNLOCK_TIME < now && record.status == CECStatusEnum.NORMAL) {
|
|
||||||
available += firstAmount
|
|
||||||
firstAvailable += firstAmount
|
|
||||||
}
|
|
||||||
if (STAGE2_UNLOCK_TIME < now
|
|
||||||
&& record.status != CECStatusEnum.STAGE2_CLAIMED
|
|
||||||
&& record.firstRate < 100) {
|
|
||||||
available += (currentTotal - firstAmount)
|
|
||||||
secondAvailable += (currentTotal - firstAmount)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stages.push({
|
|
||||||
stage: 1,
|
|
||||||
amount: firstTotal.toString(),
|
|
||||||
available: firstAvailable.toString(),
|
|
||||||
status: 0,
|
|
||||||
unlocked: STAGE1_UNLOCK_TIME < now,
|
|
||||||
unlockTime: STAGE1_UNLOCK_TIME
|
|
||||||
})
|
|
||||||
stages.push({
|
|
||||||
stage: 2,
|
|
||||||
amount: (total - firstTotal).toString(),
|
|
||||||
available: secondAvailable.toString(),
|
|
||||||
status: 0,
|
|
||||||
unlocked: STAGE2_UNLOCK_TIME < now,
|
|
||||||
unlockTime: STAGE2_UNLOCK_TIME
|
|
||||||
})
|
|
||||||
const bindRecord = await BitgetBindInfo.findOne({ address: address })
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
stage: CEC_CLAIM_STAGE,
|
||||||
total: total.toString(),
|
total: total.toString(),
|
||||||
available: available.toString(),
|
available: available.toString(),
|
||||||
claimed: claimed.toString(),
|
claimed: claimed.toString(),
|
||||||
stages,
|
unavailable: unavailable.toString(),
|
||||||
records: lists,
|
records: records.map(record => record.toJson()),
|
||||||
outerAccount: bindRecord? 1: 0
|
bindUid: bindRecord ? hidePartString(bindRecord.biggetAcc) : '',
|
||||||
|
bindAddress: bindRecord ? hidePartString(bindRecord.address) : ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,7 +175,7 @@ class CECController extends BaseController {
|
|||||||
logger.db('claim_cec', req)
|
logger.db('claim_cec', req)
|
||||||
const user = req.user
|
const user = req.user
|
||||||
const now = Date.now()
|
const now = Date.now()
|
||||||
if (STAGE1_UNLOCK_TIME > now) {
|
if (CEC_CLAIM_STAGE === 0) {
|
||||||
throw new ZError(14, 'not begin')
|
throw new ZError(14, 'not begin')
|
||||||
}
|
}
|
||||||
let wallet: string; // 通过该地址查询可以claim的cec数量
|
let wallet: string; // 通过该地址查询可以claim的cec数量
|
||||||
@ -187,33 +194,7 @@ class CECController extends BaseController {
|
|||||||
wallet = wallet.toLowerCase()
|
wallet = wallet.toLowerCase()
|
||||||
let { address } = req.params // 这个地址用于执行claim的动作
|
let { address } = req.params // 这个地址用于执行claim的动作
|
||||||
address = checkAddress(address)
|
address = checkAddress(address)
|
||||||
const bindRecord = await BitgetBindInfo.findOne({ address: wallet })
|
const { available, bit } = await queryCECClaimStatus(wallet)
|
||||||
if (bindRecord) {
|
|
||||||
throw new ZError(18, 'already bind exchange account')
|
|
||||||
}
|
|
||||||
const records = await CECRecordTotal.find({ address: wallet })
|
|
||||||
if (records.length === 0) {
|
|
||||||
throw new ZError(15, 'record not found')
|
|
||||||
}
|
|
||||||
let total = 0n
|
|
||||||
let available = 0n
|
|
||||||
let bit = 0
|
|
||||||
for (const record of records) {
|
|
||||||
let currentTotal = BigInt(record.amount)
|
|
||||||
total += currentTotal
|
|
||||||
let firstRate = record.firstRate || 50
|
|
||||||
let firstAmount = currentTotal * BigInt(firstRate) / 100n
|
|
||||||
if (STAGE1_UNLOCK_TIME < now && record.status == CECStatusEnum.NORMAL) {
|
|
||||||
available += firstAmount
|
|
||||||
bit = bit | 1 << (record.bit * 2)
|
|
||||||
}
|
|
||||||
if (STAGE2_UNLOCK_TIME < now
|
|
||||||
&& record.status != CECStatusEnum.STAGE2_CLAIMED
|
|
||||||
&& record.firstRate < 100) {
|
|
||||||
available += (currentTotal - firstAmount)
|
|
||||||
bit = bit | 1 << (record.bit * 2 + 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (available === 0n) {
|
if (available === 0n) {
|
||||||
throw new ZError(16, 'no cec to claim')
|
throw new ZError(16, 'no cec to claim')
|
||||||
}
|
}
|
||||||
@ -223,7 +204,7 @@ class CECController extends BaseController {
|
|||||||
account: wallet,
|
account: wallet,
|
||||||
token: CEC_ADDRESS,
|
token: CEC_ADDRESS,
|
||||||
amount: available.toString(),
|
amount: available.toString(),
|
||||||
bit,
|
bit: bit.toString(),
|
||||||
nonce
|
nonce
|
||||||
})
|
})
|
||||||
return { calls: [{trans_req: data, trans_id: ''}], direct: true }
|
return { calls: [{trans_req: data, trans_id: ''}], direct: true }
|
||||||
@ -232,14 +213,14 @@ class CECController extends BaseController {
|
|||||||
@router('post /api/cec/bind_account')
|
@router('post /api/cec/bind_account')
|
||||||
async bindAccount(req: any) {
|
async bindAccount(req: any) {
|
||||||
const user = req.user
|
const user = req.user
|
||||||
const { accid } = req.body
|
const { accid, address } = req.body
|
||||||
if (!accid) {
|
if (!accid || !address) {
|
||||||
throw new ZError(11, 'accid is required')
|
throw new ZError(11, 'accid is required')
|
||||||
}
|
}
|
||||||
const now = Date.now()
|
if (!ethers.utils.isAddress(address)) {
|
||||||
if (STAGE1_UNLOCK_TIME > now) {
|
throw new ZError(12, 'address is invalid')
|
||||||
throw new ZError(14, 'not begin')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let wallet: string; // 通过该地址查询可以claim的cec数量
|
let wallet: string; // 通过该地址查询可以claim的cec数量
|
||||||
if (user.plat === PlatEnum.EXTERNAL_WALLET) {
|
if (user.plat === PlatEnum.EXTERNAL_WALLET) {
|
||||||
wallet = user.openId || user.openid
|
wallet = user.openId || user.openid
|
||||||
@ -260,11 +241,11 @@ class CECController extends BaseController {
|
|||||||
throw new ZError(15, 'record not found')
|
throw new ZError(15, 'record not found')
|
||||||
}
|
}
|
||||||
|
|
||||||
let record = await BitgetBindInfo.findOne({ address: wallet })
|
let record = await BitgetBindInfo.findOne({ wallet })
|
||||||
if (record) {
|
if (record) {
|
||||||
throw new ZError(17, 'already bind')
|
throw new ZError(17, 'already bind')
|
||||||
}
|
}
|
||||||
record = new BitgetBindInfo({ address: wallet, biggetAcc: accid })
|
record = new BitgetBindInfo({ address, wallet, biggetAcc: accid })
|
||||||
await record.save()
|
await record.save()
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
|
@ -16,18 +16,33 @@ import { BaseModule } from './Base'
|
|||||||
export interface BitgetUserClass extends Base, TimeStamps {}
|
export interface BitgetUserClass extends Base, TimeStamps {}
|
||||||
|
|
||||||
@dbconn()
|
@dbconn()
|
||||||
@index({ address: 1 }, { unique: true })
|
@index({ wallet: 1 }, { unique: true })
|
||||||
@index({ biggetAcc: 1 }, { unique: false})
|
@index({ biggetAcc: 1 }, { unique: false})
|
||||||
@modelOptions({
|
@modelOptions({
|
||||||
schemaOptions: { collection: 'bitget_bing_info', timestamps: true },
|
schemaOptions: { collection: 'bitget_bing_info', timestamps: true },
|
||||||
options: { allowMixed: Severity.ALLOW },
|
|
||||||
})
|
})
|
||||||
export class BitgetBindInfoClass extends BaseModule {
|
export class BitgetBindInfoClass extends BaseModule {
|
||||||
|
/**
|
||||||
|
* 用户钱包地址, 内置钱包, metamask等
|
||||||
|
*/
|
||||||
|
@prop({ required: true })
|
||||||
|
public wallet: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 交易所账号对应的钱包地址, 需用户提交
|
||||||
|
*/
|
||||||
@prop({ required: true })
|
@prop({ required: true })
|
||||||
public address: string
|
public address: string
|
||||||
|
/**
|
||||||
|
* 交易所账号uid
|
||||||
|
*/
|
||||||
@prop()
|
@prop()
|
||||||
public biggetAcc: string
|
public biggetAcc: string
|
||||||
|
/**
|
||||||
|
* 由交易所反馈, 绑定信息无效
|
||||||
|
*/
|
||||||
|
@prop({ default: false })
|
||||||
|
public invalid: boolean
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,23 @@ export enum CECStatusEnum {
|
|||||||
STAGE1_CLAIMED = 2,
|
STAGE1_CLAIMED = 2,
|
||||||
STAGE2_CLAIMED = 3
|
STAGE2_CLAIMED = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum ClaimStatusEnum {
|
||||||
|
NORMAL = 1,
|
||||||
|
CLAIMED = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
@modelOptions({ schemaOptions: { _id: false } })
|
||||||
|
export class ClaimStatus {
|
||||||
|
@prop()
|
||||||
|
public bit: number
|
||||||
|
@prop()
|
||||||
|
public rate: number
|
||||||
|
@prop({ enum: ClaimStatusEnum, default: ClaimStatusEnum.NORMAL })
|
||||||
|
public status: ClaimStatusEnum
|
||||||
|
@prop()
|
||||||
|
public time: number
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* CEC赚取记录
|
* CEC赚取记录
|
||||||
*/
|
*/
|
||||||
@ -21,7 +38,7 @@ export enum CECStatusEnum {
|
|||||||
@modelOptions({
|
@modelOptions({
|
||||||
schemaOptions: { collection: 'cec_record_total', timestamps: true },
|
schemaOptions: { collection: 'cec_record_total', timestamps: true },
|
||||||
})
|
})
|
||||||
class CECRecordTotalClass extends BaseModule {
|
export class CECRecordTotalClass extends BaseModule {
|
||||||
@prop()
|
@prop()
|
||||||
public address: string
|
public address: string
|
||||||
|
|
||||||
@ -31,23 +48,27 @@ class CECRecordTotalClass extends BaseModule {
|
|||||||
@prop()
|
@prop()
|
||||||
public num: number
|
public num: number
|
||||||
|
|
||||||
/**
|
|
||||||
* claim时作为标记位
|
|
||||||
*
|
|
||||||
0: uaw
|
|
||||||
1: p2a
|
|
||||||
2: game test parse 1
|
|
||||||
3: Loyalty Points Rewards
|
|
||||||
4: Badge staking rewards
|
|
||||||
5: Gacha Journey
|
|
||||||
6: Rase of Gacha
|
|
||||||
7: game season rank
|
|
||||||
8: hash rate rewards
|
|
||||||
9: old game event
|
|
||||||
**/
|
|
||||||
@prop()
|
@prop()
|
||||||
public bit: number
|
public bit: number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 各claim阶段代表的bit位
|
||||||
|
* uaw: 0, 1
|
||||||
|
* p2a: 2, 3
|
||||||
|
* game test parse 1: 4
|
||||||
|
* Loyalty Points Rewards: 5
|
||||||
|
* Badge staking rewards: 6, 7
|
||||||
|
* Gacha Journey: 8, 9
|
||||||
|
* Rase of Gacha: 10, 11
|
||||||
|
* game season rank: 12, 13
|
||||||
|
* hash rate rewards: 14, 15
|
||||||
|
* old game event: 16, 17
|
||||||
|
* p2e season 2: 18
|
||||||
|
* founder's tag holder: 19
|
||||||
|
*/
|
||||||
|
@prop({ type: () => ClaimStatus, _id: false })
|
||||||
|
public claimStatus?: Map<string, ClaimStatus>;
|
||||||
|
|
||||||
@prop()
|
@prop()
|
||||||
public earnTime: string
|
public earnTime: string
|
||||||
|
|
||||||
|
66
src/models/chain/TokenClaimRecord.ts
Normal file
66
src/models/chain/TokenClaimRecord.ts
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import { getModelForClass, index, modelOptions, prop } from '@typegoose/typegoose'
|
||||||
|
import { dbconn } from 'decorators/dbconn'
|
||||||
|
import { BaseModule } from '../Base'
|
||||||
|
import { GeneralEventClass } from './GeneralEvent'
|
||||||
|
|
||||||
|
@dbconn()
|
||||||
|
@index({ chain: 1, address: 1, token: 1, account: 1 }, { unique: true })
|
||||||
|
@index({ chain: 1, address: 1, token: 1, user: 1 }, { unique: true })
|
||||||
|
@modelOptions({
|
||||||
|
schemaOptions: { collection: 'token_claim_record', timestamps: true },
|
||||||
|
})
|
||||||
|
export class TokenClaimRecordClass extends BaseModule {
|
||||||
|
@prop({ required: true })
|
||||||
|
public address!: string
|
||||||
|
@prop({ required: true })
|
||||||
|
public chain: string
|
||||||
|
|
||||||
|
@prop({ type: () => [Number], default: [] })
|
||||||
|
public blockNumbers: number[]
|
||||||
|
|
||||||
|
@prop({ type: () => [String], default: [] })
|
||||||
|
public users: string[]
|
||||||
|
|
||||||
|
@prop()
|
||||||
|
public account: string
|
||||||
|
@prop()
|
||||||
|
public token: string
|
||||||
|
@prop()
|
||||||
|
public amount: string
|
||||||
|
@prop()
|
||||||
|
public bit: string
|
||||||
|
|
||||||
|
|
||||||
|
public static async parseEvent(event: Partial<GeneralEventClass>) {
|
||||||
|
const address = event.address
|
||||||
|
const chain = event.chain
|
||||||
|
const user = event.decodedData?.user
|
||||||
|
const account = event.decodedData?.account
|
||||||
|
const token = event.decodedData?.token
|
||||||
|
const amount = event.decodedData?.amount
|
||||||
|
const bit = event.decodedData?.bit
|
||||||
|
const blockNumber = event.blockNumber
|
||||||
|
let bitBn = BigInt(bit)
|
||||||
|
let record = await TokenClaimRecord.findOne({ chain, address, account, token })
|
||||||
|
if (!record) {
|
||||||
|
record = new TokenClaimRecord({ chain, address, account, token, amount, bit, blockNumbers: [blockNumber], users: [user] })
|
||||||
|
await record.save()
|
||||||
|
} else {
|
||||||
|
if ((BigInt(record.bit) & bitBn) == 0n) {
|
||||||
|
record.amount = (BigInt(record.amount) + BigInt(amount)).toString()
|
||||||
|
record.bit = (BigInt(record.bit) | bitBn).toString()
|
||||||
|
if (!record.blockNumbers.includes(blockNumber)) {
|
||||||
|
record.blockNumbers.push(blockNumber)
|
||||||
|
}
|
||||||
|
if (!record.users.includes(user)) {
|
||||||
|
record.users.push(user)
|
||||||
|
}
|
||||||
|
await record.save()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TokenClaimRecord = getModelForClass(TokenClaimRecordClass, {
|
||||||
|
existingConnection: TokenClaimRecordClass['db'],
|
||||||
|
})
|
@ -1,7 +1,9 @@
|
|||||||
import { Contract } from 'ethers'
|
import { Contract } from 'ethers'
|
||||||
|
import { CECRecordTotalClass, CECStatusEnum } from 'models/CECRecordTotal'
|
||||||
import { CheckIn } from 'models/chain/CheckIn'
|
import { CheckIn } from 'models/chain/CheckIn'
|
||||||
import { NftHolder } from 'models/chain/NftHolder'
|
import { NftHolder } from 'models/chain/NftHolder'
|
||||||
import { NftStake } from 'models/chain/NftStake'
|
import { NftStake } from 'models/chain/NftStake'
|
||||||
|
import { TokenClaimRecord } from 'models/chain/TokenClaimRecord'
|
||||||
import { sign } from 'utils/sign.utils'
|
import { sign } from 'utils/sign.utils'
|
||||||
import { getMonthBegin, getNDayAgo } from 'utils/utcdate.util'
|
import { getMonthBegin, getNDayAgo } from 'utils/utcdate.util'
|
||||||
import { timeoutFetch } from 'zutils/utils/net.util'
|
import { timeoutFetch } from 'zutils/utils/net.util'
|
||||||
@ -167,6 +169,34 @@ export const fetchClaimStatus = async (address: string, taskId: string) => {
|
|||||||
return fetchChainStatus(address, `0x${method}${addressStr}${valStr}`)
|
return fetchChainStatus(address, `0x${method}${addressStr}${valStr}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const updateClaimStatus = async (
|
||||||
|
{address, account, token, records}:
|
||||||
|
{address: string, account: string, token: string, records: Partial<CECRecordTotalClass>[]}) => {
|
||||||
|
const chain = process.env.CHAIN + ''
|
||||||
|
const record = await TokenClaimRecord.findOne({ chain, address, account, token })
|
||||||
|
if (!record) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for (let item of records) {
|
||||||
|
let bit = BigInt(item.bit * 2)
|
||||||
|
let bit1 = bit + 1n
|
||||||
|
let changed = false
|
||||||
|
if (item.status == CECStatusEnum.NORMAL && (BigInt(record.bit) & 1n << bit) > 0n ) {
|
||||||
|
item.status = CECStatusEnum.STAGE1_CLAIMED
|
||||||
|
changed = true
|
||||||
|
}
|
||||||
|
if (item.firstRate < 100 && item.status != CECStatusEnum.STAGE2_CLAIMED && (BigInt(record.bit) & 1n << bit1) > 0n) {
|
||||||
|
item.status = CECStatusEnum.STAGE2_CLAIMED
|
||||||
|
changed = true
|
||||||
|
}
|
||||||
|
if (changed) {
|
||||||
|
//@ts-ignore
|
||||||
|
await item.save()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const claimTokenAbi = [
|
const claimTokenAbi = [
|
||||||
'function claim(address,address,uint256[4],bytes)',
|
'function claim(address,address,uint256[4],bytes)',
|
||||||
]
|
]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user