Beispiel #1
0
def crawl_monster():
    infura_client = InfuraClient(INFURA_API_URL)
    data_contract = infura_client.getDataContract()

    start_time = time.time()
    update_count = 0
    add_count = 0
    total_monster = data_contract.call().totalMonster()
    current_block_number = infura_client.getCurrentBlock()
    log.data("start_crawl_monster|total=%s,block_number=%s", total_monster,
             current_block_number)

    monster_id = 1
    while monster_id <= total_monster:
        try:
            result, add_flag, update_flag = _sync_monster_id(
                data_contract, monster_id)
            if result is False:
                break
            add_count += add_flag
            update_count += update_flag
        except:
            logging.exception("update_ema_monster_fail|monster_id=%s",
                              monster_id)
            break
        monster_id += 1

    elapsed = time.time() - start_time
    log.data(
        "end_crawl_monster|elapsed=%s,total_monster=%s,ending_monster=%s,update_count=%s,adding_count=%s,start_at_block=%s",
        elapsed, total_monster, monster_id, update_count, add_count,
        current_block_number)
Beispiel #2
0
def crawl_monster_egg_data():
    infura_client = InfuraClient(INFURA_API_URL)
    current_block_number = infura_client.getCurrentBlock()
    transform_data_contract = infura_client.getTransformDataContract()

    start_time = time.time()
    total_egg_no = transform_data_contract.call().totalEgg()
    log.data("start_crawl_egg_data|total_egg=%s,block=%s", total_egg_no,
             current_block_number)

    index = 1
    while index <= total_egg_no:
        try:
            (egg_id, mother_id, class_id, trainer_address, hatch_time,
             monster_id) = transform_data_contract.call().getEggDataById(index)
        except Exception as error:
            log.warn("query_borrow_data_error|index=%s,error=%s", index,
                     error.message)
            time.sleep(5)
            infura_client = InfuraClient(INFURA_API_URL)
            transform_data_contract = infura_client.getTransformDataContract()
            continue

        egg_record = EtheremonDB.EmaEggDataTab.objects.filter(
            egg_id=index).first()
        if egg_record:
            egg_record.mother_id = mother_id
            egg_record.class_id = class_id
            egg_record.trainer = str(trainer_address).lower()
            egg_record.hatch_time = int(hatch_time)
            egg_record.new_obj_id = monster_id
            egg_record.create_time = start_time
        else:
            EtheremonDB.EmaEggDataTab.objects.create(
                egg_id=index,
                mother_id=mother_id,
                class_id=class_id,
                trainer=str(trainer_address).lower(),
                hatch_time=int(hatch_time),
                new_obj_id=monster_id,
                create_time=start_time)
        index += 1

    log.data("end_crawl_egg_data|total_egg=%s,block=%s,elapsed=%s",
             total_egg_no, current_block_number,
             time.time() - start_time)
Beispiel #3
0
def fix_bonus_egg():
    infura_client = InfuraClient(INFURA_API_URL)
    current_block_number = infura_client.getCurrentBlock()

    mother_egg_records = EtheremonDB.EmaEggDataTab.objects.filter(
        mother_id__gt=0).filter(
            class_id__lt=25).values('mother_id').distinct()
    mother_id = []
    for mother_egg_record in mother_egg_records:
        mother_id.append(mother_egg_record["mother_id"])

    # monster
    transform_contract = infura_client.getTransformContract()
    monster_records = list(
        EtheremonDB.EmaMonsterDataTab.objects.filter(
            monster_id__in=mother_id).filter(egg_bonus__gt=0).all())
    count = 0
    while count < len(monster_records):
        monster_record = monster_records[count]
        try:
            egg_bonus = transform_contract.call().getBonusEgg(
                monster_record.monster_id)
        except Exception as error:
            log.warn("get_egg_bonus_error|monster_id=%s,error=%s",
                     monster_record.monster_id, error)
            time.sleep(4)
            continue
        if monster_record.egg_bonus != egg_bonus:
            log.info(
                "fix_egg_bonus|monster_id=%s,before_bonus=%s,after_bonus=%s,block=%s",
                monster_record.monster_id, monster_record.egg_bonus, egg_bonus,
                current_block_number)
            EtheremonDB.EmaMonsterDataTab.objects.filter(
                monster_id=monster_record.monster_id).update(
                    egg_bonus=egg_bonus)
        else:
            log.info("correct_egg_bonus|monster_id=%s",
                     monster_record.monster_id)
        count += 1
Beispiel #4
0
def get_adventure_pending_explore(request, data):
	trainer_address = data["trainer_address"].lower()
	response_data = {
		"explore_id": 0,
		"monster_type": 0,
		"monster_id": 0,
		"monster_class": 0,
		"site_id": 0,
		"start_block": 0,
		"end_block": 0,
		"current_block": 0,
		"estimated_time_back": 0,
		"can_fasten": False,
	}
	pending_explore = get_pending_explore(trainer_address)
	if pending_explore:
		if pending_explore.monster_type == EmaAdventureMonsterType.ETHEREMON:
			monster_data = get_monster_data(pending_explore.monster_id)
			if monster_data.class_id == 21:
				log.warn("sending_invalid_monster|explore_id=%s", pending_explore.explore_id)
				return api_response_result(request, ResultCode.SUCCESS, response_data)
			response_data["monster_class"] = monster_data.class_id

		response_data["explore_id"] = pending_explore.explore_id
		response_data["monster_type"] = pending_explore.monster_type
		response_data["monster_id"] = pending_explore.monster_id
		response_data["site_id"] = pending_explore.site_id
		response_data["start_block"] = pending_explore.start_block
		response_data["end_block"] = pending_explore.end_block

		infura_client = InfuraClient(INFURA_API_URLS["adventure_task"])
		response_data["current_block"] = infura_client.getCurrentBlock()
		if response_data["end_block"] > response_data["current_block"]:
			response_data["estimated_time_back"] = (response_data["end_block"] - response_data["current_block"]) * 15
		if response_data["current_block"] >= response_data["start_block"] + 2:
			response_data["can_fasten"] = True

	return api_response_result(request, ResultCode.SUCCESS, response_data)
Beispiel #5
0
def crawl_monster_bonus_egg():
    infura_client = InfuraClient(INFURA_API_URL)
    current_block_number = infura_client.getCurrentBlock()
    transform_contract = infura_client.getTransformDataContract()

    start_time = time.time()
    monster_records = list(
        EtheremonDB.EmaMonsterDataTab.objects.filter(class_id__lte=24).all())
    log.data("start_crawl_monster_bonus_egg|total_monster=%s,block=%s",
             len(monster_records), current_block_number)

    count = 0
    for monster_record in monster_records:
        count += 1
        egg_bonus = int(transform_contract.call().getBonusEgg(
            monster_record.monster_id))
        monster_record.egg_bonus = egg_bonus
        monster_record.save()
        log.info("ema_crawl_monster_egg|monster_id=%s,egg_bonus=%s",
                 monster_record.monster_id, egg_bonus)

    log.data("end_crawl_monster_bonus_egg|count=%s,block=%s,elapsed=%s", count,
             current_block_number,
             time.time() - start_time)
Beispiel #6
0
def _update_exp_contract(setting_type, app_key):
    infura_client = InfuraClient(INFURA_API_URL)
    current_block = infura_client.getCurrentBlock() - 2

    start_block = ema_settings_manager.get_setting_value(setting_type)
    end_block = start_block + SMART_CONTRACT_BLOCK_STEP

    start_time = time.time()
    contract_address = None
    if setting_type == EmaSetting.SETTING_EXP_GYM_BLOCK:
        contract_address = EtheremonGymContract.ADDRESS

    transaction_list = get_txn_list(contract_address, start_block, end_block,
                                    app_key)
    if transaction_list is None:
        return

    log.data(
        "start_update_exp_contract|setting=%s,start_block=%s,end_block=%s,len_txn=%s",
        setting_type, start_block, end_block, len(transaction_list))

    latest_load_block = start_block
    monster_id_set = set()
    for transaction in transaction_list:
        if len(transaction["input"]) < SMART_CONTRACT_METHOD_ID_LENGTH:
            log.warn("invalid_smart_contract_txn|transaction=%s", transaction)
            continue
        if int(transaction.get("isError", 1)) != 0:
            continue
        if int(transaction.get("txreceipt_status")) != 1:
            continue

        latest_load_block = max(latest_load_block,
                                int(transaction["blockNumber"]))
        if latest_load_block > current_block:
            return
        method_id = transaction["input"][0:SMART_CONTRACT_METHOD_ID_LENGTH]

        if setting_type == EmaSetting.SETTING_EXP_GYM_BLOCK:
            if method_id == GYM_CONTRACT_START_TRAINING_METHOD:
                monster_id_hash = "0x" + transaction[
                    "input"][SMART_CONTRACT_METHOD_ID_LENGTH:
                             SMART_CONTRACT_METHOD_ID_LENGTH + 64]
                monster_id = Web3.toInt(hexstr=monster_id_hash)
                monster_id_set.add(monster_id)
                log.info("update_gym_contract|monster_id=%s,hash=%s",
                         monster_id, transaction["hash"])

    total_add = 0
    total_update = 0
    if monster_id_set:
        log.info(
            "update_exp_contract|setting=%s,len_monster=%s,latest_load_block=%s",
            setting_type, len(monster_id_set), latest_load_block)
        data_contract = infura_client.getDataContract()
        for monster_id in monster_id_set:
            result, add_flag, update_flag = _sync_monster_id(
                data_contract, monster_id)
            if result is False:
                return
            total_add += add_flag
            total_update += update_flag

    block_value = latest_load_block
    if current_block < block_value:
        block_value = current_block

    ema_settings_manager.set_setting(setting_type, block_value)
    elapsed = time.time() - start_time
    if elapsed < 5:
        time.sleep(5 - elapsed)
    log.data(
        "end_update_exp_contract|setting=%s,total_add=%s,total_update=%s,start_block=%s,end_block=%s,block_sync=%s,elapsed=%s",
        setting_type, total_add, total_update, start_block, end_block,
        block_value, elapsed)
