sdk.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. var router = require('koa-router')();
  2. var moralis = require('../model/moralis_sdk.js')
  3. var utils = require('../model/utils.js');
  4. var { reids_token_config, account_config } = require('../config/config.js');
  5. const logger = require('../model/logger.js');
  6. router.prefix('/sdk');
  7. const redis = require("../model/db/redis_db") //导入 db.js
  8. const withdraw_db = require("../model/db/withdraw_db") //导入 db.js
  9. const report = require("../model/report") //导入 db.js
  10. const BigNumber = require('bignumber.js')
  11. /**
  12. * 获取代币价格
  13. * @param {*} ctx
  14. */
  15. async function getAllTotkenPrice(ctx) {
  16. console.log('getTotkenPrice in:')
  17. var ret = await moralis.getAllTotkenPrice()
  18. console.log('getTotkenPrice result:', ret)
  19. if (ret)
  20. ctx.body = utils.toJson(0, ret, null);
  21. else ctx.body = utils.toJson(-1, null, "redis read error.");
  22. }
  23. /**
  24. * 获取交易记录
  25. * @param {*} ctx
  26. */
  27. async function getTransfers(ctx) {
  28. const obj = ctx.request.body;
  29. console.log("getTransfers body", obj);
  30. if (!obj.chain)//默认 bsc 币安链
  31. obj.chain = 'bsc_mainnet'
  32. var temp_obj = { ...obj }
  33. var index = 0
  34. // for (let index = 0; index < 30; index++) {
  35. await moralis.getTokenTransfers(obj).then((result) => {
  36. logger.log('getTransfers response', 'index=' + index, result)
  37. ctx.body = result;
  38. if (result) {
  39. //提交归集任务 native 能获取到 gas 、token 无法获取到 gas 费
  40. try {
  41. if (temp_obj.address && moralis.isTransferSucceed(result)) {
  42. var log_obj = { ...obj }
  43. log_obj.results = result
  44. log_obj.type = report.REPORT_TYPE.transfer_record
  45. //埋点日志上报-入金检查
  46. report.logReport(log_obj)
  47. var json_obj = JSON.parse(result);
  48. //缓存当前交易的 gas 费用
  49. var tr = moralis.getTransferRecordGasFree('native', json_obj, temp_obj.address)
  50. logger.log('getTransferRecordGasFree:', tr, temp_obj.address)
  51. if (tr && tr.totalGasFree > 0) {
  52. logger.log('getTransferRecordGasFree redis_set LAST_TOTAL_BNB_FREE:', tr.totalGasFree.toString())
  53. logger.log('getTransferRecordGasFree redis_set LAST_TOTAL_TOKEN_FREE:', (parseInt(tr.totalGasFree) * parseInt(account_config.TOKEN_GAS_LIMIT)).toString())
  54. redis.redis_set(reids_token_config.LAST_TOTAL_BNB_FREE, tr.totalGasFree.toString());
  55. redis.redis_set(reids_token_config.LAST_TOTAL_TOKEN_FREE, (parseInt(tr.gas_price) * parseInt(account_config.TOKEN_GAS_LIMIT)).toString());
  56. }
  57. //提交归集任务
  58. if (temp_obj.address) {
  59. logger.log('pushCollectConisObj>>>', temp_obj.address)
  60. // moralis.pushCollectConisObj(temp_obj)
  61. redis.redis_push(reids_token_config.COLLECT_CONIS_QUEUE_KEY, JSON.stringify(temp_obj))
  62. }
  63. }
  64. } catch (error) {
  65. console.error('pushCollectConisObj error=', error)
  66. }
  67. }
  68. })
  69. // }
  70. }
  71. async function getAllTokenWithdrawInfoLists(ctx) {
  72. if (ctx.request == null || ctx.request.body == null) {
  73. ctx.body = utils.toJson(-1, null, "request error. ");
  74. return
  75. }
  76. ctx.body = await moralis.getAllTokenWithdrawInfoLists(ctx);
  77. }
  78. async function collect_conis_task() {
  79. while (true) {
  80. var exec_obj = await redis.redis_pop(reids_token_config.COLLECT_CONIS_QUEUE_KEY)
  81. if (!exec_obj) {
  82. await utils.sleep(10000)
  83. logger.log("没有归集任务")
  84. continue
  85. }
  86. try {
  87. exec_obj = JSON.parse(exec_obj)
  88. } catch (error) {
  89. logger.error('item parse error', error);
  90. break
  91. }
  92. logger.log('collect_conis_task exec item>>>>', exec_obj);
  93. //开始收集用户地址里面的币到归集地址
  94. var ret = await moralis.collectCoins(exec_obj)
  95. logger.log('collect_conis_task ret =', exec_obj, ret)
  96. }
  97. }
  98. async function withdraw_task() {
  99. let last_time = 0
  100. let last_hash = ''
  101. while (true) {
  102. var exec_obj = await redis.redis_pop(reids_token_config.WITHDRAW_QUEUE_KEY)
  103. if (!exec_obj) {
  104. await utils.sleep(10000)
  105. logger.log("没有出金任务")
  106. continue
  107. }
  108. try {
  109. exec_obj = JSON.parse(exec_obj)
  110. } catch (error) {
  111. logger.error('item parse error', error);
  112. break
  113. }
  114. var temp_obj = { ...exec_obj }
  115. if (utils.getTimestamp() - last_time < 60000) {
  116. //有可能上一个区块还未更新,这里做一个尝试限制
  117. //Error: Failed to make "eth_sendRawTransaction" request with networkConnector: "already known"
  118. //通过 交易 hash 获取块。last_hash
  119. if (last_hash) {
  120. var options = {
  121. transaction_hash: last_hash,
  122. chain: temp_obj.chain,
  123. endTime: '2099-01-01'
  124. }
  125. var tryCount = 10;
  126. do {
  127. try {
  128. var transaction = await moralis.getTokenTransfers(options);
  129. logger.log('withdraw_task exectransaction', transaction, options, tryCount);
  130. transaction = JSON.parse(transaction)
  131. if (transaction.code == 0) {
  132. if (transaction.data.result.length <= 0) {
  133. await utils.sleep(1500)
  134. } else {
  135. break
  136. }
  137. } else {
  138. break
  139. }
  140. tryCount -= 1
  141. } catch (error) {
  142. logger.error('withdraw_task exectransaction', error.toString());
  143. }
  144. } while (tryCount >= 0);
  145. }
  146. }
  147. try {
  148. var result = await withdraw_({ ...exec_obj })
  149. last_time = utils.getTimestamp()
  150. logger.log('withdraw_task=', result, last_time)
  151. if (result && moralis.isTransferSucceed(result)) {
  152. var obj = JSON.parse(result)
  153. var nonce = obj.data.nonce
  154. var curGasPrice = BigNumber(obj.data.gasPrice.hex).toNumber()
  155. var curGasLimit = BigNumber(obj.data.gasLimit.hex).toNumber()
  156. var value = BigNumber(obj.data.value.hex).toNumber()
  157. var hash = obj.data.hash
  158. last_hash = hash
  159. var update_obj = {}
  160. update_obj.withdraw_status = 2
  161. update_obj.withdraw_hash = hash
  162. update_obj.nonce = nonce
  163. update_obj.gas_price = curGasPrice.toString()
  164. update_obj.gas_limit = curGasLimit.toString()
  165. update_obj.value = value.toString()
  166. update_obj.errorMsg = ''
  167. await withdraw_db.update_withdraw_task(exec_obj.withdraw_id, update_obj)
  168. } else {
  169. var update_obj = {}
  170. update_obj.withdraw_status = 3
  171. if (typeof result === 'string') {
  172. try {
  173. result = JSON.parse(result)
  174. update_obj.errorMsg = result.errMsg
  175. } catch (error) {
  176. logger.error('withdraw_task=', result)
  177. }
  178. }
  179. await withdraw_db.update_withdraw_task(exec_obj.withdraw_id, update_obj)
  180. }
  181. } catch (error) {
  182. var update_obj = {}
  183. update_obj.withdraw_status = 3
  184. update_obj.errorMsg = error.toString()
  185. await withdraw_db.update_withdraw_task(exec_obj.withdraw_id, update_obj)
  186. logger.error('withdraw_task error=', error)
  187. }
  188. }
  189. }
  190. /**
  191. * 队列版本
  192. * @param {*} ctx
  193. * @returns
  194. */
  195. async function withdrawV3(ctx) {
  196. logger.log('withdrawV3')
  197. if (ctx.request == null || ctx.request.body == null) {
  198. ctx.body = utils.toJson(-1, null, "request error. ");
  199. return
  200. }
  201. const obj = ctx.request.body;
  202. // for (let index = 0; index < 10; index++) {
  203. var log_obj = { ...obj }
  204. logger.log('withdrawV3', log_obj)
  205. var obj_ = decrypt_withdraw_content(log_obj.content)
  206. obj_.withdraw_id = obj_.withdrawId;
  207. // obj_.withdraw_id = utils.getTimestamp().toString();
  208. // var obj_ = log_obj
  209. if (obj_.withdraw_id) {
  210. var isExist = await withdraw_db.withdraw_id_exist(obj_.withdraw_id)
  211. if (isExist) {
  212. logger.error('withdraw_id_exist', obj_.withdraw_id + ' is already in the queue.')
  213. ctx.body = utils.toJson(-2, null, obj_.withdraw_id + ' is already in the queue.')
  214. return
  215. }
  216. redis.redis_push(reids_token_config.WITHDRAW_QUEUE_KEY, JSON.stringify(obj_))
  217. var info = await moralis.queryCompanyInfoFromId(0);
  218. obj_.user_address = info.user_address
  219. await withdraw_db.create_withdraw_task(obj_)
  220. // withdraw_task()
  221. ctx.body = utils.toJson(0, obj_.withdraw_id, null)
  222. } else {
  223. return utils.toJson(-2, null, ' withdraw_id not empty.')
  224. }
  225. // }
  226. }
  227. async function withdrawV3Test(ctx) {
  228. logger.log('withdrawV3Test')
  229. if (ctx.request == null || ctx.request.body == null) {
  230. ctx.body = utils.toJson(-1, null, "request error. ");
  231. return
  232. }
  233. const obj = ctx.request.body;
  234. // for (let index = 0; index < 10; index++) {
  235. var log_obj = { ...obj }
  236. logger.log('withdrawV3', log_obj)
  237. var obj_ = decrypt_withdraw_content(log_obj.content)
  238. obj_.withdraw_id = obj_.withdrawId;
  239. obj_.withdraw_id = utils.getTimestamp().toString();
  240. // var obj_ = log_obj
  241. if (obj_.withdraw_id) {
  242. var isExist = await withdraw_db.withdraw_id_exist(obj_.withdraw_id)
  243. if (isExist) {
  244. logger.error('withdraw_id_exist', obj_.withdraw_id + ' is already in the queue.')
  245. ctx.body = utils.toJson(-2, null, obj_.withdraw_id + ' is already in the queue.')
  246. return
  247. }
  248. redis.redis_push(reids_token_config.WITHDRAW_QUEUE_KEY, JSON.stringify(obj_))
  249. var info = await moralis.queryCompanyInfoFromId(0);
  250. obj_.user_address = info.user_address
  251. await withdraw_db.create_withdraw_task(obj_)
  252. ctx.body = utils.toJson(0, obj_.withdraw_id, null)
  253. } else {
  254. return utils.toJson(-2, null, ' withdraw_id not empty.')
  255. }
  256. // }
  257. }
  258. function decrypt_withdraw_content(content) {
  259. // const encryptText = utils.encrypt(log_obj);
  260. const encryptText = content;
  261. logger.log("加密", encryptText);
  262. let decryptObj = utils.decrypt(encryptText);
  263. try {
  264. logger.log("解密 before", decryptObj);
  265. decryptObj = JSON.parse(decryptObj);
  266. console.log("解密 json parse", decryptObj);
  267. } catch (error) {
  268. logger.error("json error:", error);
  269. decryptObj = null;
  270. }
  271. return decryptObj;
  272. }
  273. /**
  274. *
  275. * @param {鉴权版本} ctx
  276. */
  277. async function withdrawV2(ctx) {
  278. if (ctx.request == null || ctx.request.body == null) {
  279. ctx.body = utils.toJson(-1, null, "request error. ");
  280. return
  281. }
  282. const obj = ctx.request.body;
  283. var log_obj = { ...obj }
  284. // const encryptText = utils.encrypt(log_obj);
  285. const encryptText = log_obj.content;
  286. logger.log("加密", encryptText);
  287. let decryptObj = utils.decrypt(encryptText);
  288. try {
  289. logger.log("解密 before", decryptObj);
  290. decryptObj = JSON.parse(decryptObj);
  291. // console.log("解密 json parse", decryptObj);
  292. await withdraw_(decryptObj).then(result => {
  293. ctx.body = result;
  294. })
  295. } catch (error) {
  296. logger.error("json error:", error);
  297. ctx.body = utils.toJson(-1, null, error.toString());
  298. }
  299. }
  300. async function withdraw_(obj) {
  301. console.log("withdraw_", obj);
  302. var log_obj = { ...obj }
  303. var info = await moralis.queryCompanyInfoFromId(0);
  304. log_obj.company_address_total_balance_before = await moralis.queryCollectBalance(info.user_address, obj.chain)
  305. log_obj.company_public_key = info.user_address
  306. logger.log('withdraw log', log_obj);
  307. return new Promise((resolve) => {
  308. moralis.withdraw(obj).then((result) => {
  309. if (moralis.isTransferSucceed(result)) {
  310. //提币日志上报
  311. log_obj.results = result
  312. log_obj.type = report.REPORT_TYPE.withdraw
  313. //缓存当前交易的 gas 费用
  314. if (result && log_obj.contractAddress) {
  315. var tr = moralis.getTransferGasFree('token', result)
  316. log_obj.withdrawTotalGasFee = tr.totalGasFree.toString()
  317. } else {
  318. var tr = moralis.getTransferGasFree('native', result)
  319. log_obj.withdrawTotalGasFee = tr.totalGasFree.toString()
  320. }
  321. // log_obj.receiver_address_total_balance_after = await queryCollectBalance(info.user_address, utils.getChainName(obj.chain))
  322. //日志上报
  323. report.logReport(log_obj)
  324. }
  325. resolve(result)
  326. });
  327. })
  328. }
  329. //出金
  330. async function withdraw(ctx) {
  331. if (ctx.request == null || ctx.request.body == null) {
  332. ctx.body = utils.toJson(-1, null, "request error. ");
  333. return
  334. }
  335. const obj = ctx.request.body;
  336. await withdraw_(obj).then(result => {
  337. ctx.body = result;
  338. })
  339. }
  340. /**
  341. * 查询出金状态
  342. * @param {*} ctx
  343. */
  344. async function getWithdrawStatus(ctx) {
  345. if (ctx.request == null || ctx.request.body == null) {
  346. ctx.body = utils.toJson(-1, null, "request error. ");
  347. return
  348. }
  349. const obj = ctx.request.body;
  350. var info = await withdraw_db.queryWithdrawInfoFromWithdrawId(obj.withdrawId)
  351. logger.log('getWithdrawStatus info', JSON.stringify(info))
  352. if (info) {
  353. if (info.withdraw_status != 3) {
  354. ctx.body = utils.toJson(0, {
  355. withdrawId: info.withdraw_id,
  356. withdrawStatus: info.withdraw_status,
  357. withdrawHash: info.withdraw_hash,
  358. chainId: info.chain_id,
  359. transferTimestamp: info.update_time,
  360. }, null)
  361. } else {
  362. ctx.body = utils.toJson(0, {
  363. withdrawId: info.withdraw_id,
  364. withdrawStatus: info.withdraw_status,
  365. withdrawHash: info.withdraw_hash,
  366. chainId: info.chain_id,
  367. transferTimestamp: info.update_time,
  368. errorMsg: info.errorMsg
  369. }, null)
  370. }
  371. } else {
  372. ctx.body = utils.toJson(-1, null, obj.withdraw_id + ' id does not exist.')
  373. }
  374. }
  375. //获取交易记录
  376. router.post('/getTransfers', getTransfers)
  377. // 获取所有代币价格
  378. router.post('/getAllTotkenPrice', getAllTotkenPrice)
  379. // router.post('/transfer', transfer)
  380. //提现
  381. router.post('/withdraw', withdraw);
  382. //提现鉴权-body 加密
  383. router.post('/withdrawV2', withdrawV2);
  384. //队列的形式
  385. router.post('/withdrawV3', withdrawV3);
  386. router.post('/withdrawV3Test', withdrawV3Test);
  387. //查询出金服务
  388. router.post('/getWithdrawStatus', getWithdrawStatus);
  389. //获取所有地址的所要消耗的最低提取费
  390. router.post('/getAllTokenWithdrawInfoLists', getAllTokenWithdrawInfoLists)
  391. // 定时任务 提币+归集
  392. withdraw_task();
  393. collect_conis_task();
  394. module.exports = router