Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OCT-1943: Add project searching on the server side #419

Merged
merged 4 commits into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions backend/app/infrastructure/database/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,3 +204,19 @@ class UniquenessQuotient(BaseModel):
@property
def validated_score(self):
return Decimal(self.score)


class ProjectsDetails(BaseModel):
"""
This model represents the details of a project that is consistent with data on the IPFS node.
Records here are created only by migrations.
"""

__tablename__ = "project_details"

id = Column(db.Integer, primary_key=True)
address = Column(db.String(42), nullable=False)
name = Column(db.String, nullable=False)
epoch = Column(db.Integer, nullable=False)

__table_args__ = (UniqueConstraint("address", "epoch", name="uq_address_epoch"),)
7 changes: 7 additions & 0 deletions backend/app/infrastructure/database/projects_details.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from typing import List

from app.infrastructure.database.models import ProjectsDetails


def get_projects_details_for_epoch(epoch: int) -> List[ProjectsDetails]:
return ProjectsDetails.query.filter_by(epoch=epoch).all()
59 changes: 58 additions & 1 deletion backend/app/infrastructure/routes/projects.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from flask import current_app as app
from flask import current_app as app, request
from flask_restx import Namespace, fields

from app.extensions import api
Expand All @@ -7,6 +7,7 @@
from app.modules.projects.metadata.controller import (
get_projects_metadata,
)
from app.modules.projects.details import controller as projects_details_controller

ns = Namespace("projects", description="Octant projects")
api.add_namespace(ns)
Expand All @@ -23,6 +24,29 @@
},
)

projects_details_model = api.model(
"ProjectsDetails",
{
"projects_details": fields.List(
fields.Nested(
api.model(
"ProjectsDetails",
{
"name": fields.String(
required=True, description="Project name"
),
"address": fields.String(
required=True, description="Project address"
),
},
)
),
required=False,
description="Projects details",
),
},
)


@ns.route("/epoch/<int:epoch>")
@ns.doc(
Expand All @@ -43,3 +67,36 @@ def get(self, epoch):
"projectsAddresses": projects_metadata.projects_addresses,
"projectsCid": projects_metadata.projects_cid,
}


@ns.route("/details/epoch/<int:epoch>")
@ns.doc(
description="Returns projects details for a given epoch and searchPhrase.",
params={
"epoch": "Epoch number",
"searchPhrase": "Search phrase (query parameter)",
},
)
class ProjectsDetails(OctantResource):
@ns.marshal_with(projects_details_model)
@ns.response(200, "Projects metadata is successfully retrieved")
def get(self, epoch: int):
search_phrase = request.args.get("searchPhrase", "")

app.logger.debug(
f"Getting projects details for epoch {epoch} and search phrase {search_phrase}"
)
projects_details = projects_details_controller.get_projects_details(
epoch, search_phrase
)
app.logger.debug(f"Projects details for epoch: {epoch}: {projects_details}")

return {
"projects_details": [
{
"name": project["name"],
"address": project["address"],
}
for project in projects_details
]
}
6 changes: 6 additions & 0 deletions backend/app/modules/modules_factory/current.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
UserAllocationNonceProtocol,
ScoreDelegation,
UniquenessQuotients,
ProjectsDetailsService,
)
from app.modules.modules_factory.protocols import SimulatePendingSnapshots
from app.modules.multisig_signatures.service.offchain import OffchainMultisigSignatures
Expand Down Expand Up @@ -45,6 +46,9 @@
from app.pydantic import Model
from app.shared.blockchain_types import compare_blockchain_types, ChainTypes
from app.constants import UQ_THRESHOLD_MAINNET, UQ_THRESHOLD_NOT_MAINNET
from app.modules.projects.details.service.projects_details import (
StaticProjectsDetailsService,
)


