const util = require('util'); const utils = require('./utils'); const db = require("./db"); const dbhelper = require("./dbhelper"); const bchelper = require("./bchelper"); const log = require("./log"); const dblog = require("./dblog"); const bc = require('./blockchain'); const metamgr = require('./metamgr'); const C = require('./C'); class Withdrawal { constructor(db, isNew) { this.isNew = isNew; this.db = db; } init () { setTimeout(this.start.bind(this), utils.randRange(100, 1000)); } async start() { const logClass = 'withdrawal.start'; try { await this.doStart(); } catch (err) { await this.suspend(logClass, err); } } async doStart() { const logClass = 'withdrawal.doStart'; const instanceName = this.getInstanceName(); if (!instanceName) { await this.suspend(logClass, 'instanceName is empty'); return; } await bc.mustBeActive(); await this.updateDbMustBeSuccess (logClass, [ ['state', 1] ]); const instance = bc[instanceName]; const balance = await instance.methods.balanceOf(metamgr.getUserAddress()).call(); log.info('balance:' + balance); await bc.lock(); try { const result = await instance.methods.transfer (this.db['account'], '' + this.db['amount']).send({gas: 1000000}); await this.updateDbMustBeSuccess (logClass, [ ['state', 2], ['bc_block_number', result['blockNumber']], ['bc_txhash', result['transactionHash']], ['bc_time', utils.getUtcTime()], ]); } catch(err) { await this.updateDbMustBeSuccess (logClass, [ ['state', 3] ]); await this.suspend(logClass, err); } finally { await bc.unLock(); } } getInstanceName() { if (this.db['type'] == 1) { //金币 return 'ceg_coinInstance'; } else if (this.db['type'] == 2) { //钻石 return 'cec_coinInstance'; } else { return ''; } } async updateDbMustBeSuccess(logClass, fieldList) { const err = await dbhelper.update( 't_withdrawal', [ ['idx', this.db['idx']] ], fieldList); if (err) { log.error(util.format('%s updateDbMustBeSuccess withdrawalDb:%s fieldList:%s err:%s', logClass, utils.jsonEncode(this.db), utils.jsonEncode(fieldList), err ) ); await this.suspend(logClass + ' updateDbMustBeSuccess ', err); } else { fieldList.forEach((val) => { const name = val[0]; const value = val[1]; this.db[name] = value; }); log.info(util.format('%s updateDbMustBeSuccess db:%s', logClass, utils.jsonEncode(this.db), utils.jsonEncode(fieldList) ) ); } return err; } async suspend(logClass, reason) { /* 挂起等待人工处理 为啥不抛出异常是因为: 如果在调用接口的外部try catch的话,那么挂起操作产生的异常会被吞噬,这样非常危险!!! 挂起的操作现在为无限等待不受外部try catch影响。 */ try { log.warning(util.format('%s suspend withdrawalDb:%s reason:%s', logClass, utils.jsonEncode(this.db), reason ) ); } catch (err) { log.error(util.format('%s suspend withdrawalDb:%s err:%s', logClass, utils.jsonEncode(this.db), err ) ); } while (true) { await utils.sleep(1000 * 3600 * 24); } } } exports.Withdrawal = Withdrawal;