def update_claim_reward_contract():
    infura_client = InfuraClient(INFURA_API_URL)
    current_block = infura_client.getCurrentBlock() - 5

    start_block = ema_settings_manager.get_setting_value(
        EmaSetting.SETTING_CONTRACT_CLAIM_REWARD_BLOCK)
    end_block = start_block + SMART_CONTRACT_BLOCK_STEP

    start_time = time.time()
    transaction_list = get_txn_list(EtheremonClaimRewardContract.ADDRESS,
                                    start_block, end_block, ETHERSCAN_API_KEY)
    latest_load_block = None
    log.data(
        "start_update_claim_reward_contract|current_block=%s,start_block=%s,end_block=%s,len_txn=%s",
        current_block, start_block, end_block, len(transaction_list))

    monster_id_set = set()
    for transaction in transaction_list:
        if len(transaction["input"]) < SMART_CONTRACT_METHOD_ID_LENGTH:
            log.warn("invalid_smart_contract_txn|transaction=%s", transaction)
            continue
        if int(transaction.get("isError", 1)) != 0:
            continue
        if int(transaction.get("txreceipt_status")) != 1:
            continue
        if int(transaction["blockNumber"]) > current_block:
            continue

        latest_load_block = int(
            transaction["blockNumber"]) if latest_load_block is None else max(
                latest_load_block, int(transaction["blockNumber"]))
        method_id = transaction["input"][0:SMART_CONTRACT_METHOD_ID_LENGTH]

        if method_id == CLAIM_REWARD_METHOD:
            token_bytes = transaction[
                "input"][SMART_CONTRACT_METHOD_ID_LENGTH:
                         SMART_CONTRACT_METHOD_ID_LENGTH + 256]
            token = token_bytes.decode("hex")
            token_data = decode_claim_reward_token(token)

            reward_txn_id = token_data["reward_id"]

            try:
                txn = transaction_manager.get_transaction_by_id(reward_txn_id)
                txn.txn_hash = transaction["hash"]
                txn.status = TxnStatus.FINISHED
                txn.save()
            except:
                logging.exception(
                    "process_claim_reward_failed|reward_txn_id=%s,txn_hash=%s",
                    reward_txn_id, transaction["hash"])
                continue

    record_block = latest_load_block + 1 if latest_load_block is not None else end_block + 1
    record_block = min(record_block, current_block)

    ema_settings_manager.set_or_create_setting(
        setting_id=EmaSetting.SETTING_CONTRACT_CLAIM_REWARD_BLOCK,
        name="claim reward contract",
        value=record_block)
    elapsed = time.time() - start_time
    if elapsed < 5:
        time.sleep(5 - elapsed)
    log.data(
        "end_update_claim_reward_contract|record_block=%s,total_txn=%s,total_monster=%s,elapsed=%s",
        record_block, len(transaction_list), len(monster_id_set), elapsed)
Beispiel #8
0
def update_burn_mon_contract():
    infura_client = InfuraClient(INFURA_API_URL)
    current_block = infura_client.getCurrentBlock() - 5

    start_block = ema_settings_manager.get_setting_value(
        EmaSetting.SETTING_CONTRACT_BURN_MON)
    end_block = start_block + SMART_CONTRACT_BLOCK_STEP

    start_time = time.time()
    transaction_list = get_txn_list(EtheremonBurnMonContract.ADDRESS,
                                    start_block, end_block, ETHERSCAN_API_KEY)
    latest_load_block = None
    log.data(
        "start_update_burn_mon_contract|current_block=%s,start_block=%s,end_block=%s,len_txn=%s",
        current_block, start_block, end_block, len(transaction_list))

    monster_id_set = set()

    for transaction in transaction_list:
        if len(transaction["input"]) < SMART_CONTRACT_METHOD_ID_LENGTH:
            log.warn("invalid_smart_contract_txn|transaction=%s", transaction)
            continue
        if int(transaction.get("isError", 1)) != 0:
            continue
        if int(transaction.get("txreceipt_status")) != 1:
            continue
        if int(transaction["blockNumber"]) > current_block:
            continue

        latest_load_block = int(
            transaction["blockNumber"]) if latest_load_block is None else max(
                latest_load_block, int(transaction["blockNumber"]))
        method_id = transaction["input"][0:SMART_CONTRACT_METHOD_ID_LENGTH]

        if method_id == BURN_MON_METHOD:
            contract_mon_id_hash = "0x" + transaction[
                "input"][SMART_CONTRACT_METHOD_ID_LENGTH:
                         SMART_CONTRACT_METHOD_ID_LENGTH + 64]
            contract_mon_id = Web3.toInt(hexstr=contract_mon_id_hash)
            contract_burn_id_hash = "0x" + transaction[
                "input"][SMART_CONTRACT_METHOD_ID_LENGTH +
                         64:SMART_CONTRACT_METHOD_ID_LENGTH + 128]
            contract_burn_id = Web3.toInt(hexstr=contract_burn_id_hash)

            mon_id, burn_id = burn_manager.get_mon_id_from_contract_burn_id(
                contract_burn_id)
            burn_request = burn_manager.get_burn_request_by_id(burn_id)

            if not burn_request or burn_request.mon_id != contract_mon_id:
                logging.exception(
                    "burn_mon_failed|contract_burn_id=%s,txn_hash=%s",
                    contract_burn_id, transaction["hash"])
                continue

            if burn_request.status in [BurnStatus.FINISHED, BurnStatus.FAILED]:
                logging.exception(
                    "burn_already_finished|contract_burn_id=%s,txn_hash=%s",
                    contract_burn_id, transaction["hash"])
                continue

            try:
                with transaction.atomic():
                    player_uid = user_manager.get_uid_by_address_default_0(
                        burn_request.player_address)

                    if burn_request.reward_value > 0:
                        # Only if there is reward
                        if burn_request.reward_type == BurnRewardTypes.ENERGY:
                            ema_energy_manager.add_energy(
                                burn_request.player_address,
                                burn_request.reward_value)
                        elif burn_request.reward_type == BurnRewardTypes.IN_GAME_EMONT:
                            emont_bonus_manager.add_bonus(
                                player_uid, {
                                    EmontBonusType.EVENT_BONUS:
                                    burn_request.reward_value
                                })

                        transaction_manager.create_transaction(
                            player_uid=player_uid,
                            player_address=burn_request.player_address,
                            txn_type=TxnTypes.BURN_MON_REWARD,
                            txn_info="mon %s" % burn_request.mon_id,
                            amount_type=TxnAmountTypes.IN_GAME_EMONT
                            if burn_request.reward_type
                            == BurnRewardTypes.IN_GAME_EMONT else
                            TxnAmountTypes.ENERGY,
                            amount_value=burn_request.reward_value,
                            status=TxnStatus.FINISHED,
                            txn_hash=transaction["hash"])

                        # 300 EMONT BONUS
                        # if burn_request.mon_level >= 30 and randint(1, 100) <= 3:
                        if randint(1, 100) <= 3:
                            additional_bonus = 500

                            emont_bonus_manager.add_bonus(
                                player_uid,
                                {EmontBonusType.EVENT_BONUS: additional_bonus})

                            transaction_manager.create_transaction(
                                player_uid=player_uid,
                                player_address=burn_request.player_address,
                                txn_type=TxnTypes.BURN_MON_REWARD_BONUS,
                                txn_info="mon %s" % burn_request.mon_id,
                                amount_type=TxnAmountTypes.IN_GAME_EMONT,
                                amount_value=additional_bonus,
                                status=TxnStatus.FINISHED,
                                txn_hash=transaction["hash"])

                    burn_request.status = BurnStatus.FINISHED
                    burn_request.save()
            except:
                logging.exception(
                    "burn_mon_failed|contract_burn_id=%s,txn_hash=%s",
                    contract_burn_id, transaction["hash"])
                continue

    record_block = latest_load_block + 1 if latest_load_block is not None else end_block + 1
    record_block = min(record_block, current_block)

    ema_settings_manager.set_or_create_setting(
        setting_id=EmaSetting.SETTING_CONTRACT_BURN_MON,
        name="burn mon contract",
        value=record_block)
    elapsed = time.time() - start_time
    if elapsed < 5:
        time.sleep(5 - elapsed)
    log.data(
        "end_update_burn_mon_contract|record_block=%s,total_txn=%s,total_monster=%s,elapsed=%s",
        record_block, len(transaction_list), len(monster_id_set), elapsed)
