Jelajahi Sumber

归集开发完成

DevYK 3 tahun lalu
induk
melakukan
a466c5c5d4
16 mengubah file dengan 3830 tambahan dan 1554 penghapusan
  1. 3 0
      README.md
  2. 10 0
      app.js
  3. 21 11
      config/dev_config.js
  4. 9 1
      config/prd_config.js
  5. 17 5
      config/test_config.js
  6. 394 16
      model/moralis_sdk.js
  7. 91 11
      model/mysql_db.js
  8. 7 9
      model/redis_db.js
  9. 59 0
      model/timer.js
  10. 7 1
      model/utils.js
  11. 1559 748
      node_modules/.package-lock.json
  12. 1563 750
      package-lock.json
  13. 3 1
      package.json
  14. 13 1
      routes/db_test.js
  15. 6 0
      routes/sdk.js
  16. 68 0
      test/test.js

+ 3 - 0
README.md

@@ -32,6 +32,8 @@ ssh -i de-net.pem ubuntu@34.207.131.244
 
 sudo   su root
 
+ssh    10.0.1.168
+
 docker ps
 
 docker ps  -a
@@ -48,3 +50,4 @@ pm2 logs
 - [moralis sdk](https://docs.moralis.io/moralis-dapp/web3-sdk/native#gettransaction-new)
 - [moralis server](https://admin.moralis.io/servers)
 - [node 服务文档 ](https://st94nif1cq.feishu.cn/docs/doccnNxG2UwHPCdZXbywgbdy13f#)
+- [测试币准备](https://st94nif1cq.feishu.cn/docs/doccn2G0r0HOH0L1Z05uaJDFA2g#)

+ 10 - 0
app.js

@@ -10,6 +10,11 @@ const logger = require('koa-logger')
 const users = require('./routes/users')
 var sdk = require('./routes/sdk');
 var db_test = require('./routes/db_test');
+
+require('./model/timer')
+
+
+var test = require('./test/test');
 // error handler
 onerror(app)
 
@@ -38,9 +43,14 @@ app.use(async (ctx, next) => {
 app.use(users.routes(), users.allowedMethods())
 app.use(sdk.routes(), sdk.allowedMethods())
 app.use(db_test.routes(), db_test.allowedMethods())
+
+
+app.use(test.routes(), test.allowedMethods())
 // error-handling
 app.on('error', (err, ctx) => {
   console.error('server error', err, ctx)
 });
 
+
+console.log('app start');
 module.exports = app

+ 21 - 11
config/dev_config.js

@@ -3,20 +3,29 @@ const cryppt_config = {
     KEY_IV: 'NENET_CRYPT_IV',
 }
 
+const account_config = {
+    WELLET_PRIVATE_KEY: '4Uz4Jm7Xd1gH+1nFbR0B7hk1ITmsT8O3iAgS/hC0L9TkrqAZoklsQhXl4fA1X+uqpckF4HtnXnMpwng94GvvzsRfXYirfDfboneuzfc0o7s=',
+    WELLET_PUBLIC_KEY: '0xAD48D13E77011cFE03fF19729B6A247847AfD28E',
+    TOKEN_GAS_LIMIT: '80000',
+    BNB_GAS_LIMIT: '21000',
+    BNB_GAS_PRICE: '10000000000',
+}
+
 const reids_token_config = {
     TOKENPRICE: 'TOKENPRICE',
-    TOKENWITHDRAW: 'TOKENWITHDRAW'
+    TOKENWITHDRAW: 'TOKENWITHDRAW',
+    GASPRICE: "GASPRICE",
 }
 // 设置数据库配置文件
 const db_config = {
     // 数据库配置
     mysql: {
-        DATABASE: '',   //表名字
-        USERNAME: '',   //用户
-        PASSWORD: '', //密码
-        DATABASE: '',
+        DATABASE: 'user_address',   //数据库名称
+        TABLENAME: 'user_key_manage',   //表
+        USERNAME: 'root',   //用户名
+        PASSWORD: '123456', //密码
         PORT: '3306', //连接的端口
-        HOST: 'denet-test.csi2lctklqzg.us-east-1.rds.amazonaws.com' //host
+        HOST: '127.0.0.1' //host
     },
     redis: {
         PORT: 6379, // Redis port
@@ -28,16 +37,17 @@ const db_config = {
 
 // 设置 moralis sdk 配置文件
 const moralis_config = {
-        SERVER_URL: "https://1frf5yebfh6r.usemoralis.com:2053/server",
-        APP_ID: "oSwDtyD9f4GD6XPZgfDCRHPqXrm2pvBUCTv2N0X8",
-        MASTER_KEY: "YbEUAR49HwBZ8R6Q8eNTNfwtStPFPcCYehJQkYcl",
-        MORALIS_SECRET: "BGlDVjy7054iLDpDcdc9AbH65rZrhj8QIhsThcwF6thNzTnbS2ft8XmM70x4jOpU",
-        DEFAULT_PRIVATE_KEY: "6084c2a5e39fa83d5a119c3a864a442e77287f4b03bad93cef38ec5f44bca630",
+    SERVER_URL: "https://1frf5yebfh6r.usemoralis.com:2053/server",
+    APP_ID: "oSwDtyD9f4GD6XPZgfDCRHPqXrm2pvBUCTv2N0X8",
+    MASTER_KEY: "YbEUAR49HwBZ8R6Q8eNTNfwtStPFPcCYehJQkYcl",
+    MORALIS_SECRET: "BGlDVjy7054iLDpDcdc9AbH65rZrhj8QIhsThcwF6thNzTnbS2ft8XmM70x4jOpU",
+    DEFAULT_PRIVATE_KEY: "6084c2a5e39fa83d5a119c3a864a442e77287f4b03bad93cef38ec5f44bca630",
 }
 
 module.exports = {
     db_config,
     moralis_config,
     reids_token_config,
+    account_config,
 }
 

+ 9 - 1
config/prd_config.js

@@ -1,3 +1,10 @@
+const account_config = {
+    WELLET_PRIVATE_KEY: '4Uz4Jm7Xd1gH+1nFbR0B7hk1ITmsT8O3iAgS/hC0L9TkrqAZoklsQhXl4fA1X+uqpckF4HtnXnMpwng94GvvzsRfXYirfDfboneuzfc0o7s=',
+    WELLET_PUBLIC_KEY: '0xAD48D13E77011cFE03fF19729B6A247847AfD28E',
+    BNB_GAS_LIMIT: '21000',
+    BNB_GAS_PRICE: '10000000000',
+}
+
 const cryppt_config = {
     KEY: 'NENET_CRYPT_KEY',
     KEY_IV: 'NENET_CRYPT_IV',
@@ -5,7 +12,8 @@ const cryppt_config = {
 
 const reids_token_config = {
     TOKENPRICE: 'TOKENPRICE',
-    TOKENWITHDRAW: 'TOKENWITHDRAW'
+    TOKENWITHDRAW: 'TOKENWITHDRAW',
+    GASPRICE:"GASPRICE",
 }
 // 设置数据库配置文件
 const db_config = {

+ 17 - 5
config/test_config.js

@@ -1,3 +1,12 @@
+
+const account_config = {
+    WELLET_PRIVATE_KEY: '4Uz4Jm7Xd1gH+1nFbR0B7hk1ITmsT8O3iAgS/hC0L9TkrqAZoklsQhXl4fA1X+uqpckF4HtnXnMpwng94GvvzsRfXYirfDfboneuzfc0o7s=',
+    WELLET_PUBLIC_KEY: '0xAD48D13E77011cFE03fF19729B6A247847AfD28E',
+    TOKEN_GAS_LIMIT: '80000',
+    BNB_TOKEN_LIMIT: '21000',
+    BNB_GAS_PRICE: '10000000000',
+}
+
 const cryppt_config = {
     KEY: 'NENET_CRYPT_KEY',
     KEY_IV: 'NENET_CRYPT_IV',
@@ -5,15 +14,18 @@ const cryppt_config = {
 
 const reids_token_config = {
     TOKENPRICE: 'TOKENPRICE',
-    TOKENWITHDRAW: 'TOKENWITHDRAW'
+    TOKENWITHDRAW: 'TOKENWITHDRAW',
+    GASPRICE: "GASPRICE",
 }
 // 设置数据库配置文件
 const db_config = {
     mysql: {
-        PORT: 6379, // Redis port
-        HOST: "r-bp1ps6my7lzg8rdhwxpi.redis.rds.aliyuncs.com", // Redis host
-        USERNAME: null,
-        PASSWORD: "Wqsd@2019"
+        DATABASE: 'user_address',   //数据库名称
+        TABLENAME: 'user_key_manage',   //表名
+        USERNAME: 'denet',   //用户名
+        PASSWORD: 'cyber#Together_2022', //密码
+        PORT: '3306', //连接的端口
+        HOST: '127.0.0.1' //host
     },
 
     redis: {

+ 394 - 16
model/moralis_sdk.js

@@ -1,10 +1,9 @@
 /* import moralis */
 const Moralis = require("moralis/node");
-
 var utils = require('./utils.js');
 // var config = require('../config/config.js')(db_config,
 //     moralis_config)
-var { moralis_config, reids_token_config } = require('../config/config.js')
+var { moralis_config, reids_token_config, account_config } = require('../config/config.js')
 const redis = require("./redis_db")  //导入 db.js
 const mysql = require("./mysql_db")
 
@@ -18,6 +17,8 @@ var moralisSecret = moralis_config.MORALIS_SECRET;
 const ERROR_CODE_001 = -1;
 const SUCCEED_CODE = 0;
 
+
+
 /**
  * 初始化 moralis
  * https://st94nif1cq.feishu.cn/docs/doccnNxG2UwHPCdZXbywgbdy13f#
@@ -39,6 +40,376 @@ const withdraw = async (obj) => {
     return await transfer(obj);
 }
 
+
+async function getAccountBalances(options) {
+    await initMasterSDK();
+    if (options.chain) {
+        options.chain = utils.getChainName(options.chain)
+    }
+    console.log('getAccountBalances :', options)
+    if (options.type == 'native') {
+        var opt_ret = await Moralis.Web3API.account.getNativeBalance(options);
+        console.log('getNativeBalance=', opt_ret);
+        return opt_ret
+    } else {
+        var aar = await Moralis.Web3API.account.getTokenBalances(options);
+        console.log('getTokenBalances=', aar);
+        return aar;
+    }
+}
+
+/**
+ * 获取当前账户下所有不同种类的币  主流币 + 20币
+ * 
+ * 必填项
+ * obj.chain = ?
+ * @param {*} obj 
+ */
+async function getAccountAllCoins(obj) {
+    var temp_chain = obj.chain;
+
+    //拿到我当前所有的币种
+    obj.type = 'native'
+    obj.chain = temp_chain
+    var native_balance = await getAccountBalances(obj);
+
+
+    //拿到我当前所有的 20 币
+    obj.type = '20'
+    obj.chain = temp_chain
+    var others_balances = await getAccountBalances(obj);
+    return {
+        native: native_balance,
+        other: others_balances,
+    }
+}
+
+/**
+ * 判断是否转 gas 费
+ * @param {*} my_account_all_coins 
+ */
+async function computeTransferGasFree(my_account_all_coins, tokenPrices) {
+    var totalCount = 0;
+    var tokenCount = 0;
+    var tokenGasPrice = 0;
+    var nativeGasPrice = 0;
+
+    var ret_total_gas_price = 0;
+    var ret_total_count = 0;
+    var ret_a_gas = 0;
+
+    //得到 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 => {
+            console.debug('20 element=', element);
+            var find_transfer_item = findTokenPriceItem(element.token_address, tokenPrices);
+            var total_all_usdprice = calculate_total_usdprice(element.balance, element.decimals, find_transfer_item.usdPrice);
+            console.debug('findTokenPriceItem ret=', element.token_address, find_transfer_item, total_all_usdprice);
+            if (find_transfer_item && total_all_usdprice > 1.0) {
+                tokenCount += 1;
+                console.debug('token > 1.0', tokenCount, element.token_address);
+            }
+        });
+        console.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);
+        ret_a_gas = account_config.BNB_GAS_PRICE;
+        console.log('tokenGasPrice=', tokenGasPrice);
+    }
+
+
+    //计算 native 是否满足 1美刀
+    console.log('isTransferGasFree token count:', tokenCount);
+    var nativeAllBalance = my_account_all_coins.native.balance;
+    var nativeCount = 0
+    var nativePriceItem = findTokenPriceItem('0x0000000000000000000000000000000000000000', tokenPrices);//todo 线上环境需要换
+    console.debug('native nativePriceItem=', nativePriceItem, nativeAllBalance);
+    if (nativePriceItem) {
+        var total_all_usdprice = calculate_total_usdprice(nativeAllBalance, '18', nativePriceItem.usdPrice);
+        console.debug('native total_all_usdprice=', total_all_usdprice);
+        if (total_all_usdprice > 1.0) {
+            nativeCount = 1;
+            console.debug('native > 1.0', tokenCount);
+            nativeGasPrice = parseInt(nativeCount) * parseInt(account_config.BNB_GAS_LIMIT) * parseInt(account_config.BNB_GAS_PRICE);
+            ret_a_gas = account_config.BNB_GAS_PRICE;
+        }
+    }
+
+    //计算所有币转账所需要的 gas 
+    totalCount = nativeCount + tokenCount;
+    // var gasPrice = await redis.readRedis(reids_token_config.GASPRICE);
+    console.log('nativeAllBalance', nativeAllBalance);
+    console.log('totalCount', totalCount);
+
+
+
+
+    var total2Gas = nativeGasPrice + tokenGasPrice;
+    var service_charge = 0;
+    console.log('total2Gas', total2Gas);
+
+    //如果当前的钱不够  gas
+    if (nativeAllBalance < total2Gas) {
+        if (tokenCount > 0) {//出现 token 需要转移手续费
+            service_charge = 1;
+            total2Gas = (total2Gas - nativeAllBalance);//充手续费
+            console.log('需要转账=', total2Gas);
+        }
+    }
+    ret_total_gas_price = total2Gas.toString();
+    ret_total_count = totalCount;
+
+    //返回结果
+    return {
+        gasPrice: ret_total_gas_price, //需要 归集到用户地址的 gas 费转移
+        totalCount: ret_total_count, //一共归集次数
+        aGasPrice: ret_a_gas, //单个 gas 费用
+        get_service_charge: service_charge,//是否需要服务费
+    };
+}
+
+function findTokenPriceItem(token_address, tokenPrices) {
+    return tokenPrices.tokenPrice.find(element => {
+        console.log('findTokenPriceItem find=', element.contract, token_address)
+        return element.contract.toLowerCase() == token_address.toLowerCase();
+    })
+}
+
+// function calculate_total_usdprice(amount, decimals, usdprice) {
+//     return parseInt(amount) / (10**parseInt(decimals)) * parseInt(usdprice) ;
+function calculate_total_usdprice(amount, decimals, usdprice) {
+    return parseInt(amount) / (10 ** parseInt(decimals)) * parseFloat(usdprice);
+}
+
+
+async function updateNativeBalance(nativeBalance, obj) {
+    var temp = obj
+    var retryCount = 30;
+    do {
+        //上面转账完 BNB 会减去,这里再获取一次
+        var native_ret = await Moralis.Web3API.account.getNativeBalance(temp);
+        console.log('更新余额 :', native_ret, retryCount)
+        if (nativeBalance != native_ret.balance) {
+            return native_ret.balance;
+        }
+        await utils.sleep(3000);
+        retryCount--;
+    } while (native_ret.balance == nativeBalance && retryCount > 0);
+    return null;
+}
+
+//支持多账户转账
+async function transfers(obj, my_account_all_coins) {
+    var address = obj.address;
+    var chain = obj.chain;
+    var tokenPrices = obj.tokenPrices;
+    console.log('tokenPrices=', tokenPrices, my_account_all_coins);
+    if (!my_account_all_coins || !tokenPrices) return 'error.'
+
+    console.log(' my_account_all_coins.other.lenth=', my_account_all_coins.other.length);
+
+    var isUpdateNativeBalance = 0;
+
+    //token 归集
+    if (my_account_all_coins.other && Array.isArray(my_account_all_coins.other) && my_account_all_coins.other.length > 0) {
+        var available = Array.isArray(tokenPrices.tokenPrice) && tokenPrices.tokenPrice.length > 0
+        if (!available) return -1;
+        for (let i = 0; i < my_account_all_coins.other.length; ++i) {
+            var transfer_item = my_account_all_coins.other[i];
+            if (my_account_all_coins.other[i].token_address != null) {
+                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 obj_20 = {
+                        chain: obj.chain,
+                        contractAddress: transfer_item.token_address,
+                        amount: transfer_item.balance,
+                        receiver: account_config.WELLET_PUBLIC_KEY,
+                        type: 'erc20',
+                        address: address,
+                    }
+                    console.log('start_collectCoins erc20:', obj_20);
+                    console.log('calculate_total_usdprice 20', calculate_total_usdprice(transfer_item.balance, transfer_item.decimals, '0.1'));
+                    isUpdateNativeBalance = 1;
+                    var ret = await start_collectCoins(obj_20)
+                    console.log('start_collectCoins erc20 respose...', ret);
+                }
+            } else {
+                console.error('token Must be greater than  a dollar.', transfer_item.balance, transfer_item.decimals);
+                return toJson(-1, null, 'token Must be greater than  a dollar.');
+            }
+        }
+    }
+
+    //native 归集
+    if (my_account_all_coins.native) {
+        console.log('查询本地余额参数=', obj)
+        if (obj.chain) {
+            obj.chain = utils.getChainName(obj.chain)
+        }
+        console.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. '
+
+            //     //上面转账完 BNB 会减去,这里再获取一次
+            //     var native_ret = await Moralis.Web3API.account.getNativeBalance(obj);
+            //     console.log('更新余额 :', native_ret)
+            //     if (my_account_all_coins.native.balance != native_ret.balance) {
+            //         my_account_all_coins.native.balance = native_ret.balance;
+            //         break
+            //     }
+            //     await utils.sleep(1000);
+            // } while (native_ret.balance == my_account_all_coins.native.balance);
+        }
+        obj.chain = chain;
+        console.log('查询本地余额 after', my_account_all_coins.native)
+        var find_native_item = findTokenPriceItem('0x0000000000000000000000000000000000000000', tokenPrices);//todo 线上环境需要换
+        var nativeCoins = calculate_total_usdprice(my_account_all_coins.native.balance, '18', find_native_item.usdPrice);
+        console.log('start_collectCoins nativeCoins:', nativeCoins, obj);
+        console.log('start_collectCoins obj:', obj);
+        console.log('start_collectCoins native.balance:', my_account_all_coins.native.balance);
+        //todo 计算 token 币价格 * token美元单价
+        if (find_native_item && nativeCoins > 1.0) {
+            console.log('native.balance', my_account_all_coins.native.balance)
+            console.log('aGasPrice', obj.transFerGasFree.aGasPrice)
+            console.log('gasLimint', account_config.BNB_GAS_LIMIT)
+            // var gasPrice = BigInt(obj.transFerGasFree.aGasPrice);
+
+            var gasPrice = BigInt(account_config.BNB_GAS_PRICE);
+            var gasLimit = BigInt(account_config.BNB_GAS_LIMIT);
+            var nativeBalance = BigInt(my_account_all_coins.native.balance);
+
+            console.log('native.balance>>>', nativeBalance)
+            console.log('aGasPrice>>>', gasPrice)
+            console.log('gasLimint>>>', gasLimit)
+
+            var real_native_amount = nativeBalance - gasPrice * gasLimit;
+            console.log('start_collectCoins native amount:', real_native_amount.toString());
+
+            obj = {
+                chain: chain,
+                amount: real_native_amount.toString(),
+                receiver: account_config.WELLET_PUBLIC_KEY,
+                type: 'native',
+                address: address,
+            }
+
+            // obj = {
+            //     chain: 'bsc_testnet',
+            //     amount: real_native_amount.toString(),
+            //     receiver: account_config.WELLET_PUBLIC_KEY,
+            //     type: 'native',
+            //     address: '0x7C7401fcc82D1e53C4090561c3e6fde80d74e317',
+            // }
+
+            console.log('start_collectCoins native:', obj);
+            console.log('calculate_total_usdprice native', nativeCoins, find_native_item);
+            return await start_collectCoins(obj)
+        } else {
+            return toJson(-1, null, 'native Must be greater than  a dollar.');
+        }
+    }
+}
+
+
+const start_collectCoins = async (obj) => {
+    obj.withdraw = 0;
+    return await transfer(obj);
+}
+
+
+
+/**
+ * 用户充币地址的币转移到归集地址
+ * 1、检查当前账户的 主流币或者 20 币,是否满足一美刀,并且查看是否满足转账费用 n 如果不满足,先从归集地址 -> 用户提币地址(0.*2 来回2次转移)
+ * 2、发起归集 用户账户 -> 从 mysql 拿到私钥进行解密 -> 转移到归集地址
+ * 
+ * 
+ * @param {*} obj 
+ */
+const collectCoins = async (obj) => {
+    var chain = obj.chain;
+    //1、拿到当前账户所有的币
+    //2、是否满足交易费 如果不满足则 归集地址转移 币count * 手续费 到充币地址
+    //3、遍历所有币,开始转移到归集地址
+    var my_account_all_coins = await getAccountAllCoins(obj);
+
+    //得到币价格
+    obj.tokenPrices = await redis.readRedis(reids_token_config.TOKENPRICE)
+    if (typeof obj.tokenPrices == 'string')
+        obj.tokenPrices = JSON.parse(obj.tokenPrices);
+
+    //计算 gas 费用 是否需要归集
+    var transFerGasFree = await computeTransferGasFree(my_account_all_coins, obj.tokenPrices);
+    console.log('computeTransferGasFree=', transFerGasFree)
+
+    //是否需要归集
+    if (transFerGasFree.totalCount > 0) {
+        //需要转移 gas 费
+        if (parseInt(transFerGasFree.gasPrice) > 0 && transFerGasFree.get_service_charge == 1) {
+            var obj_wd = {
+                chain: chain,
+                amount: transFerGasFree.gasPrice,
+                receiver: obj.address,
+                type: 'native',
+                address: account_config.WELLET_PUBLIC_KEY, //todo 正式环境需要替换从 mysql read
+            }
+            console.log('开始充值 gas ', obj_wd)
+            var ret = await withdraw(obj_wd)
+            console.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."
+        }
+
+        obj.chain = chain;
+        obj.transFerGasFree = transFerGasFree;
+        console.log('transfers--->', obj);
+        var ret = await transfers(obj, my_account_all_coins);
+        console.log('归集结果=', ret);
+        return ret;
+    }
+    return obj.address+':不满足归集条件';
+}
+
+var collectCoinsArrays = [];
+async function execCollectCoinsTask() {
+    // new Promise((resolve) => {
+    while (collectCoinsArrays.length > 0) {
+        var obj = collectCoinsArrays.pop();
+        //开始收集用户地址里面的币到归集地址
+        var ret = await collectCoins(obj);
+        await utils.sleep(10000);
+        console.log('execCollectCoinsTask=', obj, collectCoinsArrays.length)
+    }
+    //     resolve('result');
+    // })
+}
+
+
+function pushCollectConisObj(obj) {
+    collectCoinsArrays.push(obj)
+    execCollectCoinsTask();
+}
+
+
+async function readPriveteKeyFromMysql(address) {
+    return new Promise(resolve => {
+        mysql.queryUserPrivateKeyFromUserAddress(address).then(ret => {
+            console.log('readPriveteKeyFromMysql=', ret);
+            resolve(ret);
+        })
+    })
+}
+
 const transfer = async (obj) => {
     console.debug("fun transfer in ", obj);
     console.debug("fun transfer serverUrl ", serverUrl);
@@ -52,7 +423,7 @@ const transfer = async (obj) => {
     opts.privateKey = moralis_config.DEFAULT_PRIVATE_KEY;
     opts.type = "erc20"; //native erc20
 
-    if (!obj.receiver || !obj.amount || parseFloat(obj.amount) <= 0) {
+    if (!obj.receiver || !obj.amount || parseInt(obj.amount) <= 0) {
         console.error("fun transfer parameter error.");
         return toJson(ERROR_CODE_001, null, "please check receiver or amount parameter is ok ?");
     }
@@ -87,20 +458,26 @@ const transfer = async (obj) => {
     var privateKey = '';
     //提币
     if (obj.withdraw) {
-        //读取归集地址私钥
-        // opts.privateKey = readPriveteKeyFromMysql();
-        opts.privateKey = '4Uz4Jm7Xd1gH+1nFbR0B7hk1ITmsT8O3iAgS/hC0L9TkrqAZoklsQhXl4fA1X+uqpckF4HtnXnMpwng94GvvzsRfXYirfDfboneuzfc0o7s=';
+        //提币公司
+        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;
+        }
     }
 
-    opts.privateKey = utils.decryptPrivityKey(opts.privateKey);
     if (!opts.privateKey) {
         return toJson(-1, null, "decryptPrivityKey error.");
     }
 
-    console.log('decryptPrivityKey privateKey=', opts.privateKey)
+    opts.privateKey = utils.decryptPrivityKey(opts.privateKey);
+
+    console.log('decryptPrivityKey privateKey=', opts.privateKey);
     try {
         // sending 0.5 DAI tokens with 18 decimals on BSC testnet
-        var options = Moralis.TransferOptions = {}
+        var options;
         if (opts.contractAddress) { //如果存在就是代币
             options = Moralis.TransferOptions = {
                 type: opts.type,
@@ -108,14 +485,14 @@ const transfer = async (obj) => {
                 receiver: opts.receiver, //接收钱包地址
                 contractAddress: opts.contractAddress //用户合约地址
             };
-            // console.log("options=",options);
+            console.log("options 20 =", options);
         } else { //ETH or BNB
             options = Moralis.TransferOptions = {
                 type: opts.type,
                 amount: opts.amount,
                 receiver: opts.receiver, //接收钱包地址
             };
-            // console.log("options else=",options);
+            console.log("options native =", options, opts.chainId);
         }
 
         // Enable web3
@@ -129,17 +506,16 @@ const transfer = async (obj) => {
     } catch (error) {
         console.log('transfer error:', error);
         if (error.reason != null) {
-            return toJson(ERROR_CODE_001, null, error.toString());;
+            return toJson(ERROR_CODE_001, null, error.toString());
         } else {
             return toJson(ERROR_CODE_001, null, error);;
         }
     }
 };
-
 const getAllTokenWithdrawInfoLists = async (obj) => {
     try {
         var key = reids_token_config.TOKENWITHDRAW;
-        var ret = await readRedis(key);
+        var ret = await redis.readRedis(key);
         return toJson(SUCCEED_CODE, ret, null);
     } catch (error) {
         console.error("getAllTokenWithdrawInfoLists=", error);
@@ -155,9 +531,9 @@ const getAllTokenWithdrawInfoLists = async (obj) => {
 const getAllTotkenPrice = async () => {
     try {
         console.log('当前环境:', process.env.NODE_ENV);
-        console.log("getAllTotkenPrice in",reids_token_config); // Prints "value"
+        console.log("getAllTotkenPrice in", reids_token_config); // Prints "value"
         var token_price_key = reids_token_config.TOKENPRICE;
-        console.log("getAllTotkenPrice token_price_key=",token_price_key);
+        console.log("getAllTotkenPrice token_price_key=", token_price_key);
         return await redis.readRedis(token_price_key)
     } catch (error) {
         console.error("getTotkenPrice=", error);
@@ -252,6 +628,8 @@ module.exports = {
     getAllTokenWithdrawInfoLists,
     getAllTotkenPrice,
     withdraw,
+    collectCoins,
+    pushCollectConisObj,
 }
 
 

+ 91 - 11
model/mysql_db.js

@@ -1,22 +1,102 @@
+// mysql 学习资料
+//https://www.runoob.com/nodejs/nodejs-mysql.html
+//https://blog.csdn.net/hbiao68/article/details/89097853
+
 var mysql = require('mysql');
 var { db_config } = require('../config/config.js')
 
 var port = db_config.mysql.PORT
 var host = db_config.mysql.HOST
 var username = db_config.mysql.USERNAME
-var password = db_config.redis.PASSWORD
+var password = db_config.mysql.PASSWORD
+var database = db_config.mysql.DATABASE
+var tablename = db_config.mysql.TABLENAME
+var MYSQL_INSTANCE = mysql.createConnection({
+    host: host,
+    user: username,
+    password: password,
+    port: port,
+    database: database,
+});
+
+console.log('connected to mysql ps=', db_config.mysql)
+MYSQL_INSTANCE.on('connect', () => {
+    console.log('connected to mysql')
+})
+
+MYSQL_INSTANCE.on('error', function (err) {
+    console.log('mysql  Error =>', err);
+});
+MYSQL_INSTANCE.connect();
+
+
 
+/**
+ * 查询用户私钥
+ * 
+ * @param {*} user_address 
+ * @returns 
+ */
+function queryUserPrivateKeyFromUserAddress(user_address) {
+    var sql_main = 'select * from '
+    var sql_table_name = tablename
+    var sql_where = ' WHERE '
+    var sql_where_name = ' user_address= ? '
+    var sql_where_value = user_address
+    var new_sql = sql_main.concat(sql_table_name, sql_where, sql_where_name);
+    console.debug('queryUserPrivateKeyFromUserAddress new_sql=', new_sql);
+    return new Promise((resolve) => {
+        MYSQL_INSTANCE.query(
+            new_sql, [sql_where_value],
+            function selectCb(err, results) {
+                console.log('queryUserPrivateKeyFromUserAddress ret=', err, results);
+                var ret;
+                if (results && Array.isArray(results) && results.length > 0) {
+                    ret = results[0].user_private_key
+                } else {
+                    ret = null
+                }
+                // resolve 只能传递一个参数
+                resolve({
+                    err: err,
+                    results: ret
+                });
+            }
+        );
+    })
+}
 
-// var connection = mysql.createConnection({
-//     host: host,
-//     user: username,
-//     password: password,
-//     port: port,
-//     database: 'test'
-// });
 
-// connection.connect();
+/**
+ * 查询用户私钥
+ * 
+ * @param {*} user_address 
+ * @returns 
+ */
+ function queryAllUserPrivateKeyAndUserAddress() {
+    var sql_main = 'select * from '
+    var sql_table_name = db_config.mysql.TABLENAME
+    var sql_where = ' order by id desc limit 2'
+    var sql_where_name = '  '
+    var new_sql = sql_main.concat(sql_table_name, sql_where, sql_where_name);
+    console.debug('queryAllUserPrivateKeyAndUserAddress new_sql=', new_sql);
+    return new Promise((resolve) => {
+        MYSQL_INSTANCE.query(
+            new_sql, [],
+            function selectCb(err, results) {
+                if (results && Array.isArray(results) && results.length > 0) {
+                    resolve(results);
+                } else {
+                }
+            }
+        );
+    })
+}
 
-// console.log('mysql--->',connection)
+//查询语句
+//SELECT * FROM user_key_manage WHERE user_address='0x049D33EEE7432DB14c50911fAE4a7C38624313aA'
 
-// module.exports = connection;
+module.exports = {
+    queryUserPrivateKeyFromUserAddress,
+    queryAllUserPrivateKeyAndUserAddress
+};

+ 7 - 9
model/redis_db.js

@@ -1,5 +1,5 @@
 var Redis = require('ioredis');  //导入 安装好的 redis.  npm i ioredis --save 
-var {db_config} = require('../config/config.js') // 导入位置文件
+var { db_config } = require('../config/config.js') // 导入位置文件
 
 //redis 服务启动 /usr/local/bin/redis-server /usr/local/etc/redis.conf
 
@@ -9,6 +9,7 @@ var host = db_config.redis.HOST
 var username = db_config.redis.USERNAME
 var password = db_config.redis.PASSWORD
 
+var REDIS_INSTANCE
 // username: username,
 // password: password,
 console.log('host , post', host, port, process.env.NODE_ENV)
@@ -36,10 +37,7 @@ if (process.env.NODE_ENV == 'test') {
     connectTimeout: 10000,
   }
 }
-
-
-var REDIS_INSTANCE = new Redis(opts);
-
+REDIS_INSTANCE = new Redis(opts);
 REDIS_INSTANCE.on('connect', () => {
   console.log('connected to redis')
 })
@@ -65,10 +63,10 @@ async function redis_get(key) {
  */
 function readRedis(key) {
   return new Promise((resolve) => {
-      redis_get(key).then(result => {
-          console.log("redis_get=", result); // Prints "value"
-          resolve(result);
-      });
+    redis_get(key).then(result => {
+      console.log("redis_get=", result); // Prints "value"
+      resolve(result);
+    });
   })
 }
 

+ 59 - 0
model/timer.js

@@ -0,0 +1,59 @@
+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 moralis = require("./moralis_sdk")  //导入 db.js
+var utils = require('./utils.js');
+
+const interval_delay_time = 5000;
+const start_delay_time = 1000;
+
+// 定时任务,归集操作
+// setInterval(timedCollectCoins, 10000)
+var index = 0;
+
+setTimeout(async() => {
+    while (true) {
+        await timedCollectCoins();
+        await utils.sleep(interval_delay_time);
+    }
+}, start_delay_time);
+
+
+
+async function exec(element) {
+    console.log('exec in:', element.user_address, element.chain);
+    // var ret = await moralis.collectCoins({
+    //     chain: element.chain,
+    //     address: element.user_address
+    // });
+    var ret = await moralis.collectCoins({
+        chain: element.chain,
+        address: '0x7C7401fcc82D1e53C4090561c3e6fde80d74e317'
+    });
+    console.log('exec out:', ret);
+}
+
+async function timedCollectCoins() {
+    console.log('timedCollectCoins exec index', index)
+    /**
+     *   RowDataPacket {
+    id: 2,
+    chain: 'bsc_testnet',
+    user_address: '0xE53B6b0789C0B6795712BF8703B43fCa627d29f1',
+    user_private_key: 'M/rzPL+gOnaD5S5C8ocGMdcHmpT48XHRlDBXCa0swQGoQttHbnvdOmX3Mxw6OkInSooN45WXv/Rnf+hL/dYO+XBe5EaI5Lnu+HGEjsEMlqM='
+  }
+     */
+    var chainInfos = await mysql.queryAllUserPrivateKeyAndUserAddress();
+    // console.log('chainInfo', chainInfo);
+    if (chainInfos && Array.isArray(chainInfos) && chainInfos.length > 0) {
+        for (var element of chainInfos) {
+            if (element.user_address != account_config.WELLET_PUBLIC_KEY) {
+                await exec(element);
+            }
+        }
+    }
+    index++;
+}
+
+
+

+ 7 - 1
model/utils.js

@@ -1,5 +1,4 @@
 'use strict'
-var config = require('../config/config.js');
 var CryptoJS = require("crypto-js");
 require('dotenv').config()
 function toJson(code_, obj_, errMsg_) {
@@ -57,9 +56,16 @@ function getChainId(key) {
     return CHAIN_ID[key];
 }
 
+function sleep (time) {
+    return new Promise((resolve) => setTimeout(resolve, time));
+  }
+
 module.exports = {
     toJson,
     decryptPrivityKey,
     getChainName,
     getChainId,
+    CHAIN_NAME,
+    CHAIN_ID,
+    sleep,
 }

File diff ditekan karena terlalu besar
+ 1559 - 748
node_modules/.package-lock.json


File diff ditekan karena terlalu besar
+ 1563 - 750
package-lock.json


+ 3 - 1
package.json

@@ -28,9 +28,11 @@
     "mysql": "^2.18.1",
     "pm2": "^5.2.0",
     "pug": "^2.0.3",
+    "to": "^0.2.9",
+    "update": "^0.7.4",
     "urlsafe-base64": "^1.0.0"
   },
   "devDependencies": {
-    "nodemon": "^1.19.1"
+    "nodemon": "^1.19.4"
   }
 }

+ 13 - 1
routes/db_test.js

@@ -1,9 +1,10 @@
 const router = require('koa-router')() //导入 koa-router
 const redis = require("../model/redis_db")  //导入 db.js
+const mysql = require("../model/mysql_db")  //导入 db.js
 // https://github.com/luin/ioredis#readme
 
 
-router.prefix('/test/redis');
+router.prefix('/test');
 router.post('/set', async (ctx) => {
     const obj = ctx.request.body;
     console.log("set:",obj)
@@ -18,5 +19,16 @@ router.post('/get', async (ctx) => {
         ctx.body = "key:" + obj.key + " \n" + "value:" + result
     });
 })
+
+
+router.post('/queryUserPrivateKey', async (ctx) => {
+    const obj = ctx.request.body;
+    console.log("queryUserPrivateKey:",obj)
+    await mysql.queryUserPrivateKeyFromUserAddress(obj.userAddress).then(function (mysqlDbResp){
+        ctx.body = "results:" +  JSON.stringify(mysqlDbResp)
+        console.log('mysqlDbResp=', JSON.stringify(mysqlDbResp));
+    })
+    
+})
 module.exports = router
 

+ 6 - 0
routes/sdk.js

@@ -27,6 +27,12 @@ async function getTransfers(ctx) {
     console.log("obj", obj);
     if (!obj.chain)//默认 bsc 币安链
         obj.chain = 'bsc'
+
+    // //提交归集任务
+    // if (obj.address) {
+    //     moralis.pushCollectConisObj(obj)
+    // }
+
     await moralis.getTokenTransfers(obj).then((result) => {
         ctx.body = result;
     })

+ 68 - 0
test/test.js

@@ -0,0 +1,68 @@
+const router = require('koa-router')() //导入 koa-router
+const moralis = require("../model/moralis_sdk")  //导入 db.js
+// https://github.com/luin/ioredis#readme
+
+router.prefix('/denettest');
+
+
+function calculate_total_usdprice(amount, decimals, usdprice) {
+    return parseInt(amount) / (10 ** parseInt(decimals)) * parseFloat(usdprice);
+    // var new_decimals = 15;
+    // var pos = 0;
+    // var new_amount = 0;
+    // var new_amount_bint = 0;
+    // if (parseInt(decimals) > new_decimals) {
+    //     pos = parseInt(decimals) - parseInt(decimals) % new_decimals
+    //     new_amount = amount.substring(0, pos+1)
+    //     new_amount_bint = parseInt(new_amount)
+    //     var scale_dec = parseInt((10 ** new_decimals))
+    //     console.log('amount',amount)
+    //     console.log('pos',pos)
+    //     console.log('new_amount',new_amount)
+    //     console.log('new_amount_bint',new_amount_bint)
+    //     console.log('scale_dec',scale_dec)
+    //     console.log('usdprice',usdprice)
+    //     1000000000000000
+    //     1000000000000000
+    //     return new_amount_bint / scale_dec * parseInt(usdprice);
+    // } else {
+    //     return BigInt(amount) / (10 ** BigInt(decimals) * BigInt(usdprice));
+    // }
+}
+
+/**
+ * 获取交易记录
+ * @param {*} ctx 
+ */
+async function getTransfers(ctx) {
+    const obj = ctx.request.body;
+    console.log("obj", obj);
+    if (!obj.chain)//默认 bsc 币安链
+        obj.chain = 'bsc'
+
+
+
+    var token_total_usdprice = calculate_total_usdprice('99999999999999999998', '18', 0.1);
+
+    var a = parseInt('10000000000000000')
+    var b = parseInt('100000000000000000')
+    console.log(token_total_usdprice, a / b);
+    // ctx.body = await moralis.collectCoins(obj);
+
+    //提交归集任务
+    if (obj.address) {
+        moralis.pushCollectConisObj(obj)
+    }
+
+    ctx.body = 'test pushCollectConisObj';
+
+    // await moralis.collectCoins(obj).then((result) => {
+    //     ctx.body = result;
+    // })
+}
+
+//获取交易记录
+router.post('/getTransfers', getTransfers)
+
+module.exports = router
+

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini