def get_rewards_for_cycle_map(self, cycle):
        current_level, current_cycle = self.__get_current_level()
        logger.debug("Current level {}, current cycle {}".format(current_level, current_cycle))

        reward_data = {}
        reward_data["delegate_staking_balance"], reward_data[
            "delegators"] = self.__get_delegators_and_delgators_balances(cycle, current_level)
        reward_data["delegators_nb"] = len(reward_data["delegators"])

        # Get last block in cycle where rewards are unfrozen
        level_of_last_block_in_unfreeze_cycle = (cycle + self.preserved_cycles + 1) * self.blocks_per_cycle

        logger.debug("Cycle {}, preserved cycles {}, blocks per cycle {}, last block of cycle {}"
                     .format(cycle, self.preserved_cycles, self.blocks_per_cycle, level_of_last_block_in_unfreeze_cycle))

        if current_level - level_of_last_block_in_unfreeze_cycle >= 0:
            unfrozen_fees, unfrozen_rewards = self.__get_unfrozen_rewards(level_of_last_block_in_unfreeze_cycle, cycle)
            reward_data["total_rewards"] = unfrozen_fees + unfrozen_rewards

        else:
            logger.warn("Please wait until the rewards and fees for cycle {} are unfrozen".format(cycle))
            reward_data["total_rewards"] = 0

        reward_model = RewardProviderModel(reward_data["delegate_staking_balance"], reward_data["total_rewards"],
                                           reward_data["delegators"])

        logger.debug("delegate_staking_balance = {}, total_rewards = {}"
                     .format(reward_data["delegate_staking_balance"], reward_data["total_rewards"]))
        logger.debug("delegators = {}".format(reward_data["delegators"]))

        return reward_model
Esempio n. 2
0
    def get_rewards_for_cycle_map(self, cycle):
        root = self.helper.get_rewards_for_cycle(cycle, self.verbose)

        delegate_staking_balance = int(root["delegate_staking_balance"])
        blocks_rewards = int(root["blocks_rewards"])
        future_blocks_rewards = int(root["future_blocks_rewards"])
        endorsements_rewards = int(root["endorsements_rewards"])
        future_endorsements_rewards = int(root["future_endorsements_rewards"])
        lost_rewards_denounciation = int(
            root["lost_rewards_denounciation_baking"]) + int(
                root["lost_rewards_denounciation_endorsement"])
        lost_fees_denounciation = int(
            root["lost_fees_denounciation_baking"]) + int(
                root["lost_fees_denounciation_endorsement"])
        fees = int(root["fees"])

        total_reward_amount = (blocks_rewards + endorsements_rewards +
                               future_blocks_rewards +
                               future_endorsements_rewards + fees -
                               lost_rewards_denounciation -
                               lost_fees_denounciation)

        delegators_balance = root["delegators_balance"]

        delegator_balance_dict = {}
        for dbalance in delegators_balance:
            address = dbalance[0]["tz"]
            balance = int(dbalance[1])

            delegator_balance_dict[address] = balance

        return RewardProviderModel(delegate_staking_balance,
                                   total_reward_amount, delegator_balance_dict)
Esempio n. 3
0
    def get_rewards_for_cycle_map(self, cycle, verbose=False):

        reward_data = {}

        reward_data["delegate_staking_balance"], reward_data[
            "delegators"] = self.__get_delegators_and_delgators_balance(
                cycle, verbose)
        reward_data["delegators_nb"] = len(reward_data["delegators"])

        current_level, head_hash, current_cycle = self.__get_current_level(
            verbose)

        logger.debug("Current level {}, head hash {}".format(
            current_level, head_hash))

        # Get last block in cycle where rewards are unfrozen
        level_for_relevant_request = (
            cycle + self.preserved_cycles + 1 -
            self.cycle_offset) * self.blocks_per_cycle

        logger.debug(
            "Cycle {}, preserved cycles {}, blocks per cycle {}, level of interest {}"
            .format(cycle, self.preserved_cycles, self.blocks_per_cycle,
                    level_for_relevant_request))

        if current_level - level_for_relevant_request >= 0:
            request_metadata = COMM_BLOCK.format(
                self.node_url, head_hash,
                current_level - level_for_relevant_request) + '/metadata/'
            _, response_metadata = self.wllt_clnt_mngr.send_request(
                request_metadata)
            metadata = parse_json_response(response_metadata)
            balance_updates = metadata["balance_updates"]

            unfrozen_rewards = unfrozen_fees = 0
            for i in range(len(balance_updates)):
                balance_update = balance_updates[i]
                if balance_update["kind"] == "freezer":
                    if balance_update["delegate"] == self.baking_address:
                        if balance_update["category"] == "rewards":
                            unfrozen_rewards = -int(balance_update["change"])
                        elif balance_update["category"] == "fees":
                            unfrozen_fees = -int(balance_update["change"])
            reward_data["total_rewards"] = unfrozen_rewards + unfrozen_fees

        else:
            logger.warn(
                "Please wait until the rewards and fees for cycle {} are unfrozen"
                .format(cycle))
            reward_data["total_rewards"] = 0

        reward_model = RewardProviderModel(
            reward_data["delegate_staking_balance"],
            reward_data["total_rewards"], reward_data["delegators"])

        if self.validate:
            self.__validate_reward_data(reward_model, cycle)

        return reward_model