def update_transform_contract():
	infura_client = InfuraClient(INFURA_API_URL)
	current_block = infura_client.getCurrentBlock() - 2

	start_block = ema_settings_manager.get_setting_value(EmaSetting.SETTING_CONTRACT_TRANSFORM_BLOCK)
	end_block = start_block + SMART_CONTRACT_BLOCK_STEP

	start_time = time.time()


	transaction_list = get_txn_list(EtheremonTransformContract.ADDRESS, start_block, end_block, ETHERSCAN_API_KEY)
	
	
	
	if transaction_list is None:
		return

	log.data("start_update_transform_contract|current_block=%s,start_block=%s,end_block=%s,len_txn=%s", current_block, start_block, end_block, len(transaction_list))

	'''
	if len(transaction_list) > 50:
		log.data("update_transform|cut_down_txn|current_block=%s,start_block=%s,end_block=%s", current_block, start_block, end_block)
		transaction_list = transaction_list[:50]
	'''

	latest_load_block = start_block
	sender_set = set()
	for transaction in transaction_list:
		if len(transaction["input"]) < SMART_CONTRACT_METHOD_ID_LENGTH:
			log.warn("invalid_smart_contract_txn|transaction=%s", transaction)
			continue
		if int(transaction.get("isError", 1)) != 0:
			continue
		if int(transaction.get("txreceipt_status")) != 1:
			continue

		log.info("update_transform_contract|txn_hash=%s", transaction["hash"])
		latest_load_block = max(latest_load_block, int(transaction["blockNumber"]))
		if latest_load_block > current_block:
			return
		sender = str(transaction["from"]).lower()
		sender_set.add(sender)

	# update info by trainer
	count_new_egg = 0
	if sender_set:
		time.sleep(5)
		data_contract = infura_client.getDataContract()
		transform_contract = infura_client.getTransformContract()
		transform_data_contract = infura_client.getTransformDataContract()
		for player in sender_set:
			# update info
			result = _sync_player_dex(data_contract, player, transform_contract)
			if result is False:
				log.warn("sync_player_fail|player=%s", player)
				return

			# sync egg data
			egg_records = EtheremonDB.EmaEggDataTab.objects.filter(trainer=player).filter(new_obj_id=0).all()
			for egg_record in egg_records:
				(egg_id, mother_id, class_id, trainer_address, hatch_time, monster_id) = transform_data_contract.call().getEggDataById(egg_record.egg_id)
				if class_id == 0:
					log.warn("invalid_egg_data|egg_id=%s", egg_record.egg_id)
					return
				egg_record.mother_id = mother_id
				egg_record.class_id = class_id
				egg_record.trainer = str(trainer_address).lower()
				egg_record.hatch_time = int(hatch_time)
				egg_record.new_obj_id = monster_id
				egg_record.save()

		# sync new egg
		max_egg_record = EtheremonDB.EmaEggDataTab.objects.all().order_by("-egg_id").first()
		max_id = 0
		if max_egg_record:
			max_id = max_egg_record.egg_id
		current_total = transform_data_contract.call().totalEgg()
		index = max_id + 1
		while index <= current_total:
			(egg_id, mother_id, class_id, trainer_address, hatch_time, monster_id) = transform_data_contract.call().getEggDataById(index)
			if class_id == 0:
				log.warn("invalid_egg_data|egg_id=%s", index)
				return
			EtheremonDB.EmaEggDataTab.objects.create(
				egg_id=index,
				mother_id=mother_id,
				class_id=class_id,
				trainer=str(trainer_address).lower(),
				hatch_time=int(hatch_time),
				new_obj_id=monster_id,
				create_time=start_time
			)
			index += 1
			count_new_egg += 1

	record_block = latest_load_block
	if len(transaction_list) > 0:
		record_block += 1
		if record_block > current_block:
			record_block = current_block

	ema_settings_manager.set_setting(EmaSetting.SETTING_CONTRACT_TRANSFORM_BLOCK, record_block)
	elapsed = time.time() - start_time
	if elapsed < 5:
		time.sleep(5-elapsed)
	log.data("end_update_transform_contract|record_block=%s,total_txn=%s,total_player=%s,count_new_egg=%s,elapsed=%s",
		record_block, len(transaction_list), len(sender_set), count_new_egg, elapsed)
