Merge branch 'vic' of tac/vic.server into master

This commit is contained in:
nova.xu
2019-10-27 11:47:11 +00:00
committed by Gogs
9 changed files with 255 additions and 142 deletions

89
clean.js Normal file
View File

@@ -0,0 +1,89 @@
'use strict';
const mongoose = require('mongoose');
const Fund = require('./src/modules/fund/fund.model');
const Action = require('./src/modules/action/action.model');
const PrettyStream = require('bunyan-pretty-colors');
const bunyan = require('bunyan');
const path = require('path');
const fs = require('fs');
const prettyStdOut = new PrettyStream();
if (!fs.existsSync('clean')) {
fs.mkdirSync('clean');
}
const logger = function (option) {
option = option || {};
return bunyan.createLogger({
name: "log",
src: false,
streams: [
{
level: 'info',
stream: prettyStdOut
},
{
level: 'info',
type: 'rotating-file',
path: path.join(option.root, option.file || 'info.log'),
period: '1d', // daily rotation
count: 365 // keep 30 days
}
]
});
};
const filename = 'clean' + new Date().getFullYear() + new Date().getMonth() + new Date().getDate();
const mylog = logger(({ root: 'clean', file: filename }));
const probe = {
currentIndex: 0
};
async function clean () {
let allFund = await Fund.find({ fundSum: { $gt: 0 } });
// 批量更新,每次十个
for (let currentIndex = 0; currentIndex < allFund.length; currentIndex++) {
const userFund = allFund[currentIndex];
const fundList = userFund.fundList;
const boughtAmountSum = fundList.reduce((sum, fund) => sum + +fund.amount, 0);
const releasedAmout = (await Action.find({ type: '1', userId: userFund.userId })).reduce((sum, action) => sum + +action.amount, 0);
const rest = boughtAmountSum - releasedAmout;
mylog.info('No. ', currentIndex, '用户' + userFund.userId, '剩余 ', rest);
const vic = userFund.asset.vic || 0;
const newFund = vic + rest;
await Fund.findByIdAndUpdate(userFund.id, { vicFundSum: newFund, 'asset.vic': 0, 'asset.usdt': 0, fundList: [], snapshot: { asset: userFund.asset, fundList } });
probe.currentIndex = currentIndex;
}
}
const start = async (job, done) => {
const SysConfig = require('./configSec');
mongoose.set('useCreateIndex', true);
const { DB_USER_NAME, DB_PASSWD, DB_HOST, DB_PORT, DB_NAME } = SysConfig;
const db = mongoose.connection;
db.on('error', mylog.error);
db.once('open', function() {
mylog.info('数据库连接成功...');
});
mylog.info('开始连接数据库...');
await mongoose.connect(`mongodb://${DB_USER_NAME}:${DB_PASSWD}@${DB_HOST}:${DB_PORT}/${DB_NAME}`, {
useNewUrlParser: true,
bufferMaxEntries: 0,
autoReconnect: true,
useFindAndModify: false,
useUnifiedTopology: true
});
const beforeExit = async (msg) => {
mylog.info('意外退出', msg);
mylog.info('进行到第'+ probe.currentIndex + '个用户');
process.exit(0);
};
process.on('SIGINT', beforeExit);
process.on('uncaughtException', beforeExit);
process.on('unhandledRejection', beforeExit);
typeof process.send === 'function' && process.send('子进程开始执行mine');
clean(job, done);
typeof process.send === 'function' && process.send('子进程mine执行完毕');
process.exit();
};
start();

View File

@@ -2,5 +2,8 @@
module.exports = { module.exports = {
USDTAddr: '0xdac17f958d2ee523a2206206994597c13d831ec7', USDTAddr: '0xdac17f958d2ee523a2206206994597c13d831ec7',
startBlock: 8510200 VICAddr: '0xA5D1Eb8bBB42b7f2EBBebF174B3966510243F30c',
startBlock: 8510200,
VIC_DECIMAL: 1e18,
USDT_DECIMAL: 1e6,
}; };

View File