class CurrentUserDeposits(UserEffectiveDeposits, TotalEffectiveDeposits, Protocol):
Expand All @@ -61,6 +65,7 @@ class CurrentServices(Model):
simulated_pending_snapshot_service: SimulatePendingSnapshots
multisig_signatures_service: MultisigSignatures
projects_metadata_service: ProjectsMetadataService
projects_details_service: ProjectsDetailsService
user_budgets_service: UpcomingUserBudgets
score_delegation_service: ScoreDelegation
uniqueness_quotients: UniquenessQuotients
Expand Down Expand Up @@ -144,6 +149,7 @@ def create(chain_id: int) -> "CurrentServices":
user_tos_service=user_tos,
user_antisybil_service=user_antisybil_service,
projects_metadata_service=StaticProjectsMetadataService(),
projects_details_service=StaticProjectsDetailsService(),
user_budgets_service=user_budgets,
score_delegation_service=score_delegation,
uniqueness_quotients=uniqueness_quotients,
Expand Down
6 changes: 6 additions & 0 deletions backend/app/modules/modules_factory/finalized.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
WithdrawalsService,
SavedProjectRewardsService,
ProjectsMetadataService,
ProjectsDetailsService,
)
from app.modules.octant_rewards.general.service.finalized import FinalizedOctantRewards
from app.modules.projects.rewards.service.saved import SavedProjectRewards
Expand All @@ -26,6 +27,9 @@
StaticProjectsMetadataService,
)
from app.pydantic import Model
from app.modules.projects.details.service.projects_details import (
StaticProjectsDetailsService,
)


class FinalizedOctantRewardsProtocol(OctantRewards, Leverage, Protocol):
Expand All @@ -52,6 +56,7 @@ class FinalizedServices(Model):
withdrawals_service: WithdrawalsService
project_rewards_service: SavedProjectRewardsService
projects_metadata_service: ProjectsMetadataService
projects_details_service: ProjectsDetailsService

@staticmethod
def create() -> "FinalizedServices":
Expand All @@ -75,4 +80,5 @@ def create() -> "FinalizedServices":
withdrawals_service=withdrawals_service,
project_rewards_service=SavedProjectRewards(),
projects_metadata_service=StaticProjectsMetadataService(),
projects_details_service=StaticProjectsDetailsService(),
)
6 changes: 6 additions & 0 deletions backend/app/modules/modules_factory/finalizing.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
WithdrawalsService,
SavedProjectRewardsService,
ProjectsMetadataService,
ProjectsDetailsService,
)
from app.modules.octant_rewards.general.service.pending import PendingOctantRewards
from app.modules.octant_rewards.matched.pending import PendingOctantMatchedRewards
Expand All @@ -29,6 +30,9 @@
StaticProjectsMetadataService,
)
from app.pydantic import Model
from app.modules.projects.details.service.projects_details import (
StaticProjectsDetailsService,
)


class FinalizingOctantRewards(OctantRewards, Leverage, Protocol):
Expand All @@ -50,6 +54,7 @@ class FinalizingServices(Model):
withdrawals_service: WithdrawalsService
project_rewards_service: SavedProjectRewardsService
projects_metadata_service: ProjectsMetadataService
projects_details_service: ProjectsDetailsService

@staticmethod
def create() -> "FinalizingServices":
Expand Down Expand Up @@ -90,4 +95,5 @@ def create() -> "FinalizingServices":
withdrawals_service=withdrawals_service,
project_rewards_service=SavedProjectRewards(),
projects_metadata_service=StaticProjectsMetadataService(),
projects_details_service=StaticProjectsDetailsService(),
)
11 changes: 10 additions & 1 deletion backend/app/modules/modules_factory/future.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
from app.modules.modules_factory.protocols import OctantRewards, ProjectsMetadataService
from app.modules.modules_factory.protocols import (
OctantRewards,
ProjectsMetadataService,
ProjectsDetailsService,
)
from app.modules.octant_rewards.general.service.calculated import (
CalculatedOctantRewards,
)
Expand All @@ -10,11 +14,15 @@
StaticProjectsMetadataService,
)
from app.pydantic import Model
from app.modules.projects.details.service.projects_details import (
StaticProjectsDetailsService,
)


class FutureServices(Model):
octant_rewards_service: OctantRewards
projects_metadata_service: ProjectsMetadataService
projects_details_service: ProjectsDetailsService

@staticmethod
def create() -> "FutureServices":
Expand All @@ -24,4 +32,5 @@ def create() -> "FutureServices":
effective_deposits=ContractBalanceUserDeposits(),
),
projects_metadata_service=StaticProjectsMetadataService(),
projects_details_service=StaticProjectsDetailsService(),
)
6 changes: 6 additions & 0 deletions backend/app/modules/modules_factory/pending.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
MultisigSignatures,
ProjectsMetadataService,
UniquenessQuotients,
ProjectsDetailsService,
)
from app.modules.multisig_signatures.service.offchain import OffchainMultisigSignatures
from app.modules.octant_rewards.general.service.pending import PendingOctantRewards
Expand Down Expand Up @@ -49,6 +50,9 @@
from app.pydantic import Model
from app.shared.blockchain_types import compare_blockchain_types, ChainTypes
from app.constants import UQ_THRESHOLD_MAINNET, UQ_THRESHOLD_NOT_MAINNET
from app.modules.projects.details.service.projects_details import (
StaticProjectsDetailsService,
)


