From 99d12411235b90774cc4bed334fe17bceb3a6a35 Mon Sep 17 00:00:00 2001 From: CounterFire2023 <136581895+CounterFire2023@users.noreply.github.com> Date: Tue, 14 Jan 2025 16:09:08 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0cec=E8=B4=A8=E6=8A=BC?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api.server.ts | 2 + src/controllers/simplestake.controller.ts | 44 +++++++++++++++++++ src/models/stake/CecTvl.ts | 47 +++++++++++++++++++++ src/schedule/stake.schedule.ts | 51 +++++++++++++++++++++++ src/scripts/batch_mail.ts | 41 +++++++++++------- src/services/chain.svr.ts | 14 +++++++ src/utils/utcdate.util.ts | 7 ++++ 7 files changed, 190 insertions(+), 16 deletions(-) create mode 100644 src/controllers/simplestake.controller.ts create mode 100644 src/models/stake/CecTvl.ts create mode 100644 src/schedule/stake.schedule.ts diff --git a/src/api.server.ts b/src/api.server.ts index 95e41d3..d42d0f9 100644 --- a/src/api.server.ts +++ b/src/api.server.ts @@ -11,6 +11,7 @@ import { RouterMap, ZRedisClient } from 'zutils' import { SyncLocker } from 'common/SyncLocker' import CacheSchedule from 'schedule/cache.schedule' import CodeTaskSchedule from 'schedule/codetask.schedule' +import StakeSchedule from 'schedule/stake.schedule' const zReqParserPlugin = require('plugins/zReqParser') @@ -121,6 +122,7 @@ export class ApiServer { new CacheSchedule().scheduleAll() new CodeTaskSchedule().scheduleAll() new NonceRecordSchedule().scheduleAll() + new StakeSchedule().scheduleAll() } private setErrHandler() { diff --git a/src/controllers/simplestake.controller.ts b/src/controllers/simplestake.controller.ts new file mode 100644 index 0000000..2e6b9f7 --- /dev/null +++ b/src/controllers/simplestake.controller.ts @@ -0,0 +1,44 @@ + +import { BaseController, ROLE_ANON, role, router } from 'zutils' +import { CecTvl } from 'models/stake/CecTvl' +import { retry } from 'zutils/utils/promise.util' +import { queryCecTvl } from 'services/chain.svr' +import { fromWei } from 'zutils/utils/bn.util' +const CHAIN = process.env.CLAIM_CHAIN + +const awardList = [ + { amount: 5000000, reward: 0}, + { amount: 10000000, reward: 400000}, + { amount: 18000000, reward: 900000}, + { amount: 20000000, reward: 2000000}, +] + + +export default class SimpleStakeController extends BaseController { + @role(ROLE_ANON) + @router('get /api/simple_stake/list/:day') + async list(req) { + let day = req.params.day || 0 + let records = await CecTvl.lastNDay(CHAIN, day) + return records.map((record) => record.toJson()) + } + + @role(ROLE_ANON) + @router('get /api/simple_stake/:total') + async info(req) { + const total = req.params.total || '0' + let totalNum = parseFloat(fromWei(total, 'ether')) + totalNum = totalNum < 0 ? 0 : totalNum + totalNum = totalNum > 20000000 ? 20000000 : totalNum + // find the award from the list + let award = awardList.find((item) => totalNum < item.amount) + if (!award) { + award = awardList[awardList.length - 1] + } + let reward = award.reward + let result = (reward / totalNum)/30*360 + result = result || 0 + return result + } + +} diff --git a/src/models/stake/CecTvl.ts b/src/models/stake/CecTvl.ts new file mode 100644 index 0000000..92c6730 --- /dev/null +++ b/src/models/stake/CecTvl.ts @@ -0,0 +1,47 @@ +import { getModelForClass, index, modelOptions, prop, ReturnModelType } from '@typegoose/typegoose' +import { dbconn } from 'decorators/dbconn' +import { BaseModule } from '../Base' + +const ONE_DAY = 24 * 60 * 60 * 1000 + +@dbconn() +@index({ chain: 1, day: -1 }, { unique: true }) +@modelOptions({ + schemaOptions: { collection: 'cec_tvl', timestamps: true }, +}) +export class CecTvlClass extends BaseModule { + @prop({ required: true }) + public chain!: string + @prop({ required: true }) + public day: number + @prop({ required: true }) + public amount_show: number + @prop({ required: true }) + public amount: string + + public static async lastNDay( + this: ReturnModelType, + chain: string, + day: number + ) { + if (day > 0) { + const todayStart = ((Date.now() / ONE_DAY) | 0) * ONE_DAY + const nDayAgo = todayStart - (day - 1) * ONE_DAY + return this.find({ chain, day: {$get: nDayAgo} }).sort({ day: -1 }).exec() + } else { + return this.find({ chain }).sort({ day: -1 }).exec() + } + } + + public toJson() { + return { + day: this.day, + amount: this.amount, + amount_show: this.amount_show + } + } +} + +export const CecTvl = getModelForClass(CecTvlClass, { + existingConnection: CecTvlClass['db'], +}) diff --git a/src/schedule/stake.schedule.ts b/src/schedule/stake.schedule.ts new file mode 100644 index 0000000..ca8a6c9 --- /dev/null +++ b/src/schedule/stake.schedule.ts @@ -0,0 +1,51 @@ +import { ACTIVITY_NAME } from 'common/Constants' +import logger from 'logger/logger' + +import { retry } from 'zutils/utils/promise.util' +import { fromWei } from 'zutils/utils/bn.util' + +import * as schedule from 'node-schedule' +import { queryCecTvl } from 'services/chain.svr' +import { formatDate, getDayBegin, yesterday } from 'utils/utcdate.util' +import { singleton } from 'zutils' +import { CecTvl } from 'models/stake/CecTvl' + +const CHAIN = process.env.CLAIM_CHAIN +/** + * 每日定时更新TVL缓存 + */ +@singleton +export default class StakeSchedule { + async updateCache() { + try { + let preday = getDayBegin(yesterday(new Date())) + + const res = await retry(() => queryCecTvl(), { maxRetries: 3, whitelistErrors: [] }) + if (res.error) { + throw new Error(res.error.message) + } + let tvl = BigInt(res.result) + let tvlShow = fromWei(tvl, 'ether') + await CecTvl.insertOrUpdate( + {chain: CHAIN, day: (preday.getTime() / 1000) | 0}, + {amount_show: parseFloat(tvlShow), amount: tvl.toString()} + ) + } catch (err) { + logger.warn(err) + } + } + scheduleAll() { + const rule = new schedule.RecurrenceRule(); + rule.hour = 0; + rule.minute = 0; + rule.tz = 'Etc/UTC'; + schedule.scheduleJob(rule, async () => { + await this.updateCache() + }) + this.updateCache() + } +} + + + + diff --git a/src/scripts/batch_mail.ts b/src/scripts/batch_mail.ts index 622a451..0eec8c1 100644 --- a/src/scripts/batch_mail.ts +++ b/src/scripts/batch_mail.ts @@ -13,6 +13,7 @@ const mailHtml = ` + Counter Fire Vietnam Tournament: Join the Battle for Glory and Rewards!