Esempio n. 4
0
    def get_rewards_for_cycle_map(self, cycle, expected_reward = False):
        root = self.helper.get_rewards_for_cycle(cycle, expected_reward, self.verbose)

        delegate_staking_balance = root["delegate_staking_balance"]
        total_reward_amount = root["total_reward_amount"]
        delegators_balances_dict = root["delegators_balances"]

        return RewardProviderModel(delegate_staking_balance, total_reward_amount, delegators_balances_dict)
    def get_rewards_for_cycle_map(self, cycle, expected_reward=False):
        root = self.helper.get_rewards_for_cycle(cycle, expected_reward)

        delegate_staking_balance = root["delegate_staking_balance"]
        total_reward_amount = root["total_reward_amount"]
        delegators_balances_dict = root["delegators_balances"]

        snapshot_level = self.helper.get_snapshot_level(cycle)
        for delegator in self.dexter_contracts_set:
            dxtz.process_original_delegators_map(delegators_balances_dict,
                                                 delegator, snapshot_level,
                                                 self.helper)

        return RewardProviderModel(delegate_staking_balance,
                                   total_reward_amount,
                                   delegators_balances_dict)
    def get_rewards_for_cycle_map(self, cycle):
        try:
            current_level, current_cycle = self.__get_current_level()
            logger.debug("Current level {:d}, current cycle {:d}".format(current_level, current_cycle))

            reward_data = {}
            reward_data["delegate_staking_balance"], reward_data[
                "delegators"] = self.__get_delegators_and_delgators_balances(cycle, current_level)
            reward_data["delegators_nb"] = len(reward_data["delegators"])

            # Get last block in cycle where rewards are unfrozen
            level_of_last_block_in_unfreeze_cycle = (cycle + self.preserved_cycles + 1) * self.blocks_per_cycle

            logger.debug("Cycle {:d}, preserved cycles {:d}, blocks per cycle {:d}, last block of cycle {:d}"
                         .format(cycle, self.preserved_cycles, self.blocks_per_cycle,
                                 level_of_last_block_in_unfreeze_cycle))

            if current_level - level_of_last_block_in_unfreeze_cycle >= 0:
                unfrozen_fees, unfrozen_rewards = self.__get_unfrozen_rewards(level_of_last_block_in_unfreeze_cycle, cycle)
                reward_data["total_rewards"] = unfrozen_fees + unfrozen_rewards
            else:
                logger.warning("Please wait until the rewards and fees for cycle {:d} are unfrozen".format(cycle))
                reward_data["total_rewards"] = 0

            _, snapshot_level = self.__get_roll_snapshot_block_level(cycle, current_level)
            for delegator in self.dexter_contracts_set:
                dxtz.process_original_delegators_map(reward_data["delegators"], delegator, snapshot_level)

            reward_model = RewardProviderModel(reward_data["delegate_staking_balance"], reward_data["total_rewards"],
                                               reward_data["delegators"])

            logger.debug("delegate_staking_balance = {:d}, total_rewards = {:d}"
                         .format(reward_data["delegate_staking_balance"], reward_data["total_rewards"]))
            logger.debug("delegators = {}".format(reward_data["delegators"]))

            return reward_model

        except Exception as e:
            # We should abort here on any exception as we did not fetch all
            # necessary data to properly compute rewards
            raise e from e
    def get_rewards_for_cycle_map(self, cycle, rewards_type):

        root = self.helper.get_rewards_for_cycle(cycle)

        delegate_staking_balance = root["delegate_staking_balance"]
        num_baking_rights = root["num_baking_rights"]
        num_endorsing_rights = root["num_endorsing_rights"]
        delegators_balances_dict = root["delegators_balances"]
        rewards_and_fees = root["rewards_and_fees"]
        equivocation_losses = root["equivocation_losses"]
        denunciation_rewards = root["denunciation_rewards"]
        total_reward_amount = (
            rewards_and_fees - equivocation_losses + denunciation_rewards
        )
        offline_losses = root["offline_losses"]

        snapshot_level = self.helper.get_snapshot_level(cycle)
        for delegator in self.dexter_contracts_set:
            if delegator in delegators_balances_dict:
                dxtz.process_original_delegators_map(
                    delegators_balances_dict, delegator, snapshot_level, self.helper
                )
            else:
                logger.warning(
                    f"The configured Dexter account {delegator} is not delegated to {self.helper.baking_address} "
                    f"at snapshot level {snapshot_level} corresponding to payout cycle {cycle} or has a zero rewards"
                )

        return RewardProviderModel(
            delegate_staking_balance,
            num_baking_rights,
            num_endorsing_rights,
            total_reward_amount,
            rewards_and_fees,
            equivocation_losses,
            denunciation_rewards,
            offline_losses,
            delegators_balances_dict,
            None,
        )