Beispiel #10
0
def update_trade_contract():
	infura_client = InfuraClient(INFURA_API_URL)
	current_block = infura_client.getCurrentBlock() - 2

	start_block = ema_settings_manager.get_setting_value(EmaSetting.SETTING_CONTRACT_TRADE_BLOCK)
	end_block = start_block + SMART_CONTRACT_BLOCK_STEP

	start_time = time.time()
	transaction_list = get_txn_list(EtheremonTradeContract.ADDRESS, start_block, end_block, ETHERSCAN_API_KEY)
	if transaction_list is None:
		return

	log.data("start_update_trade_contract|current_block=%s,start_block=%s,end_block=%s,len_txn=%s", current_block, start_block, end_block, len(transaction_list))

	latest_load_block = start_block
	current_ts = get_timestamp()
	monster_id_set = set()
	for transaction in transaction_list:
		if len(transaction["input"]) < SMART_CONTRACT_METHOD_ID_LENGTH:
			log.warn("invalid_smart_contract_txn|transaction=%s", transaction)
			continue
		if int(transaction.get("isError", 1)) != 0:
			continue
		if int(transaction.get("txreceipt_status")) != 1:
			continue

		log.info("update_trade_contract|txn_hash=%s", transaction["hash"])
		latest_load_block = max(latest_load_block, int(transaction["blockNumber"]))
		if latest_load_block > current_block:
			return
		method_id = transaction["input"][0:SMART_CONTRACT_METHOD_ID_LENGTH]
		sender = str(transaction["from"]).lower()

		if method_id == TRADING_CONTRACT_PLACE_SELL_METHOD:
			monster_id_hash = "0x" + transaction["input"][SMART_CONTRACT_METHOD_ID_LENGTH:SMART_CONTRACT_METHOD_ID_LENGTH + 64]
			monster_id = Web3.toInt(hexstr=monster_id_hash)

			price_hash = "0x" + transaction["input"][SMART_CONTRACT_METHOD_ID_LENGTH + 64:SMART_CONTRACT_METHOD_ID_LENGTH + 128]
			original_price = Web3.toInt(hexstr=price_hash)
			price = original_price/MARKET_PRICE_DIVISION

			if price > 1000000000:
				log.warn("price_too_high|txn_hash=%s,origin_price=%s,price=%s", transaction["hash"], original_price, price)
				continue


			current_record = EtheremonDB.EmaMarketTab.objects.filter(type=EmaMarketType.SELL).filter(monster_id=monster_id).first()
			if current_record:
				extra_data = json.loads(current_record.extra_data)
				if current_record.price == price and extra_data.get("txn_hash") == transaction["hash"]:
					continue
				extra_data["txn_hash"] = transaction["hash"]
				current_record.player = sender
				current_record.extra_data = json.dumps(extra_data)
				current_record.price = price
				current_record.save()
			else:
				extra_data = {"txn_hash": transaction["hash"]}
				EtheremonDB.EmaMarketTab.objects.create(
					type=EmaMarketType.SELL,
					player=sender,
					monster_id=monster_id,
					price=price,
					status=EmaMarketStatus.NONE,
					extra_data=json.dumps(extra_data),
					create_time=int(transaction["timeStamp"])
				)

			# update market history
			'''
			price = original_price/HISTORY_PRICE_DIVISION
			monster_record = EtheremonDB.EmaMonsterDataTab.objects.filter(monster_id=monster_id).first()
			if monster_record is None:
				log.warn("monster_id_not_exist|monster_id=%s,trade_hash=%s", monster_id, transaction["hash"])
				return
			market_history_item = EtheremonDB.MarketHistoryTab.objects.filter(monster_id=monster_id, sell_time=int(transaction["timeStamp"])).first()
			if market_history_item:
				continue
			base_bp = (monster_record.b0 + monster_record.b1 + monster_record.b2 + monster_record.b3 + monster_record.b4 + monster_record.b5) / 6
			EtheremonDB.MarketHistoryTab.objects.create(
				monster_id=monster_id,
				price=price,
				is_sold=False,
				block_number=int(transaction["blockNumber"]),
				sell_time=int(transaction["timeStamp"]),
				buy_time=0,
				class_id=monster_record.class_id,
				base_bp=base_bp,
				create_index=monster_record.create_index,
				extra_data=json.dumps({}),
				exp=monster_record.exp
			)
			'''
			log.info("mark_list_monster_for_sell|monster_id=%s,sell_time=%s", monster_id, int(transaction["timeStamp"]))

		elif method_id == TRADING_CONTRACT_REMOVE_SELL_METHOD:
			monster_id_hash = "0x" + transaction["input"][SMART_CONTRACT_METHOD_ID_LENGTH:SMART_CONTRACT_METHOD_ID_LENGTH + 64]
			monster_id = Web3.toInt(hexstr=monster_id_hash)
			EtheremonDB.EmaMarketTab.objects.filter(type=EmaMarketType.SELL).filter(monster_id=monster_id).delete()
			log.info("remove_sell|monster_id=%s,txn_hash=%s", monster_id, transaction["hash"])

		elif method_id == TRADING_CONTRACT_BUY_METHOD:
			monster_id_hash = "0x" + transaction["input"][SMART_CONTRACT_METHOD_ID_LENGTH:SMART_CONTRACT_METHOD_ID_LENGTH + 64]
			monster_id = Web3.toInt(hexstr=monster_id_hash)

			# update monster info
			monster_id_set.add(monster_id)

			monster_record = EtheremonDB.EmaMonsterDataTab.objects.filter(monster_id=monster_id).first()
			if monster_record is None:
				log.warn("monster_id_not_exist|monster_id=%s,trade_hash=%s", monster_id, transaction["hash"])
				return

			txn_hash = transaction["hash"].lower()
			market_record = EtheremonDB.EmaMarketTab.objects.filter(type=EmaMarketType.SELL).filter(monster_id=monster_id).first()
			if not market_record:
				log.warn("market_record_not_exist|txn_hash=%s,monster_id=%s", txn_hash, monster_id)
				continue

			market_history_item = EtheremonDB.MarketHistoryTab.objects.filter(txn_hash=txn_hash).first()
			base_bp = (monster_record.b0 + monster_record.b1 + monster_record.b2 + monster_record.b3 + monster_record.b4 + monster_record.b5) / 6
			if not market_history_item:
				EtheremonDB.MarketHistoryTab.objects.create(
					monster_id=monster_id,
					txn_hash=txn_hash,
					seller=market_record.player,
					buyer=sender,
					price=market_record.price,
					is_sold=True,
					block_number=int(transaction["blockNumber"]),
					sell_time=market_record.create_time,
					buy_time=int(transaction["timeStamp"]),
					class_id=monster_record.class_id,
					base_bp=base_bp,
					create_index=monster_record.create_index,
					extra_data=json.dumps({}),
					exp=monster_record.exp
				)
			market_record.delete()

			log.info("buy_item|monster_id=%s,txn_hash=%s", monster_id, transaction["hash"])

			# update market history
			'''
			if market_history_item is None:
				log.warn("item_sold_not_found|monster_id=%s,hash=%s", monster_id, transaction["hash"])
				continue
			if market_history_item.is_sold:
				continue
			if EtheremonDB.MarketHistoryTab.objects.filter(monster_id=monster_id, buy_time=int(transaction["timeStamp"])).first() is not None:
				log.warn("item_duplicate_buy|monster_id=%s,hash=%s", monster_id, transaction["hash"])
				continue
			monster_record = EtheremonDB.EmaMonsterDataTab.objects.filter(monster_id=monster_id).first()
			if monster_record is None:
				log.warn("monster_id_not_exist|monster_id=%s,trade_hash=%s", monster_id, transaction["hash"])
				return
			base_bp = (monster_record.b0 + monster_record.b1 + monster_record.b2 + monster_record.b3 + monster_record.b4 + monster_record.b5) / 6
			market_history_item.is_sold = True
			market_history_item.buy_time = int(transaction["timeStamp"])
			market_history_item.class_id = monster_record.class_id
			market_history_item.base_bp = base_bp
			market_history_item.create_index = monster_record.create_index
			market_history_item.exp = monster_record.exp
			market_history_item.save()
			log.info("mark_buy_monster|monster_id=%s,buy_time=%s", monster_id, int(transaction["timeStamp"]))
			'''

		elif method_id == TRADING_CONTRACT_OFFER_BORROW_METHOD:
			monster_id_hash = "0x" + transaction["input"][SMART_CONTRACT_METHOD_ID_LENGTH:SMART_CONTRACT_METHOD_ID_LENGTH + 64]
			monster_id = Web3.toInt(hexstr=monster_id_hash)

			price_hash = "0x" + transaction["input"][SMART_CONTRACT_METHOD_ID_LENGTH + 64:SMART_CONTRACT_METHOD_ID_LENGTH + 128]
			price = Web3.toInt(hexstr=price_hash)
			price = price/MARKET_PRICE_DIVISION

			release_time_hash = "0x" + transaction["input"][SMART_CONTRACT_METHOD_ID_LENGTH + 128:SMART_CONTRACT_METHOD_ID_LENGTH + 192]
			release_time = Web3.toInt(hexstr=release_time_hash)

			current_record = EtheremonDB.EmaMarketTab.objects.filter(type=EmaMarketType.BORROW).filter(monster_id=monster_id).first()
			if current_record:
				extra_data = json.loads(current_record.extra_data)
				if current_record.price == price and current_record.status == EmaMarketStatus.NONE and extra_data["release_time"] == release_time and extra_data.get("txn_hash") == transaction["hash"]:
					continue
				extra_data["txn_hash"] = transaction["hash"].lower()
				extra_data["release_time"] = release_time
				extra_data["borrower"] = ""
				current_record.player=sender
				current_record.status = EmaMarketStatus.NONE
				current_record.price = price
				current_record.extra_data = json.dumps(extra_data)
				current_record.save()
			else:
				extra_data = {
					"txn_hash": transaction["hash"].lower(),
					"borrower": "",
					"release_time": release_time
				}
				EtheremonDB.EmaMarketTab.objects.create(
					type=EmaMarketType.BORROW,
					player=sender,
					monster_id=monster_id,
					price=price,
					status=EmaMarketStatus.NONE,
					extra_data=json.dumps(extra_data),
					create_time=current_ts
				)
		elif method_id == TRADING_CONTRACT_REMOVE_OFFER_BORROW_METHOD:
			monster_id_hash = "0x" + transaction["input"][SMART_CONTRACT_METHOD_ID_LENGTH:SMART_CONTRACT_METHOD_ID_LENGTH + 64]
			monster_id = Web3.toInt(hexstr=monster_id_hash)
			EtheremonDB.EmaMarketTab.objects.filter(type=EmaMarketType.BORROW).filter(monster_id=monster_id).delete()
			log.info("remove_borrow|monster_id=%s,txn_hash=%s", monster_id, transaction["hash"])

		elif method_id == TRADING_CONTRACT_BORROW_METHOD:
			monster_id_hash = "0x" + transaction["input"][SMART_CONTRACT_METHOD_ID_LENGTH:SMART_CONTRACT_METHOD_ID_LENGTH + 64]
			monster_id = Web3.toInt(hexstr=monster_id_hash)

			# update monster info
			monster_id_set.add(monster_id)

			current_record = EtheremonDB.EmaMarketTab.objects.filter(type=EmaMarketType.BORROW).filter(monster_id=monster_id).first()
			if not current_record:
				log.error("no_monster_borrow_record|monster_id=%s,txn_hash=%s", monster_id, transaction["hash"])
				break

			extra_data = json.loads(current_record.extra_data)
			extra_data["borrower"] = str(transaction["from"]).lower()
			if extra_data["release_time"] < 10000000:
				extra_data["release_time"] += int(transaction["timeStamp"])
			current_record.status = EmaMarketStatus.LENT
			current_record.extra_data = json.dumps(extra_data)
			current_record.save()

		elif method_id == TRADING_CONTRACT_GET_BACK_LENDING_METHOD:
			monster_id_hash = "0x" + transaction["input"][SMART_CONTRACT_METHOD_ID_LENGTH:SMART_CONTRACT_METHOD_ID_LENGTH + 64]
			monster_id = Web3.toInt(hexstr=monster_id_hash)
			monster_id_set.add(monster_id)

			EtheremonDB.EmaMarketTab.objects.filter(type=EmaMarketType.BORROW).filter(monster_id=monster_id).delete()
			log.info("remove_borrow|monster_id=%s,txn_hash=%s", monster_id, transaction["hash"])

	if len(monster_id_set) > 0:
		log.info("update_trade_contract|monster_len=%s,latest_load_block=%s", len(monster_id_set), latest_load_block)
		data_contract = infura_client.getDataContract()
		for monster_id in monster_id_set:
			_sync_monster_id(data_contract, monster_id)
			log.info("trade_contract|update_monster|monster_id=%s", monster_id)

	record_block = latest_load_block
	if len(transaction_list) > 0:
		record_block += 1
		if record_block > current_block:
			record_block = current_block

	ema_settings_manager.set_setting(EmaSetting.SETTING_CONTRACT_TRADE_BLOCK, record_block)
	elapsed = time.time() - start_time
	if elapsed < 5:
		time.sleep(5-elapsed)
	log.data("end_update_trade_contract|record_block=%s,total_txn=%s,total_monster=%s,elapsed=%s",
		record_block, len(transaction_list), len(monster_id_set), elapsed)
