From 0aaf45ef966b2610bfa1f5606b831a0f2108926e Mon Sep 17 00:00:00 2001 From: "kacper.golem" Date: Thu, 29 Aug 2024 12:24:35 +0200 Subject: [PATCH] fix: add ethBelowThreshold for computations --- backend/app/engine/projects/rewards/__init__.py | 13 +++++++++++++ .../app/engine/projects/rewards/preliminary.py | 11 ++++++++++- .../projects/rewards/threshold/__init__.py | 9 +++++++++ .../projects/rewards/threshold/preliminary.py | 17 +++++++++++++++++ .../octant_rewards/general/service/finalized.py | 9 ++++++++- 5 files changed, 57 insertions(+), 2 deletions(-) diff --git a/backend/app/engine/projects/rewards/__init__.py b/backend/app/engine/projects/rewards/__init__.py index 95d704bd68..f8ee852d11 100644 --- a/backend/app/engine/projects/rewards/__init__.py +++ b/backend/app/engine/projects/rewards/__init__.py @@ -1,4 +1,5 @@ from abc import ABC, abstractmethod +from collections import namedtuple from dataclasses import dataclass, field from typing import List, Optional @@ -41,6 +42,11 @@ class ProjectRewardsResult: threshold: Optional[int] = None +AllocationsBelowThreshold = namedtuple( + "AllocationsBelowThreshold", ["below_threshold", "total"] +) + + @dataclass class ProjectRewards(ABC): projects_allocations: ProjectAllocations = field(init=False) @@ -54,3 +60,10 @@ def calculate_project_rewards( def calculate_threshold(self, total_allocated: int, projects: List[str]) -> None: return None + + def get_total_allocations_below_threshold( + self, allocations: List[AllocationItem], no_projects: int + ) -> AllocationsBelowThreshold: + return AllocationsBelowThreshold( + 0, sum(map(lambda allocation: allocation.amount, allocations)) + ) diff --git a/backend/app/engine/projects/rewards/preliminary.py b/backend/app/engine/projects/rewards/preliminary.py index dd6fdc52b6..9df334452a 100644 --- a/backend/app/engine/projects/rewards/preliminary.py +++ b/backend/app/engine/projects/rewards/preliminary.py @@ -7,14 +7,17 @@ ProjectRewardsResult, ProjectRewards, ProjectRewardDTO, + AllocationsBelowThreshold, ) from app.engine.projects.rewards.allocations import ( ProjectAllocations, ProjectAllocationsPayload, + AllocationItem, ) from app.engine.projects.rewards.allocations.preliminary import ( PreliminaryProjectAllocations, ) +from app.engine.projects.rewards.leverage.preliminary import PreliminaryLeverage from app.engine.projects.rewards.threshold import ( ProjectThreshold, ProjectThresholdPayload, @@ -22,7 +25,6 @@ from app.engine.projects.rewards.threshold.preliminary import ( PreliminaryProjectThreshold, ) -from app.engine.projects.rewards.leverage.preliminary import PreliminaryLeverage @dataclass @@ -42,6 +44,13 @@ def calculate_threshold(self, total_allocated: int, projects: List[str]) -> int: ) ) + def get_total_allocations_below_threshold( + self, allocations: List[AllocationItem], no_projects: int + ) -> AllocationsBelowThreshold: + return self.projects_threshold.get_total_allocations_below_threshold( + allocations, no_projects + ) + def calculate_project_rewards( self, payload: ProjectRewardsPayload ) -> ProjectRewardsResult: diff --git a/backend/app/engine/projects/rewards/threshold/__init__.py b/backend/app/engine/projects/rewards/threshold/__init__.py index 4295633921..e06145ef8e 100644 --- a/backend/app/engine/projects/rewards/threshold/__init__.py +++ b/backend/app/engine/projects/rewards/threshold/__init__.py @@ -1,5 +1,8 @@ from abc import ABC, abstractmethod from dataclasses import dataclass +from typing import List + +from app.engine.projects.rewards import AllocationItem, AllocationsBelowThreshold @dataclass @@ -13,3 +16,9 @@ class ProjectThreshold(ABC): @abstractmethod def calculate_threshold(self, payload: ProjectThresholdPayload) -> int: pass + + @abstractmethod + def get_total_allocations_below_threshold( + self, allocations: List[AllocationItem], no_projects: int + ) -> AllocationsBelowThreshold: + pass diff --git a/backend/app/engine/projects/rewards/threshold/preliminary.py b/backend/app/engine/projects/rewards/threshold/preliminary.py index 2c68c221da..89bdb36351 100644 --- a/backend/app/engine/projects/rewards/threshold/preliminary.py +++ b/backend/app/engine/projects/rewards/threshold/preliminary.py @@ -1,5 +1,7 @@ from dataclasses import dataclass +from typing import List +from app.engine.projects.rewards import AllocationItem, AllocationsBelowThreshold from app.engine.projects.rewards.threshold import ( ProjectThreshold, ProjectThresholdPayload, @@ -19,3 +21,18 @@ def calculate_threshold(self, payload: ProjectThresholdPayload) -> int: if payload.projects_count else 0 ) + + def get_total_allocations_below_threshold( + self, allocations: List[AllocationItem], no_projects: int + ) -> AllocationsBelowThreshold: + allocations_sum = sum(map(lambda x: x.amount, allocations)) + threshold = self.calculate_threshold( + ProjectThresholdPayload(allocations_sum, no_projects) + ) + + allocations_below_threshold = 0 + for allocation in allocations: + if allocation.amount < threshold: + allocations_below_threshold += allocation.amount + + return AllocationsBelowThreshold(allocations_below_threshold, allocations_sum) diff --git a/backend/app/modules/octant_rewards/general/service/finalized.py b/backend/app/modules/octant_rewards/general/service/finalized.py index 8745231b47..249c208d07 100644 --- a/backend/app/modules/octant_rewards/general/service/finalized.py +++ b/backend/app/modules/octant_rewards/general/service/finalized.py @@ -28,13 +28,20 @@ def get_octant_rewards(self, context: Context) -> OctantRewardsDTO: int(finalized_snapshot.leftover), leftover_payload ) - allocations_sum = database.allocations.get_alloc_sum_by_epoch( + allocations_for_epoch = database.allocations.get_all_by_epoch( context.epoch_details.epoch_num ) + allocations_result = context.epoch_settings.project.rewards.get_total_allocations_below_threshold( + allocations_for_epoch, len(context.projects_details.projects) + ) + allocations_sum = allocations_result.total + allocations_below_threshold = allocations_result.below_threshold + donated_to_projects = ( int(finalized_snapshot.matched_rewards) - unused_matched_rewards + allocations_sum + - allocations_below_threshold ) return OctantRewardsDTO(