From 383e24fbfac8a2a3623a785540baf70ee37cca64 Mon Sep 17 00:00:00 2001 From: chaosBreaking Date: Sun, 8 Sep 2019 17:24:36 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=85=85=E5=80=BC=E6=9F=A5=E8=AF=A2+?= =?UTF-8?q?=E5=88=B7=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/constant.js | 3 +- src/common/deposit.js | 34 ++++++++++++++++++ src/modules/fund/fund.controller.js | 50 +++++++++++++++++--------- src/modules/fund/fund.handler.js | 28 ++++++++++++--- src/modules/fund/fund.model.js | 54 +++++++++++++++++++++-------- src/modules/fund/fund.service.js | 2 +- src/modules/user/user.controller.js | 2 +- src/utils/date.js | 34 ++++++++++++++++++ src/utils/erc20.js | 6 ++-- 9 files changed, 173 insertions(+), 40 deletions(-) create mode 100644 src/common/deposit.js create mode 100644 src/utils/date.js diff --git a/src/common/constant.js b/src/common/constant.js index d03dd48..6642841 100644 --- a/src/common/constant.js +++ b/src/common/constant.js @@ -1,5 +1,6 @@ 'use strict'; module.exports = { - USDTAddr: '0xdac17f958d2ee523a2206206994597c13d831ec7' + USDTAddr: '0xdac17f958d2ee523a2206206994597c13d831ec7', + startBlock: 6327420 }; \ No newline at end of file diff --git a/src/common/deposit.js b/src/common/deposit.js new file mode 100644 index 0000000..d440261 --- /dev/null +++ b/src/common/deposit.js @@ -0,0 +1,34 @@ +'use strict'; +const { ERC20 } = require('../utils/erc20'); +const { USDTAddr, startBlock } = require('./constant'); + +const getUSDTTxList = async address => { + if (!address) return null; + const res = await ERC20.getActions(address, USDTAddr, startBlock).catch(err => { + if (err) return []; + }); + return res; +}; + +const parseUsdtTx = txList => { + if (!txList || !Array.isArray(txList)) return []; + return txList.map(tx => { + return { + amount: +tx.value, + hash: tx.hash, + blockNumber: tx.blockNumber + }; + }); +}; + +const getNewDepositTx = (usdtTx = [], fundList = []) => { + if (fundList.length > usdtTx.length) return null; + // fundList的顺序应该与usdtTx的顺序一致,所以只要截取新的 + const newUsdtTxList = usdtTx.slice(fundList.length); + return parseUsdtTx(newUsdtTxList); +}; + +module.exports = { + getUSDTTxList, + getNewDepositTx +}; \ No newline at end of file diff --git a/src/modules/fund/fund.controller.js b/src/modules/fund/fund.controller.js index a286592..9aeaab8 100644 --- a/src/modules/fund/fund.controller.js +++ b/src/modules/fund/fund.controller.js @@ -10,6 +10,8 @@ const actionFilter = 'id type amount detail op createdAt'; const { inject } = require('../../common/Provider'); const ETH = require('../../utils/erc20').ERC20; const { USDTAddr } = require('../../common/constant'); +const { calRevenueLastday, getActiveFund } = require('./fund.handler'); +const { getDate } = require('../../utils/date'); const depositCoinsList = [{ id: 'usdtBTC', @@ -191,14 +193,40 @@ module.exports = { async refreshFund (req, res) { // todo: 要求刷新程序去刷新 const { userId } = res.locals.user; + const { inviter } = req.query; const fund = await Fund.findOne({ userId }).exec(); const tokenAddress = fund && fund.tokenAddress; if(!tokenAddress || !tokenAddress['usdtETH']) return res.json({ code: 0, data: fund.fundList }); - const txActions = await ETH.getActions(tokenAddress['usdtETH'], USDTAddr); - return this.getFundList(req, res); + const { hasNew, list } = fund.hasNewDeposit(); + if (!hasNew) return res.json({ + code: 0, + msg: '刷新成功', + data: {} + }); + const [ start, end ] = getDate(1); + const [newFund, actions] = await Promise.all([ + fund.addFund(list, { inviter }), + Action.find({ userId, type: 1, createdAt: { $gt: start, $lt: end } }) + ]); + // 计算昨日收益 + let revenueLastday = calRevenueLastday(actions); + // 筛选有效矿晶 + let activeFund = getActiveFund(fund.fundList); + return res.json({ + code: 0, + msg: '刷新成功', + data: { + list: newFund.fundList, + basic: { + activeFund, + revenueLastday, + revenueAll: newFund.fundSum + } + } + }); }, async getFundList (req, res) { const { userId } = res.locals.user; @@ -218,22 +246,12 @@ module.exports = { async getBasicInfo (req, res) { const { userId } = res.locals.user; return Fund.findOne({userId}).then(async fund => { - const start = ''; // 前天 - const end = ''; // 昨天 + const [ start, end ] = getDate(1); const actions = await Action.find({ userId, type: 1, createdAt: { $gt: start, $lt: end } }).exec(); // 计算昨日收益 - let revenueLastday = 0; - if (actions && actions.length > 0) { - for (let i = actions.length; i >= 0; i--) { - actions[i] && (revenueLastday += actions[i] && +actions[i].amount || 0); - } - } - // 筛选有效矿晶 - let activeFund = 0; - for (let i = fund.fundList.length; i >= 0; i--) { - const fundItem = fund.fundList[i]; - fundItem && (activeFund += fundItem.status === 1 ? +fundItem.amount : 0); - } + let revenueLastday = calRevenueLastday(actions); + // 筛选有效矿晶 + let activeFund = getActiveFund(fund.fundList); return res.json({ code: 0, data: { diff --git a/src/modules/fund/fund.handler.js b/src/modules/fund/fund.handler.js index e6724db..4c83a30 100644 --- a/src/modules/fund/fund.handler.js +++ b/src/modules/fund/fund.handler.js @@ -7,13 +7,16 @@ const DayLong = 24 * 60 * 60 * 1000; * 2 不可用,已耗尽 */ class Fund { - constructor (amount) { + constructor (data) { + const { amount, blockNumber, hash } = data; this.amount = +amount; + this.status = 0; + this.blockNumber = blockNumber; + this.blockHash = hash; const now = new Date(); const exp = calExpirePeriod(amount); this.createdAt = now.toISOString(); this.expiresAt = new Date(now.getTime() + exp * DayLong); - this.status = 0; } } const calExpirePeriod = amount => { @@ -37,7 +40,24 @@ const calExpirePeriod = amount => { }; module.exports = { - createNewFund (amount = 0) { - return new Fund(amount); + createNewFund (txData) { + return new Fund(txData); + }, + calRevenueLastday (actionList = []) { + let revenueLastday = 0; + if (actionList && actionList.length > 0) { + for (let i = actionList.length; i >= 0; i--) { + actionList[i] && (revenueLastday += actionList[i] && +actionList[i].amount || 0); + } + } + return revenueLastday; + }, + getActiveFund (fundList) { + let activeFund = 0; + for (let i = fundList.length; i >= 0; i--) { + const fundItem = fundList[i]; + fundItem && (activeFund += fundItem.status === 1 ? +fundItem.amount : 0); + } + return activeFund; } }; \ No newline at end of file diff --git a/src/modules/fund/fund.model.js b/src/modules/fund/fund.model.js index c720e2d..fc80624 100644 --- a/src/modules/fund/fund.model.js +++ b/src/modules/fund/fund.model.js @@ -4,6 +4,7 @@ const mongoose = require('mongoose'); const ASSETTYPES = ['gin', 'vic', 'usdtBTC', 'usdtETH', 'usdtTRX']; const { createAction } = require('../action/action.handler'); const { createNewFund } = require('./fund.handler'); +const { getNewDepositTx, getUSDTTxList } = require('../../common/deposit'); const FundSchema = new mongoose.Schema({ userId: { @@ -61,8 +62,20 @@ const FundSchema = new mongoose.Schema({ const FundModel = mongoose.model('Fund', FundSchema); + +FundModel.prototype.hasNewDeposit = async function () { + if (this.tokenAddress.usdtETH) { + const usdtTx = await getUSDTTxList(this.tokenAddress.usdtETH); + const fundList = this.fundList; + const newDepositList = getNewDepositTx(usdtTx, fundList); + if (newDepositList && newDepositList.length > 0) + return { hasNew: true, list: newDepositList }; + } + return { hasNew: false }; +}; + /** -[incFund] : 向用户添加矿晶,在用户充值USDT时调用!!!! +[addFund] : 向用户添加矿晶,在用户充值USDT时调用!!!! * 当一个用户充值, • 4% 给上面第一个 金 或 银 或 铜 会员 • 3% @@ -70,34 +83,47 @@ const FundModel = mongoose.model('Fund', FundSchema); • 如果直接上家不是金,就平分 3% 给上线所有银会员 • 2% 给上线所有金会员平分 */ -FundModel.prototype.incFund = async function (amount, option = {}) { - if (!amount || !Number.isFinite(amount) || amount <= 0) return null; +FundModel.prototype.addFund = async function (txlist = [], option) { + let newSum = 0; + const actionPromiseList = []; + const newFundList = txlist.map(txObj => { + newSum += +txObj.amount; + const action = createAction(0, { + userId: this.userId, + amount: txObj.amount, + tokenType: 'vic', // 目前设定只能挖出矿晶vic + remain: this.asset + }); + actionPromiseList.push(action.save()); + return createNewFund(txObj); + }); // 1.注入资金 - const newFund = createNewFund(amount); const res = await FundModel.findByIdAndUpdate(this.id, { $push: { - fundList: newFund + fundList: newFundList }, $inc: { - fundSum: amount + fundSum: newSum }, $set: { lastDeposit: new Date().toISOString() } // eslint-disable-next-line no-unused-vars }, { ...option, returnOriginal: false }).exec().catch(err => null); + // 2.记录action - const action = createAction(0, { - userId: this.userId, - amount, - tokenType: 'vic', // 目前设定只能挖出矿晶vic - remain: this.asset - }); - await action.save().catch(err => { + Promise.all(actionPromiseList).catch(err => { throw new Error('充值行为记录失败', err.errmsg); }); - // 3.奖励团队 + // 3.增加上家团队总额 + FundModel.findOneAndUpdate({ userId: option.inviter }, { + $inc: { + groupFundSum: newSum + } + }); + // 4.奖励团队 + // todo return res; }; FundModel.prototype.increase = async function (assetName, amount, option = {}) { diff --git a/src/modules/fund/fund.service.js b/src/modules/fund/fund.service.js index 6e56f41..f403e52 100644 --- a/src/modules/fund/fund.service.js +++ b/src/modules/fund/fund.service.js @@ -45,7 +45,7 @@ const services = [ }, { indexRoute: '/mine', - url: '/refreshFund', + url: '/refresh', method: 'GET', controller: controller.refreshFund }, diff --git a/src/modules/user/user.controller.js b/src/modules/user/user.controller.js index 90324d5..d1a5d21 100644 --- a/src/modules/user/user.controller.js +++ b/src/modules/user/user.controller.js @@ -8,7 +8,7 @@ module.exports = { changePwd, async getUserInfo (req, res) { const { userId } = res.locals.user; - return User.findById(userId, 'id nickname phone inviteCode').then(data => { + return User.findById(userId, 'id nickname phone inviteCode inviter').then(data => { res.json({ code: 0, msg: 'success', diff --git a/src/utils/date.js b/src/utils/date.js new file mode 100644 index 0000000..c119489 --- /dev/null +++ b/src/utils/date.js @@ -0,0 +1,34 @@ +'use strict'; + +module.exports = { + getDate(count) { + // 拼接时间 + const time1 = new Date(); + const time2 = new Date(); + if (count === 1) { + time1.setTime(time1.getTime() - (24 * 60 * 60 * 1000)); + } else { + if (count >= 0) { + time1.setTime(time1.getTime()); + } else { + if (count === -2) { + time1.setTime(time1.getTime() + (24 * 60 * 60 * 1000) * 2); + } else { + time1.setTime(time1.getTime() + (24 * 60 * 60 * 1000)); + } + } + } + + const Y1 = time1.getFullYear(); + const M1 = ((time1.getMonth() + 1) > 9 ? (time1.getMonth() + 1) : '0' + (time1.getMonth() + 1)); + const D1 = (time1.getDate() > 9 ? time1.getDate() : '0' + time1.getDate()); + const timer1 = Y1 + '-' + M1 + '-' + D1 + ' ' + '23:59:59'; // 当前时间 + + time2.setTime(time2.getTime() - (24 * 60 * 60 * 1000 * count)); + const Y2 = time2.getFullYear(); + const M2 = ((time2.getMonth() + 1) > 9 ? (time2.getMonth() + 1) : '0' + (time2.getMonth() + 1)); + const D2 = (time2.getDate() > 9 ? time2.getDate() : '0' + time2.getDate()); + const timer2 = Y2 + '-' + M2 + '-' + D2 + ' ' + '00:00:00'; // 之前的7天或者30天 + return [timer2, timer1]; + } +}; \ No newline at end of file diff --git a/src/utils/erc20.js b/src/utils/erc20.js index a7b4b07..8ad5b32 100644 --- a/src/utils/erc20.js +++ b/src/utils/erc20.js @@ -5,7 +5,7 @@ const axios = require('axios'); const crypto = require('./crypto'); const ethers = require('ethers'); -const ethio = require('etherscan-api').init('E3ZFFAEMNN33KX4HHVUZ4KF8XY1FXMR4BI'); +const ethio = require('etherscan-api').init('E3ZFFAEMNN33KX4HHVUZ4KF8XY1FXMR4BI', 'ropsten'); require('setimmediate'); @@ -37,8 +37,8 @@ class ERC20 extends ethers.Wallet { }; return parseInt((await axios.post(ETH_NODE, queryData)).data.result); } - static async getActions(address, contractAddress) { - let tx = await ethio.account.tokentx(address, contractAddress); + static async getActions(address, contractAddress, startBlock = 0) { + let tx = await ethio.account.tokentx(address, contractAddress, startBlock); if (tx && tx.message === "OK") return tx.result; else return [];