def update_adventure_nft_contract():
	infura_client = InfuraClient(INFURA_API_URL)
	current_block = infura_client.getCurrentBlock() - 2

	start_block = ema_settings_manager.get_setting_value(EmaSetting.SETTING_CONTRACT_ADVENTURE_ITEM)
	end_block = start_block + SMART_CONTRACT_BLOCK_STEP

	start_time = time.time()
	event_list = get_event_list(EtheremonAdventureItemContract.ADDRESS, start_block, end_block, ETHERSCAN_API_KEY, TOPIC_TRANSFER)
	if event_list is None:
		return

	log.data("start_update_adventure_nft_contract|current_block=%s,start_block=%s,end_block=%s,len_event=%s", current_block, start_block, end_block, len(event_list))

	latest_load_block = start_block
	token_id_set = set()
	token_id_address_dict = {}
	from_address_set = set()
	for event in event_list:
		latest_load_block = max(latest_load_block, int(event["blockNumber"], 16))
		if latest_load_block > current_block:
			return
		token_id_hash = event["topics"][3]
		token_id = Web3.toInt(hexstr=token_id_hash)
		token_id_set.add(token_id)
		from_address = '0x' + event["topics"][1][26:].lower()
		token_address = '0x' + event["topics"][2][26:].lower()
		from_address_set.add(from_address)
		if token_id in token_id_address_dict:
			token_id_address_dict[token_id].add(token_address)
		else:
			token_id_address_dict[token_id] = set([token_address])
		log.info("scan_adventure_event|txn_hash=%s,token_id=%s,target_address=%s,from_address=%s", event["transactionHash"], token_id, token_address, from_address)

	current_ts = get_timestamp()
	if token_id_set:
		adventure_item_contract = infura_client.getAdventureItemContract()
		for token_id in token_id_set:
			try:
				owner = adventure_item_contract.call().ownerOf(token_id)
			except Exception as error:
				log.info("error_owner_token|token_id=%s", token_id)
				owner = EMPTY_ADDRESS
			owner = owner.lower()
			if owner not in token_id_address_dict[token_id]:
				# Case current owner is different from the old transaction => ignore
				log.warn("adventure_item_owner_invalid|token_id=%s,owner=%s,owner_set=%s", token_id, owner, token_id_address_dict[token_id])
				continue
			(item_class, item_value) = adventure_item_contract.call().getItemInfo(token_id)
			if item_class == 0:
				log.warn("adventure_item_class_invalid|token_id=%s,item_class=%s,item_value=%s", token_id, item_class, item_value)
				return
			token_record = EtheremonDB.EmaAdventureItemTab.objects.filter(token_id=token_id).first()
			if token_record:
				token_record.owner = owner
				token_record.class_id = item_class
				token_record.value = item_value
				token_record.update_time = current_ts
			else:
				token_record = EtheremonDB.EmaAdventureItemTab(
					token_id=token_id,
					owner=owner,
					class_id=item_class,
					value=item_value,
					update_time=current_ts
				)
			token_record.save()

			# update claim
			if token_id < 1081:
				if token_id % 10 == 0:
					site_id = token_id / 10
					site_index = 9
				else:
					site_id = token_id / 10 + 1
					site_index = token_id % 10 - 1
				EtheremonDB.EmaAdventurePresaleTab.objects.filter(site_id=site_id).filter(site_index=site_index).update(token_id=token_id)

	# sync player data
	if from_address_set:
		log.info("update_adventure_nft_contract|sender_len=%s,latest_load_block=%s", len(from_address_set), latest_load_block)
		data_contract = infura_client.getDataContract()
		for player in from_address_set:
			result = _sync_player_dex(data_contract, player, None, True)
			if result is False:
				log.warn("sync_player_fail|player=%s", player)
				return
			log.info("contract_adventure_nft_sync_player|sync_player=%s,block=%s", player, current_block)

	record_block = latest_load_block
	if len(token_id_set) > 0:
		record_block += 1
		if record_block > current_block:
			record_block = current_block

	ema_settings_manager.set_setting(EmaSetting.SETTING_CONTRACT_ADVENTURE_ITEM, record_block)
	elapsed = time.time() - start_time
	if elapsed < 5:
		time.sleep(5-elapsed)
	log.data("end_update_adventure_item_contract|record_block=%s,total_txn=%s,total_token=%s,elapsed=%s", record_block, len(event_list), len(token_id_set), elapsed)
def update_erc20_contract():
	infura_client = InfuraClient(INFURA_API_URL)
	current_block = infura_client.getCurrentBlock() - 2

	start_block = ema_settings_manager.get_setting_value(EmaSetting.SETTING_CONTRACT_ERC20_BLOCK)
	end_block = start_block + SMART_CONTRACT_BLOCK_STEP

	start_time = time.time()
	transaction_list = get_txn_list(EtheremonEMONTContract.ADDRESS, start_block, end_block, ETHERSCAN_API_KEY)
	if transaction_list is None:
		return

	log.data("start_update_erc20_contract|current_block=%s,start_block=%s,end_block=%s,len_txn=%s", current_block, start_block, end_block, len(transaction_list))

	latest_load_block = start_block
	egg_sender_set = set()
	energy_sender_set = set()
	adventure_explore_contract = infura_client.getAdventureExploreContract()
	adventure_data_contract = infura_client.getAdventureDataContract()
	site_id_set = set()
	current_ts = get_timestamp()
	deck_sender_set = set()
	for transaction in transaction_list:
		if len(transaction["input"]) < SMART_CONTRACT_METHOD_ID_LENGTH:
			log.warn("invalid_smart_contract_txn|transaction=%s", transaction)
			continue
		if int(transaction.get("isError", 1)) != 0:
			continue
		if int(transaction.get("txreceipt_status")) != 1:
			continue
		latest_load_block = max(latest_load_block, int(transaction["blockNumber"]))
		if latest_load_block > current_block:
			return
		method_id = transaction["input"][0:SMART_CONTRACT_METHOD_ID_LENGTH]
		sender = str(transaction["from"]).lower()

		if method_id == PAY_SERVICE_METHOD:
			type_id_hash = "0x" + transaction["input"][SMART_CONTRACT_METHOD_ID_LENGTH + 64:SMART_CONTRACT_METHOD_ID_LENGTH + 128]
			type_id = Web3.toInt(hexstr=type_id_hash)

			if type_id == PayServiceType.FAST_HATCHING or type_id == PayServiceType.RANDOM_EGG:
				egg_sender_set.add(sender)
			elif type_id == PayServiceType.ENERGY_TOPUP:
				energy_sender_set.add(sender)
			elif type_id == PayServiceType.ADVENTURE:
				adventure_sub_id_hash = "0x" + transaction["input"][SMART_CONTRACT_METHOD_ID_LENGTH + 192:SMART_CONTRACT_METHOD_ID_LENGTH + 256]
				adventure_sub_id = Web3.toInt(hexstr=adventure_sub_id_hash)

				if adventure_sub_id == 1:
					# explore using emont
					pending_explore_data = adventure_explore_contract.call().getPendingExploreItem(sender)
					explore_id = pending_explore_data[0]
					if explore_id == 0:
						log.info("no_pending_txn|sender=%s", sender)
						continue
					current_record = EtheremonDB.EmaAdventureExploreTab.objects.filter(explore_id=explore_id).first()
					if not current_record:
						'''
						EtheremonDB.EmaAdventureExploreTab.objects.create(
							explore_id=explore_id,
							fee_type=EmaAdventureExploreFee.EMONT,
							sender=sender,
							monster_type=pending_explore_data[1],
							monster_id=pending_explore_data[2],
							site_id=pending_explore_data[3],
							reward_monster_class=0,
							reward_item_class=0,
							reward_item_value='0',
							start_block=pending_explore_data[4],
							end_block=pending_explore_data[5],
							claim_txn_hash='',
							create_time=current_ts
						)
						log.info("adding_new_explore|explore_id=%s,sender=%s,txn_hash=%s", explore_id, sender, transaction["hash"])
						'''
						return
					else:
						if current_record.fee_type == 0:
							current_record.fee_type = EmaAdventureExploreFee.EMONT
							current_record.save()
					site_id_set.add(pending_explore_data[3])
				else:
					# claim explore
					explore_id_hash = "0x" + transaction["input"][SMART_CONTRACT_METHOD_ID_LENGTH + 256:SMART_CONTRACT_METHOD_ID_LENGTH + 320]
					explore_id = Web3.toInt(hexstr=explore_id_hash)
					current_record = EtheremonDB.EmaAdventureExploreTab.objects.filter(explore_id=explore_id).first()
					explore_data = adventure_explore_contract.call().getExploreItem(explore_id)
					if explore_data[5] == 0 and explore_data[6] == 0 and explore_data[7] == 0:
						log.warn("invalid_explore_data_claim|explore_id=%s,explore_data=%s,txn_hash=%s", explore_id, explore_data, transaction["hash"])
						return
					if not current_record:
						log.warn("unable_to_find_explore|explore_id=%s,txn_hash=%s,adventure_sub_id=%s", explore_id, transaction["hash"], adventure_sub_id)
						'''
						explore_ending_block = explore_data[4] + EXPLORE_MIN_BLOCK_GAP + explore_data[4] % EXPLORE_MIN_BLOCK_GAP
						EtheremonDB.EmaAdventureExploreTab.objects.create(
							explore_id=explore_id,
							fee_type=EmaAdventureExploreFee.ETH,
							sender=explore_data[0].lower(),
							monster_type=explore_data[1],
							monster_id=explore_data[2],
							site_id=explore_data[3],
							reward_monster_class=explore_data[5],
							reward_item_class=explore_data[6],
							reward_item_value=str(explore_data[7]),
							start_block=explore_data[4],
							end_block=explore_ending_block,
							claim_txn_hash=transaction["hash"].lower(),
							create_time=current_ts
						)
						site_id_set.add(explore_data[3])
						'''
						return
					else:
						current_record.claim_txn_hash = transaction["hash"].lower()
						current_record.reward_monster_class = explore_data[5]
						current_record.reward_item_class = explore_data[6]
						current_record.reward_item_value = str(explore_data[7])
						current_record.save()

					site_id_set.add(current_record.site_id)

					if explore_data[5] > 0:
						deck_sender_set.add(current_record.sender)


	if egg_sender_set:
		log.info("update_erc20_egg_info|len_sender=%s,latest_load_block=%s", len(egg_sender_set), latest_load_block)
		transform_data_contract = infura_client.getTransformDataContract()
		for sender in egg_sender_set:
			egg_records = EtheremonDB.EmaEggDataTab.objects.filter(trainer=sender).filter(new_obj_id=0).all()
			for egg_record in egg_records:
				(egg_id, mother_id, class_id, trainer_address, hatch_time, monster_id) = transform_data_contract.call().getEggDataById(egg_record.egg_id)
				egg_record.mother_id = mother_id
				egg_record.class_id = class_id
				egg_record.trainer = str(trainer_address).lower()
				egg_record.hatch_time = int(hatch_time)
				egg_record.new_obj_id = monster_id
				egg_record.save()
				log.info("erc20_update_egg|trainer=%s,egg_id=%s", sender, egg_id)

		# sync new egg
		max_egg_record = EtheremonDB.EmaEggDataTab.objects.all().order_by("-egg_id").first()
		max_id = 0
		if max_egg_record:
			max_id = max_egg_record.egg_id
		current_total = transform_data_contract.call().totalEgg()
		index = max_id + 1
		while index <= current_total:
			(egg_id, mother_id, class_id, trainer_address, hatch_time, monster_id) = transform_data_contract.call().getEggDataById(index)
			if class_id is 0:
				log.warn("invalid_egg_data|egg_id=%s", index)
				return
			EtheremonDB.EmaEggDataTab.objects.create(
				egg_id=index,
				mother_id=mother_id,
				class_id=class_id,
				trainer=str(trainer_address).lower(),
				hatch_time=int(hatch_time),
				new_obj_id=monster_id,
				create_time=start_time
			)
			index += 1
			log.info("erc20_add_egg|egg_id=%s", egg_id)

	if energy_sender_set:
		log.info("update_erc20_energy_info|len_sender=%s,latest_load_block=%s", len(energy_sender_set), latest_load_block)
		energy_contract = infura_client.getEnergyContract()
		current_ts = get_timestamp()
		for sender in energy_sender_set:
			(free_amount, paid_amount, last_claim) = energy_contract.call().getPlayerEnergy(sender)
			record = EtheremonDB.EmaPlayerEnergyTab.objects.filter(trainer=sender).first()
			if record:
				record.free_amount = free_amount
				record.paid_amount = paid_amount
				record.last_claim_time = last_claim
				record.update_time = current_ts
				record.save()
			else:
				EtheremonDB.EmaPlayerEnergyTab.objects.create(
					trainer=sender,
					init_amount=0,
					free_amount=free_amount,
					paid_amount=paid_amount,
					consumed_amount=0,
					last_claim_time=last_claim,
					create_time=current_ts,
					update_time=current_ts
				)

	# check revenue
	if site_id_set:
		for site_id in site_id_set:
			site_revenue = adventure_data_contract.call().getLandRevenue(site_id)
			log.info("update_site_revenue|site_id=%s,revenue=%s", site_id, site_revenue)
			if site_revenue[0] > 0 or site_revenue[1] > 0:
				emont_amount = (1.0 * site_revenue[0]) / 10**8
				eth_amount = (1.0 * site_revenue[1]) / 10**18
				site_revenue_record = EtheremonDB.EmaAdventureRevenueSiteTab.objects.filter(site_id=site_id).first()
				if not site_revenue_record:
					EtheremonDB.EmaAdventureRevenueSiteTab.objects.create(
						site_id=site_id,
						eth_amount=eth_amount,
						emont_amount=emont_amount,
						update_time=current_ts
					)
				else:
					if site_revenue_record.eth_amount < eth_amount:
						site_revenue_record.eth_amount = eth_amount
					if site_revenue_record.emont_amount < emont_amount:
						site_revenue_record.emont_amount = emont_amount
					site_revenue_record.update_time = current_ts
					site_revenue_record.save()

	# reload sender
	if deck_sender_set:
		log.info("update_deck_erc20|len_sender=%s,latest_load_block=%s", len(deck_sender_set), latest_load_block)
		data_contract = infura_client.getDataContract()
		for player in deck_sender_set:
			result = _sync_player_dex(data_contract, player)
			if result is False:
				log.warn("sync_player_fail|player=%s", player)

	record_block = latest_load_block
	if len(transaction_list) > 0:
		record_block += 1
		if record_block > current_block:
			record_block = current_block

	ema_settings_manager.set_setting(EmaSetting.SETTING_CONTRACT_ERC20_BLOCK, record_block)
	elapsed = time.time() - start_time
	if elapsed < 5:
		time.sleep(5-elapsed)
	log.data("end_update_erc20_contract|record_block=%s,total_txn=%s,total_egg_sender=%s,total_energy_sender=%s,elapsed=%s",
		record_block, len(transaction_list), len(egg_sender_set), len(energy_sender_set), elapsed)
