|
@@ -0,0 +1,710 @@
|
|
|
|
+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');
|
|
|
|
+
|
|
|
|
+// 拿到飞书写入的 token
|
|
|
|
+const feishu_write_table_token_url = 'https://open.feishu.cn/open-apis/auth/v3/app_access_token/internal'
|
|
|
|
+const feishu_write_table_data_url = 'https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/shtcnp6zbrsep1Sz3Cvk7NXRpDg/values_batch_update'
|
|
|
|
+const feishu_insert_table_url = 'https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/shtcnp6zbrsep1Sz3Cvk7NXRpDg/insert_dimension_range'
|
|
|
|
+const reportTime = '02:00:00'
|
|
|
|
+
|
|
|
|
+//########################################### 出入金数据统计 ########################################
|
|
|
|
+
|
|
|
|
+const http_request_get = async (data) => {
|
|
|
|
+ var host = account_config.STATISTICS_URL
|
|
|
|
+ // host = 'https://api.denetme.net/denet/wallet/stat/getMoneyStat?date='
|
|
|
|
+ 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)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function getBscEnv() {
|
|
|
|
+ var bsc_env
|
|
|
|
+ switch (process.env.NODE_ENV) {
|
|
|
|
+ case 'dev':
|
|
|
|
+ case 'test':
|
|
|
|
+ bsc_env = 'bsc_testnet'
|
|
|
|
+ // bsc_env = 'bsc_mainnet'
|
|
|
|
+ break
|
|
|
|
+ case 'prd':
|
|
|
|
+ bsc_env = 'bsc_mainnet'
|
|
|
|
+ break
|
|
|
|
+ default:
|
|
|
|
+ bsc_env = 'bsc_mainnet'
|
|
|
|
+ break
|
|
|
|
+ }
|
|
|
|
+ return bsc_env;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+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) : element.chain == 'czz' ? BigInt(21000 * 2000000000) : BigInt(21000 * 5000000000)
|
|
|
|
+ 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 = getBscEnv()
|
|
|
|
+
|
|
|
|
+ //获取 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)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ if (!total_in_coins.get('0x0000000000000000000000000000000000000000')) {
|
|
|
|
+ total_in_coins.set('0x0000000000000000000000000000000000000000', {
|
|
|
|
+ amount: 0,
|
|
|
|
+ usdPrice: 0,
|
|
|
|
+ chain: filterTypt,
|
|
|
|
+ totalUsdPrice: 0
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ 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 = getBscEnv()
|
|
|
|
+
|
|
|
|
+ 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,
|
|
|
|
+ total: bsc_sl + 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 = getBscEnv()
|
|
|
|
+
|
|
|
|
+ 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 = getBscEnv()
|
|
|
|
+
|
|
|
|
+ //计算总消耗的 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 = getBscEnv()
|
|
|
|
+ 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.balance) {
|
|
|
|
+ obj.native.balance = '0'
|
|
|
|
+ }
|
|
|
|
+ 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) {
|
|
|
|
+ if (!element.decimals || element.decimals == 0)
|
|
|
|
+ element.decimals = 18
|
|
|
|
+ element.usdPrice = parseFloat(element.balance) / parseFloat(10 ** element.decimals) * priceItem.usdPrice
|
|
|
|
+ tokenTotal += element.usdPrice
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return {
|
|
|
|
+ nativeTotal: obj.native.usdPrice,
|
|
|
|
+ tokenTotal: tokenTotal,
|
|
|
|
+ total: parseFloat(obj.native.usdPrice) + parseFloat(tokenTotal)
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+async function getAllBalance() {
|
|
|
|
+ var bsc_env = getBscEnv()
|
|
|
|
+ var company = await moralis.queryCompanyInfoFromId(0)
|
|
|
|
+ logger.info('getAllBalance company', company)
|
|
|
|
+ var bsc_balance = await moralis.getAccountAllCoins({
|
|
|
|
+ chain: bsc_env,
|
|
|
|
+ address: company.user_address
|
|
|
|
+ })
|
|
|
|
+ logger.info('getAccountAllCoins bsc_balance', bsc_balance)
|
|
|
|
+ var bscb = await updateBalance(bsc_balance, 'bsc')
|
|
|
|
+ logger.info('getAccountAllCoins updateBalance bscb', bscb)
|
|
|
|
+ var czz_balance = await moralis.getAccountAllCoins({
|
|
|
|
+ chain: 'czz',
|
|
|
|
+ address: company.user_address
|
|
|
|
+ })
|
|
|
|
+ logger.info('getAccountAllCoins czz_balance', czz_balance)
|
|
|
|
+ var czzb = await updateBalance(czz_balance, 'czz')
|
|
|
|
+
|
|
|
|
+ logger.info('getAccountAllCoins updateBalance czzb', czzb)
|
|
|
|
+
|
|
|
|
+ return {
|
|
|
|
+ bsc: bscb,
|
|
|
|
+ czz: czzb,
|
|
|
|
+ totalBalance: bscb.total + czzb.total
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * 获取时间段总支出的 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()
|
|
|
|
+ logger.info('getSLGas ret', totalSLGas)
|
|
|
|
+
|
|
|
|
+ return {
|
|
|
|
+ updateTime: utils.getLastDay('YYYY-MM-DD'),
|
|
|
|
+ todayTotalProfit: parseFloat(data.data.incomeUSDTotal) - parseFloat(collectCoinsOut.totalGasFee + withdrawOut.totalGasFee),
|
|
|
|
+ todayTotalOutGasFee: collectCoinsOut.totalGasFee + withdrawOut.totalGasFee, //今日总支出的 gas fee
|
|
|
|
+ canNotWithdrawUSD: parseFloat(data.data.canNotWithdrawUSD), //不可提现余额
|
|
|
|
+ canWithdrawUSD: parseFloat(data.data.canWithdrawUSD), //可提现余额
|
|
|
|
+ todayIncomeUSDTotal: parseFloat(data.data.incomeUSDTotal), //今日总收入
|
|
|
|
+ todayIncomeUSDFee: parseFloat(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.totalBalance, //总余额
|
|
|
|
+ ylGasBalance: { //预留 gas 费余额 native 总余额 - 总入金
|
|
|
|
+ bsc: curBalances.bsc.nativeTotal - totalCollectCoinsOut.bsc.get('0x0000000000000000000000000000000000000000').totalUsdPrice,
|
|
|
|
+ czz: curBalances.czz.nativeTotal - totalCollectCoinsOut.czz.get('0x0000000000000000000000000000000000000000').totalUsdPrice,
|
|
|
|
+ total: (curBalances.bsc.nativeTotal - totalCollectCoinsOut.bsc.get('0x0000000000000000000000000000000000000000').totalUsdPrice) + (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(utils.getCurrentDate()).getTime()
|
|
|
|
+ // nowTime = new Date().getTime()
|
|
|
|
+
|
|
|
|
+ let timePoints = config.time.split(':').map(i => parseInt(i))
|
|
|
|
+
|
|
|
|
+ let recent = new Date(utils.getCurrentDate()).setHours(...timePoints)
|
|
|
|
+
|
|
|
|
+ recent >= nowTime || (recent += 24 * 3600000)
|
|
|
|
+
|
|
|
|
+ console.log('timeoutFunc-------------------', nowTime, timePoints, recent)
|
|
|
|
+ setTimeout(() => {
|
|
|
|
+
|
|
|
|
+ func()
|
|
|
|
+
|
|
|
|
+ setInterval(func, config.interval * 3600000)
|
|
|
|
+
|
|
|
|
+ }, recent - nowTime)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+const getFeishuToken = async (params) => {
|
|
|
|
+ return new Promise(resolve => {
|
|
|
|
+ axios.post(feishu_write_table_token_url,
|
|
|
|
+ {
|
|
|
|
+ app_id: "cli_a223f015abbad00e",
|
|
|
|
+ app_secret: "DMCF6tBwIpeOQPnWrFUMYd6tmjb53C4n"
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ timeout: 1 * 60 * 1000,
|
|
|
|
+ headers: {
|
|
|
|
+ 'Content-Type': "application/json; charset=utf-8"
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ .then(res => {
|
|
|
|
+ logger.log('getFeishuToken res=>', res.status, res.data);
|
|
|
|
+ resolve(res.data)
|
|
|
|
+ }).catch(err => {
|
|
|
|
+ logger.error('getFeishuToken error ', JSON.stringify(err));
|
|
|
|
+ resolve(JSON.stringify(err))
|
|
|
|
+ });
|
|
|
|
+ })
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+function writeTable(app_token, data) {
|
|
|
|
+ logger.info('writeTable', data)
|
|
|
|
+ var body = {
|
|
|
|
+ 'valueRanges': [
|
|
|
|
+ {
|
|
|
|
+ 'range': '0pRQpu!A2:C2',
|
|
|
|
+ 'values': [
|
|
|
|
+ [data.totalCollectCoinsGasFee, //归集总 gas
|
|
|
|
+ data.totalWithdrawGasFee, //提币总 gas
|
|
|
|
+ data.totalOutGasFee], //总支出 gas
|
|
|
|
+ ]
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ 'range': '1ygrMB!A2:B2',
|
|
|
|
+ 'values': [
|
|
|
|
+ [
|
|
|
|
+ data.totalInFee, //总入金
|
|
|
|
+ data.totalOutFee,//总出金
|
|
|
|
+ ],
|
|
|
|
+ ]
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ 'range': 'BMjMDr!A3:J3',
|
|
|
|
+ 'values': [
|
|
|
|
+ [
|
|
|
|
+ data.updateTime, //更新时间
|
|
|
|
+ data.todayTotalProfit,//今日总利润
|
|
|
|
+ data.todayIncomeUSDTotal,//今日总收入
|
|
|
|
+ data.todayIncomeUSDFee,//今日固定手续费收入
|
|
|
|
+ data.todayTotalOutGasFee,//今日总 gas 支出
|
|
|
|
+ data.totalBalances, //总余额
|
|
|
|
+ data.canNotWithdrawUSD, //不可提现余额
|
|
|
|
+ data.canWithdrawUSD,//可提现余额
|
|
|
|
+ data.ylGasBalance.total,//预留 gas
|
|
|
|
+ data.slGasBalance.total,//散落 gas
|
|
|
|
+ ],
|
|
|
|
+ ]
|
|
|
|
+ }
|
|
|
|
+ ]
|
|
|
|
+ }
|
|
|
|
+ return new Promise(resolve => {
|
|
|
|
+ axios.post(feishu_write_table_data_url,
|
|
|
|
+ body,
|
|
|
|
+ {
|
|
|
|
+ timeout: 1 * 60 * 1000,
|
|
|
|
+ headers: {
|
|
|
|
+ 'Content-Type': "application/json; charset=utf-8",
|
|
|
|
+ 'Authorization': 'Bearer ' + app_token
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ .then(res => {
|
|
|
|
+ logger.log('writeTable res=>', res.status, res.data);
|
|
|
|
+ resolve(res.data)
|
|
|
|
+ }).catch(err => {
|
|
|
|
+ logger.error('writeTable error ', JSON.stringify(err));
|
|
|
|
+ resolve(JSON.stringify(err))
|
|
|
|
+ });
|
|
|
|
+ })
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+async function insertTableRows(app_token) {
|
|
|
|
+ var body = {
|
|
|
|
+ dimension: {
|
|
|
|
+ sheetId: 'BMjMDr',
|
|
|
|
+ majorDimension: 'ROWS',
|
|
|
|
+ startIndex: 2,
|
|
|
|
+ endIndex: 3,
|
|
|
|
+ },
|
|
|
|
+ inheritStyle: 'AFTER'
|
|
|
|
+ }
|
|
|
|
+ return new Promise(resolve => {
|
|
|
|
+ axios.post(feishu_insert_table_url,
|
|
|
|
+ JSON.stringify(body),
|
|
|
|
+ {
|
|
|
|
+ timeout: 1 * 60 * 1000,
|
|
|
|
+ headers: {
|
|
|
|
+ 'Content-Type': "application/json; charset=utf-8",
|
|
|
|
+ 'Authorization': 'Bearer ' + app_token
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ .then(res => {
|
|
|
|
+ console.log('res=>', res.status, res.data);
|
|
|
|
+ resolve(res.data)
|
|
|
|
+ }).catch(err => {
|
|
|
|
+ logger.error('error ', JSON.stringify(err));
|
|
|
|
+ resolve(JSON.stringify(err))
|
|
|
|
+ });
|
|
|
|
+ })
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+async function exec(data) {
|
|
|
|
+ var app = await getFeishuToken()
|
|
|
|
+ await insertTableRows(app.app_access_token)
|
|
|
|
+ await writeTable(app.app_access_token, data)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+async function report2FeishuTable() {
|
|
|
|
+ try {
|
|
|
|
+ logger.error('数据统计 start')
|
|
|
|
+ logger.info('report2FeishuTable')
|
|
|
|
+ var data = await getStatisticsInfo();
|
|
|
|
+ logger.info('getStatisticsInfo', data)
|
|
|
|
+ var ret = await exec(data)
|
|
|
|
+ logger.error('数据统计 end','https://st94nif1cq.feishu.cn/sheets/shtcnp6zbrsep1Sz3Cvk7NXRpDg?sheet=BMjMDr',JSON.stringify(data),JSON.stringify(ret))
|
|
|
|
+ } catch (error) {
|
|
|
|
+ logger.error('report2FeishuTable', error.toString())
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+timeoutFunc({
|
|
|
|
+
|
|
|
|
+ interval: 1, //间隔天数,间隔为整数
|
|
|
|
+
|
|
|
|
+ runNow: false, //是否立即运行
|
|
|
|
+
|
|
|
|
+ time: reportTime //执行的时间点 时在0~23之间
|
|
|
|
+
|
|
|
|
+}, func => {
|
|
|
|
+ if (process.env.NODE_ENV == 'prd') {
|
|
|
|
+ report2FeishuTable()
|
|
|
|
+ }
|
|
|
|
+})
|
|
|
|
+// logger.info('getAllBalance ', getAllBalance())
|
|
|
|
+module.exports = {
|
|
|
|
+ getStatisticsInfo
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|