def calculate(self, reward_logs=None, total_reward_amount=None):
        """
        :param reward_logs: Nothing is expected. This value is not used. reward_logs are generated from provider object.
        :param total_reward_amount: Nothing is expected. This value is not used. total amount is calculated in calling function.
        :return: tuple (reward_logs, total reward amount)

        reward_logs is a list of RewardLog objects. Last item is owners_parent record.
        total_reward equals to sum( delegator rewards + owners_parent rewards )
        """

        ratio_sum = 0.0
        total_delegator_balance = 0
        reward_logs = []
        delegate_staking_balance = self.reward_provider_model.delegate_staking_balance
        delegators_balance_dict = self.reward_provider_model.delegator_balance_dict

        # calculate how rewards will be distributed
        # ratio is stake/total staking balance
        # total of ratios must be 1

        for address, delegator_info in delegators_balance_dict.items():

            staking_balance = delegator_info["staking_balance"]
            current_balance = delegator_info["current_balance"]
            originaladdress = (delegator_info["originaladdress"] if
                               "originaladdress" in delegator_info else None)
            total_delegator_balance += staking_balance

            ratio = staking_balance / delegate_staking_balance
            reward_item = RewardLog(
                address=address,
                type=reward_log.TYPE_DELEGATOR,
                staking_balance=staking_balance,
                current_balance=current_balance,
                originaladdress=originaladdress,
            )
            reward_item.ratio = ratio
            reward_item.ratio0 = reward_item.ratio

            ratio_sum += ratio

            reward_logs.append(reward_item)

        owners_rl = RewardLog(
            address=reward_log.TYPE_OWNERS_PARENT,
            type=reward_log.TYPE_OWNERS_PARENT,
            staking_balance=delegate_staking_balance - total_delegator_balance,
            current_balance=0,
        )
        owners_rl.ratio = 1 - ratio_sum
        owners_rl.ratio0 = owners_rl.ratio

        reward_logs.append(owners_rl)

        return reward_logs
Example #2
0
    def test_calculate(self):
        rewards = []
        ratios = [0.25, 0.05, 0.3, 0.15, 0.25]
        total_reward = 1000

        for i, ratio in enumerate(ratios, start=1):
            rl0 = RewardLog(address="addr" + str(i), type="D", staking_balance=total_reward * ratio, current_balance=0)
            rl0.ratio0 = ratio
            rewards.append(rl0)

        excluded_set = {"addr1"}

        phase1 = CalculatePhase1(excluded_set)
        new_rewards, new_total_reward = phase1.calculate(rewards, total_reward)

        self.assertEqual(total_reward * (1 - 0.25), new_total_reward)

        # check new ratios sum up to 1
        # old and new reward amount is the same
        ratio_sum = 0.0

        self.assertTrue(new_rewards)

        # first item is excluded
        # compare rest of the items
        for pr_new, ratio0 in zip(new_rewards[1:], ratios[1:]):
            ratio_sum += pr_new.ratio1

            self.assertAlmostEqual(ratio0 * total_reward, pr_new.ratio1 * new_total_reward, delta=0.000001)

        self.assertEqual(1.0, ratio_sum)