def update_energy_contract():
    infura_client = InfuraClient(INFURA_API_URL)
    current_block = infura_client.getCurrentBlock() - 2

    start_block = ema_settings_manager.get_setting_value(
        EmaSetting.SETTING_CONTRACT_ENERGY_BLOCK)
    end_block = start_block + SMART_CONTRACT_BLOCK_STEP

    start_time = time.time()
    transaction_list = get_txn_list(EtheremonEnergyContract.ADDRESS,
                                    start_block, end_block, ETHERSCAN_API_KEY)
    if transaction_list is None:
        return

    log.data(
        "start_update_energy_contract|current_block=%s,start_block=%s,end_block=%s,len_txn=%s",
        current_block, start_block, end_block, len(transaction_list))
    '''
	if len(transaction_list) > 50:
		log.data("update_energy|cut_down_txn|current_block=%s,start_block=%s,end_block=%s", current_block, start_block, end_block)
		transaction_list = transaction_list[:50]
	'''

    latest_load_block = start_block
    sender_set = set()
    for transaction in transaction_list:
        if len(transaction["input"]) < SMART_CONTRACT_METHOD_ID_LENGTH:
            log.warn("invalid_smart_contract_txn|transaction=%s", transaction)
            continue
        if int(transaction.get("isError", 1)) != 0:
            continue
        if int(transaction.get("txreceipt_status")) != 1:
            continue

        latest_load_block = max(latest_load_block,
                                int(transaction["blockNumber"]))
        if latest_load_block > current_block:
            return
        sender = str(transaction["from"]).lower()
        sender_set.add(sender)
        log.info("update_energy_contract|txn_hash=%s,sender=%s",
                 transaction["hash"], sender)

    if sender_set:
        time.sleep(5)
        log.info("update_energy_contract|len_sender=%s,latest_load_block=%s",
                 len(sender_set), latest_load_block)
        energy_contract = infura_client.getEnergyContract()
        current_ts = get_timestamp()
        for sender in sender_set:
            (free_amount, paid_amount,
             last_claim) = energy_contract.call().getPlayerEnergy(sender)
            log.info(
                "player_energy_update|sender=%s,current_block=%s,free_amount=%s,paid_amount=%s,last_claim=%s",
                sender, current_block, free_amount, paid_amount, last_claim)
            record = EtheremonDB.EmaPlayerEnergyTab.objects.filter(
                trainer=sender).first()
            if record:
                if free_amount > record.free_amount:
                    latest_gap = free_amount - record.free_amount
                    new_available_energy = record.init_amount + free_amount + record.paid_amount - record.consumed_amount - record.invalid_amount
                    if new_available_energy > 50:
                        deducted_amount = new_available_energy - 50
                        if deducted_amount > latest_gap:
                            record.invalid_amount += latest_gap
                        else:
                            record.invalid_amount += deducted_amount
                record.free_amount = free_amount
                record.paid_amount = paid_amount
                record.last_claim_time = last_claim
                record.update_time = current_ts
                record.save()
            else:
                EtheremonDB.EmaPlayerEnergyTab.objects.create(
                    trainer=sender,
                    init_amount=0,
                    free_amount=free_amount,
                    paid_amount=paid_amount,
                    invalid_amount=0,
                    consumed_amount=0,
                    last_claim_time=last_claim,
                    create_time=current_ts,
                    update_time=current_ts)

    record_block = latest_load_block
    if len(transaction_list) > 0:
        record_block += 1
        if record_block > current_block:
            record_block = current_block

    ema_settings_manager.set_setting(EmaSetting.SETTING_CONTRACT_ENERGY_BLOCK,
                                     record_block)
    elapsed = time.time() - start_time
    if elapsed < 5:
        time.sleep(5 - elapsed)
    log.data(
        "end_update_energy_contract|record_block=%s,total_txn=%s,total_player=%s,elapsed=%s",
        record_block, len(transaction_list), len(sender_set), elapsed)
