|
@@ -7,6 +7,8 @@ var { moralis_config, reids_token_config, account_config } = require('../config/
|
|
|
const redis = require("./redis_db") //导入 db.js
|
|
|
const mysql = require("./mysql_db")
|
|
|
const logger = require('./logger')
|
|
|
+
|
|
|
+const BigNumber = require('bignumber.js')
|
|
|
/* Moralis init code */
|
|
|
var serverUrl = moralis_config.SERVER_URL;
|
|
|
var appId = moralis_config.APP_ID;
|
|
@@ -35,12 +37,75 @@ function toJson(code_, obj_, errMsg_) {
|
|
|
}
|
|
|
|
|
|
|
|
|
+/**
|
|
|
+ * 获取转账的 gas 费
|
|
|
+ * @param {*} type
|
|
|
+ * @param {*} json
|
|
|
+ * @returns
|
|
|
+ */
|
|
|
+function getTransferGasFree(type, json) {
|
|
|
+ var curGasPrice = account_config.BNB_GAS_PRICE
|
|
|
+ var curGasLimit = account_config.TOKEN_GAS_LIMIT
|
|
|
+ var nativeValue = 0;
|
|
|
+ var tokenValue = 0;
|
|
|
+ var code = -1;
|
|
|
+ if (type == 'native') {
|
|
|
+ curGasLimit = account_config.BNB_GAS_LIMIT
|
|
|
+ }
|
|
|
+ var totalGasFree = parseInt(curGasLimit) * parseInt(curGasPrice);
|
|
|
+
|
|
|
+ logger.log('getTransferGasFree json=', json)
|
|
|
+
|
|
|
+ if (json) {
|
|
|
+ var obj = JSON.parse(json)
|
|
|
+ code = obj.code;
|
|
|
+ logger.log('getTransferGasFree obj=', obj)
|
|
|
+ if (obj.data && obj.data.gasPrice && obj.data.gasLimit && obj.data.gasPrice.hex && obj.data.gasLimit.hex) {
|
|
|
+ var curGasPrice = BigNumber(obj.data.gasPrice.hex).toNumber()
|
|
|
+ var curGasLimit = BigNumber(obj.data.gasLimit.hex).toNumber()
|
|
|
+ if (curGasPrice > 0 && curGasLimit > 0) {
|
|
|
+ totalGasFree = curGasPrice * curGasLimit;
|
|
|
+ }
|
|
|
+ logger.log('getTransferGasFree totalGasFree=', curGasPrice, curGasLimit, totalGasFree)
|
|
|
+ if (obj.data.value && obj.data.value.hex) {
|
|
|
+ var value = BigNumber(obj.data.value.hex).toNumber()
|
|
|
+ logger.log('getTransferGasFree native value=', value)
|
|
|
+ if (value != 0) {
|
|
|
+ nativeValue = value
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return {
|
|
|
+ code: code,
|
|
|
+ totalGasFree: totalGasFree,
|
|
|
+ nativeValue: nativeValue,
|
|
|
+ tokenValue: tokenValue,
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ *
|
|
|
+ * @param {转账是否成功} json
|
|
|
+ */
|
|
|
+function isTransferSucceed(json) {
|
|
|
+ if (json) {
|
|
|
+ var obj = JSON.parse(json)
|
|
|
+ return obj.code == 0
|
|
|
+ }
|
|
|
+ return false
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
const withdraw = async (obj) => {
|
|
|
obj.withdraw = 1;
|
|
|
- return await transfer(obj);
|
|
|
+ return await transfer_handle(obj);
|
|
|
}
|
|
|
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
async function getAccountBalances(options) {
|
|
|
await initMasterSDK();
|
|
|
if (options.chain) {
|
|
@@ -98,6 +163,9 @@ async function computeTransferGasFree(my_account_all_coins, tokenPrices) {
|
|
|
var ret_total_count = 0;
|
|
|
var ret_a_gas = 0;
|
|
|
|
|
|
+ //需要转账的数组对象
|
|
|
+ var transfer_obj = [];
|
|
|
+
|
|
|
//得到 20 币 满足 1美刀的 count
|
|
|
if (Array.isArray(my_account_all_coins.other) && my_account_all_coins.other.length > 0) {
|
|
|
my_account_all_coins.other.forEach(element => {
|
|
@@ -112,7 +180,13 @@ async function computeTransferGasFree(my_account_all_coins, tokenPrices) {
|
|
|
});
|
|
|
logger.log('account_config.TOKEN_GAS_LIMIT=', account_config.TOKEN_GAS_LIMIT);
|
|
|
|
|
|
- tokenGasPrice = parseInt(tokenCount) * parseInt(account_config.TOKEN_GAS_LIMIT) * parseInt(account_config.BNB_GAS_PRICE);
|
|
|
+ var lastTokenFree = await redis.readRedis(reids_token_config.LAST_TOTAL_TOKEN_FREE)
|
|
|
+ logger.log('LAST_TOTAL_TOKEN_FREE=', lastTokenFree);
|
|
|
+ if (lastTokenFree && reids_token_config.LAST_TOTAL_TOKEN_FREE && parseInt(lastTokenFree) > 0) {
|
|
|
+ tokenGasPrice = parseInt(tokenCount) * parseInt(lastTokenFree);
|
|
|
+ } else {
|
|
|
+ tokenGasPrice = parseInt(tokenCount) * parseInt(account_config.TOKEN_GAS_LIMIT) * parseInt(account_config.BNB_GAS_PRICE);
|
|
|
+ }
|
|
|
ret_a_gas = account_config.BNB_GAS_PRICE;
|
|
|
logger.log('tokenGasPrice=', tokenGasPrice);
|
|
|
}
|
|
@@ -130,7 +204,14 @@ async function computeTransferGasFree(my_account_all_coins, tokenPrices) {
|
|
|
if (total_all_usdprice > 1.0) {
|
|
|
nativeCount = 1;
|
|
|
logger.debug('native > 1.0', tokenCount);
|
|
|
- nativeGasPrice = parseInt(nativeCount) * parseInt(account_config.BNB_GAS_LIMIT) * parseInt(account_config.BNB_GAS_PRICE);
|
|
|
+
|
|
|
+ var lastBnbFree = await redis.readRedis(reids_token_config.LAST_TOTAL_BNB_FREE)
|
|
|
+ logger.log('LAST_TOTAL_BNB_FREE=', lastBnbFree);
|
|
|
+ if (lastTokenFree && reids_token_config.LAST_TOTAL_TOKEN_FREE && parseInt(lastTokenFree) > 0) {
|
|
|
+ nativeGasPrice = parseInt(nativeCount) * parseInt(lastBnbFree);
|
|
|
+ } else {
|
|
|
+ nativeGasPrice = parseInt(nativeCount) * parseInt(account_config.BNB_GAS_LIMIT) * parseInt(account_config.BNB_GAS_PRICE);
|
|
|
+ }
|
|
|
ret_a_gas = account_config.BNB_GAS_PRICE;
|
|
|
}
|
|
|
}
|
|
@@ -142,8 +223,6 @@ async function computeTransferGasFree(my_account_all_coins, tokenPrices) {
|
|
|
logger.log('totalCount', totalCount);
|
|
|
|
|
|
|
|
|
-
|
|
|
-
|
|
|
var total2Gas = nativeGasPrice + tokenGasPrice;
|
|
|
var service_charge = 0;
|
|
|
logger.log('total2Gas', total2Gas);
|
|
@@ -152,7 +231,7 @@ async function computeTransferGasFree(my_account_all_coins, tokenPrices) {
|
|
|
if (nativeAllBalance < total2Gas) {
|
|
|
if (tokenCount > 0) {//出现 token 需要转移手续费
|
|
|
service_charge = 1;
|
|
|
- total2Gas = (total2Gas - nativeAllBalance);//充手续费
|
|
|
+ // total2Gas = (total2Gas - nativeAllBalance);//充手续费
|
|
|
logger.log('需要转账=', total2Gas);
|
|
|
}
|
|
|
}
|
|
@@ -182,6 +261,14 @@ function calculate_total_usdprice(amount, decimals, usdprice) {
|
|
|
}
|
|
|
|
|
|
|
|
|
+function addNativeValue(nativeValue, aValue) {
|
|
|
+ return BigInt(nativeValue) + BigInt(aValue)
|
|
|
+}
|
|
|
+
|
|
|
+function reduceNativeValue(nativeValue, rValue) {
|
|
|
+ return BigInt(nativeValue) - BigInt(rValue)
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* todo --> 计算 gas
|
|
|
* @param {*} nativeBalance
|
|
@@ -210,6 +297,9 @@ async function transfers(obj, my_account_all_coins) {
|
|
|
var chain = obj.chain;
|
|
|
var tokenPrices = obj.tokenPrices;
|
|
|
logger.log('tokenPrices=', tokenPrices, my_account_all_coins);
|
|
|
+
|
|
|
+ var nativeValue = my_account_all_coins.native.balance;
|
|
|
+
|
|
|
if (!my_account_all_coins || !tokenPrices) return 'error.'
|
|
|
|
|
|
logger.log(' my_account_all_coins.other.lenth=', my_account_all_coins.other.length);
|
|
@@ -226,11 +316,12 @@ async function transfers(obj, my_account_all_coins) {
|
|
|
var find_transfer_item = findTokenPriceItem(transfer_item.token_address, tokenPrices);
|
|
|
//todo 计算 token 币价格 * token美元单价
|
|
|
if (find_transfer_item && calculate_total_usdprice(transfer_item.balance, transfer_item.decimals, find_transfer_item.usdPrice) > 1.0) {
|
|
|
+ var info =await queryCompanyInfoFromId(0);
|
|
|
var obj_20 = {
|
|
|
chain: obj.chain,
|
|
|
contractAddress: transfer_item.token_address,
|
|
|
amount: transfer_item.balance,
|
|
|
- receiver: account_config.WELLET_PUBLIC_KEY,
|
|
|
+ receiver: info.user_address,
|
|
|
type: 'erc20',
|
|
|
address: address,
|
|
|
}
|
|
@@ -239,6 +330,17 @@ async function transfers(obj, my_account_all_coins) {
|
|
|
isUpdateNativeBalance = 1;
|
|
|
var ret = await start_collectCoins(obj_20)
|
|
|
logger.log('start_collectCoins erc20 respose...', ret);
|
|
|
+
|
|
|
+ //更新 native 金额
|
|
|
+ if (!isTransferSucceed(ret)) return ret;
|
|
|
+
|
|
|
+ var transfer = getTransferGasFree('token', ret)
|
|
|
+ if (transfer && transfer.totalGasFree > 0) {
|
|
|
+ logger.log('start_collectCoins 20 tempNativeValue=', my_account_all_coins.native.balance)
|
|
|
+ var tempNativeValue = reduceNativeValue(nativeValue, transfer.totalGasFree)
|
|
|
+ my_account_all_coins.native.balance = tempNativeValue.toString();
|
|
|
+ logger.log('start_collectCoins 20 udpateNativeValue=', tempNativeValue);
|
|
|
+ } else return "get native value error."
|
|
|
}
|
|
|
} else {
|
|
|
logger.error('token Must be greater than a dollar.', transfer_item.balance, transfer_item.decimals);
|
|
@@ -253,15 +355,7 @@ async function transfers(obj, my_account_all_coins) {
|
|
|
if (obj.chain) {
|
|
|
obj.chain = utils.getChainName(obj.chain)
|
|
|
}
|
|
|
- logger.log('查询本地余额 before', my_account_all_coins.native)
|
|
|
- if (isUpdateNativeBalance) {
|
|
|
- // do {
|
|
|
- var updateBalance = await updateNativeBalance(my_account_all_coins.native.balance, obj)
|
|
|
- if (updateBalance)
|
|
|
- my_account_all_coins.native.balance = updateBalance;
|
|
|
- else
|
|
|
- return 'updateNativeBalance error. '
|
|
|
- }
|
|
|
+
|
|
|
obj.chain = chain;
|
|
|
logger.log('查询本地余额 after', my_account_all_coins.native)
|
|
|
var find_native_item = findTokenPriceItem('0x0000000000000000000000000000000000000000', tokenPrices);
|
|
@@ -286,11 +380,11 @@ async function transfers(obj, my_account_all_coins) {
|
|
|
|
|
|
var real_native_amount = nativeBalance - gasPrice * gasLimit;
|
|
|
logger.log('start_collectCoins native amount:', real_native_amount.toString());
|
|
|
-
|
|
|
+ var info =await queryCompanyInfoFromId(0);
|
|
|
obj = {
|
|
|
chain: chain,
|
|
|
amount: real_native_amount.toString(),
|
|
|
- receiver: account_config.WELLET_PUBLIC_KEY,
|
|
|
+ receiver: info.user_address,
|
|
|
type: 'native',
|
|
|
address: address,
|
|
|
}
|
|
@@ -307,7 +401,56 @@ async function transfers(obj, my_account_all_coins) {
|
|
|
|
|
|
const start_collectCoins = async (obj) => {
|
|
|
obj.withdraw = 0;
|
|
|
- return await transfer(obj);
|
|
|
+ return await transfer_handle(obj);
|
|
|
+}
|
|
|
+
|
|
|
+const transfer_handle = async (obj) => {
|
|
|
+ //提币
|
|
|
+ if (obj.withdraw) {
|
|
|
+ var id = 0
|
|
|
+ if (obj.privateKeyId)
|
|
|
+ id = obj.privateKeyId
|
|
|
+
|
|
|
+ //读取用户充币地址对应的私钥
|
|
|
+ var info = await queryCompanyInfoFromId(id);
|
|
|
+ //提币公司
|
|
|
+ obj.privateKey = info.user_private_key;
|
|
|
+ // if (process.env.NODE_ENV != 'dev') {
|
|
|
+ logger.debug('readCompanyPriveteKeyFromMysql=', obj.privateKey)
|
|
|
+ // }
|
|
|
+ } else {
|
|
|
+ //读取用户充币地址对应的私钥
|
|
|
+ obj.privateKey = await readPriveteKeyFromMysql(obj.address);
|
|
|
+ }
|
|
|
+ if (obj.privateKey && obj.privateKey.results) {
|
|
|
+ obj.privateKey = obj.privateKey.results;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!obj.privateKey) {
|
|
|
+ return toJson(-1, null, "readPriveteKeyFromMysql error.");
|
|
|
+ }
|
|
|
+
|
|
|
+ //解密
|
|
|
+ obj.privateKey = utils.decryptPrivityKey(obj.privateKey);
|
|
|
+
|
|
|
+ if (!obj.privateKey) {
|
|
|
+ return toJson(-1, null, "decryptPrivityKey error.");
|
|
|
+ }
|
|
|
+
|
|
|
+ var ret = await transfer(obj);
|
|
|
+ if (isTransferSucceed(ret)) {
|
|
|
+ //缓存当前交易的 gas 费用
|
|
|
+ if (ret && obj.contractAddress) {
|
|
|
+ var tr = getTransferGasFree('token', ret)
|
|
|
+ logger.debug('cache key token LAST_TOTAL_TOKEN_FREE getTransferGasFree', tr)
|
|
|
+ redis.redis_set(reids_token_config.LAST_TOTAL_TOKEN_FREE, tr.totalGasFree);
|
|
|
+ } else {
|
|
|
+ var tr = getTransferGasFree('native', ret)
|
|
|
+ logger.debug('cache key LAST_TOTAL_BNB_FREE getTransferGasFree', tr)
|
|
|
+ redis.redis_set(reids_token_config.LAST_TOTAL_BNB_FREE, tr.totalGasFree);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
|
|
@@ -329,6 +472,7 @@ const collectCoins = async (obj) => {
|
|
|
|
|
|
//得到币价格
|
|
|
obj.tokenPrices = await redis.readRedis(reids_token_config.TOKENPRICE)
|
|
|
+ if (!obj.tokenPrices) return 'readRedis error'
|
|
|
if (typeof obj.tokenPrices == 'string')
|
|
|
obj.tokenPrices = JSON.parse(obj.tokenPrices);
|
|
|
|
|
@@ -338,24 +482,38 @@ const collectCoins = async (obj) => {
|
|
|
|
|
|
//是否需要归集
|
|
|
if (transFerGasFree.totalCount > 0) {
|
|
|
- //需要转移 gas 费
|
|
|
- if (parseInt(transFerGasFree.gasPrice) > 0 && transFerGasFree.get_service_charge == 1) {
|
|
|
+ //需要转移 gas 费
|
|
|
+ //每次都需要充值 gas 费
|
|
|
+ if (account_config.TRANSFER_GAS || (parseInt(transFerGasFree.gasPrice) > 0 && transFerGasFree.get_service_charge == 1)) {
|
|
|
+ var info =await queryCompanyInfoFromId(0);
|
|
|
var obj_wd = {
|
|
|
chain: chain,
|
|
|
amount: transFerGasFree.gasPrice,
|
|
|
receiver: obj.address,
|
|
|
type: 'native',
|
|
|
- address: account_config.WELLET_PUBLIC_KEY, //todo 正式环境需要替换从 mysql read
|
|
|
+ // address: account_config.WELLET_PUBLIC_KEY, //todo 正式环境需要替换从 mysql read
|
|
|
+ address: info.user_address, //todo 正式环境需要替换从 mysql read
|
|
|
}
|
|
|
logger.log('开始充值 gas ', obj_wd)
|
|
|
var ret = await withdraw(obj_wd)
|
|
|
logger.log('充值完成 gas ', ret)
|
|
|
|
|
|
- //更新本地余额
|
|
|
- var updateBalance = await updateNativeBalance(my_account_all_coins.native.balance, obj)
|
|
|
- if (updateBalance)
|
|
|
- my_account_all_coins.native.balance = updateBalance;
|
|
|
- else return "error."
|
|
|
+ if (!isTransferSucceed(ret)) return ret;
|
|
|
+
|
|
|
+ var transfer = getTransferGasFree('native', ret)
|
|
|
+ logger.log('getTransferGasFree transfer =', transfer)
|
|
|
+ if (transfer && transfer.nativeValue > 0) {
|
|
|
+ logger.log('tempNativeValue=', my_account_all_coins.native.balance)
|
|
|
+ var tempNativeValue = addNativeValue(my_account_all_coins.native.balance, transfer.nativeValue)
|
|
|
+ my_account_all_coins.native.balance = tempNativeValue.toString();
|
|
|
+ logger.log('udpateNativeValue=', tempNativeValue);
|
|
|
+ } else return "get native value error."
|
|
|
+
|
|
|
+ // //更新本地余额
|
|
|
+ // var updateBalance = await updateNativeBalance(my_account_all_coins.native.balance, obj)
|
|
|
+ // if (updateBalance)
|
|
|
+ // my_account_all_coins.native.balance = updateBalance;
|
|
|
+ // else return "error."
|
|
|
}
|
|
|
|
|
|
obj.chain = chain;
|
|
@@ -394,8 +552,16 @@ async function readPriveteKeyFromMysql(address) {
|
|
|
})
|
|
|
}
|
|
|
|
|
|
+async function queryCompanyInfoFromId(id) {
|
|
|
+ return new Promise(resolve => {
|
|
|
+ mysql.queryCompanyInfoFromId(id).then(ret => {
|
|
|
+ logger.log('readPriveteKeyFromMysql=', ret);
|
|
|
+ resolve(ret);
|
|
|
+ })
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
const transfer = async (obj) => {
|
|
|
- logger.debug("fun transfer in ", obj);
|
|
|
logger.debug("fun transfer serverUrl ", serverUrl);
|
|
|
logger.debug("fun transfer appId ", serverUrl);
|
|
|
logger.debug("fun transfer moralisSecret ", moralisSecret);
|
|
@@ -408,7 +574,7 @@ const transfer = async (obj) => {
|
|
|
opts.type = "erc20"; //native erc20
|
|
|
|
|
|
if (!obj.receiver || !obj.amount || parseInt(obj.amount) <= 0) {
|
|
|
- logger.error("transfer fun transfer parameter error.",obj.receiver,obj.amount,obj.amount);
|
|
|
+ logger.error("transfer fun transfer parameter error.", obj.receiver, obj.amount, obj.amount);
|
|
|
return toJson(ERROR_CODE_001, null, "please check receiver or amount parameter is ok ?");
|
|
|
}
|
|
|
if (obj.chain != null) {
|
|
@@ -438,26 +604,6 @@ const transfer = async (obj) => {
|
|
|
opts.privateKey = obj.privateKey;
|
|
|
}
|
|
|
|
|
|
- //提币
|
|
|
- if (obj.withdraw) {
|
|
|
- //提币公司
|
|
|
- opts.privateKey = account_config.WELLET_PRIVATE_KEY;
|
|
|
- } else {
|
|
|
- //读取用户充币地址对应的私钥
|
|
|
- opts.privateKey = await readPriveteKeyFromMysql(obj.address);
|
|
|
- if (opts.privateKey && opts.privateKey.results) {
|
|
|
- opts.privateKey = opts.privateKey.results;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (!opts.privateKey) {
|
|
|
- return toJson(-1, null, "decryptPrivityKey error.");
|
|
|
- }
|
|
|
-
|
|
|
- //解密
|
|
|
- opts.privateKey = utils.decryptPrivityKey(opts.privateKey);
|
|
|
-
|
|
|
- logger.log('decryptPrivityKey privateKey=', opts.privateKey);
|
|
|
try {
|
|
|
// sending 0.5 DAI tokens with 18 decimals on BSC testnet
|
|
|
var options;
|
|
@@ -468,14 +614,14 @@ const transfer = async (obj) => {
|
|
|
receiver: opts.receiver, //接收钱包地址
|
|
|
contractAddress: opts.contractAddress //用户合约地址
|
|
|
};
|
|
|
- logger.log("options 20 =", options);
|
|
|
+ logger.tlog("options 20 =", options);
|
|
|
} else { //ETH or BNB
|
|
|
options = Moralis.TransferOptions = {
|
|
|
type: opts.type,
|
|
|
amount: opts.amount,
|
|
|
receiver: opts.receiver, //接收钱包地址
|
|
|
};
|
|
|
- logger.log("options native =", options, opts.chainId);
|
|
|
+ logger.tlog("options native =", options, opts.chainId);
|
|
|
}
|
|
|
|
|
|
// Enable web3
|
|
@@ -484,10 +630,12 @@ const transfer = async (obj) => {
|
|
|
chainId: opts.chainId,
|
|
|
privateKey: opts.privateKey,
|
|
|
});
|
|
|
+ logger.tlog("options id =", opts.chainId);
|
|
|
var ret = await Moralis.transfer(options);
|
|
|
+ logger.tlog("transfer 结果 =", ret);
|
|
|
return toJson(SUCCEED_CODE, ret, "");
|
|
|
} catch (error) {
|
|
|
- logger.error('transfer error:', error);
|
|
|
+ logger.tlog('transfer error:', error);
|
|
|
if (error.reason != null) {
|
|
|
return toJson(ERROR_CODE_001, null, error.toString());
|
|
|
} else {
|
|
@@ -582,10 +730,10 @@ async function getTokenTransfers(opt) {
|
|
|
}
|
|
|
//主流币
|
|
|
var t_1 = await Moralis.Web3API.account.getTransactions(options);
|
|
|
- setTransfersDataType('native',t_1.result)
|
|
|
+ setTransfersDataType('native', t_1.result)
|
|
|
//20币
|
|
|
var t_2 = await Moralis.Web3API.account.getTokenTransfers(options);
|
|
|
- setTransfersDataType('token',t_2.result)
|
|
|
+ setTransfersDataType('token', t_2.result)
|
|
|
let arr = t_1.result;
|
|
|
let arr1 = t_2.result;
|
|
|
if (Array.isArray(arr1) && Array.isArray(arr)) {
|