@@ -1,6 +1,6 @@
'use strict'; 'use strict';
const { ERC20 } = require('../utils/erc20'); const { ERC20 } = require('../utils/erc20');
const { USDTAddr, startBlock } = require('./constant'); const { USDTAddr, VICAddr, startBlock, VIC_DECIMAL, USDT_DECIMAL } = require('./constant');
const getUSDTTxList = async address => { const getUSDTTxList = async address => {
if (!address) return null; if (!address) return null;
@@ -9,23 +9,43 @@ const getUSDTTxList = async address => {
}); });
return res.filter(tx => tx.tokenName === 'Tether USD' && tx.tokenSymbol === 'USDT' && tx.to === address && tx.from !== address); //只取转入到本地址的 return res.filter(tx => tx.tokenName === 'Tether USD' && tx.tokenSymbol === 'USDT' && tx.to === address && tx.from !== address); //只取转入到本地址的
}; };
const getVICTxList = async address => {
if (!address) return null;
const res = await ERC20.getActions(address, VICAddr, startBlock).catch(err => {
if (err) return [];
});
return res.filter(tx => tx.tokenName === 'Value of Individual' && tx.tokenSymbol === 'VIC' && tx.to === address && tx.from !== address); //只取转入到本地址的
};
const parseUsdtTx = txList => { const parseETHTx = txList => {
if (!txList || !Array.isArray(txList)) return []; if (!txList || !Array.isArray(txList)) return [];
return txList.map(tx => { return txList.map(tx => {
tx.amount = (+tx.value) / 1e6; tx.amount = (+tx.value) / VIC_DECIMAL;
return tx; return tx;
}); });
}; };
// usdt
const getNewDepositTx = (usdtTx = [], fundList = []) => { const getNewUSDTDepositTx = (usdtTx = [], fundList = []) => {
if (fundList.length > usdtTx.length) return null; if (fundList.length > usdtTx.length) return null;
// fundList的顺序应该与usdtTx的顺序一致所以只要截取新的 // fundList的顺序应该与usdtTx的顺序一致所以只要截取新的
const newUsdtTxList = usdtTx.slice(fundList.length); const newUsdtTxList = usdtTx.slice(fundList.length);
return parseUsdtTx(newUsdtTxList); return parseETHTx(newUsdtTxList);
};
// vic
const getNewDepositTx = (vicTx = [], fundList = []) => {
if (fundList.length >= vicTx.length) return null;
const newList = [];
const existedFund = fundList.map(fund => fund.txHash).filter(f => f !== null);
for (let i = 0, len = vicTx.length; i < len; ++i) {
if (!existedFund.includes(vicTx[i].hash)) {
newList.push(vicTx[i]);
}
}
return parseETHTx(newList);
}; };
module.exports = { module.exports = {
getVICTxList,
getUSDTTxList, getUSDTTxList,
getNewDepositTx getNewDepositTx
}; };

View File

