添加cec质押相关接口

This commit is contained in:
CounterFire2023 2025-01-14 16:09:08 +08:00
parent 8657ac2af7
commit 99d1241123
7 changed files with 190 additions and 16 deletions

View File

@ -11,6 +11,7 @@ import { RouterMap, ZRedisClient } from 'zutils'
import { SyncLocker } from 'common/SyncLocker' import { SyncLocker } from 'common/SyncLocker'
import CacheSchedule from 'schedule/cache.schedule' import CacheSchedule from 'schedule/cache.schedule'
import CodeTaskSchedule from 'schedule/codetask.schedule' import CodeTaskSchedule from 'schedule/codetask.schedule'
import StakeSchedule from 'schedule/stake.schedule'
const zReqParserPlugin = require('plugins/zReqParser') const zReqParserPlugin = require('plugins/zReqParser')
@ -121,6 +122,7 @@ export class ApiServer {
new CacheSchedule().scheduleAll() new CacheSchedule().scheduleAll()
new CodeTaskSchedule().scheduleAll() new CodeTaskSchedule().scheduleAll()
new NonceRecordSchedule().scheduleAll() new NonceRecordSchedule().scheduleAll()
new StakeSchedule().scheduleAll()
} }
private setErrHandler() { private setErrHandler() {

View 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
}
}

View 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'],
})

View 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()
}
}

View File

@ -13,6 +13,7 @@ const mailHtml = `
<html xmlns:th="http://www.thymeleaf.org"> <html xmlns:th="http://www.thymeleaf.org">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>Counter Fire Vietnam Tournament: Join the Battle for Glory and Rewards! </title>
<style type="text/css"> <style type="text/css">
body { background-color: #fff; color: #333; } body { background-color: #fff; color: #333; }
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
@ -30,23 +31,31 @@ const mailHtml = `
<body> <body>
<div class="email-container"> <div class="email-container">
<p>Dear Counter Fire Community,</p> <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>We are thrilled to announce the launch of the <b>first-ever Counter Fire Vietnam Tournament</b>! </p>
<p>This update will introduce exciting new features and improvements designed to enhance your gaming experience. Heres what you can expect: 🎮</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/medium_poster_a.jpg" /></p> <p><img src="https://res.counterfire.games/img/vietnam_photo.jpg" /></p>
<p>&nbsp;</p> <p>&nbsp;</p>
<h1>Update Highlights:</h1> <h2>🏆The rules for the tournament are as follows:</h2>
<h2>🔥 Piggy Bank:</h2> <ol>
<p>With this new feature, everyone can earn Gold Coins for free!</p> <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>
<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> <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>
<h2>🌟 Newcomer Tasks:</h2> <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>A 7-day task system has been introduced to help new players get up to speed. Complete tasks to earn generous rewards! 🎁</p> <p><b>Cumulative Ranking 1st place: </b>the latest iPhone 16, plus NFT Heroes, Game Diamonds and more!</p>
<h2>🛒 Hashrate Store:</h2> <p><b>Cumulative Ranking 2nd to 5th place:</b> 150 USDC Each</p></li>
<p>The Hashrate Store is online now! Players can use in-game currency to purchase items and enhance your gaming journey! 🤑</p> <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> <h2>Note:</h2>
<hr/> <p>1The 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>
<h2>Big news coming - CF Season 1 Tournament! Stay tuned for Oct 28th! </h2> <p>2This 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>Thank you for your continued support of Counter Fire! We cant wait to see you in-game and hope you enjoy the new features and improvements! Happy gaming! 🎉</p> <p>3How 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 competitionits 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? Dont 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>Best Regards,</p>
<p>The Counter Fire Team</p> <p>The Counter Fire Team</p>
<p>&nbsp;</p> <p>&nbsp;</p>
@ -103,7 +112,7 @@ const sendOneMail = async (to) => {
const msgData = { const msgData = {
from: 'Counter Fire <noreply@counterfire.games>', from: 'Counter Fire <noreply@counterfire.games>',
to: to, to: to,
subject: 'Exciting Hot Update for Counter Fire! ', subject: 'Counter Fire Vietnam Tournament: Join the Battle for Glory and Rewards!',
text: mailText, text: mailText,
html: mailHtml, html: mailHtml,
}; };

View File

@ -247,3 +247,17 @@ export const buildTokenClaimData = async ({
console.log(JSON.stringify(params)) console.log(JSON.stringify(params))
return contract.populateTransaction['claim'](...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)
}

View File

@ -52,3 +52,10 @@ export const getMonthBegin = (date: Date): Date => {
const month = date.getUTCMonth() const month = date.getUTCMonth()
return new Date(year, month, 1) 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()
}