瀏覽代碼

merge test

DevYK 2 年之前
父節點
當前提交
b4f55016f9
共有 18 個文件被更改,包括 751 次插入132 次删除
  1. 7 0
      README.md
  2. 4 1
      app.js
  3. 6 2
      config/dev_config.js
  4. 4 0
      config/prd_config.js
  5. 8 2
      config/test_config.js
  6. 0 0
      model/core/moralis_core.js
  7. 7 4
      model/db/mysql_db.js
  8. 26 4
      model/db/redis_db.js
  9. 219 0
      model/db/withdraw_db.js
  10. 27 0
      model/feishu.js
  11. 3 1
      model/logger.js
  12. 64 43
      model/moralis_sdk.js
  13. 10 7
      model/report.js
  14. 3 4
      model/timer.js
  15. 19 3
      model/utils.js
  16. 286 46
      routes/sdk.js
  17. 26 12
      test/db_test.js
  18. 32 3
      test/test.js

+ 7 - 0
README.md

@@ -45,7 +45,13 @@ ssh -i /home/ubuntu/denet-security.pem   ubuntu@10.0.1.25
 pm2 logs
 
 ```
+
+监控:
+https://open.feishu.cn/open-apis/bot/v2/hook/18dfe21f-b1bd-46ca-a8c7-c85e1c84f02d
+
 ## 文档
+- [moralis 中文版](https://www.w3cschool.cn/moralis/moralis-39s73nzu.html)
+- [moralis 英文版](https://docs.moralis.io/moralis-dapp/web3-api/rate-limit)
 - [token 技术文档](https://st94nif1cq.feishu.cn/docs/doccnNxG2UwHPCdZXbywgbdy13f)
 - [项目排期](https://st94nif1cq.feishu.cn/docs/doccntqBN5JHQriK7xz1SId3EC0)
 - [node 业务服务流程图](https://st94nif1cq.feishu.cn/docs/doccn45PiFsrLnlDLjs5KXNa57d#)
@@ -53,3 +59,4 @@ pm2 logs
 - [moralis server](https://admin.moralis.io/servers)
 - [node 服务文档 ](https://st94nif1cq.feishu.cn/docs/doccnNxG2UwHPCdZXbywgbdy13f#)
 - [测试币准备](https://st94nif1cq.feishu.cn/docs/doccn2G0r0HOH0L1Z05uaJDFA2g#)
+- [监控预警](https://github.com/zhangky01/feishu-robot)

+ 4 - 1
app.js

@@ -18,6 +18,9 @@ var test = require('./test/test');
 // error handler
 onerror(app)
 
+
+// log.error("getTransactions error:", 'error')
+
 // middlewares
 app.use(bodyparser({
   enableTypes: ['json', 'form', 'text']
@@ -48,7 +51,7 @@ app.use(db_test.routes(), db_test.allowedMethods())
 app.use(test.routes(), test.allowedMethods())
 // error-handling
 app.on('error', (err, ctx) => {
-  log.error('server error', err, ctx)
+  log.error('server error ', err.toString())
 });
 
 

+ 6 - 2
config/dev_config.js

@@ -1,7 +1,7 @@
 const cryppt_config = {
     KEY: 'NENET_CRYPT_KEY',
     KEY_IV: 'NENET_CRYPT_IV',
-    WITHDRAW_KEY:'denet!@#$%^&2022',
+    WITHDRAW_KEY: 'denet!@#$%^&2022',
 }
 
 
@@ -14,7 +14,7 @@ const account_config = {
     WELLET_PUBLIC_KEY: '0xAD48D13E77011cFE03fF19729B6A247847AfD28E',
     TOKEN_GAS_LIMIT: '80000',
     BNB_GAS_LIMIT: '21000',
-    BNB_GAS_PRICE: '10000000000',
+    BNB_GAS_PRICE: '13000000000',
     TRANSFER_GAS: true,
 }
 
@@ -25,6 +25,10 @@ const reids_token_config = {
     LAST_TOTAL_BNB_FREE: 'LAST_TOTAL_BNB_FREE',
     LAST_TOTAL_TOKEN_FREE: 'LAST_TOTAL_TOKEN_FREE',
     LAST_GAS_PRICE: 'LAST_TOKEN_GAS_PRICE',
+    WITHDRAW_QUEUE_KEY: 'WITHDRAW_QUEUE_KEY_DEV',
+    WITHDRAW_QUEUE_STATUS:'WITHDRAW_QUEUE_STATUS',
+    COLLECT_CONIS_QUEUE_KEY:'COLLECT_CONIS_QUEUE_KEY_DEV',
+
 }
 
 // http 埋点上报配置

+ 4 - 0
config/prd_config.js

@@ -24,6 +24,10 @@ const reids_token_config = {
     LAST_TOTAL_BNB_FREE: 'LAST_TOTAL_BNB_FREE',
     LAST_TOTAL_TOKEN_FREE: 'LAST_TOTAL_TOKEN_FREE',
     LAST_GAS_PRICE: 'LAST_TOKEN_GAS_PRICE',
+    WITHDRAW_QUEUE_KEY: 'WITHDRAW_QUEUE_KEY',
+    WITHDRAW_QUEUE_STATUS:'WITHDRAW_QUEUE_STATUS',
+    COLLECT_CONIS_QUEUE_KEY:'COLLECT_CONIS_QUEUE_KEY',
+    
 
 }
 

+ 8 - 2
config/test_config.js

@@ -7,7 +7,7 @@ const account_config = {
     WELLET_PUBLIC_KEY: '0xAD48D13E77011cFE03fF19729B6A247847AfD28E',
     TOKEN_GAS_LIMIT: '80000',
     BNB_GAS_LIMIT: '21000',
-    BNB_GAS_PRICE: '10000000000',
+    BNB_GAS_PRICE: '13000000000',
     TRANSFER_GAS: true,
 }
 
@@ -24,6 +24,9 @@ const reids_token_config = {
     LAST_TOTAL_BNB_FREE: 'LAST_TOTAL_BNB_FREE',
     LAST_TOTAL_TOKEN_FREE: 'LAST_TOTAL_TOKEN_FREE',
     LAST_GAS_PRICE: 'LAST_TOKEN_GAS_PRICE',
+    WITHDRAW_QUEUE_KEY: 'WITHDRAW_QUEUE_KEY',
+    WITHDRAW_QUEUE_STATUS:'WITHDRAW_QUEUE_STATUS',
+    COLLECT_CONIS_QUEUE_KEY:'COLLECT_CONIS_QUEUE_KEY',
 }
 
 
@@ -62,10 +65,13 @@ const moralis_config = {
     MASTER_KEY: "YbEUAR49HwBZ8R6Q8eNTNfwtStPFPcCYehJQkYcl",
     MORALIS_SECRET: "BGlDVjy7054iLDpDcdc9AbH65rZrhj8QIhsThcwF6thNzTnbS2ft8XmM70x4jOpU",
     DEFAULT_PRIVATE_KEY: "xxx",
+    // SERVER_URL: "https://ibvcojbk1qau.usemoralis.com:2053/server",
+    // APP_ID: "AtqyMPVoEGhT6szQtl4iwsk3GkKHFPdDJJpp3Fs9",
+    // MASTER_KEY: "YM89Fna2MK7u1Bb6C0y7yyTUSQm6e4vCNDUfwez6",
+    // MORALIS_SECRET: "J0GEeEBh5MVtabeWI6XWuIPWSilnw4HVS6hEiSXJEX4zcN0rlMIGb0EkToUc0lGb"
 }
 
 
-
 const logger_config = {
     BASE_PATH: `/datalog/denetnode`,
 }

+ 0 - 0
model/core/moralis_core.js


+ 7 - 4
model/mysql_db.js → model/db/mysql_db.js

@@ -4,9 +4,9 @@
 //https://github.com/mysqljs/mysql
 
 var mysql = require('mysql');
-var { db_config } = require('../config/config.js')
-const logger = require('./logger')
-const utils = require('./utils.js')
+var { db_config } = require('../../config/config.js')
+const logger = require('../logger')
+const utils = require('../utils.js')
 var port = db_config.mysql.PORT
 var host = db_config.mysql.HOST
 var username = db_config.mysql.USERNAME
@@ -68,7 +68,7 @@ function addConnEvent() {
         });
 
         MYSQL_INSTANCE.on('connection', function (connection) {
-            logger.log('mysql connection', connection);
+            logger.log('mysql connection', connection.threadId);
         });
         MYSQL_INSTANCE.on('enqueue', function () {
             logger.log('Waiting for available connection slot');
@@ -301,8 +301,11 @@ function queryAllUserPrivateKeyAndUserAddress() {
 //查询语句
 //SELECT * FROM user_key_manage WHERE user_address='0x049D33EEE7432DB14c50911fAE4a7C38624313aA'
 
+
+
 module.exports = {
     queryUserPrivateKeyFromUserAddress,
     queryAllUserPrivateKeyAndUserAddress,
     queryCompanyInfoFromId,
+    getMySqlInstance,
 };

+ 26 - 4
model/redis_db.js → model/db/redis_db.js

@@ -1,6 +1,6 @@
 var Redis = require('ioredis');  //导入 安装好的 redis.  npm i ioredis --save 
-var { db_config } = require('../config/config.js') // 导入位置文件
-const logger = require('./logger')
+var { db_config } = require('../../config/config.js') // 导入位置文件
+const logger = require('../logger')
 //redis 服务启动 /usr/local/bin/redis-server /usr/local/etc/redis.conf
 
 
@@ -51,11 +51,31 @@ REDIS_INSTANCE.on('error', function (err) {
 });
 
 function redis_set(key, value) {
-  logger.log("redis set=", key,value);
+  logger.log("redis set=", key, value);
   try {
     REDIS_INSTANCE.set(key, value);
   } catch (error) {
-    logger.error('redis_set error:', key,value, error)
+    logger.error('redis_set error:', key, value, error)
+    return null;
+  }
+}
+
+function redis_push(key, value) {
+  logger.log("redis_push=", key, value);
+  try {
+    REDIS_INSTANCE.rpush(key, value);
+  } catch (error) {
+    logger.error('redis_push error:', key, value, error)
+    return null;
+  }
+}
+
+function redis_pop(key) {
+  logger.log("redis_pop=", key);
+  try {
+    return REDIS_INSTANCE.lpop(key);
+  } catch (error) {
+    logger.error('redis_pop error:', key, error)
     return null;
   }
 }
@@ -91,6 +111,8 @@ async function readRedis(key) {
 
 module.exports = {
   redis_set,
+  redis_push,
+  redis_pop,
   redis_get,
   readRedis,
 }

+ 219 - 0
model/db/withdraw_db.js

@@ -0,0 +1,219 @@
+
+const mysql = require("./mysql_db")
+const logger = require('../logger')
+var { db_config } = require('../../config/config.js')
+const utils = require('../utils.js')
+/**
+ * 创建提币任务
+ * 
+ * @param {*} task_obj 
+ */
+async function create_withdraw_task(task_obj) {
+    logger.log('create_withdraw_task', task_obj)
+    // 提币 id
+    var withdraw_id = task_obj.withdraw_id;
+    if (!withdraw_id) {
+        return {
+            code: -1,
+            error: 'withdraw_id cannot be empty.'
+        }
+    }
+    //提币任务创建时间
+    var withdraw_create_time = utils.getTimestamp();
+    var from_address = task_obj.user_address
+    var to_address = task_obj.receiver
+    var contract_address = task_obj.contractAddress
+    var chain_id = parseInt(utils.getChainId(task_obj.chain))
+    var type = task_obj.type
+    var amount = task_obj.amount
+
+    if (!from_address || !to_address) {
+        return {
+            code: -1,
+            error: 'from_address and to_address cannot be empty.'
+        }
+    }
+    var create_withdraw_sql = 'INSERT INTO withdraw_manage (withdraw_id,withdraw_status,create_time,from_address,to_address,chain_id,type,contract_address,amount)' +
+        'VALUES(?,?,?,?,?,?,?,?,?)'
+    var create_withdraw_params = [withdraw_id, 0, withdraw_create_time, from_address, to_address, chain_id, type, contract_address ? contract_address : '', amount]
+
+    logger.log('create_withdraw_task create_withdraw_sql', create_withdraw_sql);
+    return new Promise((resolve) => {
+        mysql.getMySqlInstance().getConnection(function (err, connection) {
+            if (err) {
+                logger.error('create_withdraw_task', err)
+                logger.error('create_withdraw_sql', create_withdraw_sql)
+                resolve(null);
+                return;
+            }
+            connection.query(
+                create_withdraw_sql, create_withdraw_params,
+                function selectCb(error, results) {
+                    if (error) {
+                        logger.error('create_withdraw_task', error, create_withdraw_sql, create_withdraw_params)
+                        resolve(null);
+                        return;
+                    }
+                    logger.log('create_withdraw_task ret=', error, results);
+                    //用完当前连接需要释放,归还给连接池
+                    connection.release();
+                    resolve({
+                        err: error,
+                        results: results.insertId
+                    });
+                }
+            );
+        })
+    })
+
+}
+
+/**
+ * 更新提币任务
+ * @param {*} task_obj 
+ */
+function update_withdraw_task(withdraw_id, ret_obj) {
+    logger.log('update_withdraw_task', ret_obj, withdraw_id)
+    // 提币 id
+    var withdraw_id = withdraw_id;
+    if (!withdraw_id) {
+        return {
+            code: -1,
+            error: 'withdraw_id cannot be empty.'
+        }
+    }
+    var update_withdraw_sql = 'update  withdraw_manage SET withdraw_status=?,withdraw_hash=?,nonce=?,update_time=?,gas_price=?,gas_limit=?,value=?,errorMsg=? WHERE withdraw_id=?'
+
+    var status = ret_obj.withdraw_status
+    var hash = ret_obj.withdraw_hash
+    var nonce = ret_obj.nonce
+    var update_time = ret_obj.update_time
+    var gas_price = ret_obj.gas_price
+    var gas_limit = ret_obj.gas_limit
+    if (!status)
+        status = 3
+    if (!update_time)
+        update_time = utils.getTimestamp()
+    var update_withdraw_params = [status, hash, nonce, update_time, gas_price, gas_limit, ret_obj.value, ret_obj.errorMsg ? ret_obj.errorMsg : '', withdraw_id]
+    return new Promise((resolve) => {
+        mysql.getMySqlInstance().getConnection(function (err, connection) {
+            if (err) {
+                logger.error('update_withdraw_task', err)
+                logger.error('update_withdraw_task', update_withdraw_sql)
+                resolve(null);
+                return;
+            }
+            connection.query(
+                update_withdraw_sql, update_withdraw_params,
+                function selectCb(error, results) {
+                    if (error) {
+                        logger.error('update_withdraw_task', error, update_withdraw_sql, update_withdraw_params)
+                        resolve(null);
+                        return;
+                    }
+                    logger.log('update_withdraw_task ret=', error, results);
+                    //用完当前连接需要释放,归还给连接池
+                    connection.release();
+                    resolve({
+                        err: error,
+                        results: results
+                    });
+                }
+            );
+        })
+    })
+}
+
+function queryWithdrawInfoFromWithdrawId(withdrawId){
+    logger.log('queryWithdrawInfoFromWithdrawId', withdrawId)
+    // 提币 id
+    if (!withdrawId) {
+        return {
+            code: -1,
+            error: 'withdraw_id cannot be empty.'
+        }
+    }
+    var create_withdraw_sql = 'select * from withdraw_manage WHERE withdraw_id=?'
+    var create_withdraw_params = [withdrawId]
+    return new Promise((resolve) => {
+        mysql.getMySqlInstance().getConnection(function (err, connection) {
+            if (err) {
+                logger.error('queryWithdrawInfoFromWithdrawId', err)
+                logger.error('queryWithdrawInfoFromWithdrawId', create_withdraw_sql)
+                resolve(null);
+                return;
+            }
+            connection.query(
+                create_withdraw_sql, create_withdraw_params,
+                function selectCb(error, results) {
+                    if (error) {
+                        logger.error('queryWithdrawInfoFromWithdrawId', error, create_withdraw_sql, create_withdraw_params)
+                        resolve(null);
+                        return;
+                    }
+                    logger.log('queryWithdrawInfoFromWithdrawId ret=', error, results);
+                    //用完当前连接需要释放,归还给连接池
+                    connection.release();
+                    if (results && Array.isArray(results) && results.length > 0) {
+                        resolve(results[0]);
+                    } else {
+                        resolve(null);
+                    }
+                }
+            );
+        })
+    })
+}
+
+/**
+ * 判断该任务是否存在
+ * @param {*} withdrawId 
+ */
+function withdraw_id_exist(withdrawId) {
+    logger.log('create_withdraw_task', withdrawId)
+    // 提币 id
+    if (!withdrawId) {
+        return {
+            code: -1,
+            error: 'withdraw_id cannot be empty.'
+        }
+    }
+    var create_withdraw_sql = 'select * from withdraw_manage WHERE withdraw_id=?'
+    var create_withdraw_params = [withdrawId]
+    return new Promise((resolve) => {
+        mysql.getMySqlInstance().getConnection(function (err, connection) {
+            if (err) {
+                logger.error('withdraw_id_exist', err)
+                logger.error('withdraw_id_exist', create_withdraw_sql)
+                resolve(null);
+                return;
+            }
+            connection.query(
+                create_withdraw_sql, create_withdraw_params,
+                function selectCb(error, results) {
+                    if (error) {
+                        logger.error('withdraw_id_exist', error, create_withdraw_sql, create_withdraw_params)
+                        resolve(null);
+                        return;
+                    }
+                    logger.log('withdraw_id_exist ret=', error, results);
+                    //用完当前连接需要释放,归还给连接池
+                    connection.release();
+                    if (results && Array.isArray(results) && results.length > 0) {
+                        resolve(true);
+                    } else {
+                        resolve(false);
+                    }
+                }
+            );
+        })
+    })
+}
+
+
+module.exports = {
+    create_withdraw_task,
+    update_withdraw_task,
+    queryWithdrawInfoFromWithdrawId,
+    withdraw_id_exist
+}

+ 27 - 0
model/feishu.js

@@ -0,0 +1,27 @@
+
+const axios = require('axios');
+
+const url = 'https://open.feishu.cn/open-apis/bot/v2/hook/18dfe21f-b1bd-46ca-a8c7-c85e1c84f02d'
+
+const sendMessage = async (...params) => {
+    var log = '环境:'+process.env.NODE_ENV +' ----> ';
+    for (let index = 0; index < params.length; index++) {
+        log = log.concat(params[index].toString())
+    }
+    params = log;
+    console.log('sendMessage', log)
+    var data = {
+        msg_type: "text",
+        content: { text: params }
+    }
+    axios.post(url, data)
+        .then(res => {
+            console.log('res=>', res.status, res.data);
+        }).catch(err => {
+            console.error('http_request_post error ', err);
+        });
+}
+
+module.exports = {
+    sendMessage
+}

+ 3 - 1
model/logger.js

@@ -4,6 +4,7 @@
 
 const log4js = require('log4js')
 var { logger_config } = require('../config/config.js')
+var feishu = require('./feishu')
 
 const BASE_PATH = logger_config.BASE_PATH
 
@@ -77,6 +78,7 @@ module.exports = {
     },
     error() {
         errorLogger.error.call(errorLogger, ...arguments)
+        feishu.sendMessage(...arguments)
     },
     fatal() {
         errorLogger.fatal.call(errorLogger, ...arguments)
@@ -86,7 +88,7 @@ module.exports = {
     },
 
     //转账log
-    tlog(){
+    tlog() {
         return transferLogger.debug.call(transferLogger, ...arguments)
     }
 }

+ 64 - 43
model/moralis_sdk.js

@@ -4,8 +4,8 @@ var utils = require('./utils.js');
 // var config = require('../config/config.js')(db_config,
 //     moralis_config)
 var { moralis_config, reids_token_config, account_config } = require('../config/config.js')
-const redis = require("./redis_db")  //导入 db.js
-const mysql = require("./mysql_db")
+const redis = require("./db/redis_db")  //导入 db.js
+const mysql = require("./db/mysql_db")
 const logger = require('./logger')
 const report = require("./report")  //导入 db.js
 const BigNumber = require('bignumber.js')
@@ -27,13 +27,19 @@ var isExecCollect = false;
 var masterInit = false
 var secretInit = false
 
-
 // 对 shib 做限制
 const SHIB_AMOUNT_LIMIT = 20000
 const SHIB_AMOUNT_FEE_LIMIT = 10000
 const SHIB_ADDRESS = '0x2859e4544C4bB03966803b044A93563Bd2D0DD4D'
 
 
+
+// logger.log('Moralis.settings',Moralis)
+// Moralis.settings.setAPIRateLimit({
+//     anonymous:10, authenticated:20, windowMs:60000
+//   })
+
+
 /**
  * 初始化 moralis
  * https://st94nif1cq.feishu.cn/docs/doccnNxG2UwHPCdZXbywgbdy13f#
@@ -175,7 +181,7 @@ async function getAccountBalances(options) {
             return aar;
         }
     } catch (error) {
-        logger.error('getAccountBalances error:', error)
+        logger.error('getBalances error:', error.toString(), JSON.stringify(options))
         return null
     }
 
@@ -226,10 +232,8 @@ async function computeTransferGasFree(obj, my_account_all_coins, tokenPrices) {
     var receiver_info = await queryCompanyInfoFromId(0);
     //得到 20 币 满足 1美刀的 count
     if (Array.isArray(my_account_all_coins.other) && my_account_all_coins.other.length > 0) {
-
         for (let index = 0; index < my_account_all_coins.other.length; index++) {
             const element = my_account_all_coins.other[index];
-            // }
             // my_account_all_coins.other.forEach(element => {
             logger.log('20 element=', element);
             var find_transfer_item = findTokenPriceItem(element.token_address, tokenPrices);
@@ -243,10 +247,10 @@ async function computeTransferGasFree(obj, my_account_all_coins, tokenPrices) {
 
             if (find_transfer_item) {
                 var total_all_usdprice = calculate_total_usdprice(element.balance, element.decimals, find_transfer_item.usdPrice);
-                logger.debug('findTokenPriceItem ret=', element.token_address, find_transfer_item, total_all_usdprice);
+                logger.log('findTokenPriceItem ret=', element.token_address, find_transfer_item, total_all_usdprice);
                 if (find_transfer_item && total_all_usdprice > 1.0) {
                     tokenCount += 1;
-                    logger.debug('token > 1.0', tokenCount, element.token_address);
+                    logger.log('token > 1.0', tokenCount, element.token_address);
 
                     var obj_20 = {
                         chain: obj.chain,
@@ -259,7 +263,7 @@ async function computeTransferGasFree(obj, my_account_all_coins, tokenPrices) {
                     transfer_obj.push(obj_20)
                 }
             } else {
-                logger.log('findTokenPriceItem error=', element);
+                logger.log('findTokenPriceItem not fount =', element);
             }
             // });
         }
@@ -280,17 +284,17 @@ async function computeTransferGasFree(obj, my_account_all_coins, tokenPrices) {
     //计算 native 是否满足 1美刀
     logger.log('isTransferGasFree token count:', tokenCount);
     var nativeAllBalance = 0;
-    if (my_account_all_coins.native.balance)
+    if (my_account_all_coins.native && my_account_all_coins.native.balance)
         nativeAllBalance = my_account_all_coins.native.balance
     var nativeCount = 0
     var nativePriceItem = findTokenPriceItem('0x0000000000000000000000000000000000000000', tokenPrices);//todo 线上环境需要换
-    logger.debug('native nativePriceItem=', nativePriceItem, nativeAllBalance);
+    logger.log('native nativePriceItem=', nativePriceItem, nativeAllBalance);
     if (nativePriceItem) {
         var total_all_usdprice = calculate_total_usdprice(nativeAllBalance, '18', nativePriceItem.usdPrice);
-        logger.debug('native total_all_usdprice=', total_all_usdprice);
+        logger.log('native total_all_usdprice=', total_all_usdprice);
         if (total_all_usdprice > 1.0) {
             nativeCount = 1;
-            logger.debug('native > 1.0', tokenCount);
+            logger.log('native > 1.0', tokenCount);
 
             var lastBnbFree = await redis.readRedis(reids_token_config.LAST_TOTAL_BNB_FREE)
             logger.log('LAST_TOTAL_BNB_FREE=', lastBnbFree);
@@ -441,6 +445,7 @@ async function transfers(obj, my_account_all_coins, logParams) {
                 }
             } else {
                 logger.tlog('start_collectCoins  error=', ret);
+                logger.error('start_collectCoins 归集 error=', ret, ti.toString());
             };
         }
         if (t_i == my_account_all_coins.transfer_arrays.length) {
@@ -483,7 +488,7 @@ const transfer_handle = async (obj) => {
         //提币公司
         obj.privateKey = info.user_private_key;
         // if (process.env.NODE_ENV != 'dev') {
-        logger.debug('readCompanyPriveteKeyFromMysql=', obj.privateKey)
+        logger.log('readCompanyPriveteKeyFromMysql=', obj.privateKey)
         // }
     } else {
         //读取用户充币地址对应的私钥
@@ -494,6 +499,8 @@ const transfer_handle = async (obj) => {
     }
 
     if (!obj.privateKey) {
+        logger.error('readPriveteKeyFromMysql error.', obj);
+        //提币公司
         return toJson(-1, null, "readPriveteKeyFromMysql error.");
     }
 
@@ -502,18 +509,16 @@ const transfer_handle = async (obj) => {
         obj.privateKey = utils.decryptPrivityKey(obj.privateKey);
 
         if (!obj.privateKey) {
+            logger.error('decryptPrivityKey error', obj);
             return toJson(-1, null, "decryptPrivityKey error.");
         }
     } catch (error) {
+        logger.error('decryptPrivityKey error', error.toString(), JSON.stringify(obj));
         if (!obj.privateKey) {
             return toJson(-1, null, "decryptPrivityKey error.", error.toString());
         }
     }
 
-    if (!obj.privateKey) {
-        return toJson(-1, null, "decryptPrivityKey error.");
-    }
-
 
     var ret = await transfer(obj);
     if (isTransferSucceed(ret)) {
@@ -527,6 +532,8 @@ const transfer_handle = async (obj) => {
             logger.debug('cache setkey LAST_TOTAL_BNB_FREE getTransferGasFree', tr)
             redis.redis_set(reids_token_config.LAST_TOTAL_BNB_FREE, tr.totalGasFree);
         }
+    } else {
+        logger.error('transfer_handle transfer error', JSON.stringify(obj));
     }
     return ret;
 }
@@ -545,6 +552,7 @@ async function queryCollectBalance(address, chain) {
         // return await getAccountBalances(queryCollectBalance);
         return await getAccountAllCoins(queryCollectBalance);
     } catch (error) {
+        logger.error('queryCollectBalance error', error.toString(), address, chain);
         return 0;
     }
 
@@ -561,6 +569,7 @@ async function queryCollectBalance(address, chain) {
  * @param {*} obj 
  */
 const collectCoins = async (obj) => {
+    logger.log('fun collectCoins in =', obj)
     var chain = obj.chain;
     //1、拿到当前账户所有的币
     //2、是否满足交易费 如果不满足则 归集地址转移 币count * 手续费 到充币地址
@@ -570,8 +579,8 @@ const collectCoins = async (obj) => {
     var logParams = {};
 
     var my_account_all_coins = await getAccountAllCoins(obj);
-    logger.log('getAccountAllCoins=', my_account_all_coins)
-    if (!my_account_all_coins.native && !my_account_all_coins.other) {
+    logger.log('collectCoins getAccountAllCoins=', my_account_all_coins)
+    if (!my_account_all_coins.native  && !my_account_all_coins.other) {
         return 'getAccountAllCoins error.' + my_account_all_coins
     }
 
@@ -582,14 +591,16 @@ const collectCoins = async (obj) => {
     if (process.env.NODE_ENV == 'dev') {
         var test_json = '{"tokenPrice": [{"contract": "0x0000000000000000000000000000000000000000", "usdPrice": 400}, {"contract": "0x03716F32f72c692a0B355fa04639669E3341B94e", "usdPrice": 0.1}]}'
         obj.tokenPrices = JSON.parse(test_json);
-        logger.log('dev tokenPrices=', obj.tokenPrices)
     } else {
         obj.tokenPrices = await redis.readRedis(reids_token_config.TOKENPRICE)
-        if (!obj.tokenPrices) return 'readRedis error'
+        if (!obj.tokenPrices) {
+            logger.error('readRedis TOKENPRICE error')
+            return 'readRedis error'
+        }
         if (typeof obj.tokenPrices == 'string')
             obj.tokenPrices = JSON.parse(obj.tokenPrices);
     }
-
+    logger.log('tokenPrices=', obj.tokenPrices)
 
     obj.chain = chain;
     //计算 gas 费用 是否需要归集
@@ -606,9 +617,6 @@ const collectCoins = async (obj) => {
 
     logger.log('computeTransferGasFree=', transFerGasFree)
     logger.log(' logParams.transfers=', logParams.transfers)
-    if (transFerGasFree) {
-        // return
-    }
 
     //是否需要归集
     if (transFerGasFree.totalCount > 0) {
@@ -635,7 +643,6 @@ const collectCoins = async (obj) => {
 
             if (!isTransferSucceed(ret)) return ret;
 
-
             var transfer = getTransferGasFree('native', ret)
             logger.log('getTransferGasFree transfer =', transfer)
             if (transfer && transfer.nativeValue > 0) {
@@ -644,7 +651,6 @@ const collectCoins = async (obj) => {
                 my_account_all_coins.native.balance = tempNativeValue.toString();
                 logger.log('udpateNativeValue=', tempNativeValue);
             } else return "get native value error."
-
         }
 
         obj.chain = chain;
@@ -674,7 +680,7 @@ async function execCollectCoinsTask() {
 
 
 function pushCollectConisObj(obj) {
-    logger.debug('collectCoinsArrays length=', collectCoinsArrays.length, collectCoinsArrays)
+    logger.log('collectCoinsArrays length=', collectCoinsArrays.length, collectCoinsArrays)
     if (collectCoinsArrays.length > 0) {
         var findItem = collectCoinsArrays.find(element => {
             return (obj.address == element.address)
@@ -749,10 +755,9 @@ const transfer = async (obj) => {
     if (obj.privateKey != null) {
         opts.privateKey = obj.privateKey;
     }
-
+    var options;
     try {
         // sending 0.5 DAI tokens with 18 decimals on BSC testnet
-        var options;
         if (opts.contractAddress) { //如果存在就是代币
             
             // if (opts.contractAddress == SHIB_ADDRESS) {
@@ -793,10 +798,11 @@ const transfer = async (obj) => {
         return toJson(SUCCEED_CODE, ret, "");
     } catch (error) {
         logger.tlog('transfer error:', error);
+        logger.error('transfer error:', error.toString(), JSON.stringify(options))
         if (error.reason != null) {
             return toJson(ERROR_CODE_001, null, error.toString());
         } else {
-            return toJson(ERROR_CODE_001, null, error);;
+            return toJson(ERROR_CODE_001, null, error.toString());;
         }
     }
 };
@@ -842,14 +848,14 @@ function setTransfersDataType(type, ret) {
 //hash 0xe09ba3a4c9f7a8902e01af68d0f1f91906f3f7db1195227e61c45c0e86b2630a
 async function getTokenTransfers(opt) {
     await initMasterSDK();
-    logger.debug("fun getTokenTransfers in ", opt);
+    logger.log("fun getTokenTransfers in ", opt);
     const options = {};
     options.type = 'all';
     options.chain = 'bsc_mainnet';
 
     if (opt.chain != null) {
         options.chain = utils.getChainName(opt.chain);
-        logger.log('getTokenTransfers=', options.chain);
+        logger.log('getTokenTransfers getChainName =', options.chain);
     }
 
     if (opt.order != null) {
@@ -877,33 +883,46 @@ async function getTokenTransfers(opt) {
         options.type = 'transaction_hash';
     }
 
-    logger.debug('getTokenTransfers-->>>', options);
+    logger.log('getTokenTransfers >>>>>', options);
     if (options.type == 'all') {//查询主流币和 20 币所有的交易
         try {
             if (opt.address != null) {
                 options.address = opt.address;
             } else {
+                logger.error('getTokenTransfers error please check address parameter is ok ?', options);
                 return toJson(ERROR_CODE_001, null, "please check address parameter is ok ?");
             }
-            logger.log('getTransactions options', options)
+
+            logger.log('getTokenTransfers account getTransactions>>>>>', options);
             //主流币
             var t_1 = await Moralis.Web3API.account.getTransactions(options);
-            logger.log('getTransactions ret', t_1)
+            logger.log('getTokenTransfers native ret -->>> t_1', t_1);
             setTransfersDataType('native', t_1.result)
             //20币
             //token 获取交易记录如果没有时间有些地址会失败
             if (!options.to_block) {
                 options.to_block = '10000000000'
             }
-            logger.log('getTokenTransfers options', options)
+
+            logger.log('getTokenTransfers account getTokenTransfers>>>>>', options);
             var t_2 = await Moralis.Web3API.account.getTokenTransfers(options);
-            logger.log('getTransactions getTokenTransfers', t_2)
+
+            //异常
+            if (t_2 && t_2.total > 0 && Array.isArray(t_2.result) && t_2.result.length <= 0) {
+                logger.error('getTokenTransfers token 数据异常 -->>>', t_2.toString(), JSON.stringify(options));
+            }
+
+            logger.log('getTokenTransfers token ret -->>> t_2', t_2);
             setTransfersDataType('token', t_2.result)
             let arr = t_1.result;
             let arr1 = t_2.result;
             if (Array.isArray(arr1) && Array.isArray(arr)) {
                 let arr2 = arr.concat(arr1);
                 t_1.result = arr2;
+                logger.log('getTokenTransfers-->>> concat t_1', t_1);
+                if (t_1.total) {
+                    t_1.total = t_1.result.length
+                }
             }
 
             //将结果排序
@@ -912,24 +931,26 @@ async function getTokenTransfers(opt) {
                 let t2 = new Date(Date.parse(b.block_timestamp))
                 return t2.getTime() - t1.getTime()
             })
-            logger.log('getTransactions sort', t_1)
+            logger.log('getTokenTransfers-->>> sort t_1', t_1);
             return toJson(SUCCEED_CODE, t_1, null);
         } catch (error) {
-            logger.error("getTransactions error:", error)
+            logger.error("getTransactions error:", error.toString(), JSON.stringify(options))
             return toJson(ERROR_CODE_001, null, error.toString());
         }
     } else if (options.type == 'transaction_hash') {//根据哈希查询
         try {
+            logger.log('transaction_hash getTransaction options-->>> ', options);
             //native
             const transaction = await Moralis.Web3API.native.getTransaction(options);
             var arr = [];
             if (transaction)
                 arr.push(transaction)
             var obj = { result: arr }
+            logger.log('transaction_hash getTransaction ret-->>> ', transaction, obj);
             return toJson(SUCCEED_CODE, obj, null);
         } catch (error) {
-            logger.error("native getTransaction error:", error)
-            return toJson(ERROR_CODE_001, null, error);
+            logger.error("native getTransaction error:", error.toString(), JSON.stringify(options))
+            return toJson(ERROR_CODE_001, null, error.toString());
         }
     } else {
         return toJson(ERROR_CODE_001, null, "This type is not supported.");;

+ 10 - 7
model/report.js

@@ -1,8 +1,8 @@
 const axios = require('axios');
 var utils = require('./utils.js');
 var { http_log_report_config } = require('../config/config.js')
-const redis = require("./redis_db")  //导入 db.js
-const mysql = require("./mysql_db")
+const redis = require("./db/redis_db")  //导入 db.js
+const mysql = require("./db/mysql_db")
 const logger = require('./logger')
 
 //埋点文档 https://st94nif1cq.feishu.cn/docs/doccnoEvFRxdD0zy4I0MVhzCMLg#
@@ -11,7 +11,8 @@ const logger = require('./logger')
 const REPORT_TYPE = {
     transfer_record: 'transfer_record',
     collect_coins: 'collect_coins',
-    withdraw: 'withdraw'
+    withdraw: 'withdraw',
+    monitor: 'monitor'
 }
 
 
@@ -55,18 +56,20 @@ const logReport = async (obj) => {
                         return element.to_address.toString().toLowerCase() == obj.address.toString().toLowerCase()
                     })
                     // console.log('filter results', results)
-                    if (results) {
+                    if (results && Array.isArray(results) && results.length > 0) {
                         obj.results = results
+                    } else {
+                        return
                     }
-                } 
+                }
             }
             var params = {
                 eventData: obj
             }
             params.logType = http_log_report_config.LOG_TYPE
             logger.log('transfer_record')
-            if(!obj.results){
-                logger.log('transfer_record',obj.results)
+            if (!obj.results) {
+                logger.log('transfer_record', obj.results)
                 return
             }
             http_request_post(params);

+ 3 - 4
model/timer.js

@@ -1,10 +1,11 @@
 var { moralis_config, reids_token_config, account_config, timer_config } = require('../config/config.js')
-const redis = require("./redis_db")  //导入 db.js
-const mysql = require("./mysql_db")
+const redis = require("./db/redis_db")  //导入 db.js
+const mysql = require("./db/mysql_db")
 const moralis = require("./moralis_sdk")  //导入 db.js
 var utils = require('./utils.js');
 const logger = require('./logger')
 
+
 const interval_delay_time = 5000;
 const start_delay_time = 1000;
 
@@ -44,5 +45,3 @@ async function timedCollectCoins() {
     index++;
 }
 
-
-

+ 19 - 3
model/utils.js

@@ -57,7 +57,7 @@ const SECRET_IV = CryptoJS.enc.Utf8.parse("68F37CFC40C330D9FAAC0A16D49C8AD5");
  * @param data
  * @returns {string}
  */
- function encrypt(data) {
+function encrypt(data) {
     if (typeof data === "object") {
         try {
             data = JSON.stringify(data);
@@ -78,7 +78,7 @@ const SECRET_IV = CryptoJS.enc.Utf8.parse("68F37CFC40C330D9FAAC0A16D49C8AD5");
 * @param data
 * @returns {string}
 */
- function decrypt(data) {
+function decrypt(data) {
     // const key = CryptoJS.enc.Hex.parse(SECRET_KEY);
     const decrypt = CryptoJS.AES.decrypt(data, SECRET_KEY, {
         mode: CryptoJS.mode.ECB,
@@ -99,10 +99,20 @@ const CHAIN_ID = {
     bsc_mainnet: '0x38'
 }
 
+const CHAIN_ID_NAME = {
+    97: 'bsc_testnet',
+    56: 'bsc_mainnet',
+}
+
 function getChainName(key) {
     return CHAIN_NAME[key];
 }
 
+
+function getChainIdToName(key) {
+    return CHAIN_ID_NAME[key];
+}
+
 function getChainId(key) {
     return CHAIN_ID[key];
 }
@@ -111,6 +121,10 @@ function sleep(time) {
     return new Promise((resolve) => setTimeout(resolve, time));
 }
 
+function getTimestamp() {
+    return new Date().getTime()
+}
+
 module.exports = {
     toJson,
     decryptPrivityKey,
@@ -120,5 +134,7 @@ module.exports = {
     CHAIN_ID,
     sleep,
     encrypt,
-    decrypt
+    decrypt,
+    getTimestamp,
+    getChainIdToName,
 }

+ 286 - 46
routes/sdk.js

@@ -4,8 +4,10 @@ var utils = require('../model/utils.js');
 var { reids_token_config, account_config } = require('../config/config.js');
 const logger = require('../model/logger.js');
 router.prefix('/sdk');
-const redis = require("../model/redis_db")  //导入 db.js
+const redis = require("../model/db/redis_db")  //导入 db.js
+const withdraw_db = require("../model/db/withdraw_db")  //导入 db.js
 const report = require("../model/report")  //导入 db.js
+const BigNumber = require('bignumber.js')
 /**
  * 获取代币价格
  * @param {*} ctx 
@@ -24,15 +26,17 @@ async function getAllTotkenPrice(ctx) {
  * @param {*} ctx 
  */
 async function getTransfers(ctx) {
-    console.log("body", ctx);
     const obj = ctx.request.body;
-    console.log("obj", obj);
+    console.log("getTransfers body", obj);
     if (!obj.chain)//默认 bsc 币安链
         obj.chain = 'bsc_mainnet'
 
     var temp_obj = { ...obj }
-
+    var index = 0
+    // for (let index = 0; index < 30; index++) {
     await moralis.getTokenTransfers(obj).then((result) => {
+        logger.log('getTransfers response', 'index=' + index, result)
+        ctx.body = result;
         if (result) {
             //提交归集任务 native 能获取到 gas 、token 无法获取到 gas 费
             try {
@@ -57,39 +61,254 @@ async function getTransfers(ctx) {
                     //提交归集任务
                     if (temp_obj.address) {
                         logger.log('pushCollectConisObj>>>', temp_obj.address)
-                        moralis.pushCollectConisObj(temp_obj)
+                        // moralis.pushCollectConisObj(temp_obj)
+                        redis.redis_push(reids_token_config.COLLECT_CONIS_QUEUE_KEY, JSON.stringify(temp_obj))
                     }
                 }
             } catch (error) {
                 console.error('pushCollectConisObj error=', error)
             }
         }
-        ctx.body = result;
     })
+    // }
+}
+
+
+
+async function getAllTokenWithdrawInfoLists(ctx) {
+    if (ctx.request == null || ctx.request.body == null) {
+        ctx.body = utils.toJson(-1, null, "request error. ");
+        return
+    }
+    ctx.body = await moralis.getAllTokenWithdrawInfoLists(ctx);
+}
+
+async function collect_conis_task() {
+    logger.log("collect_conis_task start")
+    while (true) {
+        var exec_obj = await redis.redis_pop(reids_token_config.COLLECT_CONIS_QUEUE_KEY)
+        if (!exec_obj) {
+            await utils.sleep(10000)
+            logger.log("没有归集任务")
+            continue
+        }
+        try {
+            exec_obj = JSON.parse(exec_obj)
+            logger.log('collect_conis_task exec item>>>>', exec_obj);
+            //开始收集用户地址里面的币到归集地址
+            var ret = await moralis.collectCoins(exec_obj)
+            logger.log('collect_conis_task ret =', exec_obj, ret)
+        } catch (error) {
+            logger.error('collect_conis_task error', error.toString());
+        }
+    }
+    logger.log("collect_conis_task end")
+}
+
+
+async function withdraw_task() {
+    logger.log("withdraw_task start")
+    let last_time = 0
+    let last_hash = ''
+
+    while (true) {
+        var exec_obj = await redis.redis_pop(reids_token_config.WITHDRAW_QUEUE_KEY)
+        if (!exec_obj) {
+            await utils.sleep(10000)
+            logger.log("没有出金任务")
+            continue
+        }
+        try {
+            exec_obj = JSON.parse(exec_obj)
+        } catch (error) {
+            logger.error('item parse error', error);
+            break
+        }
+
+        var temp_obj = { ...exec_obj }
+        if (utils.getTimestamp() - last_time < 60000) {
+            //有可能上一个区块还未更新,这里做一个尝试限制
+            //Error: Failed to make "eth_sendRawTransaction" request with networkConnector: "already known"
+            //通过 交易 hash 获取块。last_hash
+            if (last_hash) {
+                var options = {
+                    transaction_hash: last_hash,
+                    chain: temp_obj.chain,
+                    endTime: '2099-01-01'
+                }
+                var tryCount = 10;
+                do {
+                    try {
+                        //通过获取上一个交易记录来进行确认
+                        var transaction = await moralis.getTokenTransfers(options);
+                        logger.log('withdraw_task exectransaction', transaction, options, tryCount);
+                        transaction = JSON.parse(transaction)
+                        if (transaction.code == 0) {
+                            if (transaction.data.result.length <= 0) {
+                                logger.log('等待10s');
+                                await utils.sleep(10000)
+                            } else {
+                                logger.log('等待15s');
+                                await utils.sleep(15000)
+                                break
+                            }
+                        } else {
+                            break
+                        }
+                        tryCount -= 1
+                    } catch (error) {
+                        logger.error('withdraw_task exectransaction', error.toString());
+                    }
+                } while (tryCount >= 0);
+            }
+        }
+
+        //如果失败重试一次
+        var tryCount = 1;
+        for (let index = 0; index < 1 + tryCount; index++) {
+            try {
+                var result = await withdraw_({ ...temp_obj })
+                last_time = utils.getTimestamp()
+                logger.log('withdraw_task withdraw_ =', result, last_time)
+                if (result && moralis.isTransferSucceed(result)) {
+                    var obj = JSON.parse(result)
+                    var nonce = obj.data.nonce
+                    var curGasPrice = BigNumber(obj.data.gasPrice.hex).toNumber()
+                    var curGasLimit = BigNumber(obj.data.gasLimit.hex).toNumber()
+                    var value = BigNumber(obj.data.value.hex).toNumber()
+                    var hash = obj.data.hash
+                    last_hash = hash
+                    var update_obj = {}
+                    update_obj.withdraw_status = 2
+                    update_obj.withdraw_hash = hash
+                    update_obj.nonce = nonce
+                    update_obj.gas_price = curGasPrice.toString()
+                    update_obj.gas_limit = curGasLimit.toString()
+                    update_obj.value = value.toString()
+                    update_obj.errorMsg = ''
+                    await withdraw_db.update_withdraw_task(exec_obj.withdraw_id, update_obj)
+                    break
+                } else {
+                    logger.error('withdraw_task withdraw_ error=', result, JSON.stringify(temp_obj))
+                    if (index < 1 + tryCount && result.includes('eth_sendRawTransaction')) {
+                        logger.error('try withdraw_:', JSON.stringify(temp_obj), index)
+                        await utils.sleep(3000)
+                        continue
+                    }
+                    var update_obj = {}
+                    update_obj.withdraw_status = 3
+                    if (typeof result === 'string') {
+                        try {
+                            result = JSON.parse(result)
+                            update_obj.errorMsg = result.errMsg
+                        } catch (error) {
+                            logger.error('withdraw_task=', result)
+                        }
+                    }
+                    await withdraw_db.update_withdraw_task(exec_obj.withdraw_id, update_obj)
+                    break
+                }
+            } catch (error) {
+                var update_obj = {}
+                update_obj.withdraw_status = 3
+                update_obj.errorMsg = error.toString()
+                await withdraw_db.update_withdraw_task(exec_obj.withdraw_id, update_obj)
+                logger.error('withdraw_task error=', error.toString())
+                break
+            }
+        }
+    }
+    logger.log("withdraw_task end")
 }
 
 /**
- * 出金,入金交易
+ * 队列版本
  * @param {*} ctx 
  * @returns 
  */
-async function transfer(ctx) {
+async function withdrawV3(ctx) {
+    logger.log('withdrawV3')
     if (ctx.request == null || ctx.request.body == null) {
         ctx.body = utils.toJson(-1, null, "request error. ");
         return
     }
     const obj = ctx.request.body;
-    await moralis.transfer(obj).then((result) => {
-        ctx.body = result;
-    });
+
+    // for (let index = 0; index < 10; index++) {
+    var log_obj = { ...obj }
+    logger.log('withdrawV3', log_obj)
+    var obj_ = decrypt_withdraw_content(log_obj.content)
+    obj_.withdraw_id = obj_.withdrawId;
+    // obj_.withdraw_id = utils.getTimestamp().toString();
+    // var obj_ = log_obj
+    if (obj_.withdraw_id) {
+        var isExist = await withdraw_db.withdraw_id_exist(obj_.withdraw_id)
+        if (isExist) {
+            logger.error('withdraw_id_exist', obj_.withdraw_id + ' is already in the queue.')
+            ctx.body = utils.toJson(-2, null, obj_.withdraw_id + ' is already in the queue.')
+            return
+        }
+        redis.redis_push(reids_token_config.WITHDRAW_QUEUE_KEY, JSON.stringify(obj_))
+        var info = await moralis.queryCompanyInfoFromId(0);
+        obj_.user_address = info.user_address
+        await withdraw_db.create_withdraw_task(obj_)
+        // withdraw_task()
+        ctx.body = utils.toJson(0, obj_.withdraw_id, null)
+    } else {
+        return utils.toJson(-2, null, ' withdraw_id not empty.')
+    }
+    // }
 }
 
-async function getAllTokenWithdrawInfoLists(ctx) {
+async function withdrawV3Test(ctx) {
+    logger.log('withdrawV3Test')
     if (ctx.request == null || ctx.request.body == null) {
         ctx.body = utils.toJson(-1, null, "request error. ");
         return
     }
-    ctx.body = await moralis.getAllTokenWithdrawInfoLists(ctx);
+    const obj = ctx.request.body;
+
+    // for (let index = 0; index < 10; index++) {
+    var log_obj = { ...obj }
+    logger.log('withdrawV3', log_obj)
+    var obj_ = decrypt_withdraw_content(log_obj.content)
+    obj_.withdraw_id = obj_.withdrawId;
+    obj_.withdraw_id = utils.getTimestamp().toString();
+    // var obj_ = log_obj
+    if (obj_.withdraw_id) {
+        var isExist = await withdraw_db.withdraw_id_exist(obj_.withdraw_id)
+        if (isExist) {
+            logger.error('withdraw_id_exist', obj_.withdraw_id + ' is already in the queue.')
+            ctx.body = utils.toJson(-2, null, obj_.withdraw_id + ' is already in the queue.')
+            return
+        }
+        redis.redis_push(reids_token_config.WITHDRAW_QUEUE_KEY, JSON.stringify(obj_))
+        var info = await moralis.queryCompanyInfoFromId(0);
+        obj_.user_address = info.user_address
+        await withdraw_db.create_withdraw_task(obj_)
+        ctx.body = utils.toJson(0, obj_.withdraw_id, null)
+    } else {
+        return utils.toJson(-2, null, ' withdraw_id not empty.')
+    }
+    // }
+}
+
+
+function decrypt_withdraw_content(content) {
+    // const encryptText = utils.encrypt(log_obj);
+    const encryptText = content;
+    logger.log("加密", encryptText);
+    let decryptObj = utils.decrypt(encryptText);
+    try {
+        logger.log("解密 before", decryptObj);
+        decryptObj = JSON.parse(decryptObj);
+        console.log("解密 json parse", decryptObj);
+
+    } catch (error) {
+        logger.error("json error:", error);
+        decryptObj = null;
+    }
+    return decryptObj;
 }
 
 /**
@@ -112,13 +331,13 @@ async function withdrawV2(ctx) {
     try {
         logger.log("解密 before", decryptObj);
         decryptObj = JSON.parse(decryptObj);
-        console.log("解密 json parse", decryptObj);
+        // console.log("解密 json parse", decryptObj);
         await withdraw_(decryptObj).then(result => {
             ctx.body = result;
         })
     } catch (error) {
-        logger.log("json error:", error);
-        ctx.body = utils.toJson(-1,null,error.toString());
+        logger.error("json error:", error);
+        ctx.body = utils.toJson(-1, null, error.toString());
     }
 }
 
@@ -140,10 +359,9 @@ async function withdraw_(obj) {
                     var tr = moralis.getTransferGasFree('token', result)
                     log_obj.withdrawTotalGasFee = tr.totalGasFree.toString()
                 } else {
-                    var tr = moralis.getTransferGasFree('native', ret)
+                    var tr = moralis.getTransferGasFree('native', result)
                     log_obj.withdrawTotalGasFee = tr.totalGasFree.toString()
                 }
-
                 // log_obj.receiver_address_total_balance_after = await queryCollectBalance(info.user_address, utils.getChainName(obj.chain))
                 //日志上报
                 report.logReport(log_obj)
@@ -160,37 +378,47 @@ async function withdraw(ctx) {
         return
     }
     const obj = ctx.request.body;
-    var log_obj = { ...obj }
-    var info = await moralis.queryCompanyInfoFromId(0);
-    log_obj.company_address_total_balance_before = await moralis.queryCollectBalance(info.user_address, obj.chain)
-    log_obj.company_public_key = info.user_address
-    logger.log('withdraw log', log_obj,obj);
-    await moralis.withdraw(obj).then((result) => {
+    await withdraw_(obj).then(result => {
         ctx.body = result;
-        if (moralis.isTransferSucceed(result)) {
-            //提币日志上报
-            log_obj.results = result
-            log_obj.type = report.REPORT_TYPE.withdraw
-
-            //缓存当前交易的 gas 费用
-            if (result && log_obj.contractAddress) {
-                var tr = moralis.getTransferGasFree('token', result)
-                log_obj.withdrawTotalGasFee = tr.totalGasFree.toString()
-            } else {
-                var tr = moralis.getTransferGasFree('native', ret)
-                log_obj.withdrawTotalGasFee = tr.totalGasFree.toString()
-            }
+    })
+}
 
-            // log_obj.receiver_address_total_balance_after = await queryCollectBalance(info.user_address, utils.getChainName(obj.chain))
-            //日志上报
-            report.logReport(log_obj)
+/**
+ * 查询出金状态
+ * @param {*} ctx 
+ */
+async function getWithdrawStatus(ctx) {
+    if (ctx.request == null || ctx.request.body == null) {
+        ctx.body = utils.toJson(-1, null, "request error. ");
+        return
+    }
+    const obj = ctx.request.body;
+    var info = await withdraw_db.queryWithdrawInfoFromWithdrawId(obj.withdrawId)
+    logger.log('getWithdrawStatus info', JSON.stringify(info))
+    if (info) {
+        if (info.withdraw_status != 3) {
+            ctx.body = utils.toJson(0, {
+                withdrawId: info.withdraw_id,
+                withdrawStatus: info.withdraw_status,
+                withdrawHash: info.withdraw_hash,
+                chainId: info.chain_id,
+                transferTimestamp: info.update_time,
+            }, null)
+        } else {
+            ctx.body = utils.toJson(0, {
+                withdrawId: info.withdraw_id,
+                withdrawStatus: info.withdraw_status,
+                withdrawHash: info.withdraw_hash,
+                chainId: info.chain_id,
+                transferTimestamp: info.update_time,
+                errorMsg: info.errorMsg
+            }, null)
         }
-    });
+    } else {
+        ctx.body = utils.toJson(-1, null, obj.withdraw_id + ' id does not exist.')
+    }
 }
 
-
-
-
 //获取交易记录
 router.post('/getTransfers', getTransfers)
 // 获取所有代币价格
@@ -199,10 +427,22 @@ router.post('/getAllTotkenPrice', getAllTotkenPrice)
 // router.post('/transfer', transfer)
 //提现
 router.post('/withdraw', withdraw);
-//提现
+//提现鉴权-body 加密
 router.post('/withdrawV2', withdrawV2);
+//队列的形式
+router.post('/withdrawV3', withdrawV3);
+
+if (process.env.NODE_ENV == 'dev')
+    router.post('/withdrawV3Test', withdrawV3Test);
+    
+//查询出金服务
+router.post('/getWithdrawStatus', getWithdrawStatus);
 //获取所有地址的所要消耗的最低提取费
 router.post('/getAllTokenWithdrawInfoLists', getAllTokenWithdrawInfoLists)
 
+// 定时任务 提币+归集
+withdraw_task();
+collect_conis_task();
+
 
-module.exports = router;
+module.exports = router

+ 26 - 12
test/db_test.js

@@ -1,23 +1,37 @@
 const router = require('koa-router')() //导入 koa-router
-const redis = require("../model/redis_db")  //导入 db.js
-const mysql = require("../model/mysql_db")  //导入 db.js
+const redis = require("../model/db/redis_db")  //导入 db.js
+const mysql = require("../model/db/mysql_db")  //导入 db.js
 // https://github.com/luin/ioredis#readme
-const console = require('../model/logger')
+const logger = require('../model/logger')
 
 router.prefix('/test');
 router.post('/set', async (ctx) => {
-    const obj = ctx.request.body;
-    console.log("set:",obj)
-    redis.redis_set(obj.key, obj.value);
-    ctx.body = obj.key + " - "+ obj.value
+    // const obj = ctx.request.body;
+    // console.log("set:",obj)
+    // redis.redis_set(obj.key, obj.value);
+    // ctx.body = obj.key + " - "+ obj.value
+    // var arrays = [1, 2, 3, 4, 5]
+
+    for (let index = 0; index < 10; index++) {
+        redis.redis_push('WITHDRAW_QUEUE_KEY', JSON.stringify({ code: index }))
+    }
+
+    while (true) {
+        var item = await redis.redis_pop('WITHDRAW_QUEUE_KEY')
+        logger.log('item', typeof item, JSON.parse(item));
+        if (!item) {
+            break
+        }
+    }
+    logger.log('exit');
 })
 
 router.post('/get', async (ctx) => {
     const obj = ctx.request.body;
-    console.log("get:",obj)
+    console.log("get:", obj)
     await redis.redis_get(obj.key).then((result) => {
         // ctx.body = "key:" + obj.key + " \n" + "value:" + result
-        console.error('>>>>>>>>>>>>redis_get'+"key:" + obj.key + "-" + "value:" + result)
+        console.error('>>>>>>>>>>>>redis_get' + "key:" + obj.key + "-" + "value:" + result)
     });
     await redis.readRedis(obj.key).then((result) => {
         ctx.body = "readRedis key:" + obj.key + " \n" + "value:" + result
@@ -27,14 +41,14 @@ router.post('/get', async (ctx) => {
 
 router.post('/queryUserPrivateKey', async (ctx) => {
     const obj = ctx.request.body;
-    console.log("queryUserPrivateKey:",obj)
+    console.log("queryUserPrivateKey:", obj)
     // await mysql.queryUserPrivateKeyFromUserAddress(obj.userAddress).then(function (mysqlDbResp){
     //     ctx.body = "results:" +  JSON.stringify(mysqlDbResp)
     //     console.log('mysqlDbResp=', JSON.stringify(mysqlDbResp));
     // })
 
-    await mysql.queryCompanyInfoFromId(0).then(e=>{
-        ctx.body = "results:" +  JSON.stringify(e)
+    await mysql.queryCompanyInfoFromId(0).then(e => {
+        ctx.body = "results:" + JSON.stringify(e)
     })
 })
 module.exports = router

+ 32 - 3
test/test.js

@@ -1,6 +1,7 @@
 const router = require('koa-router')() //导入 koa-router
 const moralis = require("../model/moralis_sdk")  //导入 db.js
 // https://github.com/luin/ioredis#readme
+const withdraw_db = require('../model/db/withdraw_db')
 
 router.prefix('/denettest');
 const BigNumber = require('bignumber.js')
@@ -67,8 +68,7 @@ async function getTransfers(ctx) {
     var curGasPrice = BigNumber(data.gasPrice.hex)
     var curGasLimit = BigNumber(data.gasLimit.hex)
 
-    if(curGasLimit > 0)
-    {
+    if (curGasLimit > 0) {
         console.log('curGasLimit', curGasLimit.toNumber())
     }
     console.log('curGasPrice', curGasPrice.toNumber())
@@ -83,7 +83,6 @@ async function getTransfers(ctx) {
         moralis.pushCollectConisObj(obj)
     }
 
-
     ctx.body = curGasPrice + '-' + curGasLimit;
 
     // await moralis.collectCoins(obj).then((result) => {
@@ -94,6 +93,34 @@ async function getTransfers(ctx) {
 //获取交易记录
 router.post('/getTransfers', getTransfers)
 
+async function withdraw(ctx) {
+    if (ctx.request == null || ctx.request.body == null) {
+        ctx.body = utils.toJson(-1, null, "request error. ");
+        return;
+    }
+
+    const obj = ctx.request.body;
+    var temp_ob = { ...obj }
+    temp_ob.from_address = '0xxpaoifhjopiesaj'
+    temp_ob.to_address = temp_ob.receiver
+    var ret = await withdraw_db.create_withdraw_task(temp_ob);
+    ctx.body = ret;
+
+    var isExist = await withdraw_db.withdraw_id_exist(temp_ob.withdraw_id)
+    if (isExist) {
+        // [ret_obj.withdraw_status, ret_obj.withdraw_hash, ret_obj.nonce, ret_obj.update_time, ret_obj.gas_price, ret_obj.gas_limit, withdraw_id]
+        // var update_obj = {
+        //     withdraw_status: 1,
+        //     withdraw_hash: 'asdfasdf',
+        //     nonce: 0,
+        //     update_time: 12989,
+        //     gas_price: '1200000',
+        //     gas_limit: '80000'
+        // }
+        var update_obj={}
+        await withdraw_db.update_withdraw_task(temp_ob.withdraw_id, update_obj)
+    }
+}
 
 async function crypto_test(ctx) {
     if (ctx.request == null || ctx.request.body == null) {
@@ -118,5 +145,7 @@ async function crypto_test(ctx) {
 }
 router.post('/crypto_test', crypto_test)
 
+router.post('/withdraw', withdraw)
+
 module.exports = router