Merge branch 'vic' of tac/vic.server into master
This commit is contained in:
89
clean.js
Normal file
89
clean.js
Normal 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();
|
||||||
@@ -2,5 +2,8 @@
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
USDTAddr: '0xdac17f958d2ee523a2206206994597c13d831ec7',
|
USDTAddr: '0xdac17f958d2ee523a2206206994597c13d831ec7',
|
||||||
startBlock: 8510200
|
VICAddr: '0xA5D1Eb8bBB42b7f2EBBebF174B3966510243F30c',
|
||||||
|
startBlock: 8510200,
|
||||||
|
VIC_DECIMAL: 1e18,
|
||||||
|
USDT_DECIMAL: 1e6,
|
||||||
};
|
};
|
||||||
@@ -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
|
||||||
};
|
};
|
||||||
@@ -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('挖矿程序执行完毕');
|
||||||
|
|||||||
115
src/jobs/mine.js
115
src/jobs/mine.js
@@ -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;
|
return revenue;
|
||||||
await Fund.findByIdAndUpdate(fund.id, {
|
|
||||||
$inc: {
|
|
||||||
[`fundList.${i}.mineCount`]: 1,
|
|
||||||
[`fundList.${i}.releasedAmout`]: profit,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
sum += profit;
|
|
||||||
}
|
|
||||||
return sum.toFixed(2);
|
|
||||||
}
|
|
||||||
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);
|
||||||
|
|||||||
@@ -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();
|
||||||
// 计算昨日收益
|
// 计算昨日收益
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -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) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user