Esempio n. 8
0
    def get_rewards_for_cycle_map(self, cycle, expected_reward=False):

        root = self.helper.get_rewards_for_cycle(cycle, expected_reward)

        delegate_staking_balance = root["delegate_staking_balance"]
        total_reward_amount = root["total_reward_amount"]
        delegators_balances_dict = root["delegators_balances"]

        snapshot_level = self.helper.get_snapshot_level(cycle)
        for delegator in self.dexter_contracts_set:
            if delegator in delegators_balances_dict:
                dxtz.process_original_delegators_map(delegators_balances_dict,
                                                     delegator, snapshot_level,
                                                     self.helper)
            else:
                logger.warning(
                    f"The configured Dexter account {delegator} is not delegated to {self.helper.baking_address} "
                    f"at snapshot level {snapshot_level} corresponding to payout cycle {cycle} or has a zero rewards"
                )

        return RewardProviderModel(delegate_staking_balance,
                                   total_reward_amount,
                                   delegators_balances_dict)
Esempio n. 9
0
    def get_rewards_for_cycle_map(self, cycle,
                                  rewards_type) -> RewardProviderModel:
        """
        Returns reward split in a specified format
        :param cycle:
        :return: RewardProviderModel(
            delegate_staking_balance=5265698993303,
            num_blocks=333,
            num_endorsements=3333,
            delegators_balances={
                'tz1azSbB91MbdcEquhsmJvjVroLs5t4kpdCn': {
                    'staking_balance': 1935059821,
                    'current_balance': 1977503559
                }
            }

        )
        """
        split = self.api.get_reward_split(address=self.baking_address,
                                          cycle=cycle,
                                          fetch_delegators=True)

        delegate_staking_balance = split["stakingBalance"]

        # calculate estimated rewards
        num_blocks = (split["ownBlocks"] + split["missedOwnBlocks"] +
                      split["uncoveredOwnBlocks"] + split["futureBlocks"])

        num_endorsements = (split["endorsements"] +
                            split["missedEndorsements"] +
                            split["uncoveredEndorsements"] +
                            split["futureEndorsements"])

        # rewards earned (excluding equivocation losses)
        rewards_and_fees = (split["ownBlockRewards"] +
                            split["extraBlockRewards"] +
                            split["endorsementRewards"] +
                            split["ownBlockFees"] + split["extraBlockFees"] +
                            split["revelationRewards"])
        denunciation_rewards = (split["doubleBakingRewards"] +
                                split["doubleEndorsingRewards"])
        equivocation_losses = (split["doubleBakingLostDeposits"] +
                               split["doubleBakingLostRewards"] +
                               split["doubleBakingLostFees"] +
                               split["doubleEndorsingLostDeposits"] +
                               split["doubleEndorsingLostRewards"] +
                               split["doubleEndorsingLostFees"] +
                               split["revelationLostRewards"] +
                               split["revelationLostFees"])
        total_reward_amount = max(
            0, rewards_and_fees + denunciation_rewards - equivocation_losses)
        # losses due to being offline or not having enough bond
        offline_losses = (
            split["missedOwnBlockRewards"] + split["missedExtraBlockRewards"] +
            split["uncoveredOwnBlockRewards"] +
            split["uncoveredExtraBlockRewards"] +
            split["missedEndorsementRewards"] +
            split["uncoveredEndorsementRewards"] +
            split["missedOwnBlockFees"] + split["missedExtraBlockFees"] +
            split["uncoveredOwnBlockFees"] + split["uncoveredExtraBlockFees"])

        delegators_balances = {
            item["address"]: {
                "staking_balance": item["balance"],
                "current_balance": item["currentBalance"],
            }
            for item in split["delegators"] if item["balance"] > 0
        }

        # TODO: support Dexter for TzKt
        # snapshot_level = self.api.get_snapshot_level(cycle)
        # for delegator in self.dexter_contracts_set:
        #    dxtz.process_original_delegators_map(delegators_balances, delegator, snapshot_level)

        return RewardProviderModel(
            delegate_staking_balance,
            num_blocks,
            num_endorsements,
            total_reward_amount,
            rewards_and_fees,
            equivocation_losses,
            denunciation_rewards,
            offline_losses,
            delegators_balances,
            None,
        )
    def get_rewards_for_cycle_map(self,
                                  cycle,
                                  expected_reward=False
                                  ) -> RewardProviderModel:
        """
        Returns reward split in a specified format
        :param cycle:
        :param expected_reward:
        :return: RewardProviderModel(
            delegate_staking_balance=5265698993303,
            total_reward_amount=2790471275,
            delegators_balances={
                'tz1azSbB91MbdcEquhsmJvjVroLs5t4kpdCn': {
                    'staking_balance': 1935059821,
                    'current_balance': 1977503559
                }
            }
        )
        """
        split = self.api.get_reward_split(address=self.baking_address,
                                          cycle=cycle,
                                          fetch_delegators=True)

        delegate_staking_balance = split['stakingBalance']

        if expected_reward:
            num_blocks = \
                split['ownBlocks'] \
                + split['missedOwnBlocks'] \
                + split['uncoveredOwnBlocks'] \
                + split['futureBlocks']

            num_endorsements = \
                split['endorsements'] \
                + split['missedEndorsements'] \
                + split['uncoveredEndorsements'] \
                + split['futureEndorsements']

            total_reward_amount = self.calc_expected_reward(
                cycle, num_blocks, num_endorsements)
        else:
            total_reward_amount = \
                split['ownBlockRewards'] \
                + split['extraBlockRewards'] \
                + split['endorsementRewards'] \
                + split['ownBlockFees'] \
                + split['extraBlockFees'] \
                + split['revelationRewards'] \
                + split['doubleBakingRewards'] \
                + split['doubleEndorsingRewards'] \
                - split['doubleBakingLostDeposits'] \
                - split['doubleBakingLostRewards'] \
                - split['doubleBakingLostFees'] \
                - split['doubleEndorsingLostDeposits'] \
                - split['doubleEndorsingLostRewards'] \
                - split['doubleEndorsingLostFees'] \
                - split['revelationLostRewards'] \
                - split['revelationLostFees']

            total_reward_amount = max(0, total_reward_amount)

        delegators_balances = {
            item['address']: {
                'staking_balance': item['balance'],
                'current_balance': item['currentBalance']
            }
            for item in split['delegators'] if item['balance'] > 0
        }

        # TODO: support Dexter for TzKt
        # snapshot_level = self.api.get_snapshot_level(cycle)
        # for delegator in self.dexter_contracts_set:
        #    dxtz.process_original_delegators_map(delegators_balances, delegator, snapshot_level)

        return RewardProviderModel(delegate_staking_balance,
                                   total_reward_amount, delegators_balances)
    def get_rewards_for_cycle_map(self, cycle, rewards_type):
        try:
            current_level, current_cycle = self.__get_current_level()
            logger.debug(
                "Current level {:d}, current cycle {:d}".format(
                    current_level, current_cycle
                )
            )

            reward_data = {}
            (
                reward_data["delegate_staking_balance"],
                reward_data["delegators"],
            ) = self.__get_delegators_and_delgators_balances(cycle, current_level)
            reward_data["delegators_nb"] = len(reward_data["delegators"])

            # Get last block in cycle where rewards are unfrozen
            if cycle >= FIRST_CYCLE_REWARDS_GRANADA:
                # Since cycle 394, we use an offset of 1589248 blocks (388 cycles pre-Granada of 4096 blocks each)
                # Cycles start at 0
                level_of_last_block_in_unfreeze_cycle = BLOCKS_BEFORE_GRANADA + (
                    (cycle - CYCLES_BEFORE_GRANADA + self.preserved_cycles + 1)
                    * self.blocks_per_cycle
                )
                level_of_first_block_in_preserved_cycles = BLOCKS_BEFORE_GRANADA + (
                    (cycle - CYCLES_BEFORE_GRANADA - self.preserved_cycles)
                    * self.blocks_per_cycle
                    + 1
                )
            else:
                # Using pre-Granada calculation
                level_of_last_block_in_unfreeze_cycle = (
                    cycle + self.preserved_cycles + 1
                ) * BLOCKS_PER_CYCLE_BEFORE_GRANADA
                level_of_first_block_in_preserved_cycles = (
                    cycle - self.preserved_cycles
                ) * BLOCKS_PER_CYCLE_BEFORE_GRANADA + 1

            logger.debug(
                "Cycle {:d}, preserved cycles {:d}, blocks per cycle {:d}, last block of cycle {:d}, "
                "last block unfreeze cycle {:d}".format(
                    cycle,
                    self.preserved_cycles,
                    self.blocks_per_cycle,
                    level_of_first_block_in_preserved_cycles,
                    level_of_last_block_in_unfreeze_cycle,
                )
            )

            # Determine how many priority 0 baking rights delegate had
            baking_rights = self.__get_baking_rights(
                cycle, level_of_first_block_in_preserved_cycles
            )
            endorsement_rights = self.__get_endorsement_rights(
                cycle, level_of_first_block_in_preserved_cycles
            )
            nb_blocks = len([r for r in baking_rights if r["priority"] == 0])
            nb_endorsements = sum([len(r["slots"]) for r in endorsement_rights])

            total_reward_amount = None
            if not rewards_type.isEstimated():
                # Calculate actual rewards
                if current_level - level_of_last_block_in_unfreeze_cycle >= 0:
                    unfrozen_fees, unfrozen_rewards = self.__get_unfrozen_rewards(
                        level_of_last_block_in_unfreeze_cycle, cycle
                    )
                    total_reward_amount = unfrozen_fees + unfrozen_rewards
                else:
                    frozen_fees, frozen_rewards = self.__get_frozen_rewards(
                        cycle, current_level
                    )
                    total_reward_amount = frozen_fees + frozen_rewards

            # Without an indexer, it is not possible to itemize rewards
            # so setting these values below to "None"
            rewards_and_fees = None
            equivocation_losses = None
            denunciation_rewards = None

            offline_losses = None
            if rewards_type.isIdeal():
                # Calculate offline losses
                missed_baking_income = 0
                for count, r in enumerate(baking_rights):
                    if count % 10 == 0:
                        logger.info(
                            "Verifying bake ({}/{}).".format(count, len(baking_rights))
                        )
                    if r["priority"] == 0:
                        if self.__get_block_author(r["level"]) != self.baking_address:
                            logger.warning(
                                "Found missed baking slot {}, adding {:<,d} mutez reward anyway.".format(
                                    r, self.block_reward
                                )
                            )
                            missed_baking_income += self.block_reward
                missed_endorsing_income = 0
                for count, r in enumerate(endorsement_rights):
                    if count % 10 == 0:
                        logger.info(
                            "Verifying endorsement ({}/{}).".format(
                                count, len(endorsement_rights)
                            )
                        )
                    authored_endorsement_slots = (
                        self.__get_authored_endorsement_slots_by_level(r["level"] + 1)
                    )
                    if authored_endorsement_slots != r["slots"]:
                        mutez_to_add = self.endorsement_reward * len(r["slots"])
                        logger.warning(
                            "Found {} missed endorsement(s) at level {}, adding {:<,d} mutez reward anyway.".format(
                                len(r["slots"]), r["level"], mutez_to_add
                            )
                        )
                        missed_endorsing_income += mutez_to_add
                offline_losses = missed_baking_income + missed_endorsing_income

            # TODO: support Dexter for RPC
            # _, snapshot_level = self.__get_roll_snapshot_block_level(cycle, current_level)
            # for delegator in self.dexter_contracts_set:
            #     dxtz.process_original_delegators_map(reward_data["delegators"], delegator, snapshot_level)

            reward_model = RewardProviderModel(
                reward_data["delegate_staking_balance"],
                nb_blocks,
                nb_endorsements,
                total_reward_amount,
                rewards_and_fees,
                equivocation_losses,
                denunciation_rewards,
                offline_losses,
                reward_data["delegators"],
                None,
            )

            logger.debug(
                "delegate_staking_balance = {:d}".format(
                    reward_data["delegate_staking_balance"]
                )
            )
            logger.debug("delegators = {}".format(reward_data["delegators"]))

            return reward_model

        except Exception as e:
            # We should abort here on any exception as we did not fetch all
            # necessary data to properly compute rewards
            raise e from e
    def get_rewards_for_cycle_map(self, cycle, expected_rewards=False):
        try:
            current_level, current_cycle = self.__get_current_level()
            logger.debug("Current level {:d}, current cycle {:d}".format(current_level, current_cycle))

            reward_data = {}
            reward_data["delegate_staking_balance"], reward_data[
                "delegators"] = self.__get_delegators_and_delgators_balances(cycle, current_level)
            reward_data["delegators_nb"] = len(reward_data["delegators"])

            # Get last block in cycle where rewards are unfrozen
            level_of_last_block_in_unfreeze_cycle = (cycle + self.preserved_cycles + 1) * self.blocks_per_cycle
            level_of_first_block_in_preserved_cycles = (cycle - self.preserved_cycles) * self.blocks_per_cycle + 1

            logger.debug("Cycle {:d}, preserved cycles {:d}, blocks per cycle {:d}, last block of cycle {:d}, "
                         "last block unfreeze cycle {:d}"
                         .format(cycle, self.preserved_cycles, self.blocks_per_cycle,
                                 level_of_first_block_in_preserved_cycles, level_of_last_block_in_unfreeze_cycle))

            # Decide on if paying actual rewards earned, or paying expected/ideal rewards
            if expected_rewards:

                # Determine how many priority 0 baking rights delegate had
                nb_blocks = self.__get_number_of_baking_rights(cycle, level_of_first_block_in_preserved_cycles)
                nb_endorsements = self.__get_number_of_endorsement_rights(cycle, level_of_first_block_in_preserved_cycles)

                logger.debug("Number of 0 priority blocks: {}, Number of endorsements: {}".format(nb_blocks, nb_endorsements))
                logger.debug("Block reward: {}, Endorsement Reward: {}".format(self.block_reward, self.endorsement_reward))

                # "ideally", the baker baked every priority 0 block they had rights for,
                # and every block they baked contained 32 endorsements
                total_block_reward = nb_blocks * self.block_reward
                total_endorsement_reward = nb_endorsements * self.endorsement_reward

                logger.info("Ideal rewards for cycle {:d}, {:,} block rewards ({:d} blocks), {:,} endorsing rewards ({:d} slots)".format(
                            cycle, total_block_reward, nb_blocks, total_endorsement_reward, nb_endorsements))

                reward_data["total_rewards"] = total_block_reward + total_endorsement_reward

            # Calculate actual rewards
            else:

                if current_level - level_of_last_block_in_unfreeze_cycle >= 0:
                    unfrozen_fees, unfrozen_rewards = self.__get_unfrozen_rewards(level_of_last_block_in_unfreeze_cycle, cycle)
                    reward_data["total_rewards"] = unfrozen_fees + unfrozen_rewards
                else:
                    logger.warning("Please wait until the rewards and fees for cycle {:d} are unfrozen".format(cycle))
                    reward_data["total_rewards"] = 0

            # TODO: support Dexter for RPC
            # _, snapshot_level = self.__get_roll_snapshot_block_level(cycle, current_level)
            # for delegator in self.dexter_contracts_set:
            #     dxtz.process_original_delegators_map(reward_data["delegators"], delegator, snapshot_level)

            reward_model = RewardProviderModel(reward_data["delegate_staking_balance"], reward_data["total_rewards"],
                                               reward_data["delegators"])

            logger.debug("delegate_staking_balance = {:d}, total_rewards = {:d}"
                         .format(reward_data["delegate_staking_balance"], reward_data["total_rewards"]))
            logger.debug("delegators = {}".format(reward_data["delegators"]))

            return reward_model

        except Exception as e:
            # We should abort here on any exception as we did not fetch all
            # necessary data to properly compute rewards
            raise e from e