添加cec质押相关接口
This commit is contained in:
parent
8657ac2af7
commit
99d1241123
@ -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() {
|
||||
|
44
src/controllers/simplestake.controller.ts
Normal file
44
src/controllers/simplestake.controller.ts
Normal file
@ -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
|
||||
}
|
||||
|
||||
}
|
47
src/models/stake/CecTvl.ts
Normal file
47
src/models/stake/CecTvl.ts
Normal file
@ -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<typeof CecTvlClass>,
|
||||
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'],
|
||||
})
|
51
src/schedule/stake.schedule.ts
Normal file
51
src/schedule/stake.schedule.ts
Normal file
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -13,6 +13,7 @@ const mailHtml = `
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Counter Fire Vietnam Tournament: Join the Battle for Glory and Rewards! </title>
|
||||
<style type="text/css">
|
||||
body { background-color: #fff; color: #333; }
|
||||
@media (prefers-color-scheme: dark) {
|
||||
@ -30,23 +31,31 @@ const mailHtml = `
|
||||
<body>
|
||||
<div class="email-container">
|
||||
<p>Dear Counter Fire Community,</p>
|
||||
<p>We are thrilled to announce that a hot update will be implemented on <b>Oct 23rd 14:00PM (UTC +8)</b>! </p>
|
||||
<p>This update will introduce exciting new features and improvements designed to enhance your gaming experience. Here’s what you can expect: 🎮✨</p>
|
||||
<p><img src="https://res.counterfire.games/img/medium_poster_a.jpg" /></p>
|
||||
<p>We are thrilled to announce the launch of the <b>first-ever Counter Fire Vietnam Tournament</b>! </p>
|
||||
<p>Starting on <b>October 28 at 8:00 PM UTC+7</b>, this event will offer a month-long competitive experience, packed with action, rewards, and unforgettable battles. Get ready to dive in, compete against others, and showcase your skills!</p>
|
||||
<p><img src="https://res.counterfire.games/img/vietnam_photo.jpg" /></p>
|
||||
<p> </p>
|
||||
<h1>Update Highlights:</h1>
|
||||
<h2>🔥 Piggy Bank:</h2>
|
||||
<p>With this new feature, everyone can earn Gold Coins for free!</p>
|
||||
<p>N-rank heroes have 3 times to play gold, the gold obtained after using it in GOLD mode will be stored in the piggy bank, which can be opened once a day through “smash” or completing tasks to get a certain amount of gold. The number of times will be refreshed at 0:00 UTC, and the number of times you have not opened the pot on that day will be zeroed out after the refreshing.💪</p>
|
||||
<h2>🌟 Newcomer Tasks:</h2>
|
||||
<p>A 7-day task system has been introduced to help new players get up to speed. Complete tasks to earn generous rewards! 🎁</p>
|
||||
<h2>🛒 Hashrate Store:</h2>
|
||||
<p>The Hashrate Store is online now! Players can use in-game currency to purchase items and enhance your gaming journey! 🤑</p>
|
||||
<h2>🏆The rules for the tournament are as follows:</h2>
|
||||
<ol>
|
||||
<li><b>Duration:</b> The Tournament will take place from October 28 to November 24, 2024 from 8:00 to 10:00 pm (UTC +7) every night!</li>
|
||||
<li><b>Rules:</b> Players will be automatically entered into the Tournament by downloading Counter Fire and participating in PVP games during the event time. They will have the chance to win up to 2,000 USDC in the weekly prize pool and 4,000 USDC in the cumulative leaderboard.</li>
|
||||
<li><p><b>Rewards:</b> <b>80 USDC</b> for the top 5 players each week and more for the top 5 players in the cumulative leaderboard!</p>
|
||||
<p><b>Cumulative Ranking 1st place: </b>the latest iPhone 16, plus NFT Heroes, Game Diamonds and more!</p>
|
||||
<p><b>Cumulative Ranking 2nd to 5th place:</b> 150 USDC Each</p></li>
|
||||
<li><p><b>Special Rewards: Statue of Glory (SOG)</b></p>
|
||||
<p>In the main interface of the game, the avatars and names of the top three players in the weekly leaderboard will be displayed. </p>
|
||||
<p>After clicking on them, you can also check the detailed information of the top three players, which will show the glory experience of players in Counter Fire!</p>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<p>More details: <a href="https://link.medium.com/PxFpR2CsTNb">https://link.medium.com/PxFpR2CsTNb</a></p>
|
||||
<hr/>
|
||||
<h2>Big news coming - CF Season 1 Tournament! Stay tuned for Oct 28th! </h2>
|
||||
<p>Thank you for your continued support of Counter Fire! We can’t wait to see you in-game and hope you enjoy the new features and improvements! Happy gaming! 🎉❤️</p>
|
||||
<h2>Note:</h2>
|
||||
<p>1)The Cumulative Leaderboard rewards are almost double the weekly rewards, so the earlier you join, the higher your score and the better your chances of winning more rewards!</p>
|
||||
<p>2)This is the Vietnam tour, so the game server is only open in Vietnam, we will explore more regions in the next tour, so stay tuned!</p>
|
||||
<p>3)How To Earn Gold Coins For Free:<a href="https://link.medium.com/cW28EZLb3Nb">https://link.medium.com/cW28EZLb3Nb</a></p>
|
||||
<p>More details: <a href="https://link.medium.com/EC7a8auq3Nb">https://link.medium.com/EC7a8auq3Nb</a></p>
|
||||
<p>This tournament is more than just a competition—it’s a platform offering players a chance to earn additional rewards. Beyond this event, players can use referral codes to invite friends and earn extra rewards by teaming up. </p>
|
||||
<p>Worried about joining late? Don’t be! New players can take advantage of the 7-Day Task for Newcomers to earn extra items and level up their characters.</p>
|
||||
<p><b>👏Pick your hero, gear up with your weapons, and take on the tournament for your chance to win rewards!</b></p>
|
||||
<p>Best Regards,</p>
|
||||
<p>The Counter Fire Team</p>
|
||||
<p> </p>
|
||||
@ -103,7 +112,7 @@ const sendOneMail = async (to) => {
|
||||
const msgData = {
|
||||
from: 'Counter Fire <noreply@counterfire.games>',
|
||||
to: to,
|
||||
subject: 'Exciting Hot Update for Counter Fire! ',
|
||||
subject: 'Counter Fire Vietnam Tournament: Join the Battle for Glory and Rewards!',
|
||||
text: mailText,
|
||||
html: mailHtml,
|
||||
};
|
||||
|
@ -247,3 +247,17 @@ export const buildTokenClaimData = async ({
|
||||
console.log(JSON.stringify(params))
|
||||
return contract.populateTransaction['claim'](...params)
|
||||
}
|
||||
|
||||
const CONTRACT_STAKE = process.env.STAKE_CONTRACT
|
||||
const STAKE_RPC = process.env.STAKE_RPC
|
||||
export const queryCecTvl = async () => {
|
||||
const params = [
|
||||
{
|
||||
data: '0x817b1cd2',
|
||||
from: CONTRACT_STAKE,
|
||||
to: CONTRACT_STAKE,
|
||||
},
|
||||
'latest',
|
||||
]
|
||||
return requestChain(STAKE_RPC, 'eth_call', params)
|
||||
}
|
@ -52,3 +52,10 @@ export const getMonthBegin = (date: Date): Date => {
|
||||
const month = date.getUTCMonth()
|
||||
return new Date(year, month, 1)
|
||||
}
|
||||
|
||||
// get begin of today
|
||||
export const todayStart = (): number => {
|
||||
const date = new Date()
|
||||
date.setUTCHours(0, 0, 0, 0)
|
||||
return date.getTime()
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user