def bet_in(self, dic): change_type_41 = '41' # 即时开中奖 change_type_42 = '42' # 即时开投注 id = dic.get("game_instance_id", "") # 项目id user_id = dic.get("user_id", "") # 用户id user_channel_id = dic.get("user_channel_id", "") # 用户下注渠道id conin_id = dic.get("coin_id", "") # 投入币种id bet_amount = dic.get("bet_amount", "") # 投注数量 bet_start = dic.get("bet_start", 0) bet_end = dic.get("bet_end", 0) faker = True # merge_id = dic.get("merge_id", -1) # 合并投注id # transaction_password = dic.get("transaction_password", "") # 交易密码 with MysqlTools().session_scope() as session: # 查询项目 model = session.query(InstantGameInstanceModel).filter( InstantGameInstanceModel._id == id).first() template = session.query(InstantGameTemplateModel). \ order_by(InstantGameTemplateModel._id.desc()).first() if model is None: return self.return_error(60001) if model.status == 1: return self.return_error(60002) if model.status == 2: return self.return_error(60003) if model.status == 0: can_bet = model.need - model.bet_number if can_bet <= 0: return self.return_error(60002) if int(bet_amount) > can_bet: return self.return_error(60004) if model.support_token >= 0 and int( conin_id) != model.support_token and int(conin_id) != int( _COIN_ID_EXP): return self.return_error(60008) if int(bet_amount) > model.need * (model.max_bet_ratio / 100): return self.return_error(40025) # 查询币价 币种实际需要金额 exchange_rate = get_exchange_rate(int(conin_id)) # (投注数量 * 投注单位) / 投注币种兑换usdt比例 bet_money = (int(bet_amount) * model.bet_unit) / exchange_rate['price'] # 体验金相关逻辑 if int(conin_id) == int(_COIN_ID_EXP): # 检查本次投注体验金使用数量 (允许范围: 1~10) if int(bet_amount) < 1 or int(bet_amount) > 10: self.return_error(60015) # 体验金使用额度 exp = int(model.experience / 100 * model.need) # 检查项目体验金占比剩余额度以及个人当天最大体验金使用额度(每天最多用10个) limit = self.check_instance_exp_limit(session, user_id, model.game_serial) # instance_limit = limit['instance_limit'] user_limit = limit['user_limit'] total_pay_number = limit['total_pay_number'] if user_limit > 10 - int(bet_amount): self.return_error(60017) # if instance_limit >= exp: # self.return_error(60016) if total_pay_number >= int( model.need) * model.reward_quantity * ( (100 + template.exceeded_ratio) / 100): model.full_load_time = datetime.datetime.utcnow() faker = False else: limit = self.check_instance_exp_limit(session, user_id, model.game_serial) total_pay_number = limit['total_pay_number'] raise_logger("总下注金额" + "USDT:" + str(total_pay_number), "game_publish_lottery", "info") if total_pay_number >= int( model.need) * model.reward_quantity * ( (100 + template.exceeded_ratio) / 100): model.full_load_time = datetime.datetime.utcnow() faker = False # 查询用户资产 account_service = AccountService() user_info = account_service.get_inner_user_account_by_token( session, user_id, conin_id) if isinstance(user_info, int): if user_info == 20001: return self.return_error(20001) balance = get_decimal(user_info.get("balance"), digits=8, decimal_type="down") # 账户余额 < 需要下注金额 if balance < bet_money: return self.return_error(60005) # 获取下注编号 numbers = [] user_lottery_num_list = [] i = int(bet_amount) # start_num = random.randint(1, model.need 0- int(bet_amount)) bet_start = int(bet_start) bet_end = int(bet_end) user_lottery_num_list.append(bet_start) user_lottery_num_list.append(bet_end) while i > 0: numbers.append(bet_start) bet_start += 1 i -= 1 if isinstance(numbers, list): nick_name = account_service.get_inner_user_account_info( session, user_id).get("nick_name") # 添加参与记录 participate_in_model = ParticipateInModel( game_instance_id=0, template_id=model.template_id, game_serial=model.game_serial, game_title=model.game_title, release_type=model.release_type, bet_token=model.bet_token, bet_unit=model.bet_unit, user_id=user_id, nick_name=nick_name, channel=user_channel_id, bet_number=int(bet_amount), pay_token=int(conin_id), pay_number=get_decimal(bet_money, digits=8, decimal_type="down"), award_numbers=json.dumps(numbers), user_type=0, merge_id=-1) session.add(participate_in_model) session.flush() # raise_logger("add participate_in_model", "game_bet_in", "info") # 提交扣款申请 result = account_service.do_bet( session, user_id, conin_id, get_decimal(bet_money, digits=8, decimal_type="down"), str(participate_in_model._id), int(bet_amount), model.game_serial, user_channel_id, change_type_42) # raise_logger("do_bet success", "game_bet_in", "info") if isinstance(result, int): if result == 0: instant_game_service = InstantGameModelService() # print('user_lottery_num_list-=-=', user_lottery_num_list) # print('model.need-=-=', model.need) # print('faker-=-=', faker) lottery_result = WalletEosService().\ lottery_instant_adduce(get_timestamp(), user_lottery_num_list, model.need, faker) # print('lottery_result-=-=', lottery_result) if not any(lottery_result): raise_logger("lottery_result empty", "game_bet_in", "info") session.rollback() return self.return_error(40026) # 开奖 hash_numbers = lottery_result['block_hash'] raise_logger( "项目:" + str(id) + " 中奖区块号:" + str(hash_numbers), "game_publish_lottery", "info") if hash_numbers == "": raise_logger("开奖异常:80001", "game_publish_lottery", "info") return False # prize_number = int(hash_numbers, 16) % model.need + 1 prize_number = lottery_result['lottery_num'] raise_logger( "项目:" + str(id) + " 中奖号码:" + str(prize_number), "game_publish_lottery", "info") participate_in_model.win_number = prize_number participate_in_model.block_no = lottery_result[ 'block_num'] participate_in_model.bet_hash = hash_numbers participate_in_model.received_time = lottery_result[ 'timestamp'] # 中奖 is_win = False if prize_number in numbers: is_win = True participate_in_model.result = 1 model.lottery_time = datetime.datetime.utcnow() instant_game_service.automatic_release( session, model.template_id) do_win = account_service.do_win( session, user_id, model.reward_token, model.reward_quantity, str(participate_in_model._id), int(bet_amount), model.game_serial, change_type_41) if isinstance(do_win, int) is False: raise_logger("分钱失败" + "user:"******"game_publish_lottery", "info") session.rollback() return False if do_win != 0: raise_logger("分钱失败" + "user:"******"game_publish_lottery", "info") session.rollback() return False session.commit() return { 'is_win': is_win, 'prize_number': prize_number, 'part_in_id': participate_in_model._id } else: session.rollback() return self.return_error(60009) else: session.rollback() return self.return_error(60010) else: session.rollback() return self.return_error(60007)
def get_node_url(coin_id, mold="server", node_env=None, pattern=None): filters = {} if not node_env: node_env = get_env() filters["coin_id"] = coin_id filters["node_env"] = node_env if mold == "server": filters["server_status"] = _ONE_S else: filters["script_status"] = _ONE_S conn = None with MysqlTools().session_scope() as session: node = session.query(TokenNodeConfModel).filter_by( **filters).first() if node: url, port = node.node_url, node.node_port if coin_id == _ZERO_S: conn, err = TokenNodeConfModel.check_btc(url, port) elif coin_id == _SIXTY_S: conn, err = TokenNodeConfModel.check_eth(url, port) elif coin_id == _COIN_ID_EOS: conn, err = TokenNodeConfModel.check_eos( url, port, node.api_key, pattern) if conn: if node.mark != "": node.mark = "" session.commit() return conn else: if mold == "server": node.server_status = _ZERO_S else: node.script_status = _ZERO_S node.mark = err if mold == "server": del filters["server_status"] else: del filters["script_status"] node_list = session.query(TokenNodeConfModel).filter_by( **filters).all() if not node_list: raise Exception("db not have available node!") for next_node in node_list: url, port = next_node.node_url, next_node.node_port if coin_id == _ZERO_S: conn, err = TokenNodeConfModel.check_btc(url, port) elif coin_id == _SIXTY_S: conn, err = TokenNodeConfModel.check_eth(url, port) elif coin_id == _COIN_ID_EOS: conn, err = TokenNodeConfModel.check_eos( url, port, node.api_key) if conn: if mold == "server": next_node.server_status = _ONE_S else: next_node.script_status = _ONE_S if next_node.mark != "": next_node.mark = "" break else: next_node.mark = err session.commit() if conn: return conn raise Exception("db not have available node!")
def get_instant_part_in_list(self, limit, offset, game_serial='', bet_time_start='', bet_time_end='', result='', user_name='', start_id=None): offset = get_offset_by_page(offset, limit) result_dict = { 'limit': limit, 'offset': offset, 'count': 0, 'content': [], 'total': 0 } with MysqlTools().session_scope() as session: account_service = AccountService() q = session.query(ParticipateInModel) if user_name != '': q = q.filter(ParticipateInModel.nick_name == user_name) if game_serial != '': q = q.filter(ParticipateInModel.game_serial == game_serial) if bet_time_start != '': q = q.filter(ParticipateInModel.created_at >= bet_time_start) if bet_time_end != '': q = q.filter(ParticipateInModel.created_at <= bet_time_end) if result != '': q = q.filter(ParticipateInModel.result == result) game_instance_id = 0 q = q.filter( ParticipateInModel.game_instance_id == game_instance_id) record_count = q.count() result_dict['total'] = record_count result_dict['count'] = get_page_by_offset(record_count, limit) if start_id is not None: start_id = str(start_id) q = q.filter(ParticipateInModel._id < start_id) q = q.order_by(ParticipateInModel.created_at.desc()) participate_in_list = q.limit(limit).offset(offset).all() for participate in participate_in_list: # user_type 0:真实用户 1:机器人 if participate.user_type == 0: user_info = account_service.get_inner_user_account_info( session, participate.user_id) user_name = user_info['nick_name'] else: user_name = participate.nick_name is_win = False if participate.win_number in participate.award_numbers: is_win = True result_dict['content'].append({ "id": participate._id, "user": user_name, "bet_time": str(participate.created_at), "channel": participate.channel, "bet_token": self.get_coin_name(participate.bet_token), "bet_unit": participate.bet_unit, "bet_number": decimal_to_str(participate.bet_number, 8), "pay_token": self.get_coin_name(participate.pay_token), "pay_number": decimal_to_str(participate.pay_number, 8), 'game_serial': participate.game_serial, "is_win": is_win }) return result_dict
def send_transaction(self, args): """ "order_no", "parameter", "sign" :param args: :return: """ order_no = args.get("order_no", "") parameter = args.get("parameter", "") sign = args.get("sign", "") check_flag = None coin_id = None symbol = None address = None calc = None if not order_no or not sign: self.return_error(20003) if isinstance(sign, dict): sign_tmp = sign for k, v in sign_tmp.items(): if isinstance(v, bytes): sign_tmp[k] = str(v, encoding="utf8") sign_log = json.dumps(sign_tmp) else: sign_log = str(sign) if isinstance(parameter, dict): coin_id = parameter.get("coin_id", "") address = parameter.get("address", "") symbol = parameter.get("symbol", "") calc = parameter.get("calc", "") if coin_id and address and symbol: check_flag = True if not check_flag: self.return_error(20003) # 判断币种类型合法性 if coin_id not in self.symbol_to_model: self.return_error(90002) # 判断钱包类型合法性 if symbol not in self.category: self.return_error(90004) # 获取对应model chain_model = self.symbol_to_model[coin_id][self.category[symbol]] # 查询结果,并记录流水 with MysqlTools().session_scope() as session: record = session.query(RecordSignModel).filter(RecordSignModel.order_no == order_no).first() if record: self.return_error(10008) wallet = session.query(chain_model).filter(chain_model.sub_public_address == address).first() if not wallet: self.return_error(90003) public_key_aes = wallet.acct_public_key_aes private_key_aes = wallet.sub_private_key_aes salt = session.query(TokenSaltModel).filter(TokenSaltModel.public_key_aes == public_key_aes).first() if not salt: self.return_error(90005) key = salt.key_aes nonce = salt.nonce_aes record_sign = RecordSignModel( order_no=order_no, coin_id=coin_id, parameter=json.dumps(parameter), sign=sign_log ) session.add(record_sign) session.commit() # 处理私钥 sub_private_key = None if coin_id in [_ZERO_S, _SIXTY_S]: try: sub_private_key = super_deAES(private_key_aes, key, nonce) except Exception as e: self.return_error(90005, str(e)) # 发送交易 if coin_id == _ZERO_S: # btc交易 tx_info, do_result = self.btc_send_tx(sign, sub_private_key, calc) elif coin_id == _SIXTY_S: # eth交易 tx_info, do_result = self.eth_send_tx(sign, sub_private_key) elif coin_id == _COIN_ID_EOS: # eos交易 tx_info, do_result = self.eos_send_tx(sign) else: tx_info = do_result = "" # 记录结果 response = { "data": tx_info, "status": do_result } with MysqlTools().session_scope() as session: record_finally = session.query(RecordSignModel).filter(RecordSignModel.order_no == order_no).first() record_finally.response = json.dumps(response) record_finally.do_result = do_result session.commit() return response
class TokenSyncBlockEosScript(object): ec = None sync_success = _ONE sync_fail = _ZERO eos_coin_id = _COIN_ID_EOS slog = Slog("token_sync_block_eos_script") mysql_tool = MysqlTools() wait_lottery_dict = {} def __init__(self): self.ec = TokenNodeConfModel.get_eos_node_script(script_unit=_ZERO_S) # 获取eos connect连接 # pass def get_local_block_num(self): """ 获取本地区块的高度 :return: """ with self.mysql_tool.session_scope() as session: f_filter = { "status": self.sync_success, "coin_id": self.eos_coin_id } local_block = session.query(SyncBlockModel).filter_by(**f_filter).first() if not local_block: raise Exception("Mysql database SyncBlockModel lacks configuration data") local_block_num = local_block.block_no return local_block_num def get_remote_block_num(self): """ 获取远端节点的最新区块高度 :return: """ remote_block = self.ec.http_get_latest_block() remote_block_num = remote_block.get("block_num", "") if not remote_block_num: raise Exception("Remote eos node has error") return remote_block_num def async_block_multi(self, begin=None, end=None, sync_block_num_list=None): block_data_dict = {} thread_list = [] if not sync_block_num_list: for j in range(begin, end): t = threading.Thread(target=self._get_block_detail, args=(block_data_dict, j)) t.setDaemon(True) thread_list.append(t) for t in thread_list: t.start() for t in thread_list: t.join() else: for j in sync_block_num_list: t = threading.Thread(target=self._get_block_detail, args=(block_data_dict, j)) t.setDaemon(True) thread_list.append(t) for t in thread_list: t.start() for t in thread_list: t.join() return block_data_dict def _get_block_detail(self, block_data_dict, temp_remote_block_num): temp_insert_block_data = self.ec.http_get_block_detail(temp_remote_block_num) block_data_dict[str(temp_remote_block_num)] = temp_insert_block_data def sync_block(self, local_block_num, remote_block_num, interval=8): """ 同步区块,默认每8个块创建一个session scope,防止长连接 同步到SyncEosModel 同步到SyncBlockModel :param local_block_num: 本地block num :param remote_block_num: 远程block num :param interval: 创建MySQL链接的块数间隔 :return: """ for i in range(local_block_num + 1, remote_block_num, interval): temp_remote_block_num = i + interval if temp_remote_block_num > remote_block_num: temp_remote_block_num = remote_block_num sync_eos_model_list = [] temp_last_sync_block_no = None temp_last_sync_block_hash = "" # 调用协程读取 block_data_dict = self.async_block_multi(i, temp_remote_block_num) btime = time.time() block_data_dict_keys = [] eos_model_dict = {} with self.mysql_tool.session_scope() as session_select: for block_no_item in range(i, temp_remote_block_num): block_data_dict_keys.append(block_no_item) temp_last_sync_block_no = block_no_item temp_insert_block_data = block_data_dict.get(str(block_no_item), {}) if not temp_insert_block_data: time_stamp_decimal = get_decimal(block_no_item, digits=3) * -1 temp_last_sync_block_hash = "" eos_model = SyncEosModel( block_num=int(block_no_item), time_stamp_decimal=time_stamp_decimal, status=self.sync_fail ) sync_eos_model_list.append(eos_model) eos_model_dict[str(block_no_item)] = eos_model else: time_stamp = temp_insert_block_data.get("timestamp", "") if time_stamp: time_stamp_decimal = get_decimal(str_to_timestamp(time_stamp), digits=3) temp_last_sync_block_hash = temp_insert_block_data.get("id") eos_model = SyncEosModel( block_num=temp_insert_block_data.get("block_num"), block_hash=temp_last_sync_block_hash, time_stamp=time_stamp, time_stamp_decimal=time_stamp_decimal, previous=temp_insert_block_data.get("previous"), status=self.sync_success ) sync_eos_model_list.append(eos_model) eos_model_dict[str(block_no_item)] = eos_model self.slog.info("sync block_num:", temp_last_sync_block_no, "sync block_hash:", temp_last_sync_block_hash) if sync_eos_model_list: session_select.add_all(sync_eos_model_list) try: session_select.query(SyncBlockModel).filter(SyncBlockModel.coin_id == self.eos_coin_id).update({ SyncBlockModel.block_no: temp_last_sync_block_no, SyncBlockModel.block_hash: temp_last_sync_block_hash}) session_select.commit() except Exception as e: self.slog.error(str(e)) print("insert error,about have duplicate data") try: sync_eos_model_list = [] with self.mysql_tool.session_scope() as session_select: already_sync_eos_models = session_select.query(SyncEosModel).filter(SyncEosModel.block_num.in_(block_data_dict_keys)).all() if already_sync_eos_models: for already_sync_eos_model in already_sync_eos_models: already_sync_eos_block_num = already_sync_eos_model.block_num if already_sync_eos_block_num and already_sync_eos_block_num in block_data_dict_keys: block_data_dict_keys.remove(already_sync_eos_block_num) for block_data_dict_key in block_data_dict_keys: sync_eos_model_list.append(eos_model_dict[str(block_data_dict_key)]) session_select.add_all(sync_eos_model_list) session_select.query(SyncBlockModel).filter(SyncBlockModel.coin_id == self.eos_coin_id).update({ SyncBlockModel.block_no: temp_last_sync_block_no, SyncBlockModel.block_hash: temp_last_sync_block_hash}) session_select.commit() except Exception as e: self.slog.error(str(e)) print("insert time " + str(time.time() - btime)) return True def process_game_list(self): f_filters = { "block_hash": "", "status": _ZERO } with self.mysql_tool.session_scope() as session: base_block_num_not_have_model_list = session.query(GameGetLotteryBlockInfoEosModel).filter(GameGetLotteryBlockInfoEosModel.base_block_num < _ZERO).all() if base_block_num_not_have_model_list: for base_block_num_not_have_model in base_block_num_not_have_model_list: base_time_stamp = base_block_num_not_have_model.base_time_stamp lottery_block_add = base_block_num_not_have_model.block_num confirm_block_add = base_block_num_not_have_model.confirm_block_num base_block = session.query(SyncEosModel).filter(SyncEosModel.time_stamp_decimal >= base_time_stamp).order_by(SyncEosModel.block_num.asc()).first() if base_block and base_block.time_stamp_decimal - base_time_stamp <= _SIXTY: base_block_num = base_block.block_num base_block_num_not_have_model.base_block_num = base_block_num base_block_num_not_have_model.block_num = base_block_num + lottery_block_add base_block_num_not_have_model.confirm_block_num = base_block_num + lottery_block_add + confirm_block_add session.commit() wait_lottery_model_list = session.query(GameGetLotteryBlockInfoEosModel).filter_by(**f_filters).filter(GameGetLotteryBlockInfoEosModel.base_block_num > _ZERO).all() if wait_lottery_model_list: wait_lottery_dict = {} wait_lottery_list = [] for lottery_info_model in wait_lottery_model_list: wait_lottery_dict[str(lottery_info_model.confirm_block_num)] = { "game_instance_id": lottery_info_model.game_instance_id, "block_num": lottery_info_model.block_num} wait_lottery_list.append(lottery_info_model.confirm_block_num) sync_eos_model_list = session.query(SyncEosModel).filter( SyncEosModel.block_num.in_(wait_lottery_list), SyncEosModel.status == self.sync_success).all() if sync_eos_model_list: for sync_eos_model in sync_eos_model_list: confirm_block_num = sync_eos_model.block_num game_instance_id = wait_lottery_dict[str(confirm_block_num)]["game_instance_id"] block_no = wait_lottery_dict[str(confirm_block_num)]["block_num"] lottery_eos_model = session.query(SyncEosModel).filter(SyncEosModel.block_num == block_no).first() if lottery_eos_model: block_hash = lottery_eos_model.block_hash sync_eos = self.update_sync_eos(session, block_no, block_hash) if sync_eos: block_hash = sync_eos["block_hash"] received_time = timestamp = sync_eos["time_stamp"] TokenSyncBlockEosScript.lottery_callback(session, game_instance_id, block_no, block_hash, timestamp, received_time) if str(confirm_block_num) in wait_lottery_dict: del wait_lottery_dict[str(confirm_block_num)] session.commit() self.wait_lottery_dict = wait_lottery_dict return True def update_sync_eos(self, session, block_num, block_hash): """ 开奖时,如果再次查询节点上的该区块,如果hash有变化,说明回滚,取最新区块详情,修改该区块 :param session: :param block_num: :param block_hash: :return: """ block_detail = self.ec.http_get_block_detail(block_num) if block_detail: remote_block_hash = block_detail.get("id", "") time_stamp = block_detail.get("timestamp", "") if remote_block_hash: if remote_block_hash != block_hash: sync_eos_model = session.query(SyncEosModel).filter(SyncEosModel.block_num == block_num).first() if sync_eos_model: time_stamp_decimal = get_decimal(str_to_timestamp(time_stamp), digits=3) previous = block_detail.get("previous", "") sync_eos_model.block_hash = remote_block_hash sync_eos_model.time_stamp = time_stamp sync_eos_model.time_stamp_decimal = time_stamp_decimal sync_eos_model.previous = previous sync_eos_model.status = self.sync_success self.slog.info("lottery block_num:", block_num, "lottery block_hash:", remote_block_hash) return { "block_hash": remote_block_hash, "time_stamp": time_stamp, } return {} @staticmethod def lottery_callback(session, game_instance_id, block_no, block_hash, timestamp, received_time): """ :param session: :param game_instance_id: :param block_no: :param block_hash: :param timestamp: :param received_time: :return: """ process_res = WalletEosService.lottery_callback(game_instance_id, block_no, block_hash, timestamp, received_time) session.query(GameGetLotteryBlockInfoEosModel).filter( GameGetLotteryBlockInfoEosModel.game_instance_id == game_instance_id).update({ GameGetLotteryBlockInfoEosModel.block_hash: block_hash, GameGetLotteryBlockInfoEosModel.time_stamp: timestamp, GameGetLotteryBlockInfoEosModel.status: process_res }) return True def work(self): # 1.查询已经同步的区块高度 local_block_num = self.get_local_block_num() # 2.查询当前节点的区块最新高度 remote_block_num = self.get_remote_block_num() # local_block_num, remote_block_num = 37657192, 37657202 # 3.遍历区块号,8个块创建一个session scope sync_res = self.sync_block(local_block_num, remote_block_num) return sync_res
def main_page(self): with MysqlTools().session_scope() as session: account_service = AccountService() banners = [] announcements = [] participates = [] instance_info = {} merges = [] banner_list = session.query(BannerManageModel). \ filter(BannerManageModel.status == 1).all() if len(banner_list) > 0: for banner in banner_list: banners.append({ 'image': banner.image, 'site': banner.site }) announcement_list = session.query(AnnouncementManageModel). \ filter(AnnouncementManageModel.status == 1).all() if len(announcement_list) > 0: for announcement in announcement_list: announcements.append({ 'title': announcement.title, 'site': announcement.site }) participate_list = session.query(ParticipateInModel). \ order_by(ParticipateInModel.created_at.desc()).limit(5).offset(0).all() if len(participate_list) > 0: for participate in participate_list: if participate.user_type == 0: user_info = account_service.get_inner_user_account_info( session, participate.user_id) user_name = user_info['nick_name'] else: user_name = participate.nick_name participates.append({ "user": user_name, "bet_time": str(participate.created_at), "channel": participate.channel, "bet_token": participate.bet_token, "bet_number": participate.bet_number, "pay_token": participate.pay_token, "pay_number": str(participate.pay_number) }) instance = session.query(GameDigitalInstanceModel). \ order_by(GameDigitalInstanceModel.status.asc(), GameDigitalInstanceModel.created_at.desc()).first() ins_instance = session.query(InstantGameInstanceModel). \ order_by(InstantGameInstanceModel.status.asc(), InstantGameInstanceModel.created_at.desc()).first() if ins_instance is None: ins_instance = { 'id': '', 'game_serial': '', # 'game_title': instance.game_title, # 'game_describe': instance.game_describe, # 'status': instance.status, 'support_token': '', 'reward_token': '', 'reward_quantity': '', } else: ins_instance = { 'id': ins_instance._id, 'game_serial': ins_instance.game_serial, 'support_token': ins_instance.support_token, 'reward_token': ins_instance.reward_token, 'reward_quantity': ins_instance.reward_quantity, } winner = '' bet_serial = '' bet_number = 0 merge_id = -1 if instance is not None: merge_list = session.query(MergeParticipateInModel). \ filter(MergeParticipateInModel.game_instance_id == instance._id). \ order_by(MergeParticipateInModel.created_at.desc()).limit(3).offset(0).all() if len(merge_list) > 0: merge_id = 1 for merge in merge_list: initiate_user = account_service.get_inner_user_account_info( session, merge.initiate_user_id) merges.append({ 'merge_id': merge._id, 'name': initiate_user['nick_name'], 'portrait': initiate_user['profile_picture'] }) if instance.status == 2: winning_record = session.query(WinningRecordModel). \ filter(WinningRecordModel.game_instance_id == instance._id).first() if winning_record is not None: if winning_record.user_type == 0: account_service = AccountService() user_info = account_service.get_inner_user_account_info( session, winning_record.user_id) winner = user_info['nick_name'] elif winning_record.user_type == 1: robot = session.query(RobotAccountModel).filter( RobotAccountModel.user_id == winning_record.user_id).first() winner = robot.nick_name else: winner = 'X@17Yau8' bet_serial = winning_record.bet_serial merge_id = winning_record.merge_id bet_number = winning_record.bet_number # progress = 0 progress = (instance.bet_number / instance.need) * 100 if 0 < progress < 1: progress = 1 if progress > 1: progress = int(progress) result = { 'banner_list': banners, 'announcement_list': announcements, 'ins_instance': ins_instance, 'instance': { 'id': instance._id, 'game_serial': instance.game_serial, 'game_title': instance.game_title, 'game_describe': instance.game_describe, 'progress': progress, 'remain': int(instance.need - instance.bet_number), 'status': instance.status, 'lottery_time': str(instance.lottery_time), 'winners': winner, 'bet_serial': bet_serial, 'bet_token': self.get_coin_name(instance.bet_token), 'bet_number': bet_number, 'reward_token': self.get_coin_name(instance.reward_token), 'reward_quantity': instance.reward_quantity, 'merge_id': merge_id, 'merge_list': merges }, 'participate': participates } else: result = { 'banner_list': banners, 'announcement_list': announcements, 'instance': {}, 'participate': participates } return result
def automatic_release_instance(self): # now = int(time.time()) # time_struct = time.localtime(now) # str_time = time.strftime("%Y-%m-%d %H:%M:%S", time_struct) str_time = get_utc_now() with MysqlTools().session_scope() as session: template_result = session.query(GameDigitalTemplateModel). \ filter(GameDigitalTemplateModel.template_status == 1, GameDigitalTemplateModel.auto_release == 1).all() if len(template_result) > 0: for row in template_result: btc_usdt_rate = get_exchange_rate( row.reward_token)['price'] ceiling = row.need_ceiling floor = row.need_floor email_config = get_sms_email('common') if email_config == {}: self.return_error(35034) send_email_config = get_sms_email("send_email_config") subject = email_config['email_subject'] if btc_usdt_rate > ceiling or btc_usdt_rate < floor: self.slog.info("instantiation fail. rate is ", str(btc_usdt_rate)) self.slog.info("game template id is ", str(row._id)) # 警告邮件 send_mail( "game自动实例化失败, GAME模板id:" + str(row._id) + ",奖励币种价格:" + str(btc_usdt_rate), send_email_config['user'], send_email_config['pwd'], email_config['email'], subject, send_email_config['smtp_server'], send_email_config['smtp_port']) else: template_id = row._id instance_list = session.query(GameDigitalInstanceModel). \ filter(GameDigitalInstanceModel.status == 0, GameDigitalInstanceModel.template_id == template_id).all() if len(instance_list) <= 0: phase_prefix = row.phase_prefix need = btc_usdt_rate * row.reward_quantity * ( (100 + row.exceeded_ratio) / 100) game_serial = generate_phase(str(phase_prefix)) digital_instance_model = GameDigitalInstanceModel( template_id=template_id, game_serial=game_serial, game_title=row.game_title, bet_token=row.bet_token, bet_unit=row.bet_unit, support_token=row.support_token, reward_token=row.reward_token, reward_quantity=row.reward_quantity, handling_fee=row.handling_fee, game_describe=row.game_describe, experience=row.experience, merge_threshold=row.merge_threshold, release_time=str_time, need=int(need), status=0, release_type=1, chain_status=0) # if create_all_bet_number(game_serial, int(need)) != 2000: # self.slog.info("create all bet number fail") if not GameNumberSetService().createNumbers( { "game_serial": game_serial, "total": int(need) }): self.slog.info("create all bet number fail") self.return_error(40015) session.add(digital_instance_model) session.flush() try: # 发布信息上链 if BlockChainInfoService( ).insert_block_chain_info( '', str(digital_instance_model._id), 2, { "instance_id": digital_instance_model._id, "template_id": template_id, "game_serial": game_serial, "support_token": row.support_token, "bet_token": row.bet_token, "bet_unit": row.bet_unit, "reward_token": row.reward_token, "reward_quantity": row.reward_quantity, "handling_fee": str(row.handling_fee), "game_describe": row.game_describe, "release_time": str_time.strftime("%Y-%m-%d %H:%M:%S"), "status": 0, "need": int(need), "release_type": 0, }): digital_instance_model.chain_status = 1 self.slog.info( "insert_block_chain_info success") else: self.slog.info( "insert_block_chain_info fail") except Exception as e: self.slog.info("insert_block_chain_info fail") self.slog.info(f"Exception: {e}") # self.slog.info("automatic_release_instance fail") # session.rollback() session.commit() # send_mail("game自动实例化成功, GAME模板id:" + str(template_id) + ",奖励币种价格:" + str(btc_usdt_rate), # send_email_config['user'], send_email_config['pwd'], # email_config['email'], # subject, send_email_config['smtp_server'], send_email_config['smtp_port']) self.slog.info( "automatic_release_instance success")
def get_dice_award_rate(self, user_id): with MysqlTools().session_scope() as session: account_service = AccountService() award_rate_info = session.query(DiceParticipateInModel.user_dice, func.count(DiceParticipateInModel._id).label('total_award')). \ filter(DiceParticipateInModel.dice_result == 0). \ group_by(DiceParticipateInModel.user_dice).all() stone = 0 scissors = 0 cloth = 0 # balance_btc = '' # balance_eth = '' # balance_usdt = '' # balance_eos = '' # balance_exp = '' # print(award_rate_info) account_balance = account_service.get_user_token_list( user_id, None, 1, 10)['content'][0] balance_btc = account_balance['BTC'] balance_eth = account_balance['ETH'] if account_balance.get('EOS', None) is not None: balance_eos = account_balance['EOS'] else: balance_eos = 0 balance_usdt = account_balance['USDT'] balance_exp = account_balance['USDT_EXPERIENCE'] if len(award_rate_info) > 0: award_total = 0 for award_rate in award_rate_info: award_total += award_rate[1] if award_rate[0] == 0: stone = award_rate[1] elif award_rate[0] == 1: scissors = award_rate[1] elif award_rate[0] == 2: cloth = award_rate[1] stone_rate = stone / award_total * 100 scissors_rate = scissors / award_total * 100 cloth_rate = cloth / award_total * 100 result = { 'stone': decimal_to_str(stone_rate, 2), 'scissors': decimal_to_str(scissors_rate, 2), 'cloth': decimal_to_str(cloth_rate, 2), 'balance': { 'btc': decimal_to_str(balance_btc, 8), 'eth': decimal_to_str(balance_eth, 8), 'eos': decimal_to_str(balance_eos, 8), 'usdt': decimal_to_str(balance_usdt, 4), 'exp': decimal_to_str(balance_exp, 4) } } # print(result) return result else: return { 'stone': '', 'scissors': '', 'cloth': '', 'balance': { 'btc': decimal_to_str(balance_btc, 8), 'eth': decimal_to_str(balance_eth, 8), 'eos': decimal_to_str(balance_eos, 8), 'usdt': decimal_to_str(balance_usdt, 4), 'exp': decimal_to_str(balance_exp, 4) } }
def dice_chip_in_fast(self, user_id, user_channel_id, coin_id, bet_amount, user_dice): change_type_31 = '31' # 扣款 change_type_32 = '32' # 返还 change_type_33 = '33' # 中奖 with MysqlTools().session_scope() as session: # 查询用户资产 account_service = AccountService() user_info = account_service.get_inner_user_account_by_token( session, user_id, coin_id) if isinstance(user_info, int): if user_info == 20001: return self.return_error(20001) balance = get_decimal(user_info.get("balance"), digits=8, decimal_type="down") # 账户余额 < 需要下注金额 bet_number = get_decimal(bet_amount, digits=4, decimal_type="down") if balance < bet_number: return self.return_error(60005) dice_serial = dice_generate_phase() # 获取最新eos区块,计算开奖区块高度 dice_time = get_timestamp() ec = TokenNodeConfModel.get_eos_node_script(script_unit=_THREE_S) latest_eos_block_info = ec.http_get_latest_block() # print('latest_eos_block_info=-=-=', latest_eos_block_info) block_no = latest_eos_block_info['block_num'] dice_part_in_model = DiceParticipateInModel( dice_serial=dice_serial, user_id=user_id, user_dice=user_dice, channel=user_channel_id, bet_number=bet_number, bet_token=coin_id, reward_token=coin_id, reward_quantity=bet_number, dice_timestamp=dice_time, block_no=block_no) session.add(dice_part_in_model) session.flush() # 提交扣款申请 dice_part_id = dice_part_in_model._id result = account_service.do_bet( session, user_id, coin_id, bet_number, 'dice_bet' + str(dice_part_in_model._id), 1, dice_serial, user_channel_id, change_type_31) if result != 0: session.rollback() raise_logger("do_bet result" + str(result), "game_bet_in", "info") # -------------------------------- 开奖 -------------------------------- # block_timestamp = latest_eos_block_info['timestamp'] block_hash = latest_eos_block_info['id'] dice_result = -1 banker_dice = int(block_hash, 16) % 3 # 0石头 1剪刀 2布 user_dice = int(user_dice) if banker_dice == user_dice: dice_result = 1 # 0用户胜 1平局 2庄家胜 -1未知 else: if banker_dice == 0 and user_dice == 1: dice_result = 2 elif banker_dice == 0 and user_dice == 2: dice_result = 0 elif banker_dice == 1 and user_dice == 0: dice_result = 0 elif banker_dice == 1 and user_dice == 2: dice_result = 2 elif banker_dice == 2 and user_dice == 0: dice_result = 2 elif banker_dice == 2 and user_dice == 1: dice_result = 0 dice_part_in_model.banker_dice = banker_dice dice_part_in_model.dice_result = dice_result dice_part_in_model.block_hash = block_hash dice_part_in_model.block_timestamp = block_timestamp # session.flush() change_type = change_type_32 # ------------ 中奖控制 ------------ # winning_control = 0 if dice_result in [0, 1]: win_dice_num = session.query(func.count(DiceParticipateInModel._id)). \ filter(DiceParticipateInModel.user_id == user_id, DiceParticipateInModel.dice_result == 0, func.date_format(DiceParticipateInModel.created_at, "%Y-%m-%d") == func.date_format(get_utc_now(), "%Y-%m-%d")).first() if win_dice_num[0] >= decimal.Decimal(500): raise_logger( "dice winning control userid = " + str(user_id), "game_bet_in", "info") dice_part_in_model.banker_dice = user_dice dice_part_in_model.dice_result = 1 dice_result = 1 winning_control = 1 # ------------ 中奖控制结束 ------------ # if dice_result in [0, 1]: reward_quantity = 0 dice_config = session.query(DiceConfigModel). \ filter(DiceConfigModel.support_token_id == dice_part_in_model.bet_token).first() if dice_config is None: return self.return_error(40022) if dice_result == 0: change_type = change_type_33 # 用户获胜 中奖金额为投注金额+奖励金额(投注金额=奖励金额) 扣除手续费 reward_quantity = (dice_part_in_model.reward_quantity + dice_part_in_model.bet_number) * ( 100 - dice_config.handling_fee) / 100 elif dice_result == 1: change_type = change_type_32 # 平局 中奖金额为投注金额 reward_quantity = dice_part_in_model.bet_number result = account_service.do_win( session, dice_part_in_model.user_id, dice_part_in_model.reward_token, reward_quantity, 'dice_win' + str(dice_part_in_model._id), dice_part_in_model.user_dice, dice_part_in_model.dice_serial, change_type) if isinstance(result, int) is False: raise_logger( "dice分钱失败" + "user:"******"game_publish_lottery", "info") session.rollback() return False if result != 0: raise_logger( "dice分钱失败" + "user:"******"game_publish_lottery", "info") session.rollback() return False # -------------------------------- 开奖结束 -------------------------------- # session.commit() if winning_control == 1: return self.return_error(40023) return { 'dice_result': dice_result, 'banker_dice': banker_dice, 'user_dice': user_dice, 'dice_timestamp': timestamp_to_str(dice_time, format_style="%Y-%m-%d %H:%M:%S"), 'dice_id': str(dice_part_id), 'dice_serial': dice_serial, 'reward_token': self.get_coin_name(coin_id), 'reward_quantity': decimal_to_str( str((bet_number + bet_number) * decimal.Decimal(0.99)), 6) }
def dice_chip_in(self, user_id, user_channel_id, coin_id, bet_amount, user_dice): with MysqlTools().session_scope() as session: # 查询用户资产 account_service = AccountService() user_info = account_service.get_inner_user_account_by_token( session, user_id, coin_id) if isinstance(user_info, int): if user_info == 20001: return self.return_error(20001) balance = get_decimal(user_info.get("balance"), digits=8, decimal_type="down") # 账户余额 < 需要下注金额 bet_number = get_decimal(bet_amount, digits=4, decimal_type="down") if balance < bet_number: return self.return_error(60005) dice_serial = dice_generate_phase() block_no = '' # 获取最新eos区块,计算开奖区块高度 dice_time = get_timestamp() latest_eos_block_info = session.query(SyncEosModel). \ order_by(SyncEosModel._id.desc()).first() latest_eos_block_no = latest_eos_block_info.block_num latest_eos_block_time = latest_eos_block_info.time_stamp_decimal block_delay = math.ceil( (dice_time - latest_eos_block_time) / decimal.Decimal(0.5)) block_no = latest_eos_block_no + block_delay + 1 # raise_logger("最新区块高度=" + str(latest_eos_block_no) + "时间:" + get_utc_now().strftime( # "%Y-%m-%d %H:%M:%S.%f"), "game_bet_in", "info") # raise_logger("最新区块时间=" + str(latest_eos_block_time) + "时间:" + get_utc_now().strftime( # "%Y-%m-%d %H:%M:%S.%f"), "game_bet_in", "info") # raise_logger("时间延迟=" + str(block_delay) + "时间:" + get_utc_now().strftime( # "%Y-%m-%d %H:%M:%S.%f"), "game_bet_in", "info") dice_part_in_model = DiceParticipateInModel( dice_serial=dice_serial, user_id=user_id, user_dice=user_dice, channel=user_channel_id, bet_number=bet_number, bet_token=coin_id, reward_token=coin_id, reward_quantity=bet_number, dice_timestamp=dice_time, block_no=block_no) session.add(dice_part_in_model) session.flush() # raise_logger("添加dice参与记录成功, id= " + str(dice_part_in_model._id) + "时间:" + get_utc_now().strftime( # "%Y-%m-%d %H:%M:%S.%f"), "game_bet_in", "info") # 提交扣款申请 dice_part_id = dice_part_in_model._id result = account_service.do_bet( session, user_id, coin_id, bet_number, 'dice_bet' + str(dice_part_in_model._id), 1, dice_serial, user_channel_id) if result != 0: session.rollback() raise_logger("do_bet result" + str(result), "game_bet_in", "info") # raise_logger("提交扣款申请成功 " + "时间:" + get_utc_now().strftime( # "%Y-%m-%d %H:%M:%S.%f"), "game_bet_in", "info") session.commit() return { # 'result': True, 'dice_timestamp': timestamp_to_str(dice_time, format_style="%Y-%m-%d %H:%M:%S"), 'dice_id': dice_part_id, 'dice_serial': dice_serial }
def check_dice_sold_out_by_eos(self): # raise_logger("sold_out开始" + " 时间:" + get_utc_now().strftime( # "%Y-%m-%d %H:%M:%S.%f"), "game_bet_in", "info") with MysqlTools().session_scope() as session: account_service = AccountService() not_lottery_list = session.query(DiceParticipateInModel). \ filter(DiceParticipateInModel.dice_result == -1).all() if len(not_lottery_list) > 0: for not_lottery in not_lottery_list: # raise_logger("需开奖记录id=" + str(not_lottery._id) + " 时间:" + get_utc_now().strftime( # "%Y-%m-%d %H:%M:%S.%f"), "game_bet_in", "info") lottery_block = not_lottery.block_no lottery_eos_block_info = session.query(SyncEosModel). \ filter(SyncEosModel.block_num == lottery_block).first() if lottery_eos_block_info is not None: # raise_logger("找到开奖区块lottery_block" + str( # lottery_eos_block_info.block_hash) + " 时间:" + get_utc_now().strftime( # "%Y-%m-%d %H:%M:%S.%f"), "game_bet_in", "info") not_lottery.block_timestamp = lottery_eos_block_info.time_stamp not_lottery.block_hash = lottery_eos_block_info.block_hash dice_result = -1 banker_dice = int(not_lottery.block_hash, 16) % 3 # 0石头 1剪刀 2布 user_dice = not_lottery.user_dice # 0石头 1剪刀 2布 if banker_dice == user_dice: dice_result = 1 # 0用户胜 1平局 2庄家胜 -1未知 else: if banker_dice == 0 and user_dice == 1: dice_result = 2 elif banker_dice == 0 and user_dice == 2: dice_result = 0 elif banker_dice == 1 and user_dice == 0: dice_result = 0 elif banker_dice == 1 and user_dice == 2: dice_result = 2 elif banker_dice == 2 and user_dice == 0: dice_result = 2 elif banker_dice == 2 and user_dice == 1: dice_result = 0 not_lottery.banker_dice = banker_dice not_lottery.dice_result = dice_result session.flush() if dice_result in [0, 1]: reward_quantity = 0 dice_config = session.query(DiceConfigModel). \ filter(DiceConfigModel.support_token_id == not_lottery.bet_token).first() if dice_config is None: return self.return_error(40022) if dice_result == 0: # 用户获胜 中奖金额为投注金额+奖励金额(投注金额=奖励金额) 扣除手续费 reward_quantity = ( not_lottery.reward_quantity + not_lottery.bet_number) * ( 100 - dice_config.handling_fee) / 100 elif dice_result == 1: # 平局 中奖金额为投注金额 reward_quantity = not_lottery.bet_number result = account_service.do_win( session, not_lottery.user_id, not_lottery.reward_token, reward_quantity, 'dice_win' + str(not_lottery._id), not_lottery.user_dice, not_lottery.dice_serial) if isinstance(result, int) is False: raise_logger( "dice分钱失败" + "user:"******"game_publish_lottery", "info") session.rollback() return False if result != 0: raise_logger( "dice分钱失败" + "user:"******"game_publish_lottery", "info") session.rollback() return False session.commit() # raise_logger("sold_out结束" + " 时间:" + get_utc_now().strftime( # "%Y-%m-%d %H:%M:%S.%f"), "game_bet_in", "info") return {'result': True}
def get_coin_type(self): with MysqlTools().session_scope() as session: coin = session.query(TokenCoinModel).filter(TokenCoinModel.coin_id == self.coin_id).first() return coin.coin_name
def sync_block(self, token_conf, last_net_block_num, last_local_block, address_list, gather_address_list, eth_tx_list): confirm_last_block_num = token_conf["confirm_last_block_num"] end_listen_block_num = int(last_net_block_num) - int(confirm_last_block_num) # 确认起始侦听区块号 if not last_local_block: begin_listen_block_num = end_listen_block_num else: if end_listen_block_num <= _ZERO: raise Exception("last net_block_num less than confirm_last_block_num") last_local_block_num = last_local_block["block_no"] last_local_block_status = last_local_block["status"] begin_listen_block_num = last_local_block_num + _ONE if last_local_block_status else last_local_block_num for listen_num in range(begin_listen_block_num, end_listen_block_num + _ONE): if self.process_index is not None: if listen_num % self.process_count != self.process_index: continue self.slog.info("listen block: ", str(listen_num)) block_info = self.get_eth_block_info(listen_num) block_hash = block_info["hash"] block_number = block_info["number"] transactions = block_info["transactions"] tx_model_list = [] multi_withdraw_record = None foreign_gather_record = None wallet_eth = None with MysqlTools().session_scope() as session: for tx in transactions: # 查询交易详情 tx_info = self.get_eth_tx_info(tx) if not tx_info: continue tx_info_receipt = self.get_eth_tx_info_receipt(tx) # 处理 块上的交易Tx 是否碰撞 平台发起的交易Tx if tx in eth_tx_list: # 获取实际到账金额 和 手续费 listening_value_ether = get_decimal(self.w3.fromWei(tx_info["value"], self.unit) if tx_info["value"] else _ZERO_S, 18) listening_gas_price_ether = get_decimal(self.w3.fromWei(int(tx_info["gasPrice"]), self.unit) if tx_info["gasPrice"] else _ZERO_S, 18) listening_gas_price_used_ether = get_decimal(tx_info_receipt["gasUsed"] if tx_info_receipt["gasUsed"] else _ZERO_S, 18) listening_gas_ether = listening_gas_price_ether * listening_gas_price_used_ether # 如果存在 更改listening 提现侦听表 状态 listening_tx = self.update_wallet_eth_tx(session, tx) listening_tx.listen_flag = _ZERO listening_tx.block_no = block_number record_no = listening_tx.record_no # 改流水表 成功 withdraw_order_record = self.get_foreign_withdraw_order_record(session, record_no) if not withdraw_order_record: self.slog.error("没有找到withdraw_order_record根据listening_tx.record_no:", record_no) continue withdraw_order_record.withdraw_status = self.withdraw_success withdraw_order_record.confirm_at = get_utc_now() # 计算已花费未上块时消耗的手续费累计,如果没有一般是0 withdraw_consume_total_fee = get_decimal(withdraw_order_record.withdraw_consume_total_fee, 18) # 计算预计冻结金额 amount_frozen = withdraw_order_record.withdraw_amount # 计算花费完手续费剩余返还给用户的金额 withdraw_remain_fee = amount_frozen - listening_value_ether - listening_gas_ether - withdraw_consume_total_fee # 判断 提现类型 用户提现和中奖 if withdraw_order_record.withdraw_type in self.account_withdraw_type_list: # 获取 批量提现流水 if not multi_withdraw_record: multi_withdraw_record = self.get_foreign_multi_withdraw_order_record(session, withdraw_order_record.relate_flow_no) # 通知 账户成功 withdraw_result = _FOUR_S do_withdraw_result = WalletCallbackService.withdraw_notify_callback(withdraw_order_record.req_no, withdraw_order_record.order_no, withdraw_result, listening_value_ether, listening_gas_ether, withdraw_remain_fee) # 保存 账户处理结果 withdraw_order_record.do_withdraw_result = do_withdraw_result # 判断用户系统返回结果 "0"是正确 if do_withdraw_result == _ZERO_S: # 加钱 提现流水 单笔 withdraw_order_record.withdraw_actual_amount = listening_value_ether withdraw_order_record.withdraw_actual_fee = listening_gas_ether + withdraw_consume_total_fee # 加钱 批量提现流水 累计 multi_withdraw_record.verified_amount += listening_value_ether multi_withdraw_record.verified_gas += listening_gas_ether + withdraw_consume_total_fee # 减钱 归集地址 冻结金额 wallet_eth = self.get_wallet_eth_gather(session, withdraw_order_record.from_address) wallet_eth.amount_frozen -= amount_frozen wallet_eth.amount += withdraw_remain_fee # 判断 提现类型 普通归集和归集转归集 elif withdraw_order_record.withdraw_type in self.gather_withdraw_type_list: # 获取 归集操作流水 if not foreign_gather_record: foreign_gather_record = self.get_foreign_gather_record(session, withdraw_order_record.relate_flow_no) # 加钱 提现流水 单笔 withdraw_order_record.withdraw_actual_amount = listening_value_ether withdraw_order_record.withdraw_actual_fee = listening_gas_ether + withdraw_consume_total_fee # 加钱 归集流水 累计 foreign_gather_record.actual_amount += listening_value_ether foreign_gather_record.actual_fee += listening_gas_ether + withdraw_consume_total_fee # 更新 归集流水 部分成功 foreign_gather_record.gather_status = self.withdraw_part_success # 判断 普通归集 if withdraw_order_record.withdraw_type == _TWO_S: # 获取 用户地址 wallet_eth = self.get_wallet_eth(session, withdraw_order_record.from_address) # 判断 归集转归集 elif withdraw_order_record.withdraw_type == _THREE_S: # 获取 归集地址 wallet_eth = self.get_wallet_eth_gather(session, withdraw_order_record.from_address) # 减钱 相关地址 冻结金额 wallet_eth.amount_frozen -= amount_frozen wallet_eth.amount += withdraw_remain_fee else: # 其他类型 暂不处理 pass self.slog.info("listening block_number: ", str(block_number)) self.slog.info("listening tx: ", str(tx)) self.slog.info("listening amount: ", str(listening_value_ether)) self.slog.info("listening gas: ", str(listening_gas_ether)) # 处理 块上的每笔交易Tx详情 to_address 是否碰撞 平台的子钱包地址 和 归集账户的地址 listening_address = tx_info["to"] check_address_flag = None source_status = None do_recharge_result = "" if listening_address in address_list: check_address_flag = _ZERO elif listening_address in gather_address_list: check_address_flag = _ONE if check_address_flag is not None: listening_value_ether = get_decimal(self.w3.fromWei(tx_info["value"], self.unit) if tx_info["value"] else _ZERO_S, 18) # 检查 有没有记录过这个tx在tx_list_eth流水 tx_list_model = session.query(TxListEthModel).filter(TxListEthModel.tx_no == tx).first() if not tx_list_model: tx_id = generate_order_no() # 更新子钱包和归集账户地址的钱 wallet_model = self.wallet_model_list[check_address_flag] sub_wallet = session.query(wallet_model).filter(wallet_model.sub_public_address == listening_address).first() if check_address_flag == _ZERO: account_id = sub_wallet.account_id # 通知账户加钱 do_recharge_result = WalletCallbackService.recharge_notify_callback(account_id, listening_value_ether, self.coin_id, listening_address, tx_id) if do_recharge_result == _ZERO_S: # 更新子钱包和归集账户地址的钱 sub_wallet.amount += listening_value_ether source_status = _ZERO_S # 线上用户地址充值 elif check_address_flag == _ONE: if tx not in eth_tx_list: source_status = _ONE_S # 线下归集账户充值 else: source_status = _ZERO_S # 线上普通归集归集转归集 sub_wallet.amount += listening_value_ether # 线下充值或者归集 # 增加tx_list记录 tx_model = TxListEthModel( tx_id=tx_id, tx_no=tx, block_no=block_number, value=listening_value_ether, address=listening_address, source_status=source_status, do_recharge_result=do_recharge_result ) tx_model_list.append(tx_model) if tx not in eth_tx_list: self.slog.info("recharge block_number: ", str(block_number)) self.slog.info("recharge tx: ", str(tx)) self.slog.info("recharge address: ", str(listening_address)) self.slog.info("recharge amount: ", str(listening_value_ether)) if tx_model_list: session.add_all(tx_model_list) # 更新SyncBlockModel本地同步远程节点数据块编号 if not self.block_num_temp: self.update_wallet_eth_address(session, listen_num, block_hash) # 提交事物 session.commit() return True
class TokenSyncLotteryScript(object): ec = None sync_success = _ONE sync_fail = _ZERO eos_coin_id = _COIN_ID_EOS slog = Slog("token_sync_lottery_script") mysql_tool = MysqlTools() wait_lottery_dict = {} def __init__(self): pass def work(self): # 逻辑: 查找GameGetLotteryBlockInfoEosModel看看是否有未开奖 规则 满额时间点的第60个区块(包含当前时间点的块) # 找到未开奖列表,查找时间戳 对应的基础区块号,因为是最新时间,基本上数据库都会没有找到该区块 # 根据基础区块号,生成 开奖区块 确认区块 # 如果没有找到对应的基础区块号,根据找到的区块号,往回查询EOSPark(睡1秒),直到找到符合时间戳的区块,规则是 一直大,直到找到小的,小的区块号下一个就是是基础区块 # 更新 sync_eos表 基础区块 # 找到已经同步的确认区块,返回去查开奖区块,查询EOSPark,更新开奖区块 # 更新 sync_eos表 开奖区块 # 更新 GameGetLotteryBlockInfoEosModel 开奖区块hash 状态完成 # 调韩梦 通知开奖 with self.mysql_tool.session_scope() as session: lottery_block_info_eos_model_list = session.query(GameGetLotteryBlockInfoEosModel).filter(GameGetLotteryBlockInfoEosModel.status != self.sync_success).all() if not lottery_block_info_eos_model_list: return True for lottery_block_info_eos_model in lottery_block_info_eos_model_list: if lottery_block_info_eos_model.base_block_num < _ZERO: base_time_stamp = lottery_block_info_eos_model.base_time_stamp sync_eos_model = session.query(SyncEosModel).filter(SyncEosModel.time_stamp_decimal >= base_time_stamp).order_by(SyncEosModel.block_num.asc()).first() if sync_eos_model: # 找到基础块 base_block_num = sync_eos_model.block_num # 基础块 if sync_eos_model.time_stamp_decimal - base_time_stamp < 0.5: lottery_block = base_block_num + lottery_block_info_eos_model.block_num # 开奖块 confirm_block = lottery_block + lottery_block_info_eos_model.confirm_block_num # 确认块 # 更新开奖块 确认块数据 lottery_block_info_eos_model.base_block_num = base_block_num lottery_block_info_eos_model.block_num = lottery_block lottery_block_info_eos_model.confirm_block_num = confirm_block else: # 基础块时间>0.5 找到的不对 right_block_detail = self.find_right_block(base_block_num, base_time_stamp) right_sync_eos_model = session.query(SyncEosModel).filter(SyncEosModel.block_num == right_block_detail["block_num"]).first() if right_sync_eos_model: right_sync_eos_model.block_hash = right_block_detail["id"] right_sync_eos_model.time_stamp = right_block_detail["timestamp"] right_sync_eos_model.time_stamp_decimal = right_block_detail["time_stamp_decimal"] right_sync_eos_model.previous = right_block_detail["previous"] right_sync_eos_model.status = self.sync_success else: sync_eos_model = SyncEosModel( block_num=right_block_detail["block_num"], block_hash=right_block_detail["id"], time_stamp=right_block_detail["timestamp"], time_stamp_decimal=right_block_detail["time_stamp_decimal"], previous=right_block_detail["previous"], status=self.sync_success ) session.add(sync_eos_model) else: # 没有找到基础块数据, # 等待脚本下次执行 pass else: # 有基础块数据 找确认块数据 confirm_block_num = lottery_block_info_eos_model.confirm_block_num lottery_block_num = lottery_block_info_eos_model.block_num confirm_block_model = session.query(SyncEosModel).filter(SyncEosModel.block_num == confirm_block_num).first() lottery_block_model = session.query(SyncEosModel).filter(SyncEosModel.block_num == lottery_block_num).first() game_instance_id = lottery_block_info_eos_model.game_instance_id notice_flag = None node_block_detail_block_hash = None node_block_detail_time_stamp = None if confirm_block_model: node_block_detail = self.find_right_block(lottery_block_num) node_block_detail_block_hash = node_block_detail["id"] node_block_detail_time_stamp = node_block_detail["timestamp"] if lottery_block_model and lottery_block_model.block_hash and lottery_block_model.time_stamp: lottery_block_hash = lottery_block_model.block_hash lottery_time_stamp = lottery_block_model.time_stamp if lottery_block_hash != node_block_detail_block_hash or lottery_time_stamp != node_block_detail_time_stamp: lottery_block_model.block_hash = node_block_detail_block_hash lottery_block_model.time_stamp = node_block_detail_time_stamp lottery_block_model.time_stamp_decimal = node_block_detail["time_stamp_decimal"] lottery_block_model.previous = node_block_detail["previous"] else: # 没有找到同步区块,但是找到了确认区块 或者 没有找到这个块hash和time_stamp if lottery_block_model: # 有开奖区块,没有块hash或者time_stamp lottery_block_model.block_hash = node_block_detail_block_hash lottery_block_model.time_stamp = node_block_detail_time_stamp lottery_block_model.time_stamp_decimal = node_block_detail["time_stamp_decimal"] lottery_block_model.previous = node_block_detail["previous"] else: sync_eos_model = SyncEosModel( block_num=lottery_block_num, block_hash=node_block_detail_block_hash, time_stamp=node_block_detail_time_stamp, time_stamp_decimal=node_block_detail["time_stamp_decimal"], previous=node_block_detail["previous"], status=self.sync_success ) session.add(sync_eos_model) notice_flag = True else: lasted_block_detail = self.composing_right_block() lasted_block_num = lasted_block_detail.get("block_num", "") if lasted_block_num and int(lasted_block_num) >= int(confirm_block_num): node_block_detail = self.composing_right_block(lottery_block_num) node_block_detail_block_hash = node_block_detail.get("id", "") node_block_detail_time_stamp = node_block_detail.get("timestamp", "") if lottery_block_model: # 有开奖区块,没有块hash或者time_stamp lottery_block_model.block_hash = node_block_detail_block_hash lottery_block_model.time_stamp = node_block_detail_time_stamp lottery_block_model.time_stamp_decimal = node_block_detail["time_stamp_decimal"] lottery_block_model.previous = node_block_detail["previous"] else: sync_eos_model = SyncEosModel( block_num=lottery_block_num, block_hash=node_block_detail_block_hash, time_stamp=node_block_detail_time_stamp, time_stamp_decimal=node_block_detail["time_stamp_decimal"], previous=node_block_detail["previous"], status=self.sync_success ) session.add(sync_eos_model) notice_flag = True else: # 还没有同步到确认区块 等待脚本下次执行 print("1 record is not the lottery, not find confirm_block_num: " + str(int(confirm_block_num))) print("Wait for the next script loop!") if notice_flag: # 通知韩梦 process_res = WalletEosService.lottery_callback(game_instance_id, lottery_block_num, node_block_detail_block_hash, node_block_detail_time_stamp, node_block_detail_time_stamp) lottery_block_info_eos_model.block_hash = node_block_detail_block_hash lottery_block_info_eos_model.time_stamp = node_block_detail_time_stamp lottery_block_info_eos_model.status = process_res print("lottery success, notice Mr Han!!!") print("lottery_block_num: " + str(int(lottery_block_num))) print("lottery_block_hash: " + str(node_block_detail_block_hash)) print("lottery_time_stamp: " + str(node_block_detail_time_stamp)) session.commit() return True def find_right_block(self, block_num, base_time_stamp=None): """ 找到对应的区块,时间戳小于0.5的 :param block_num: :param base_time_stamp: :return: """ print("find_right_block args:") print("block_num: " + str(int(block_num))) if base_time_stamp: print("base_time_stamp: " + str(base_time_stamp)) block_detail = self.composing_right_block(block_num) if base_time_stamp: base_time_stamp = float(base_time_stamp) # 假设一个块间隔生成时间需要0.5秒,也就是1秒2块 tmp_right_time_stamp = block_detail["time_stamp_decimal"] tmp_right_block_num = block_num - (tmp_right_time_stamp - base_time_stamp) // _TWO for i in range(3600): tmp_block_detail = self.composing_right_block(tmp_right_block_num) if tmp_block_detail: print("find tmp_right_block_num: " + str(int(tmp_right_block_num))) print("find tmp_right_time_stamp: " + str(tmp_right_time_stamp)) tmp_right_time_stamp = tmp_block_detail["time_stamp_decimal"] if tmp_right_time_stamp >= base_time_stamp: if tmp_right_time_stamp - base_time_stamp > 100: tmp_right_block_num -= (tmp_right_time_stamp - base_time_stamp) // _TWO continue else: if tmp_right_time_stamp - base_time_stamp < 0.5: block_detail = tmp_block_detail print("find right_block_num right!!!!!: " + str(int(tmp_right_block_num))) print("find right_time_stamp right!!!!: " + str(tmp_right_time_stamp)) break else: tmp_right_block_num -= _ONE else: if base_time_stamp - tmp_right_time_stamp > 100: tmp_right_block_num -= (base_time_stamp - tmp_right_time_stamp) // _TWO continue else: tmp_right_block_num += _ONE return block_detail def composing_right_block(self, block_num=None): """ 查找并组装正确区块 :param block_num: :return: """ block_detail = {} # 如果一个小时都没有找到合适的块,就算了,肯定是其他问题 for i in range(3600): block_detail = self.get_node_block_detail_from_block_num(block_num, ["block_num", "timestamp", "id", "previous"]) if block_detail: right_time_stamp_str = block_detail.get("timestamp") right_time_stamp = str_to_timestamp(right_time_stamp_str) if right_time_stamp: block_detail["time_stamp_decimal"] = right_time_stamp break else: time.sleep(0.5) return block_detail def get_node_block_detail_from_block_num(self, block_num=None, target_parameter_list=None): """ 根据区块号,获取节点详情 :param block_num: :param target_parameter_list: :return: """ print("get_node_block_detail_from_block_num") print("server local time: " + str(time.time())) if self.ec is None: self.ec = TokenNodeConfModel.get_eos_node_script(script_unit=_ONE_S) if block_num: print("block_num: " + str(block_num)) block_num = int(block_num) block_detail = self.ec.http_get_block_detail(block_num) else: block_detail = self.ec.http_get_latest_block() ret_dict = {} if block_detail: print("timestamp: " + block_detail.get("timestamp", "")) if not target_parameter_list: return block_detail else: for i in target_parameter_list: ret_dict[i] = block_detail.get(i, "") return ret_dict return ret_dict def process_game_list(self): f_filters = { "block_hash": "", "status": _ZERO } with self.mysql_tool.session_scope() as session: base_block_num_not_have_model_list = session.query(GameGetLotteryBlockInfoEosModel).filter(GameGetLotteryBlockInfoEosModel.base_block_num < _ZERO).all() if base_block_num_not_have_model_list: for base_block_num_not_have_model in base_block_num_not_have_model_list: base_time_stamp = base_block_num_not_have_model.base_time_stamp lottery_block_add = base_block_num_not_have_model.block_num confirm_block_add = base_block_num_not_have_model.confirm_block_num base_block = session.query(SyncEosModel).filter(SyncEosModel.time_stamp_decimal >= base_time_stamp).order_by(SyncEosModel.block_num.asc()).first() if base_block and base_block.time_stamp_decimal - base_time_stamp <= _SIXTY: base_block_num = base_block.block_num base_block_num_not_have_model.base_block_num = base_block_num base_block_num_not_have_model.block_num = base_block_num + lottery_block_add base_block_num_not_have_model.confirm_block_num = base_block_num + lottery_block_add + confirm_block_add session.commit() wait_lottery_model_list = session.query(GameGetLotteryBlockInfoEosModel).filter_by(**f_filters).filter(GameGetLotteryBlockInfoEosModel.base_block_num > _ZERO).all() if wait_lottery_model_list: wait_lottery_dict = {} wait_lottery_list = [] for lottery_info_model in wait_lottery_model_list: wait_lottery_dict[str(lottery_info_model.confirm_block_num)] = { "game_instance_id": lottery_info_model.game_instance_id, "block_num": lottery_info_model.block_num} wait_lottery_list.append(lottery_info_model.confirm_block_num) sync_eos_model_list = session.query(SyncEosModel).filter( SyncEosModel.block_num.in_(wait_lottery_list), SyncEosModel.status == self.sync_success).all() if sync_eos_model_list: for sync_eos_model in sync_eos_model_list: confirm_block_num = sync_eos_model.block_num game_instance_id = wait_lottery_dict[str(confirm_block_num)]["game_instance_id"] block_no = wait_lottery_dict[str(confirm_block_num)]["block_num"] lottery_eos_model = session.query(SyncEosModel).filter(SyncEosModel.block_num == block_no).first() if lottery_eos_model: block_hash = lottery_eos_model.block_hash sync_eos = self.update_sync_eos(session, block_no, block_hash) if sync_eos: block_hash = sync_eos["block_hash"] received_time = timestamp = sync_eos["time_stamp"] TokenSyncLotteryScript.lottery_callback(session, game_instance_id, block_no, block_hash, timestamp, received_time) if str(confirm_block_num) in wait_lottery_dict: del wait_lottery_dict[str(confirm_block_num)] session.commit() self.wait_lottery_dict = wait_lottery_dict return True def update_sync_eos(self, session, block_num, block_hash): """ 开奖时,如果再次查询节点上的该区块,如果hash有变化,说明回滚,取最新区块详情,修改该区块 :param session: :param block_num: :param block_hash: :return: """ block_detail = self.ec.http_get_block_detail(block_num) if block_detail: remote_block_hash = block_detail.get("id", "") time_stamp = block_detail.get("timestamp", "") if remote_block_hash: if remote_block_hash != block_hash: sync_eos_model = session.query(SyncEosModel).filter(SyncEosModel.block_num == block_num).first() if sync_eos_model: time_stamp_decimal = get_decimal(str_to_timestamp(time_stamp), digits=3) previous = block_detail.get("previous", "") sync_eos_model.block_hash = remote_block_hash sync_eos_model.time_stamp = time_stamp sync_eos_model.time_stamp_decimal = time_stamp_decimal sync_eos_model.previous = previous sync_eos_model.status = self.sync_success self.slog.info("lottery block_num:", block_num, "lottery block_hash:", remote_block_hash) return { "block_hash": remote_block_hash, "time_stamp": time_stamp, } return {} @staticmethod def lottery_callback(session, game_instance_id, block_no, block_hash, timestamp, received_time): """ :param session: :param game_instance_id: :param block_no: :param block_hash: :param timestamp: :param received_time: :return: """ process_res = WalletEosService.lottery_callback(game_instance_id, block_no, block_hash, timestamp, received_time) session.query(GameGetLotteryBlockInfoEosModel).filter( GameGetLotteryBlockInfoEosModel.game_instance_id == game_instance_id).update({ GameGetLotteryBlockInfoEosModel.block_hash: block_hash, GameGetLotteryBlockInfoEosModel.time_stamp: timestamp, GameGetLotteryBlockInfoEosModel.status: process_res }) return True
def game_instance_info_list(self, limit, offset, status='', start_id=None): offset = get_offset_by_page(offset, limit) result_dict = { 'limit': limit, 'offset': offset, 'count': 0, 'content': [] } account_service = AccountService() with MysqlTools().session_scope() as session: if status != '': q = session.query(GameDigitalInstanceModel). \ order_by(GameDigitalInstanceModel.status.asc(), GameDigitalInstanceModel.created_at.desc(), GameDigitalInstanceModel._id != 0) q = q.filter(GameDigitalInstanceModel.status == status) else: q = session.query(GameDigitalInstanceModel). \ order_by(GameDigitalInstanceModel.created_at.desc(), GameDigitalInstanceModel._id != 0) record_count = q.count() result_dict['count'] = get_page_by_offset(record_count, limit) if start_id is not None: start_id = str(start_id) q = q.filter(GameDigitalInstanceModel._id < start_id) query_result = q.limit(limit).offset(offset).all() winner = '' bet_serial = '' bet_number = 0 # --------------- 即时开 --------------- # if status == '': ins_instance = session.query(InstantGameInstanceModel). \ order_by(InstantGameInstanceModel.created_at.desc()).first() if ins_instance is not None: result_dict['content'].append({ 'id': ins_instance._id, 'created_at': str(ins_instance.created_at), 'game_serial': ins_instance.game_serial, 'game_title': ins_instance.game_title, 'progress': 0, 'remain': 0, 'bet_token': self.get_coin_name(ins_instance.bet_token), 'bet_number': 0, 'reward_token': self.get_coin_name(ins_instance.reward_token), 'reward_quantity': ins_instance.reward_quantity, 'support_token': ins_instance.support_token, 'status': -1, 'lottery_time': str(ins_instance.lottery_time), 'winners': '', 'bet_serial': '', 'game_describe': ins_instance.game_describe, 'participation': ins_instance.participation, 'merge_id': -1, 'merge_list': [] }) # --------------- 即时开end --------------- # for i in query_result: merge_id = -1 merges = [] merge_list = session.query(MergeParticipateInModel). \ filter(MergeParticipateInModel.game_instance_id == i._id). \ order_by(MergeParticipateInModel.created_at.desc()).limit(3).offset(0).all() if len(merge_list) > 0: merge_id = 1 for merge in merge_list: initiate_user = account_service.get_inner_user_account_info( session, merge.initiate_user_id) merges.append({ 'merge_id': merge._id, 'name': initiate_user['nick_name'], 'portrait': initiate_user['profile_picture'] }) if i.status == 2: winning_record = session.query(WinningRecordModel). \ filter(WinningRecordModel.game_instance_id == i._id).first() if winning_record is not None: if winning_record.user_type == 0: account_service = AccountService() user_info = account_service.get_inner_user_account_info( session, winning_record.user_id) winner = user_info['nick_name'] elif winning_record.user_type == 1: robot = session.query(RobotAccountModel).filter( RobotAccountModel.user_id == winning_record.user_id).first() winner = robot.nick_name else: winner = 'X@17Yau8' bet_serial = winning_record.bet_serial merge_id = winning_record.merge_id bet_number = winning_record.bet_number progress = 0 progress = (i.bet_number / i.need) * 100 if 0 < progress < 1: progress = 1 if progress > 1: progress = int(progress) result_dict['content'].append({ 'id': i._id, 'created_at': str(i.created_at), 'game_serial': i.game_serial, 'game_title': i.game_title, 'progress': progress, 'remain': int(i.need - i.bet_number), 'bet_token': self.get_coin_name(i.bet_token), 'bet_number': bet_number, 'reward_token': self.get_coin_name(i.reward_token), 'reward_quantity': i.reward_quantity, 'support_token': i.support_token, 'status': i.status, 'lottery_time': str(i.lottery_time), 'winners': winner, 'bet_serial': bet_serial, 'game_describe': i.game_describe, 'participation': i.participation, 'merge_id': merge_id, 'merge_list': merges }) return result_dict
def dice_sold_out_new(self, dice_id): change_type_31 = '31' # 扣款 change_type_32 = '32' # 返还 change_type_33 = '33' # 中奖 reward_quantity = decimal.Decimal(0) with MysqlTools().session_scope() as session: account_service = AccountService() dice_info = session.query(DiceParticipateInModel). \ filter(DiceParticipateInModel._id == dice_id).first() if dice_info is None: self.return_error(40021) ec = TokenNodeConfModel.get_eos_node_script(script_unit=_THREE_S) latest_eos_block_info = ec.http_get_latest_block() # print('latest_eos_block_info=-=-=', latest_eos_block_info) dice_info.block_no = latest_eos_block_info.get('block_num', None) dice_info.block_timestamp = latest_eos_block_info.get( 'timestamp', None) dice_info.block_hash = latest_eos_block_info.get('id', None) if dice_info.block_no is None or \ dice_info.block_timestamp is None or \ dice_info.block_hash is None: self.return_error(40024) else: dice_result = -1 banker_dice = int(dice_info.block_hash, 16) % 3 # 0石头 1剪刀 2布 user_dice = dice_info.user_dice # 0石头 1剪刀 2布 if banker_dice == user_dice: dice_result = 1 # 0用户胜 1平局 2庄家胜 -1未知 else: if banker_dice == 0 and user_dice == 1: dice_result = 2 elif banker_dice == 0 and user_dice == 2: dice_result = 0 elif banker_dice == 1 and user_dice == 0: dice_result = 0 elif banker_dice == 1 and user_dice == 2: dice_result = 2 elif banker_dice == 2 and user_dice == 0: dice_result = 2 elif banker_dice == 2 and user_dice == 1: dice_result = 0 dice_info.banker_dice = banker_dice dice_info.dice_result = dice_result # session.flush() if dice_result in [0, 1]: change_type = change_type_32 dice_config = session.query(DiceConfigModel). \ filter(DiceConfigModel.support_token_id == dice_info.bet_token).first() if dice_config is None: return self.return_error(40022) if dice_result == 0: change_type = change_type_33 # 用户获胜 中奖金额为投注金额+奖励金额(投注金额=奖励金额) 扣除手续费 reward_quantity = ( dice_info.reward_quantity + dice_info.bet_number ) * (100 - dice_config.handling_fee) / 100 dice_info.reward_quantity = reward_quantity elif dice_result == 1: change_type = change_type_32 # 平局 中奖金额为投注金额 reward_quantity = dice_info.bet_number result = account_service.do_win( session, dice_info.user_id, dice_info.reward_token, reward_quantity, 'dice_win' + str(dice_info._id), dice_info.user_dice, dice_info.dice_serial, change_type) if isinstance(result, int) is False: raise_logger( "dice分钱失败" + "user:"******"game_publish_lottery", "info") session.rollback() return False if result != 0: raise_logger( "dice分钱失败" + "user:"******"game_publish_lottery", "info") session.rollback() return False # ret_info = dice_info # print(ret_info) session.commit() session.refresh(dice_info) # session.expunge(dice_info) response = { 'dice_result': dice_info.dice_result, 'banker_dice': dice_info.banker_dice, 'user_dice': dice_info.user_dice, # 'dice_timestamp': timestamp_to_str(dice_info.dice_timestamp, format_style="%Y-%m-%d %H:%M:%S"), 'dice_id': str(dice_info._id), 'dice_serial': dice_info.dice_serial, 'reward_token': self.get_coin_name(dice_info.reward_token), 'reward_quantity': decimal_to_str(reward_quantity, 6) # 'reward_quantity': decimal_to_str( # str((dice_info.bet_number + dice_info.bet_number) * decimal.Decimal(0.99)), 6) } if dice_info.reward_token == int(_COIN_ID_USDT): response['reward_quantity'] = decimal_to_str(reward_quantity, 4) return response
def indiana_record(self, limit, offset, user_id, start_id=None): offset = get_offset_by_page(offset, limit) result_dict = { 'limit': limit, 'offset': offset, 'count': 0, 'content': [] } with MysqlTools().session_scope() as session: q = session.query(ParticipateInModel._id, ParticipateInModel.game_instance_id, ParticipateInModel.game_serial, ParticipateInModel.bet_token, (ParticipateInModel.bet_unit * ParticipateInModel.bet_number).label( 'total_bet'), ParticipateInModel.merge_id, ParticipateInModel.created_at, ParticipateInModel.pay_token, ParticipateInModel.pay_number). \ filter(ParticipateInModel.user_id == user_id). \ order_by(ParticipateInModel.created_at.desc()) record_count = q.count() result_dict['count'] = get_page_by_offset(record_count, limit) if start_id is not None: start_id = str(start_id) q = q.filter(ParticipateInModel._id < start_id) participate_list = q.limit(limit).offset(offset).all() for i in participate_list: instance_info = session.query(GameDigitalInstanceModel.need, GameDigitalInstanceModel.status, GameDigitalInstanceModel.bet_token, GameDigitalInstanceModel.participation). \ filter(GameDigitalInstanceModel._id == i.game_instance_id).first() if instance_info is None: continue total = instance_info.participation lower = session.query((func.count(ParticipateInModel._id)).label('lower_users')). \ filter(ParticipateInModel.game_instance_id == i.game_instance_id, ParticipateInModel.bet_unit * ParticipateInModel.bet_number < int(i.total_bet)). \ first() hc = hcf(int(i.total_bet), int(instance_info.need)) probability = str(int(int(i.total_bet) / hc)) + '/' + str( int(int(instance_info.need) / hc)) if lower is None: lower = total else: lower = lower.lower_users if int(i.pay_token) == int(_COIN_ID_EXP): pay_number = int(i.pay_number) else: pay_number = decimal_to_str(i.pay_number, 8) result_dict['content'].append({ 'instance_id': i.game_instance_id, 'participate_id': i._id, 'game_serial': i.game_serial, 'bet_token': self.get_coin_name(i.bet_token), 'total_bet': int(i.total_bet), 'need': instance_info.need, 'status': instance_info.status, 'need_token': self.get_coin_name(instance_info.bet_token), 'probability': probability, 'ranking': math.ceil((lower / total) * 100), 'merge_id': i.merge_id, 'part_in_time': str(i.created_at), "pay_token": self.get_coin_name(i.pay_token), "pay_number": pay_number }) return result_dict
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.mysql_token = MysqlTools(get_about_conf()) self.coin_id = None
def indiana_record_new(self, limit, offset, user_id, start_id=None): offset = get_offset_by_page(offset, limit) result_dict = { 'limit': limit, 'offset': offset, 'count': 0, 'content': [] } with MysqlTools().session_scope() as session: q = session.query(ParticipateInModel._id, ParticipateInModel.game_instance_id, ParticipateInModel.game_serial, ParticipateInModel.bet_token, ParticipateInModel.award_numbers, ParticipateInModel.win_number, (ParticipateInModel.bet_unit * ParticipateInModel.bet_number).label( 'total_bet'), ParticipateInModel.merge_id, ParticipateInModel.created_at, ParticipateInModel.pay_token, ParticipateInModel.pay_number). \ filter(ParticipateInModel.user_id == user_id). \ order_by(ParticipateInModel.created_at.desc()) record_count = q.count() result_dict['count'] = get_page_by_offset(record_count, limit) if start_id is not None: start_id = str(start_id) q = q.filter(ParticipateInModel._id < start_id) participate_list = q.limit(limit).offset(offset).all() for i in participate_list: award_numbers_list = i.award_numbers if i.game_instance_id == 0: instance_info = session.query(InstantGameInstanceModel.need, InstantGameInstanceModel.status, InstantGameInstanceModel.bet_token, InstantGameInstanceModel.participation). \ filter(InstantGameInstanceModel.game_serial == i.game_serial).first() if instance_info is None: continue if i.win_number in award_numbers_list: is_win = True else: is_win = False else: instance_info = session.query(GameDigitalInstanceModel.need, GameDigitalInstanceModel.status, GameDigitalInstanceModel._id, GameDigitalInstanceModel.bet_token, GameDigitalInstanceModel.participation). \ filter(GameDigitalInstanceModel._id == i.game_instance_id).first() if instance_info is None: continue if instance_info.status == 2: winning_record = session.query(WinningRecordModel). \ filter(WinningRecordModel.game_instance_id == instance_info._id).first() if winning_record.bet_serial in award_numbers_list: is_win = True else: is_win = False else: is_win = False if int(i.pay_token) == int(_COIN_ID_EXP): pay_number = int(i.pay_number) else: pay_number = decimal_to_str(i.pay_number, 8) result_dict['content'].append({ 'is_win': is_win, 'instance_id': i.game_instance_id, 'participate_id': i._id, 'game_serial': i.game_serial, 'bet_token': self.get_coin_name(i.bet_token), 'total_bet': int(i.total_bet), # 'need': instance_info.need, 'status': instance_info.status, 'need_token': self.get_coin_name(instance_info.bet_token), # 'probability': probability, # 'ranking': math.ceil((lower / total) * 100), 'merge_id': i.merge_id, 'part_in_time': str(i.created_at), "pay_token": self.get_coin_name(i.pay_token), "pay_number": pay_number }) return result_dict
def get_private_key_from_address(self, args): order_no = args["order_no"] coin_type = args["type"].upper() address = args["address"] category = args.get("category", self._normal) # 查询coin_id with self.mysql_token.session_scope() as session: # 查询 token_id token = session.query(TokenCoinModel).filter( TokenCoinModel.coin_name == coin_type).first() if not token: self.return_error(90002) self.coin_id = token.coin_id # 判断地址合法性 if isinstance(address, str): address = [address] else: if not isinstance(address, list): self.return_error(90001) # 判断币种类型合法性 if coin_type not in self.symbol_to_model: self.return_error(90002) # 判断地址类型合法性 if category == self._normal: model_index = _ONE ret = {"category": self._normal} elif category == self._gather: model_index = _TWO ret = {"category": self._gather} else: self.return_error(90004) ret = {} model_index = _ZERO # 获取对应model chain_model = self.symbol_to_model[coin_type][model_index] # 地址转成字符串 address_record = get_str_from_list(address) # 查询结果,并记录流水 with MysqlTools().session_scope() as session: record = session.query(RecordPkModel).filter( RecordPkModel.order_no == order_no).first() if record: self.return_error(10008) wallets = session.query(chain_model).filter( chain_model.sub_public_address.in_( address)).with_for_update().all() if not wallets: self.return_error(90003) for w in wallets: public_key_aes = w.acct_public_key_aes public_address = w.sub_public_address private_key_aes = w.sub_private_key_aes if public_key_aes not in ret: ret[public_key_aes] = [{ "public_address": public_address, "private_key_aes": private_key_aes, }] else: ret[public_key_aes].append({ "public_address": public_address, "private_key_aes": private_key_aes, }) record_pk = RecordPkModel(order_no=order_no, coin_id=self.coin_id, address=address_record, response=json.dumps(ret), category=category) session.add(record_pk) session.commit() return ret
class WalletService(BaseService): symbol_to_token_coin = { _BTC: _COIN_ID_BTC, _ETH: _COIN_ID_ETH, _EOS: _COIN_ID_EOS } symbol_to_model = { _BTC: [ WalletBtcModel, SecretBtcModel, WalletBtcGatherModel, SecretBtcGatherModel ], _ETH: [ WalletEthModel, SecretEthModel, WalletEthGatherModel, SecretEthGatherModel ], _EOS: [ WalletEosModel, SecretEosModel, WalletEosGatherModel, SecretEosGatherModel ], } _gather = "gather" _normal = "normal" interval = _HUNDRED * _ONE def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) wc = get_wallet_config(remove_type=False) self.wallet = None self.chain_model = None self.chain_token_model = None self.acct_pub_key_b58_aes = None self.coin_id = None self.symbol = wc["symbol"].upper() self.key = str(wc["key"]) self.nonce = str(wc["nonce"]) self.mnemonic = wc["mnemonic"] self.passphrase = wc["passphrase"] self.category = wc.get("category", self._normal).lower() self.mysql_token = MysqlTools(get_about_conf()) self.mysql_wallet = MysqlTools() def wallet_init(self): """ :return: """ if self.symbol not in self.symbol_to_model or self.symbol not in self.symbol_to_token_coin: raise Exception("There is no corresponding symbol") if self.category == self._normal: token_model_index = _ZERO secret_model_index = _ONE elif self.category == self._gather: token_model_index = _TWO secret_model_index = _THREE else: raise Exception("The category does not exist") self.chain_token_model = self.symbol_to_model[ self.symbol][token_model_index] self.chain_model = self.symbol_to_model[ self.symbol][secret_model_index] self.wallet = Wallet(symbol=self.symbol) self.wallet.init_acct(self.mnemonic, self.passphrase) self.acct_pub_key_b58_aes = super_AES( self.wallet.get_acct_key()["acct_pub_key_b58"], self.key, self.nonce) # 查询 token_id self.coin_id = self.symbol_to_token_coin[self.symbol] with self.mysql_wallet.session_scope() as session: # 查询或插入 token_salt salt = session.query(TokenSaltModel).filter( TokenSaltModel.public_key_aes == self.acct_pub_key_b58_aes, TokenSaltModel.coin_id == self.coin_id).first() if not salt: new_salt = TokenSaltModel( coin_id=self.coin_id, public_key_aes=self.acct_pub_key_b58_aes, key_aes=self.key, nonce_aes=self.nonce) session.add(new_salt) else: if salt.key_aes != self.key or salt.nonce_aes != self.nonce: raise Exception( "Table token_salt contains this key nonce, results already generated cannot be replaced with new key or nonce" ) session.commit() def wallet_generate(self, count): """ 生成HD子钱包 :param count: 生成的子钱包个数, 按index顺序生成, 接续数据库索引 :return: """ remainder = count % self.interval times = count // self.interval + _ONE if remainder else count // self.interval for num in range(_ONE, times + _ONE): count = self.interval if num == times: if remainder: count = remainder # 获取数据库现有索引 with self.mysql_wallet.session_scope() as session: wallets = session.query(self.chain_model).filter( self.chain_model.acct_public_key_aes == self.acct_pub_key_b58_aes).with_for_update().order_by( self.chain_model.sub_index.desc(), self.chain_model._id.desc()).first() if not wallets: begin = None else: begin = int(wallets.sub_index) + _ONE print("-" * 20) print("The latest index is: " + str(begin - _ONE) if begin else str(_ZERO)) wallet_list, wallet_token_list = self.chain_model_generate( count, begin) with self.mysql_token.session_scope() as session_token: session_token.add_all(wallet_token_list) session_token.commit() session.add_all(wallet_list) session.commit() print("Now we've successfully inserted: " + str(count) + "!!!") print("-" * 20) return True def chain_model_generate(self, count, begin): """ 批量生成chain model :param count: :param begin: :return: model list """ sub_key = self.wallet.get_sub_key(count, begin) sub_key_aes = {} if self.symbol in [_BTC, _ETH]: for k, v in sub_key.items(): sub_key_aes[k] = super_AES(v, self.key, self.nonce) elif self.symbol in [_EOS]: sub_key_aes = sub_key wallet_list = [] wallet_token_list = [] for sub_index, index_info in sub_key_aes.items(): if self.symbol in [_EOS] and self.category == self._gather: index_info["sub_private_key"] = super_AES( index_info["sub_private_key"], self.key, self.nonce) index_info["sub_address"] = self.mnemonic print(' change_index: ' + index_info["change_index"] + " public_address: " + index_info["sub_address"]) w = self.chain_model( sub_index=int(sub_index), change_index=index_info["change_index"], sub_private_key_aes=index_info["sub_private_key"], sub_public_key_aes=index_info["sub_public_key"], sub_public_address=index_info["sub_address"], acct_public_key_aes=self.acct_pub_key_b58_aes, coin_id=self.coin_id) w_token = self.chain_token_model( sub_index=int(sub_index), change_index=index_info["change_index"], sub_public_address=index_info["sub_address"], acct_public_key_aes=self.acct_pub_key_b58_aes, coin_id=self.coin_id) wallet_list.append(w) wallet_token_list.append(w_token) return wallet_list, wallet_token_list @staticmethod def generate_key_nonce(key, nonce): """ transform origin args type :param key: must be origin :param nonce: :return: """ return {"key": encode_str_hex(key), "nonce": encode_str_hex(nonce)}
def test_mysql(): with MysqlTools().session_scope() as session: yield from asyncio.sleep(10) res = session.query(TokenConfModel).first() print(res.coid)