def update_erc721_contract():
    infura_client = InfuraClient(INFURA_API_URL)
    current_block = infura_client.getCurrentBlock() - 2

    start_block = ema_settings_manager.get_setting_value(
        EmaSetting.SETTING_CONTRACT_ERC721_BLOCK)
    end_block = start_block + SMART_CONTRACT_BLOCK_STEP

    start_time = time.time()
    transaction_list = get_txn_list(EtheremonERC721Contract.ADDRESS,
                                    start_block, end_block, ETHERSCAN_API_KEY)
    if transaction_list is None:
        return

    log.data(
        "start_update_erc721_contract|current_block=%s,start_block=%s,end_block=%s,len_txn=%s",
        current_block, start_block, end_block, len(transaction_list))

    latest_load_block = start_block
    sender_set = set()
    for transaction in transaction_list:
        if len(transaction["input"]) < SMART_CONTRACT_METHOD_ID_LENGTH:
            log.warn("invalid_smart_contract_txn|transaction=%s", transaction)
            continue
        if int(transaction.get("isError", 1)) != 0:
            continue
        if int(transaction.get("txreceipt_status")) != 1:
            continue

        latest_load_block = max(latest_load_block,
                                int(transaction["blockNumber"]))
        if latest_load_block > current_block:
            return
        sender = str(transaction["from"]).lower()
        sender_set.add(sender)
        log.info("update_erc721|txn_hash=%s,sender=%s", transaction["hash"],
                 sender)

    if sender_set:
        log.info("update_erc721|len_sender=%s,latest_load_block=%s",
                 len(sender_set), latest_load_block)
        data_contract = infura_client.getDataContract()
        for player in sender_set:
            result = _sync_player_dex(data_contract, player)
            if result is False:
                log.warn("sync_player_fail|player=%s", player)
                return

    record_block = latest_load_block
    if len(transaction_list) > 0:
        record_block += 1
        if record_block > current_block:
            record_block = current_block

    ema_settings_manager.set_setting(EmaSetting.SETTING_CONTRACT_ERC721_BLOCK,
                                     record_block)
    elapsed = time.time() - start_time
    if elapsed < 5:
        time.sleep(5 - elapsed)
    log.data(
        "end_update_erc721_contract|record_block=%s,total_txn=%s,total_player=%s,elapsed=%s",
        record_block, len(transaction_list), len(sender_set), elapsed)
def update_worldnft_contract():
	infura_client = InfuraClient(INFURA_API_URL)
	current_block = infura_client.getCurrentBlock() - 2

	start_block = ema_settings_manager.get_setting_value(EmaSetting.SETTING_CONTRACT_WORLD_NFT_BLOCK)
	end_block = start_block + SMART_CONTRACT_BLOCK_STEP

	start_time = time.time()
	transaction_list = get_txn_list(EtheremonWorldNFTContract.ADDRESS, start_block, end_block, ETHERSCAN_API_KEY)
	if transaction_list is None:
		return

	log.data("start_update_worldnft_contract|current_block=%s,start_block=%s,end_block=%s,len_txn=%s", current_block, start_block, end_block, len(transaction_list))

	latest_load_block = start_block
	sender_set = set()
	for transaction in transaction_list:
		if len(transaction["input"]) < SMART_CONTRACT_METHOD_ID_LENGTH:
			log.warn("invalid_smart_contract_txn|transaction=%s", transaction)
			continue
		if int(transaction.get("isError", 1)) != 0:
			continue
		if int(transaction.get("txreceipt_status")) != 1:
			continue

		latest_load_block = max(latest_load_block, int(transaction["blockNumber"]))
		if latest_load_block > current_block:
			return
		sender = str(transaction["from"]).lower()
		sender_set.add(sender)
		log.info("update_worldnft|txn_hash=%s,sender=%s", transaction["hash"], sender)
		method_id = transaction["input"][0:SMART_CONTRACT_METHOD_ID_LENGTH]

		if method_id == CATCH_MONSTER_NFT_METHOD_ID:

			monster_class_id_hash = "0x" + transaction["input"][SMART_CONTRACT_METHOD_ID_LENGTH:SMART_CONTRACT_METHOD_ID_LENGTH + 64]
			monster_class_id = Web3.toInt(hexstr=monster_class_id_hash)

			current_ts = get_timestamp()
			trainer_address = str(transaction["from"]).lower()
			trainer_record = EtheremonDB.WorldTrainerTab.objects.filter(trainer=trainer_address).first()
			monster_create_time = int(transaction["timeStamp"])
			if not trainer_record:
				extra_data = [(monster_class_id, monster_create_time)]
				flag = WorldTrainerFlag.NONE
				if monster_class_id not in FREE_MONSTER_CLASS_IDS:
					flag = WorldTrainerFlag.SPEND_ETH
				EtheremonDB.WorldTrainerTab.objects.create(
					trainer=trainer_address,
					flag=flag,
					extra_data=json.dumps(extra_data),
					create_time=current_ts,
					update_time=current_ts
				)
			else:
				extra_data = json.loads(trainer_record.extra_data)
				existed = False
				for pair in extra_data:
					if pair[0] == monster_class_id and pair[1] == monster_create_time:
						existed = True
						break
				if existed:
					continue
				extra_data.append((monster_class_id, monster_create_time))
				if monster_class_id not in FREE_MONSTER_CLASS_IDS:
					trainer_record.flag = WorldTrainerFlag.SPEND_ETH
				trainer_record.extra_data = json.dumps(extra_data)
				trainer_record.update_time = current_ts
				trainer_record.save()
			log.data("player_catch_monster|address=%s,class_id=%s", trainer_address, monster_class_id)

	if sender_set:
		log.info("update_worldnft|len_sender=%s,latest_load_block=%s", len(sender_set), latest_load_block)
		data_contract = infura_client.getDataContract()
		for player in sender_set:
			result = _sync_player_dex(data_contract, player)
			if result is False:
				log.warn("sync_player_fail|player=%s", player)
				return

	record_block = latest_load_block
	if len(transaction_list) > 0:
		record_block += 1
		if record_block > current_block:
			record_block = current_block

	ema_settings_manager.set_setting(EmaSetting.SETTING_CONTRACT_WORLD_NFT_BLOCK, record_block)
	elapsed = time.time() - start_time
	if elapsed < 5:
		time.sleep(5-elapsed)
	log.data("end_update_worldnft_contract|record_block=%s,total_txn=%s,total_player=%s,elapsed=%s",
		record_block, len(transaction_list), len(sender_set), elapsed)
Beispiel #16
0
def crawl_market():
    infura_client = InfuraClient(INFURA_API_URL)
    trade_contract = infura_client.getTradeContract()

    total_sell = trade_contract.call().getTotalSellingMonsters()
    total_borrow = trade_contract.call().getTotalBorrowingMonsters()
    current_block_number = infura_client.getCurrentBlock()
    log.data(
        "start_crawl_market|total_sell=%s,total_borrow=%s,block_number=%s",
        total_sell, total_borrow, current_block_number)

    # clear all table
    EtheremonDB.EmaMarketTab.objects.filter(id__gte=0).delete()

    # clone sell
    current_ts = get_timestamp()
    index = 0
    while index < total_sell:
        try:
            (obj_id, class_id, exp, bp, trainer, create_index, price,
             create_time) = trade_contract.call().getSellingItem(index)
        except Exception as error:
            log.warn("query_sell_data_error|index=%s,error=%s", index,
                     error.message)
            time.sleep(5)
            infura_client = InfuraClient(INFURA_API_URL)
            trade_contract = infura_client.getTradeContract()
            continue

        price = price / MARKET_PRICE_DIVISION
        extra_data = {}

        EtheremonDB.EmaMarketTab.objects.create(
            type=EmaMarketType.SELL,
            player=trainer,
            monster_id=obj_id,
            price=price,
            status=EmaMarketStatus.NONE,
            extra_data=json.dumps(extra_data),
            create_time=create_time)
        index += 1

    # clone borrow
    index = 0
    while index < total_borrow:
        try:
            (obj_id, owner, borrower, price, lent, create_time,
             release_time) = trade_contract.call().getBorrowingItem(index)
        except Exception as error:
            log.warn("query_borrow_data_error|index=%s,error=%s", index,
                     error.message)
            time.sleep(5)
            infura_client = InfuraClient(INFURA_API_URL)
            trade_contract = infura_client.getTradeContract()
            continue

        owner = owner.lower()
        price = price / MARKET_PRICE_DIVISION
        extra_data = {
            "borrower": borrower,
            "create_time": create_time,
            "release_time": release_time
        }
        status = EmaMarketStatus.NONE
        if lent:
            status = EmaMarketStatus.LENT

        EtheremonDB.EmaMarketTab.objects.create(
            type=EmaMarketType.BORROW,
            player=owner,
            monster_id=obj_id,
            price=price,
            status=status,
            extra_data=json.dumps(extra_data),
            create_time=create_time)
        index += 1

    log.data("end_crawl_market|block=%s,elapsed=%s", current_block_number,
             time.time() - current_ts)