class PendingOctantRewardsService(OctantRewards, Leverage, Protocol):
Expand Down Expand Up @@ -87,6 +91,7 @@ class PendingServices(Model):
project_rewards_service: PendingProjectRewardsProtocol
multisig_signatures_service: MultisigSignatures
projects_metadata_service: ProjectsMetadataService
projects_details_service: ProjectsDetailsService
uniqueness_quotients: UniquenessQuotients

@staticmethod
Expand Down Expand Up @@ -159,5 +164,6 @@ def create(chain_id: int) -> "PendingServices":
project_rewards_service=project_rewards,
multisig_signatures_service=multisig_signatures,
projects_metadata_service=StaticProjectsMetadataService(),
projects_details_service=StaticProjectsDetailsService(),
uniqueness_quotients=uniqueness_quotients,
)
6 changes: 6 additions & 0 deletions backend/app/modules/modules_factory/pre_pending.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
UserEffectiveDeposits,
SavedProjectRewardsService,
ProjectsMetadataService,
ProjectsDetailsService,
)
from app.modules.octant_rewards.general.service.calculated import (
CalculatedOctantRewards,
Expand All @@ -24,6 +25,9 @@
)
from app.pydantic import Model
from app.shared.blockchain_types import compare_blockchain_types, ChainTypes
from app.modules.projects.details.service.projects_details import (
StaticProjectsDetailsService,
)


class PrePendingUserDeposits(UserEffectiveDeposits, AllUserEffectiveDeposits, Protocol):
Expand All @@ -36,6 +40,7 @@ class PrePendingServices(Model):
pending_snapshots_service: PendingSnapshots
project_rewards_service: SavedProjectRewardsService
projects_metadata_service: ProjectsMetadataService
projects_details_service: ProjectsDetailsService

@staticmethod
def create(chain_id: int) -> "PrePendingServices":
Expand Down Expand Up @@ -63,4 +68,5 @@ def create(chain_id: int) -> "PrePendingServices":
pending_snapshots_service=pending_snapshots_service,
project_rewards_service=SavedProjectRewards(),
projects_metadata_service=StaticProjectsMetadataService(),
projects_details_service=StaticProjectsDetailsService(),
)
9 changes: 9 additions & 0 deletions backend/app/modules/modules_factory/protocols.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
)
from app.modules.history.dto import UserHistoryDTO
from app.modules.multisig_signatures.dto import Signature
from app.modules.projects.details.service.projects_details import ProjectsDetailsDTO


@runtime_checkable
Expand Down Expand Up @@ -226,6 +227,14 @@ def get_projects_metadata(self, context: Context) -> ProjectsMetadata:
...


@runtime_checkable
class ProjectsDetailsService(Protocol):
def get_projects_details_by_search_phrase(
self, context: Context, search_phrase: str
) -> ProjectsDetailsDTO:
...


@runtime_checkable
class UserAllocationNonceProtocol(Protocol):
def get_user_next_nonce(self, user_address: str) -> int:
Expand Down
19 changes: 19 additions & 0 deletions backend/app/modules/projects/details/controller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from app.context.manager import epoch_context
from app.modules.registry import get_services
from app.modules.projects.details.service.projects_details import ProjectsDetailsDTO


def get_projects_details(epoch: int, search_phrase: str):
context = epoch_context(epoch)
service = get_services(context.epoch_state).projects_details_service

filtered_projects: ProjectsDetailsDTO = (
service.get_projects_details_by_search_phrase(context, search_phrase)
)
return [
{
"name": project["name"],
"address": project["address"],
}
for project in filtered_projects.projects_details
]
20 changes: 20 additions & 0 deletions backend/app/modules/projects/details/core.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from typing import List

from app.infrastructure.database.models import ProjectsDetails


def filter_projects_details(
projects_details: List[ProjectsDetails], search_phrase: str
) -> List[ProjectsDetails]:
search_phrase = search_phrase.strip().lower()

filtered_project_details = []

for project_details in projects_details:
if (
search_phrase in project_details.name.lower()
or search_phrase in project_details.address.lower()
):
filtered_project_details.append(project_details)

return filtered_project_details
Loading