'use strict'; const User = require('../user/user.model'); const Action = require('../action/action.model'); const Fund = require('./fund.model'); const { createAction } = require('../action/action.handler'); const { createTicket } = require('../ticket/ticket.handler'); const { deriveNewAccount } = require('../../utils/account'); 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: 'usdtETH', label: 'usdtETH', rate: '1' }]; const withdrawCoinsList = [{ id: 'vic', label: 'vic', fee: 0.005 }, { id: 'usdt', label: 'usdt', fee: 0.005 }]; module.exports = { async getFundDetail (req, res) { const { userId } = res.locals.user; return Fund.findOne({ userId }, 'asset').then(fund => { return res.json({ code: 0, msg: 'success', data: fund && fund.asset }); }).catch(err => { mylog.error("[getFundDetail]", err); return res.json({ code: 1, error: err.errmsg }); }); }, async getActions (req, res) { const { userId } = res.locals.user; const { pageIndex = 1, pageSize = 0 } = req.query; return await Action.find({ userId }, actionFilter).skip((+pageIndex - 1) * +pageSize).limit(+pageSize) .exec().then(data => { return res.json({ code: 0, data }); }) .catch(err => { return res.json({ code: 1, error: err.errmsg }); }); }, async getActionDetail (req, res) { const { id } = req.query; return await Action.findById(id, actionFilter).exec().then(data => { res.json({ code: 0, data }); }).catch(err => res.json({ code: 1, error: err.errmsg })); }, async getSupportCoinsList (req, res) { // eslint-disable-next-line no-undef return res.json({ code: 0, data: depositCoinsList }); }, async withdraw (req, res) { /** * 1.创建工单 * 2.创建用户action * 3.返回状态 */ const { userId } = res.locals.user; const { coinId, targetAddress, amount, password } = req.body; // 暂且硬编码支持币种!!!! if (!coinId || !targetAddress || !amount || !password) return res.json({ code: 6, msg: '缺少必要参数', error: '缺少必要参数' }); if (!Number.isFinite(+amount) || !Number.isSafeInteger(+amount) || Number.isNaN(+amount)) return res.json({ code: 5, msg: '非法额度', error: '非法额度' }); if (coinId !== 'usdt' && coinId !== 'vic') return res.json({ code: 4, msg: '不支持的提现币种', error: '不支持的提现币种', }); const [user, fund] = await Promise.all([User.findById(userId), Fund.findOne({ userId })]); if ( (coinId === 'vic' && amount < 1000) || (coinId === 'usdt' && fund.lastWithdraw.usdt || (new Date() - new Date(fund.lastWithdraw.usdt)) / (1000 * 3600 * 24 * 7) >= 1) ) { return res.json({ code: 4, msg: '不满足提现条件', error: '不满足提现条件', }); } if (user.fundPwd !== password) return res.json({ code: 1, msg: '资金密码错误', 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 ticket = createTicket('withdraw', { userId, amount: +amount, action, targetAddress, coinId }); try { await fund.decrease(coinId, cost); } catch (error) { mylog.error('[Fund提现] ', error); action.detail = { error }; await action.save(); return res.json({ code: 3, msg: '扣款失败', error: JSON.stringify(error) }); } return await Promise.all([ticket.save(), action.save()]).then(() => { return res.json({ code: 0, msg: '工单已创建' }); }).catch(err => { return res.json({ code: 3, msg: '工单创建失败', error: JSON.stringify(err) }); }); }, getDepositAddress: inject(function (SysConfig) { const { ROOTSECWORD } = SysConfig; if (!ROOTSECWORD) throw new Error('ROOTSECWORD is required'); return async (req, res) => { const { userId } = res.locals.user; const userFund = await Fund.findOne({userId}).exec(); let data = userFund.tokenAddress; if (!data.usdtBTC || !data.usdtETH) { const seed = parseInt(userId.substring(0, 8), 16).toString().slice(4); //前4位与Date.now前4位重复; const btc = deriveNewAccount(ROOTSECWORD, { coin: 'BTC', seed }); const eth = deriveNewAccount(ROOTSECWORD, { coin: 'ETH', seed }); const fund = await Fund.findOneAndUpdate({userId}, { $set: { tokenAddress: { usdtBTC: btc, usdtETH: eth } } }, { returnOriginal: false }).exec().catch(err => { mylog.error(err); return null; }); data = fund && fund.tokenAddress; } return data ? res.json({ code: 0, data: Object.keys(data).map(key => { return { id: key, label: key, address: data[key] && data[key].address }; }) }) : res.json({ code: 500, msg: '系统错误' }); }; }), 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({ code: 0, data: list }); }, // 查询资金,直接拉数据库,区块链的查询交给定时任务 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 { hasNew, list } = fund.hasNewDeposit(); if (!hasNew) { const [ start, end ] = getDate(1); const actions = await 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: fund.fundList, basic: { activeFund, revenueLastday, revenueAll: fund.fundSum || 0 } } }); } 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; return Fund.findOne({userId}, 'fundList').then(fund => { return res.json({ code: 0, data: fund.fundList }); }).catch(err => { mylog.error(err); res.json({ code: 500, msg: '系统错误' }); }); }, async getBasicInfo (req, res) { const { userId } = res.locals.user; return Fund.findOne({userId}).then(async fund => { const [ start, end ] = getDate(1); const actions = await Action.find({ userId, type: 1, createdAt: { $gt: start, $lt: end } }).exec(); // 计算昨日收益 let revenueLastday = calRevenueLastday(actions); // 筛选有效矿晶 let activeFund = getActiveFund(fund.fundList); return res.json({ code: 0, data: { activeFund, revenueLastday, revenueAll: fund.asset && fund.asset['vic'] } }); }).catch(err => { mylog.error(err); res.json({ code: 500, msg: '系统错误' }); }); }, };