def check_block(block_info, operator: ERC20Token): """检查区块是否回滚""" if not block_info: return False info = operator.get_block(int(block_info.block_num) + 1) if not info: return False if hexstr_if_str(to_hex, info['parentHash']) == block_info.block_hash: new_block_info = { 'block_num': int(info['number']), 'block_hash': hexstr_if_str(to_hex, info['hash']), 'coin_type': coin_type } else: new_block_info = { 'coin_type': coin_type, 'block_num': int(block_info.block_num) - int(config.eth_confirmations), } roll_back_info = operator.get_block(new_block_info['block_num']) new_block_info['block_hash'] = hexstr_if_str(to_hex, roll_back_info['hash']) new_block_info = { 'block_num': int(roll_back_info['number']), 'block_hash': hexstr_if_str(to_hex, roll_back_info['hash']), 'coin_type': coin_type } return new_block_info
def check_success(operator: ERC20Token, item): """检查是否成功 :param operator: 区块链接口 :param item: 交易信息 :return: """ res = operator.is_success(operator.get_transaction(item.txid)) if res: return AskFeeStatusEnum.SUCCESS else: return AskFeeStatusEnum.FAILED
def withdraw_eth(cls, address, amount): private_key = hexstr_if_str(to_hex, load_keyfile(config.eth_private_key_file, config.eth_password) ) eth = ERC20Token(provider_endpoint=config.eth_wallet_url, private_key=private_key, password=config.eth_password) checksum_address = eth.web3.toChecksumAddress(address) try: tx_id = eth.send_ether(checksum_address, amount) tb = { 'amount': amount, 'txid': tx_id, 'coin_type': 'ETH', 'from_address': config.eth_tb_address, 'to_address': address, 'status': TbStatusEnum.TRANSFER } except Exception as e: logger.exception(e) else: try: document = TbRecord(**tb) document.insert() return tx_id except Exception as e: logger.exception(e) logger.error("提币行为已经发生,但数据没有插入数据库{}".format(tb))
def send2address(self, address, amount, *args, **kwargs): password = config.etc_password private_key = hexstr_if_str( to_hex, load_keyfile(config.etc_private_key_file, password)) eth = ERC20Token(ipc_path=config.etc_ipc_path, private_key=private_key, password=password) checksum_address = eth.web3.toChecksumAddress(address) try: tx_id = eth.send_ether(checksum_address, amount) tb = { 'amount': amount, 'txid': tx_id, 'coin_type': 'ETC', 'from_address': config.etc_tb_address, 'to_address': address, } except Exception as e: logger.exception(e) else: try: document = TbRecord(**tb) document.insert() return tx_id except Exception as e: logger.exception(e) logger.error("提币行为已经发生,但数据没有插入数据库{}".format(tb))
def __init__(self, session_maker): """ :param session_maker: mysql的session_maker """ super().__init__(session_maker) self.coin_category = "ETH" self.chain_api = ERC20Token()
def tx_process(session, tx_id, operator: ERC20Token): """交易处理函数""" tx_data = operator.get_transaction_data(tx_id) from_address = tx_data.from_address black_list = get_black_list() if from_address in black_list: return if not check_account_exists(session, tx_data.to_address): return coin = coin_type if tx_data.token_address: coin_info = session.query(coin_setting_document).filter_by( coin_setting_document.token_address.in_( (tx_data.token_address, to_normalized_address(tx_data.token_address)))).first() if not coin_info: logger.error(f'not found token address: {tx_data.token_address}') return coin = coin_info.coin_type tx_data.token_amount = from_unit(tx_data.token_amount, coin_info.token_unit) recharge_record = session.query(coin_recharge_document).filter_by( txid=tx_id).first() if recharge_record: return data = { 'amount': tx_data.ether_amount, 'txid': tx_id, 'created_at': datetime.utcnow(), 'confirmation_count': tx_data.num_confirmations, 'from_address': tx_data.from_address, 'to_address': tx_data.to_address, 'coin_type': coin, 'coin_series': coin_type, } r = Recharge(**data) session.add(r) try: session.commit() except Exception as e: logger.exception("冲币记录到数据库时发生错误{}".format(e)) session.rollback() raise else: recharge(address=data["to_address"], from_address=data["from_address"], amount=float(data["amount"]), txid=data["txid"], coin_type=data["coin_type"], confirmations=data["confirmation_count"], status=0, destination_tag=None) logger.info('检测到{}充币到{}{}个'.format(tx_data.from_address, tx_data.to_address, tx_data.ether_amount))
def main(): session = Session() init_block_info(session) while True: try: operator = ERC20Token(provider_endpoint=config.eth_wallet_url) # 获取区块信息及交易列表 block_info = session.query(block_info_document).filter_by( coin_type=coin_type).first() checked_block_info = check_block(block_info, operator) if not checked_block_info: continue tx_list = operator.get_block_tx_id_list( checked_block_info['block_num']) # 遍历交易列表 for tx_id in tx_list: tx_process(session, hexstr_if_str(to_hex, tx_id), operator) logger.info( f'pull block finished: {checked_block_info["block_num"]}') except Exception as e: logger.exception(e) else: block_info.block_hash = checked_block_info['block_hash'] block_info.block_num = checked_block_info['block_num'] try: session.commit() except Exception as e: logger.exception("更新区块发生错误{}".format(e)) session.rollback() time.sleep(3)
def init_block_info(session): """第一次初始化数据库区块信息""" block_info = session.query(BlockInfo).filter_by( coin_type=coin_type).first() if block_info: return while True: try: operator = ERC20Token(provider_endpoint=config.eth_wallet_url) info = operator.get_block(int(operator.get_block_number())) block_info = BlockInfo( **{ 'block_num': int(info['number']), 'block_hash': hexstr_if_str(to_hex, info['hash']), 'coin_type': coin_type }) session.add(block_info) session.commit() logger.info('block_info init success') break except Exception as e: logger.exception("初始化区块失败{}".format(e)) session.rollback() time.sleep(15)
def __init__(self, configure): self.coin_type = configure.coin_type self.block_record = BlockInfoRecord(configure) self.token_address = CoinSettingRecord(configure).token_address self.wallet_op = ERC20Token() self.tb_address = configure.tb_address self.confirmation_count = configure.confirmation_count try: self.block_num, self.block_hash = self.block_record.retrieve_head_block( ) except RecordNotFound as e: logger.exception(e) self.block_num, self.block_hash = self._retrieve_head_block()
def withdraw_token(cls, to_address, amount, coin_type): token_info = CoinSetting.find_one({'id': coin_type, 'main_coin': 'ETH'}) if not token_info: logger.warning('不存在的币种类型{}'.format(coin_type)) return token_address = token_info['token_address'] private_key = hexstr_if_str(to_hex, load_keyfile(config.eth_private_key_file, config.eth_password) ) token = ERC20Token( provider_endpoint=config.eth_wallet_url, contract_address=token_address, password=config.eth_password, private_key=private_key) try: tx_id = token.send_tokens(to_address, amount, token_info['token_unit']) data = { 'amount': amount, 'txid': tx_id, 'from_address': getattr(config, f'{coin_type}_tb_address'), 'coin_type': coin_type, 'to_address': to_address, 'status': TbStatusEnum.TRANSFER } logger.info('withdraw {} to {}'.format(coin_type, to_address)) except Exception as e: logger.exception(e) else: try: tb = TbRecord(**data) tb.insert() return tx_id except Exception as e: logger.exception(e) logger.error("提币行为已经发生,但数据没有插入数据库{}".format(data))