@@ -39,7 +39,7 @@ watcher.on('startMine', () => {
mylog.info('挖矿程序执行完毕'); mylog.info('挖矿程序执行完毕');
}); });
rl.on('message', function (msg) { rl.on('message', function (msg) {
mylog.info('MineInfo', msg) mylog.info('MineInfo', msg);
}); });
rl.on('exit', function () { rl.on('exit', function () {
mylog.info('挖矿程序执行完毕'); mylog.info('挖矿程序执行完毕');

View File

@@ -37,82 +37,81 @@ const User = require('../modules/user/user.model');
const Fund = require('../modules/fund/fund.model'); const Fund = require('../modules/fund/fund.model');
const system = require('../modules/system/system.model'); const system = require('../modules/system/system.model');
const { createAction } = require('../modules/action/action.handler'); const { createAction } = require('../modules/action/action.handler');
const revenueLadderSheet = [
{amount: 10000, rate: 0.001},
{amount: 40000, rate: 0.003},
{amount: 50000, rate: 0.006},
{amount: 100000, rate: 0.01},
{amount: 300000, rate: 0.015},
{amount: 500000, rate: 0.018},
{amount: NaN, rate: 0.02}
];
const tokenReleaseRate = 0.02; const probe = {
const inviteReward = 2.5; currentIndex: 0
};
async function awardMine(user, fund) { function awardMine(fund) {
if (!user || !fund || fund.fundList.length === 0) return 0; if (!fund || fund.vicFundSum === 0) return 0;
let sum = 0; let rest = +fund.vicFundSum;
for (let i = 0, len = fund.fundList.length; i < len; ++i) { let revenue = 0;
const released = fund.releasedAmout || 0; for (let level of revenueLadderSheet) {
if (released === fund.releasedAmout) { if (rest - level.amount > 0) {
mylog.info('矿晶失效,开始标记'); revenue += level.amount * level.rate;
await Fund.findByIdAndUpdate(fund.id, { rest -= level.amount;
$set: { } else {
[`fundList.${i}.status`]: 2 //标记失效 revenue += rest * level.rate;
} break;
});
return 0;
} }
const profit = +fund.fundList[i].amount * tokenReleaseRate;
await Fund.findByIdAndUpdate(fund.id, {
$inc: {
[`fundList.${i}.mineCount`]: 1,
[`fundList.${i}.releasedAmout`]: profit,
},
});
sum += profit;
} }
return sum.toFixed(2); return revenue;
}
function awardInvite(user, fund) {
const follerNum = user.group.length || 0;
const hasAwardFoller = fund.option && fund.option.usedGroupReward / 10 || 0; // 求增量: 总额 - 已领取总额(fundSum)
const newFoller = follerNum - hasAwardFoller;
if (newFoller < 0) return 0;
// 挖矿奖励 = 充值金额奖励 + 社区奖励
return (newFoller * inviteReward).toFixed(2);
} }
// fund.option.usedGroupReward : 已领取的社群奖励总额 // fund.option.usedGroupReward : 已领取的社群奖励总额
const doReward = async (user, fund) => { const doReward = async (user, fund) => {
// 1.对于充值的fundList的每一项按照2%进行发放累加到asset.vic添加action类型为1
// 2.对于社团成员进行人头数目按照10vic/人进行奖励累加到asset.vic添加action类型为2
if (!user || !fund) return 0; if (!user || !fund) return 0;
const rewardMine = await awardMine(user, fund); const rewardMine = awardMine(fund);
// const rewardInvite = awardInvite(user, fund); if (rewardMine === 0) return 0;
const rewardInvite = 0;
const reward = +rewardMine + rewardInvite;
mylog.info('挖矿奖励: ', rewardMine); mylog.info('挖矿奖励: ', rewardMine);
mylog.info('社群奖励: ', rewardInvite); rewardMine && await Fund.findByIdAndUpdate(fund.id, {
reward && await Fund.findByIdAndUpdate(fund.id, {
$inc: { $inc: {
'asset.vic': reward, vicFundSum: rewardMine,
'asset.usdt': rewardInvite, // 用来记录所有社群奖励总额
}, },
$set: { $set: {
'option.newFoller': rewardInvite / 5, lastMine: new Date().toISOString()
'option.usedGroupReward': rewardInvite, // 本次的奖励值累加到已领取团队奖励总和内
'lastMine': new Date().toISOString()
} }
}).then(() => { }).then(async () => {
rewardMine > 0 && createAction(1, { rewardMine > 0 && createAction(1, {
userId: user.id, userId: user.id,
tokenType: 'vic', tokenType: 'vic2vic', // 新模式标记
amount: rewardMine, amount: rewardMine,
remain: fund.asset remain: fund.asset
}).save(); }).save();
rewardInvite > 0 && createAction(2, { if (user.inviter) {
userId: user.id, const inviter = await Fund.findOne({ userId: user.inviter });
tokenType: 'vic', if (inviter && +inviter.vicFundSum >= 10000) {
amount: rewardInvite, const rewardInviter = rewardMine * 0.1;
remain: fund.asset Promise.all([
}).save(); Fund.findOneAndUpdate({ userId: user.inviter }, {
$inc: {
vicFundSum: rewardInviter
}
}),
createAction(4, {
userId: user.inviter,
tokenType: 'vic2vic', // 新模式标记
amount: rewardInviter,
remain: fund.asset,
detail: { level: 1, info: '1级奖励' }
}).save()
]).catch((err) => mylog.error(err.errmsg));
}
}
}); });
}; };
const mock = { const mock = {
touch: () => {mylog.info('-----------------\n');}, touch: () => { mylog.info('-----------------\n'); },
done: () => {mylog.info('done');}, done: () => { mylog.info('done'); },
}; };
async function mine (job = mock, done = mock) { async function mine (job = mock, done = mock) {
@@ -137,7 +136,7 @@ async function mine (job = mock, done = mock) {
}); });
// 批量更新,每次十个 // 批量更新,每次十个
for (; currentIndex < allFundNum;) { for (; currentIndex < allFundNum;) {
const userFundList = await Fund.find().sort('_id').limit(10).skip(currentIndex); const userFundList = await Fund.find({ vicFundSum: { $gt: 0 } }).sort('_id').limit(10).skip(currentIndex);
typeof job.touch === 'function' && job.touch(); typeof job.touch === 'function' && job.touch();
if (!userFundList || !Array.isArray(userFundList)) return 0; if (!userFundList || !Array.isArray(userFundList)) return 0;
for (let i = 0, len = userFundList.length; i < len; ++i) { for (let i = 0, len = userFundList.length; i < len; ++i) {
@@ -185,9 +184,7 @@ async function mine (job = mock, done = mock) {
typeof done === 'function' && done('收益计算分配完成'); typeof done === 'function' && done('收益计算分配完成');
process.exit(); process.exit();
} }
const probe = {
currentIndex: 0
};
const start = async (job, done) => { const start = async (job, done) => {
const SysConfig = require('../../configSec'); const SysConfig = require('../../configSec');
mongoose.set('useCreateIndex', true); mongoose.set('useCreateIndex', true);

View File

@@ -11,12 +11,11 @@ const { calRevenueLastday, getActiveFund } = require('./fund.handler');
const { getDate } = require('../../utils/date'); const { getDate } = require('../../utils/date');
const Crypto = require('../../utils/crypto'); const Crypto = require('../../utils/crypto');
const actionFilter = 'id type amount detail op createdAt tokenType'; const actionFilter = 'id type amount detail op createdAt tokenType';
const { USDT2VIC_RATE } = require('./constant');
const depositCoinsList = [{ const depositCoinsList = [{
id: 'usdtETH', id: 'usdtETH',
label: 'usdt', label: 'vic',
rate: USDT2VIC_RATE rate: 1
}]; }];
const withdrawCoinsList = [{ const withdrawCoinsList = [{
id: 'vic', id: 'vic',
@@ -33,11 +32,11 @@ const withdrawCoinsList = [{
module.exports = { module.exports = {
async getFundDetail (req, res) { async getFundDetail (req, res) {
const { userId } = res.locals.user; const { userId } = res.locals.user;
return Fund.findOne({ userId }, 'asset').then(fund => { return Fund.findOne({ userId }, 'vicFundSum').then(fund => {
return res.json({ return res.json({
code: 0, code: 0,
msg: 'success', msg: 'success',
data: fund && fund.asset data: { vic: fund.vicFundSum || 0, usdt: 0 }
}); });
}).catch(err => { }).catch(err => {
mylog.error("[getFundDetail]", err); mylog.error("[getFundDetail]", err);
@@ -123,9 +122,9 @@ module.exports = {
}); });
const [user, fund] = await Promise.all([User.findById(userId), Fund.findOne({ userId })]); const [user, fund] = await Promise.all([User.findById(userId), Fund.findOne({ userId })]);
if ( if (
(coinId === 'vic' && +amount < 30) +amount < 1000
|| ||
+fund.fundSum < 500 +fund.vicFundSum < 1000
|| ||
+user.verifyLevel < 1 +user.verifyLevel < 1
) { ) {
@@ -135,6 +134,12 @@ module.exports = {
error: '不满足提现条件', error: '不满足提现条件',
}); });
} }
const cost = +amount * 1.005;
if (fund.asset && +fund.asset[coinId] < cost) return res.json({
code: 2,
msg: '资金不足',
error: 'insufficient fund'
});
let hashpwd = password; let hashpwd = password;
if (hashpwd.length < 30) { if (hashpwd.length < 30) {
hashpwd = Crypto.hash(password, {hasher: 'md5'}); hashpwd = Crypto.hash(password, {hasher: 'md5'});
@@ -144,16 +149,10 @@ module.exports = {
msg: '资金密码错误', msg: '资金密码错误',
error: '资金密码错误', error: '资金密码错误',
}); });
const cost = +amount * 1.005;
if (fund.asset && +fund.asset[coinId] < cost) return res.json({
code: 2,
msg: '资金不足',
error: 'insufficient fund'
});
const action = createAction(3, { userId, amount, remain: fund.asset, op: 0, detail: { targetAddress, coinId } }); const action = createAction(3, { userId, amount, remain: fund.asset, op: 0, detail: { targetAddress, coinId } });
const ticket = createTicket('withdraw', { userId, amount: +amount, action, targetAddress, coinId }); const ticket = createTicket('withdraw', { userId, amount: +amount, action, targetAddress, coinId });
try { try {
await fund.decrease(coinId, cost); await fund.decFund(cost);
} catch (error) { } catch (error) {
mylog.error('[Fund提现] ', error); mylog.error('[Fund提现] ', error);
action.detail = { error }; action.detail = { error };
@@ -217,12 +216,6 @@ module.exports = {
}; };
}), }),
async getWithdrawCoinsList (req, res) { async getWithdrawCoinsList (req, res) {
// const { userId } = res.locals.user;
// const userFund = await Fund.findOne({userId}).exec();
// const asset = userFund.asset;
// const list = [];
// (asset['vic'] >= 1000) && list.push(withdrawCoinsList[0]);
// (asset['usdt'] > 0 && (!userFund.lastWithdraw.usdt || (new Date() - new Date(userFund.lastWithdraw.usdt)) / (1000 * 3600 * 24 * 7) >= 1)) && list.push(withdrawCoinsList[1]);
return res.json({ return res.json({
code: 0, code: 0,
data: withdrawCoinsList data: withdrawCoinsList
@@ -249,7 +242,8 @@ module.exports = {
// 计算昨日收益 // 计算昨日收益
let revenueLastday = calRevenueLastday(actions); let revenueLastday = calRevenueLastday(actions);
// 筛选有效矿晶 // 筛选有效矿晶
let activeFund = getActiveFund(fund.fundList); // let activeFund = getActiveFund(fund.fundList);
let activeFund = fund.vicFundSum;
let revenueAll = Array.isArray(allAction) && allAction.reduce((pre, cur) => pre + (+cur.amount || 0), 0) || 0; let revenueAll = Array.isArray(allAction) && allAction.reduce((pre, cur) => pre + (+cur.amount || 0), 0) || 0;
revenueAll = revenueAll.toFixed(4); revenueAll = revenueAll.toFixed(4);
return res.json({ return res.json({
@@ -272,7 +266,8 @@ module.exports = {
// 计算昨日收益 // 计算昨日收益
let revenueLastday = calRevenueLastday(actions); let revenueLastday = calRevenueLastday(actions);
// 筛选有效矿晶 // 筛选有效矿晶
let activeFund = getActiveFund(fund.fundList); // let activeFund = getActiveFund(fund.fundList);
let activeFund = fund.vicFundSum;
if (!newFund || !newFund.fundList) newFund = fund; if (!newFund || !newFund.fundList) newFund = fund;
let revenueAll = Array.isArray(allAction) && allAction.reduce((pre, cur) => pre + (+cur.amount || 0), 0) || 0; let revenueAll = Array.isArray(allAction) && allAction.reduce((pre, cur) => pre + (+cur.amount || 0), 0) || 0;
revenueAll = revenueAll.toFixed(4); revenueAll = revenueAll.toFixed(4);
@@ -291,7 +286,7 @@ module.exports = {
}, },
async getFundList (req, res) { async getFundList (req, res) {
const { userId } = res.locals.user; const { userId } = res.locals.user;
return Fund.findOne({userId}, 'fundList').then(fund => { return Fund.findOne({ userId }, 'fundList').then(fund => {
return res.json({ return res.json({
code: 0, code: 0,
data: fund.fundList data: fund.fundList
@@ -310,7 +305,8 @@ module.exports = {
const [ start, end ] = getDate(1); const [ start, end ] = getDate(1);
let now = new Date(); let now = new Date();
// 筛选有效矿晶 // 筛选有效矿晶
let activeFund = getActiveFund(fund.fundList); // let activeFund = getActiveFund(fund.fundList);
let activeFund = fund.vicFundSum;
const actions = await Action.find({ userId, type: 1, createdAt: { $gt: start, $lt: now } }).exec(); const actions = await Action.find({ userId, type: 1, createdAt: { $gt: start, $lt: now } }).exec();
const allAction = await Action.find({ userId, type: 1 }).exec(); const allAction = await Action.find({ userId, type: 1 }).exec();
// 计算昨日收益 // 计算昨日收益

View File

@@ -8,13 +8,13 @@ const DayLong = 24 * 60 * 60 * 1000;
*/ */
class Fund { class Fund {
constructor (data = {}) { constructor (data = {}) {
const { amount, blockNumber, hash = '', blockHash = '', from = '', to = '', timeStamp = '', usdtValue = 0, type = 'deposit' } = data; const { amount, blockNumber, hash = '', blockHash = '', from = '', to = '', timeStamp = '', rawAmount = 0, type = 'deposit' } = data;
this.status = 0; this.status = 0;
this.type = type; this.type = type;
this.amount = +amount; this.amount = +amount;
this.from = from; this.from = from;
this.to = to; this.to = to;
this.usdtValue = usdtValue; this.rawAmount = rawAmount;
this.timeStamp = timeStamp; this.timeStamp = timeStamp;
this.blockNumber = blockNumber; this.blockNumber = blockNumber;
this.blockHash = blockHash; this.blockHash = blockHash;

View File

@@ -4,10 +4,9 @@ const mongoose = require('mongoose');
const ASSETTYPES = ['gin', 'vic', 'usdtBTC', 'usdtETH', 'usdtTRX']; const ASSETTYPES = ['gin', 'vic', 'usdtBTC', 'usdtETH', 'usdtTRX'];
const { createAction } = require('../action/action.handler'); const { createAction } = require('../action/action.handler');
const { createNewFund } = require('./fund.handler'); const { createNewFund } = require('./fund.handler');
const { getNewDepositTx, getUSDTTxList } = require('../../common/deposit'); const { getNewDepositTx, getVICTxList } = require('../../common/deposit');
const User = require('../user/user.model'); const User = require('../user/user.model');
const System = require('../system/system.model');
const { USDT2VIC_RATE } = require('./constant');
const FundSchema = new mongoose.Schema({ const FundSchema = new mongoose.Schema({
userId: { userId: {
@@ -16,6 +15,7 @@ const FundSchema = new mongoose.Schema({
tokenAddress: { tokenAddress: {
type: {}, type: {},
default: { default: {
'vic': '',
'usdtBTC': '', 'usdtBTC': '',
'usdtETH': '', 'usdtETH': '',
'usdtTRX': '' 'usdtTRX': ''
@@ -33,6 +33,11 @@ const FundSchema = new mongoose.Schema({
type: Number, type: Number,
default: 0 default: 0
}, },
// vic兑换的基金
vicFundSum: {
type: Number,
default: 0
},
// asset表示用户的收益包括VIC和团队奖励的USDT // asset表示用户的收益包括VIC和团队奖励的USDT
// vic是挖矿得到的奖励 // vic是挖矿得到的奖励
// usdt是社群奖励后面加上了糖果也代表糖果数量 // usdt是社群奖励后面加上了糖果也代表糖果数量
@@ -44,6 +49,10 @@ const FundSchema = new mongoose.Schema({
} }
}, },
// 团队总充值资产 // 团队总充值资产
groupVicFundSum: {
type: Number,
default: 0
},
groupFundSum: { groupFundSum: {
type: Number, type: Number,
default: 0 default: 0
@@ -77,10 +86,10 @@ const FundModel = mongoose.model('Fund', FundSchema);
FundModel.prototype.hasNewDeposit = async function () { FundModel.prototype.hasNewDeposit = async function () {
if (this.tokenAddress.usdtETH) { if (this.tokenAddress.usdtETH) {
const usdtTx = await getUSDTTxList(this.tokenAddress.usdtETH.address); const vicTx = await getVICTxList(this.tokenAddress.usdtETH.address);
if (usdtTx && usdtTx.length > 0) { if (vicTx && vicTx.length > 0) {
const fundList = this.fundList; const fundList = this.fundList;
const newDepositList = getNewDepositTx(usdtTx, fundList); const newDepositList = getNewDepositTx(vicTx, fundList);
if (newDepositList && newDepositList.length > 0) { if (newDepositList && newDepositList.length > 0) {
mylog.info(`用户${this.userId} 有新的充值记录`); mylog.info(`用户${this.userId} 有新的充值记录`);
return { hasNew: true, list: newDepositList }; return { hasNew: true, list: newDepositList };
@@ -89,16 +98,17 @@ FundModel.prototype.hasNewDeposit = async function () {
} }
return { hasNew: false }; return { hasNew: false };
}; };
const DEFAULT_RATE = 1;
/**
[addFund] : 向用户添加矿晶在用户充值USDT时调用
、 */
FundModel.prototype.addFund = async function (txlist = [], option) { FundModel.prototype.addFund = async function (txlist = [], option) {
let newSum = 0; let newSum = 0;
const VIC_RATE = (await System.findOne({ key: 'VIC_RATE' }).exec().catch(() => {
mylog.error('没有获取到vic兑换比例');
return DEFAULT_RATE;
})) || DEFAULT_RATE;
const actionPromiseList = []; const actionPromiseList = [];
const newFundList = txlist.map(txObj => { const newFundList = txlist.map(txObj => {
txObj.usdtValue = txObj.amount; txObj.rawAmount = txObj.amount; // tx.amout是区块链交易的数值已经除了精度
const depositAmount = +txObj.amount * USDT2VIC_RATE; const depositAmount = +txObj.amount * (Number.isSafeInteger(VIC_RATE) ? VIC_RATE : DEFAULT_RATE);
newSum += depositAmount; newSum += depositAmount;
const action = createAction(0, { const action = createAction(0, {
userId: this.userId, userId: this.userId,
@@ -108,6 +118,7 @@ FundModel.prototype.addFund = async function (txlist = [], option) {
}); });
typeof action.save === 'function' && actionPromiseList.push(action.save()); typeof action.save === 'function' && actionPromiseList.push(action.save());
txObj.amount = depositAmount; // 之后返回fundList里的数值需要把区块链的数值乘以比率 txObj.amount = depositAmount; // 之后返回fundList里的数值需要把区块链的数值乘以比率
txObj.type = 'vic2fund';
return createNewFund({...txObj}); return createNewFund({...txObj});
}); });
// 1.注入资金 // 1.注入资金
@@ -116,13 +127,12 @@ FundModel.prototype.addFund = async function (txlist = [], option) {
fundList: newFundList fundList: newFundList
}, },
$inc: { $inc: {
fundSum: newSum vicFundSum: newSum
}, },
$set: { $set: {
lastDeposit: new Date().toISOString() lastDeposit: new Date().toISOString()
} }
// eslint-disable-next-line no-unused-vars }, { ...option, returnOriginal: false }).exec().catch(err => mylog.error(err.errmsg));
}, { ...option, returnOriginal: false }).exec().catch(err => null);
// 2.记录action // 2.记录action
Promise.all(actionPromiseList).catch(err => { Promise.all(actionPromiseList).catch(err => {
@@ -131,41 +141,12 @@ FundModel.prototype.addFund = async function (txlist = [], option) {
// 3.增加上家团队总额 // 3.增加上家团队总额
option.inviter && FundModel.findOneAndUpdate({ userId: option.inviter }, { option.inviter && FundModel.findOneAndUpdate({ userId: option.inviter }, {
$inc: { $inc: {
groupFundSum: newSum groupVicFundSum: newSum
} }
}).exec(); }).exec();
// 3.对于自己的邀请者进行奖励按照自己充值金额的十分之一累加到邀请人的fundList里类型为1
const myId = this.userId;
User.findById(myId).then(async user => {
if (!user && !user.inviter) return 0;
const award = +newSum * 0.1;
const inviteFund = createNewFund({
type: 'inviteAward',
amount: award,
blockNumber: 'followerReward',
hash: myId
});
User.findByIdAndUpdate(user.inviter, {
$push: {
fundList: inviteFund
}
});
createAction(4, {
userId: user.inviter,
amount: award, // 充值记录的数值仍然是区块链的数值
tokenType: 'vic', // 目前设定只能挖出矿晶vic
remain: this.asset,
detail: {
desc: `${user.id}充值${newSum} 奖励其推荐人${user.inviter}: ${award}矿晶`,
from: myId,
to: user.inviter
}
}).save();
}).catch(err => {
mylog.error(`${myId}充值奖励其推荐人时出错 `, JSON.stringify(err));
});
return res; return res;
}; };
FundModel.prototype.increase = async function (assetName, amount, option = {}) { FundModel.prototype.increase = async function (assetName, amount, option = {}) {
if (!assetName || !amount || amount <= 0 || !Number.isFinite(amount) || !ASSETTYPES.includes(assetName)) return null; if (!assetName || !amount || amount <= 0 || !Number.isFinite(amount) || !ASSETTYPES.includes(assetName)) return null;
const asset = 'asset.' + assetName; const asset = 'asset.' + assetName;
@@ -179,6 +160,7 @@ FundModel.prototype.increase = async function (assetName, amount, option = {}) {
if (res.asset[assetName] < 0) throw new Error('Insufficient funds'); if (res.asset[assetName] < 0) throw new Error('Insufficient funds');
return res; return res;
}; };
FundModel.prototype.decrease = async function (assetName, amount, option) { FundModel.prototype.decrease = async function (assetName, amount, option) {
// 传入的amount应该是大于0的正数 // 传入的amount应该是大于0的正数
if (!assetName || !amount || amount <= 0 || !Number.isFinite(amount) || !ASSETTYPES.includes(assetName)) return null; if (!assetName || !amount || amount <= 0 || !Number.isFinite(amount) || !ASSETTYPES.includes(assetName)) return null;
@@ -195,4 +177,30 @@ FundModel.prototype.decrease = async function (assetName, amount, option) {
return res; return res;
}; };
FundModel.prototype.incFund = async function (amount, option = {}) {
if (!amount || amount <= 0 || !Number.isFinite(amount)) return null;
const asset = 'vicFundSum';
const res = await FundModel.findByIdAndUpdate(this.id, {
$inc: {
[asset]: amount
}
}, { ...option, returnOriginal: false }).exec().catch(err => mylog.error(err));
if (!res || !res.asset) throw new Error('用户资产修改[increase]失败!');
return res;
};
FundModel.prototype.decFund = async function (amount, option) {
// 传入的amount应该是大于0的正数
if (!amount || amount <= 0 || !Number.isFinite(amount)) return null;
amount = 0 - amount;
const asset = 'vicFundSum';
const res = await FundModel.findByIdAndUpdate(this.id, {
$inc: {
[asset]: amount
}
}, { ...option, returnOriginal: false }).exec().catch(err => mylog.error(err));
if (!res || !res.asset) throw new Error('用户资产修改[decrease]失败!');
return res;
};
module.exports = FundModel; module.exports = FundModel;

View File

@@ -1,5 +1,5 @@
const User = require('./user.model'); const User = require('./user.model');
const Fund = require('../fund/fund.model'); const Action = require('../action/action.model');
const VReq = require('../vreq/vreq.model'); const VReq = require('../vreq/vreq.model');
const MsgCode = require('../msgCode/msgCode.controller'); const MsgCode = require('../msgCode/msgCode.controller');
const changePwd = require('../sign/sign.controller').changePasswd; const changePwd = require('../sign/sign.controller').changePasswd;
@@ -124,13 +124,13 @@ module.exports = {
}, },
async getGroupBasicInfo (req, res) { async getGroupBasicInfo (req, res) {
const { userId } = res.locals.user; const { userId } = res.locals.user;
const [user, fund] = await Promise.all([User.findById(userId), Fund.findOne({userId})]); const [user, action] = await Promise.all([User.findById(userId), Action.findOne({userId, type: '4'})]);
if (!user) return res.json({ if (!user) return res.json({
code: 1, code: 1,
msg: '未知用户' msg: '未知用户'
}); });
const follower = user.group && user.group.length || 0; const follower = user.group && user.group.length || 0;
const reward = fund.asset && fund.asset.usdt || 0; const reward = Array.isArray(action) && action.reduce((acc, obj) => acc + +obj.amount, 0) || 0;
// const list = await User.find({ inviter: { $in: user.group } }).exec(); // const list = await User.find({ inviter: { $in: user.group } }).exec();
const list = await User.find({ inviter: userId }).exec(); const list = await User.find({ inviter: userId }).exec();
const sum = list.reduce((acc, u) => { const sum = list.reduce((acc, u) => {