const logger = require('../model/logger') var remote_config_db = require("../model/db/remote_config_db"); var collect_coins_db = require("../model/db/collect_coins_db"); var withdraw_db = require("../model/db/withdraw_db"); var moralis = require("../model/moralis_sdk"); var utils = require("../model/utils"); const axios = require('axios'); var { account_config } = require('../config/config.js'); const { max } = require('moment'); //########################################### 出入金数据统计 ######################################## const http_request_get = async (data) => { var host = account_config.STATISTICS_URL var path = data var url = host + path logger.log('http_request_get', url) return new Promise(response => { axios.get(url) .then(res => { logger.log('res=>', res.status, res.data); if (res.data.code == 0) { response(res.data) } else { response({ code: 0, msg: err.toString(), data: { canNotWithdrawUSD: '0', canWithdrawUSD: '0', incomeUSDTotal: '0', incomeUSDFee: '0' } }) } }).catch(err => { logger.error('http_request_get', err.toString(), url.toString()); response({ code: -1, msg: err.toString(), data: { canNotWithdrawUSD: '0', canWithdrawUSD: '0', incomeUSDTotal: '0', incomeUSDFee: '0' } }) }); }) } async function computeAddressPrice(total_in_coins) { //计算总的价格 for (key of total_in_coins.keys()) { var item = total_in_coins.get(key) var amount = item.amount var usdPrice = item.usdPrice if (key == '0x0000000000000000000000000000000000000000') { item.totalUsdPrice = parseFloat(amount) / parseFloat(10 ** 18) * parseFloat(usdPrice) } else { var decimals = 18 try { decimals = await redis.readAppendRedis('REDIS_ERC20_CONTRACT_DECIMALS', item.chain, key.toLowerCase()) logger.info('REDIS_ERC20_CONTRACT_DECIMALS', key.toLowerCase(), decimals) } catch (error) { decimals = 18 } item.totalUsdPrice = parseFloat(amount) / parseFloat(10 ** decimals) * parseFloat(usdPrice) } } } async function filterCollectCoinsLists(collect_ret, filterTypt) { const total_in_coins = new Map(); var total_gas_fee = 0 for (let index = 0; index < collect_ret.results.length; index++) { const element = collect_ret.results[index]; if (element.chain == null || element.chain == filterTypt) { var before_gas_fee = element.before_gas_fee ? BigInt(element.before_gas_fee) : BigInt('0') total_gas_fee = BigInt(element.total_gas_fee) + BigInt(before_gas_fee) + BigInt(total_gas_fee) if (element.transfers) { var opts = JSON.parse(element.transfers) for (let index = 0; index < opts.length; index++) { const transfers = opts[index]; if (transfers.chain == filterTypt) { var address = transfers.contractAddress ? transfers.contractAddress : '0x0000000000000000000000000000000000000000' if (total_in_coins.get(address) != null) { var ins = total_in_coins.get(address) ins.amount = BigInt(ins.amount) + BigInt(transfers.amount) total_in_coins.set(address, ins) } else { total_in_coins.set(address, { amount: BigInt(transfers.amount), //总入金 usdPrice: transfers.usdPrice, chain: transfers.chain, }) } } } } } } //计算总的价格 await computeAddressPrice(total_in_coins) var bsc_env switch (process.env.NODE_ENV) { case 'dev': case 'test': bsc_env = 'bsc_testnet' break case 'prd': bsc_env = 'bsc_mainnet' break default: bsc_env = 'bsc_mainnet' break } //获取 total gas try { if (total_in_coins.size > 0) { switch (filterTypt) { case 'bsc_testnet': case 'bsc_mainnet': var price = await moralis.getAllTotkenPrice({ chain: bsc_env }) if (typeof price === 'string') { price = JSON.parse(price) } var bnbPriceItem = moralis.findTokenPriceItem('0x0000000000000000000000000000000000000000', price) total_gas_fee = parseFloat(total_gas_fee) / parseFloat(10 ** 18) * parseFloat(bnbPriceItem.usdPrice) logger.info('new-total_gas_fee ', total_gas_fee, bnbPriceItem) break case 'czz': var price = await moralis.getAllTotkenPrice({ chain: 'czz' }) if (typeof price === 'string') { price = JSON.parse(price) } var czzPriceItem = moralis.findTokenPriceItem('0x0000000000000000000000000000000000000000', price) total_gas_fee = parseFloat(total_gas_fee) / parseFloat(10 ** 18) * parseFloat(czzPriceItem.usdPrice) logger.info('new-total_gas_fee czz', total_gas_fee, czzPriceItem) break } } } catch (error) { logger.error('total_gas_fee', error) } return { map: total_in_coins, totalGasFee: total_gas_fee //总入金所消耗的 gas fee } } function sumBalance(map) { var balances = 0; for (key of map.keys()) { balances += map.get(key).totalUsdPrice } return balances } async function getSLGas() { var maps = new Map() var collect_ret = await collect_coins_db.query_collect_total_fee(null, null); for (let index = 0; index < collect_ret.results.length; index++) { var element = collect_ret.results[index] try { if (element.prestore_gas_fee && typeof element.prestore_gas_fee === 'string') { var pre_gas_obj = JSON.parse(element.prestore_gas_fee) var bgf = element.before_gas_fee if (!bgf && pre_gas_obj.amount) { bgf = pre_gas_obj.amount } logger.info('getSLGas item', bgf, pre_gas_obj, element) if (maps.get(pre_gas_obj.chain)) { maps.get(pre_gas_obj.chain).sl_gas_fee = BigInt(maps.get(pre_gas_obj.chain).sl_gas_fee) + (BigInt(pre_gas_obj.amount) - BigInt(bgf)) } else { maps.set(pre_gas_obj.chain, { sl_gas_fee: BigInt(pre_gas_obj.amount) - BigInt(bgf) }) } } } catch (error) { logger.error('getSLGas error', error.toString()) } } var bsc_env switch (process.env.NODE_ENV) { case 'dev': case 'test': bsc_env = 'bsc_testnet' break case 'prd': bsc_env = 'bsc_mainnet' break default: bsc_env = 'bsc_mainnet' break } logger.info('getSLGas', maps) var bsc_sl var czz_sl for (key of maps.keys()) { var item = maps.get(key) switch (key) { case "bsc_mainnet": case "bsc_testnet": var price = await moralis.getAllTotkenPrice({ chain: bsc_env }) if (typeof price === 'string') { price = JSON.parse(price) } var bnbPriceItem = moralis.findTokenPriceItem('0x0000000000000000000000000000000000000000', price) bsc_sl = parseFloat(item.sl_gas_fee) / parseFloat(10 ** 18) * parseFloat(bnbPriceItem.usdPrice) break case "czz": var price = await moralis.getAllTotkenPrice({ chain: 'czz' }) if (typeof price === 'string') { price = JSON.parse(price) } var czzPriceItem = moralis.findTokenPriceItem('0x0000000000000000000000000000000000000000', price) czz_sl = parseFloat(item.sl_gas_fee) / parseFloat(10 ** 18) * parseFloat(czzPriceItem.usdPrice) break } } return { bsc: bsc_sl, czz: czz_sl } } async function getCollectCoinsOutInfo(startTime, endTime) { var collect_ret = await collect_coins_db.query_collect_total_fee(startTime, endTime); logger.info('getCollectCoinsOutInfo query_collect_total_fee', startTime, endTime) var bsc_env switch (process.env.NODE_ENV) { case 'dev': case 'test': bsc_env = 'bsc_testnet' break case 'prd': bsc_env = 'bsc_mainnet' break default: bsc_env = 'bsc_mainnet' break } var bsc_envnet = await filterCollectCoinsLists(collect_ret, bsc_env) logger.info('getCollectCoinsOutInfo bsc_env', bsc_env, bsc_envnet) var czz = await filterCollectCoinsLists(collect_ret, 'czz') logger.info('getCollectCoinsOutInfo czz', czz) logger.info('getCollectCoinsOutInfo total ', bsc_envnet.totalGasFee, czz.totalGasFee) return { bsc: bsc_envnet.map, czz: czz.map, totalGasFee: parseFloat(bsc_envnet.totalGasFee) + parseFloat(czz.totalGasFee), //总归集消耗的 gas fee totalInFee: sumBalance(bsc_envnet.map) + sumBalance(czz.map),//总入金美元 } } async function filterWithdrawTotalOutFee(chain_id, filterItem) { const withdraw_out_map = new Map(); var price = await moralis.getAllTotkenPrice({ chain: chain_id + "" }) if (typeof price === 'string') { price = JSON.parse(price) } for (let index = 0; index < filterItem.length; index++) { const element = filterItem[index]; if (element.chain_id == chain_id) { var address = element.type == 'native' ? '0x0000000000000000000000000000000000000000' : element.contract_address if (withdraw_out_map.get(address) != null) { var item = withdraw_out_map.get(address) item.totalAmount = BigInt(element.amount) + BigInt(item.totalAmount) } else { var priceItem = moralis.findTokenPriceItem(address, price) var decimals = 18 if (key == '0x0000000000000000000000000000000000000000') { item.totalUsdPrice = parseFloat(amount) / parseFloat(10 ** 18) * parseFloat(usdPrice) } else { try { decimals = await redis.readAppendRedis('REDIS_ERC20_CONTRACT_DECIMALS', chain_id + "", address.toLowerCase()) logger.info('REDIS_ERC20_CONTRACT_DECIMALS', key.toLowerCase(), decimals) } catch (error) { decimals = 18 } } withdraw_out_map.set(address, { totalAmount: BigInt(element.amount), //出金数量 usdPrice: priceItem.usdPrice, chain: element.chain_id, decimals: decimals, }) } } } logger.info('filterWithdrawTotalOutFee', withdraw_out_map, chain_id) return withdraw_out_map } async function getWithdrawOutInfo(startTime, endTime) { if (startTime && endTime) { startTime = new Date(startTime).getTime() endTime = new Date(endTime).getTime() } var withdraw_ret = await withdraw_db.getWidthdrawTotalFee(startTime, endTime) const withdraw_gas_map = new Map(); for (let index = 0; index < withdraw_ret.length; index++) { const element = withdraw_ret[index]; if (element.gas_price && element.gas_limit) var total_gas_fee2 = (BigInt(element.gas_price) * BigInt(element.gas_limit)) if (withdraw_gas_map.get(element.chain_id) != null) { withdraw_gas_map.get(element.chain_id).total_gas_fee = BigInt(withdraw_gas_map.get(element.chain_id).total_gas_fee) + BigInt(total_gas_fee2) } else { withdraw_gas_map.set(element.chain_id, { total_gas_fee: BigInt(total_gas_fee2), total_withdraw: null } ) } } var bsc_env switch (process.env.NODE_ENV) { case 'dev': case 'test': bsc_env = 'bsc_testnet' break case 'prd': bsc_env = 'bsc_mainnet' break default: bsc_env = 'bsc_mainnet' break } //计算总消耗的 gas var keys = withdraw_gas_map.keys(); var total_gas_fee = 0 for (key of keys) { console.log(key, withdraw_gas_map.get(key)); // map.get(key)可得value值。 var value = withdraw_gas_map.get(key).total_gas_fee //获取币价 try { if (key == 2019) { var price = await moralis.getAllTotkenPrice({ chain: 'czz' }) if (typeof price === 'string') { price = JSON.parse(price) } var czzPriceItem = moralis.findTokenPriceItem('0x0000000000000000000000000000000000000000', price) total_gas_fee += parseFloat(value) / parseFloat(10 ** 18) * parseFloat(czzPriceItem.usdPrice) logger.info('new-total_gas_fee czz', total_gas_fee, czzPriceItem) } else { var price = await moralis.getAllTotkenPrice({ chain: bsc_env }) if (typeof price === 'string') { price = JSON.parse(price) } var bnbPriceItem = moralis.findTokenPriceItem('0x0000000000000000000000000000000000000000', price) total_gas_fee += parseFloat(value) / parseFloat(10 ** 18) * parseFloat(bnbPriceItem.usdPrice) logger.info('new-total_gas_fee bsc', total_gas_fee, bnbPriceItem) } } catch (error) { logger.error('total_gas_fee', error) } } var withdrawout = 0 if (!startTime && !endTime) { for (key of withdraw_gas_map.keys()) { try { var outs = await filterWithdrawTotalOutFee(key, withdraw_ret) withdraw_gas_map.get(key).total_withdraw = outs logger.error('withdraw_gas_map.get(key).total_withdraw outs', outs) if (outs) { for (ckey of outs.keys()) { var item = outs.get(ckey); withdrawout = parseFloat(withdrawout) + (parseFloat(item.totalAmount) / parseFloat(10 ** item.decimals) * parseFloat(item.usdPrice)) } } } catch (error) { logger.error('filterWithdrawTotalOutFee error', error.toString()) } } } return { outmap: withdraw_gas_map, totalGasFee: total_gas_fee, totalWithdraw: withdrawout }; } async function updateBalance(obj, type) { var price if (type == 'bsc') { var bsc_env switch (process.env.NODE_ENV) { case 'dev': case 'test': bsc_env = 'bsc_testnet' break case 'prd': bsc_env = 'bsc_mainnet' break default: bsc_env = 'bsc_mainnet' break } price = await moralis.getAllTotkenPrice({ chain: bsc_env }) } else if (type == 'czz') { price = await moralis.getAllTotkenPrice({ chain: 'czz' }) } if (typeof price === 'string') { price = JSON.parse(price) } var priceItem = moralis.findTokenPriceItem('0x0000000000000000000000000000000000000000', price, price) if (obj.native) { obj.native.usdPrice = parseFloat(obj.native.balance) / parseFloat(10 ** 18) * priceItem.usdPrice logger.info('findTokenPriceItem 0x0000000000000000000000000000000000000000 ', obj, priceItem, type) } var tokenTotal = 0 if (obj.other && Array.isArray(obj.other)) { for (let index = 0; index < obj.other.length; index++) { const element = obj.other[index]; priceItem = moralis.findTokenPriceItem(element.token_address, price) logger.info('findTokenPriceItem element ', priceItem, element.token_address) if (priceItem) { element.usdPrice = parseFloat(element.balance) / parseFloat(10 ** element.decimals) * priceItem.usdPrice tokenTotal += element.usdPrice } } } return { nativeTotal: obj.native.usdPrice, tokenTotal: tokenTotal, } } async function getAllBalance() { var bsc_env switch (process.env.NODE_ENV) { case 'dev': case 'test': bsc_env = 'bsc_testnet' break case 'prd': bsc_env = 'bsc_mainnet' break default: bsc_env = 'bsc_mainnet' break } var company = await moralis.queryCompanyInfoFromId(0) var bsc_balance = await moralis.getAccountAllCoins({ chain: bsc_env, address: company.user_address }) var bscb = await updateBalance(bsc_balance, 'bsc') var czz_balance = await moralis.getAccountAllCoins({ chain: 'czz', address: company.user_address }) var czzb = await updateBalance(czz_balance, 'czz') return { bsc: bscb, czz: czzb } } /** * 获取时间段总支出的 gas fee * @param {*} startTime * @param {*} endTime */ async function getStatisticsInfo() { // //今日 var startTime = utils.getLastDay('YYYY-MM-DD') + " 00:00:00" var endTime = utils.getLastDay('YYYY-MM-DD') + " 23:59:59" logger.info('getTotalOutGasFee', startTime, endTime) //归集 var collectCoinsOut = await getCollectCoinsOutInfo(startTime, endTime) logger.info('getCollectCoinsOutInfo collectCoinsOut', collectCoinsOut) //提币 var withdrawOut = await getWithdrawOutInfo(startTime, endTime) logger.info('getWithdrawOutInfo withdrawOut ', withdrawOut) var data = await http_request_get(utils.getLastDay('YYYYMMDD')) //历史,总的 //归集 var totalCollectCoinsOut = await getCollectCoinsOutInfo(null, null) logger.info('totalCollectCoinsOut ', totalCollectCoinsOut) //提币 var totalWithdrawOut = await getWithdrawOutInfo(null, null) logger.info('totalWithdrawOut ', totalWithdrawOut) //获取当前账户总余额 var curBalances = await getAllBalance() logger.info('getAllBalance ', curBalances) //获取散落 gas var totalSLGas = await getSLGas() return { todayTotalOutGasFee: collectCoinsOut.totalGasFee + withdrawOut.totalGasFee, //今日总支出的 gas fee todayCanNotWithdrawUSD: data.data.canNotWithdrawUSD, //今日不可提现余额 todayCanWithdrawUSD: data.data.canWithdrawUSD, //今日可提现余额 todayIncomeUSDTotal: data.data.incomeUSDTotal, //今日总收入 todayIncomeUSDFee: data.data.incomeUSDFee, //今日固定收入 totalOutGasFee: totalCollectCoinsOut.totalGasFee + totalWithdrawOut.totalGasFee, //总支出 gas fee totalWithdrawGasFee: totalWithdrawOut.totalGasFee, //总提币 gas fee totalCollectCoinsGasFee: totalCollectCoinsOut.totalGasFee, //总归集 gas fee totalInFee: totalCollectCoinsOut.totalInFee, totalNativeInFee: { bsc: totalCollectCoinsOut.bsc.get('0x0000000000000000000000000000000000000000').totalUsdPrice, czz: totalCollectCoinsOut.czz.get('0x0000000000000000000000000000000000000000').totalUsdPrice }, //总 native 入金 totalOutFee: totalWithdrawOut.totalWithdraw, //总出金 totalBalances: curBalances, //总余额 ylGasBalance: { //预留 gas 费余额 native 总余额 - 总入金 bsc: curBalances.bsc.nativeTotal - totalCollectCoinsOut.bsc.get('0x0000000000000000000000000000000000000000').totalUsdPrice, czz: curBalances.czz.nativeTotal - totalCollectCoinsOut.czz.get('0x0000000000000000000000000000000000000000').totalUsdPrice }, slGasBalance: totalSLGas, //散落 gas 费余额 充值 0.5 gas - 使用 0.3 gas= 散落 0.2gas } } function timeoutFunc(config, func) { config.runNow && func() let nowTime = new Date().getTime() let timePoints = config.time.split(':').map(i => parseInt(i)) let recent = new Date().setHours(...timePoints) recent >= nowTime || (recent += 24 * 3600000) setTimeout(() => { func() setInterval(func, config.interval * 3600000) }, recent - nowTime) } timeoutFunc({ interval: 1, //间隔天数,间隔为整数 runNow: false, //是否立即运行 time: "08:00:00" //执行的时间点 时在0~23之间 }, func => { getStatisticsInfo() }) module.exports = { getStatisticsInfo }