def update_adventure_revenue_contract():
    infura_client = InfuraClient(INFURA_API_URL)
    current_block = infura_client.getCurrentBlock() - 2

    start_block = ema_settings_manager.get_setting_value(
        EmaSetting.SETTING_CONTRACT_ADVENTURE_REVENUE_BLOCK)
    end_block = start_block + SMART_CONTRACT_BLOCK_STEP

    start_time = time.time()
    transaction_list = get_txn_list(EtheremonAdventureRevenueContract.ADDRESS,
                                    start_block, end_block, ETHERSCAN_API_KEY)
    if transaction_list is None:
        return

    log.data(
        "start_update_adventure_revenue_contract|current_block=%s,start_block=%s,end_block=%s,len_txn=%s",
        current_block, start_block, end_block, len(transaction_list))

    latest_load_block = start_block
    current_ts = get_timestamp()
    adventure_data_contract = infura_client.getAdventureDataContract()
    token_id_set = set()
    for transaction in transaction_list:
        if len(transaction["input"]) < SMART_CONTRACT_METHOD_ID_LENGTH:
            log.warn("invalid_smart_contract_txn|transaction=%s", transaction)
            continue
        if int(transaction.get("isError", 1)) != 0:
            continue
        if int(transaction.get("txreceipt_status")) != 1:
            continue

        log.info("update_adventure_revenue_contract|txn_hash=%s",
                 transaction["hash"])

        latest_load_block = max(latest_load_block,
                                int(transaction["blockNumber"]))
        if latest_load_block > current_block:
            return
        method_id = transaction["input"][0:SMART_CONTRACT_METHOD_ID_LENGTH]

        sender = str(transaction["from"]).lower()

        if method_id == ADVENTURE_CLAIM_EARNING_METHOD:
            token_id_hash = "0x" + transaction[
                "input"][SMART_CONTRACT_METHOD_ID_LENGTH:
                         SMART_CONTRACT_METHOD_ID_LENGTH + 64]
            token_id = Web3.toInt(hexstr=token_id_hash)
            token_id_set.add(token_id)
            log.info("claim_earning|sender=%s,token_id=%s,txn_hash=%s", sender,
                     token_id, transaction["hash"])

    if token_id_set:
        for token_id in token_id_set:
            claim_data = adventure_data_contract.call().getTokenClaim(token_id)
            eth_amount = 1.0 * claim_data[1] / 10**18
            emont_amount = 1.0 * claim_data[0] / 10**8
            claim_record = EtheremonDB.EmaAdventureClaimTokenTab.objects.filter(
                token_id=token_id).first()
            if not claim_record:
                EtheremonDB.EmaAdventureClaimTokenTab.objects.create(
                    token_id=token_id,
                    claimed_eth_amount=eth_amount,
                    claimed_emont_amount=emont_amount,
                    update_time=current_ts)
            else:
                if claim_record.claimed_eth_amount < eth_amount:
                    claim_record.claimed_eth_amount = eth_amount
                if claim_record.claimed_emont_amount < emont_amount:
                    claim_record.claimed_emont_amount = emont_amount
                claim_record.update_time = current_ts
                claim_record.save()

    record_block = latest_load_block
    if len(transaction_list) > 0:
        record_block += 1
        if record_block > current_block:
            record_block = current_block

    ema_settings_manager.set_setting(
        EmaSetting.SETTING_CONTRACT_ADVENTURE_REVENUE_BLOCK, record_block)
    elapsed = time.time() - start_time
    if elapsed < 5:
        time.sleep(5 - elapsed)
    log.data(
        "end_update_adventure_contract|record_block=%s,total_txn=%s,elapsed=%s",
        record_block, len(transaction_list), elapsed)
Beispiel #18
0
def crawl_rank_data():
    start_time = time.time()

    infura_client = InfuraClient(INFURA_API_URL)
    rank_data_contract = infura_client.getRankDataContract()
    rank_reward_contract = infura_client.getRankRewardContract()
    ladder_contract = infura_client.getLadderContract()

    current_block = infura_client.getCurrentBlock()
    total_player = rank_data_contract.call().totalPlayer()

    log.data("start_crawl_rank_data|total=%s,block_number=%s", total_player,
             current_block)

    for index in range(total_player):
        player_id = index + 1
        player_contract_data = rank_data_contract.call().getPlayerData(
            player_id)
        if not player_contract_data[4]:
            log.warn("invalid_contract_data|player_contract_data=%s",
                     player_contract_data)
            continue

        player_record = get_rank_data(player_id)
        if not player_record:
            player_record = EtheremonDB.UserLadderTab(player_id=player_id)
        trainer_address = player_contract_data[0]
        trainer_address = trainer_address.lower()
        player_record.trainer = trainer_address
        player_record.point = player_contract_data[3]
        player_record.total_win = player_contract_data[1]
        player_record.total_lose = player_contract_data[2]
        player_record.a0 = player_contract_data[4]
        player_record.a1 = player_contract_data[5]
        player_record.a2 = player_contract_data[6]
        player_record.s0 = player_contract_data[7] if player_contract_data[
            7] else 0
        player_record.s1 = player_contract_data[8] if player_contract_data[
            8] else 0
        player_record.s2 = player_contract_data[9] if player_contract_data[
            9] else 0

        # total claim match
        total_win_claim = rank_reward_contract.call().getWinClaim(player_id)
        player_record.total_match = player_record.total_win + player_record.total_lose + total_win_claim

        # calculate avg bp
        total_bp = ladder_contract.call().getMonsterCP(player_record.a0)
        total_bp += ladder_contract.call().getMonsterCP(player_record.a1)
        total_bp += ladder_contract.call().getMonsterCP(player_record.a2)

        # calculate avg level
        total_level = 0
        level_info = ladder_contract.call().getMonsterLevel(player_record.a0)
        total_level += level_info[1]
        level_info = ladder_contract.call().getMonsterLevel(player_record.a1)
        total_level += level_info[1]
        level_info = ladder_contract.call().getMonsterLevel(player_record.a2)
        total_level += level_info[1]

        player_record.avg_bp = total_bp / 3
        player_record.avg_level = total_level / 3

        player_record.energy = player_contract_data[10]
        player_record.last_claim = player_contract_data[11]
        player_record.update_time = get_timestamp()
        player_record.save()

    elapsed = time.time() - start_time
    log.data("end_crawl_rank_data|elapsed=%s,total_player=%s,start_block=%s",
             elapsed, total_player, current_block)
Beispiel #19
0
def update_claim_contract():
    infura_client = InfuraClient(INFURA_API_URL)
    current_block = infura_client.getCurrentBlock() - 5

    start_block = ema_settings_manager.get_setting_value(
        EmaSetting.SETTING_CONTRACT_CLAIM_BLOCK)
    end_block = start_block + SMART_CONTRACT_BLOCK_STEP

    start_time = time.time()
    transaction_list = get_txn_list(EtheremonClaimContract.ADDRESS,
                                    start_block, end_block, ETHERSCAN_API_KEY)
    if transaction_list is None:
        return

    log.data(
        "start_update_claim_contract|current_block=%s,start_block=%s,end_block=%s,len_txn=%s",
        current_block, start_block, end_block, len(transaction_list))

    latest_load_block = start_block
    monster_id_set = set()
    for transaction in transaction_list:
        if len(transaction["input"]) < SMART_CONTRACT_METHOD_ID_LENGTH:
            log.warn("invalid_smart_contract_txn|transaction=%s", transaction)
            continue
        if int(transaction.get("isError", 1)) != 0:
            continue
        if int(transaction.get("txreceipt_status")) != 1:
            continue

        latest_load_block = max(latest_load_block,
                                int(transaction["blockNumber"]))
        if latest_load_block > current_block:
            return

        method_id = transaction["input"][0:SMART_CONTRACT_METHOD_ID_LENGTH]

        if method_id == CLAIM_MONSTER_EXP_METHOD:
            token_bytes = transaction[
                "input"][SMART_CONTRACT_METHOD_ID_LENGTH:
                         SMART_CONTRACT_METHOD_ID_LENGTH + 64]
            token = token_bytes.decode("hex")
            token_data = decode_claim_exp_token(token)
            request_id = token_data["request_id"]
            monster_id = token_data["monster_id"]

            result = proceed_pending_exp_claim(request_id)
            monster_id_set.add(monster_id)
            log.info(
                "process_exp_claim|request_id=%s,result=%s,txn_hash=%s,monster_id=%s",
                request_id, result, transaction["hash"], monster_id)
        elif method_id == CLAIM_WIN_RANK_METHOD:
            token_bytes = transaction[
                "input"][SMART_CONTRACT_METHOD_ID_LENGTH:
                         SMART_CONTRACT_METHOD_ID_LENGTH + 64]
            token = token_bytes.decode("hex")
            token_data = decode_claim_win_token(token)
            request_id = token_data["request_id"]
            try:
                result = proceed_pending_win_claim(request_id)
            except:
                logging.exception(
                    "process_win_claim_invalid|request_id=%s,txn_hash=%s",
                    request_id, transaction["hash"])
                continue
            log.info("process_win_claim|request_id=%s,result=%s,txn_hash=%s",
                     request_id, result, transaction["hash"])
        elif method_id == CLAIM_TOP_RANK_METHOD:
            token_bytes = transaction[
                "input"][SMART_CONTRACT_METHOD_ID_LENGTH:
                         SMART_CONTRACT_METHOD_ID_LENGTH + 64]
            token = token_bytes.decode("hex")
            token_data = decode_claim_top_token(token)
            request_id = token_data["request_id"]

            result = proceed_pending_top_claim(request_id)
            log.info("process_top_claim|request_id=%s,result=%s,txn_hash=%s",
                     request_id, result, transaction["hash"])

    # update monster id
    if monster_id_set:
        log.info(
            "update_claim_contract|monster_len=%s,latest_load_block=%s,current_block=%s",
            len(monster_id_set), latest_load_block, current_block)
        data_contract = infura_client.getDataContract()
        for monster_id in monster_id_set:
            result, add_flag, update_flag = _sync_monster_id(
                data_contract, monster_id)
            if result is False:
                return

    record_block = latest_load_block
    if len(transaction_list) > 0:
        record_block += 1
        if record_block > current_block:
            record_block = current_block

    ema_settings_manager.set_setting(EmaSetting.SETTING_CONTRACT_CLAIM_BLOCK,
                                     record_block)
    elapsed = time.time() - start_time
    if elapsed < 5:
        time.sleep(5 - elapsed)
    log.data(
        "end_update_claim_contract|record_block=%s,total_txn=%s,total_monster=%s,elapsed=%s",
        record_block, len(transaction_list), len(monster_id_set), elapsed)