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

Leaderboard metadata #968

Merged
merged 6 commits into from
Jan 30, 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
53 changes: 53 additions & 0 deletions engineapi/alembic/versions/71e888082a6d_leaderboard_metadata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
"""leaderboard metadata

Revision ID: 71e888082a6d
Revises: 040f2dfde5a5
Create Date: 2023-11-15 13:21:16.108399

"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision = "71e888082a6d"
down_revision = "040f2dfde5a5"
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column(
"leaderboards",
sa.Column(
"blockchain_ids",
sa.ARRAY(sa.Integer()),
nullable=False,
server_default="{}",
),
)
op.add_column(
"leaderboards",
sa.Column(
"wallet_connect", sa.Boolean(), nullable=False, server_default="false"
),
)
op.add_column(
"leaderboards",
sa.Column(
"columns_names",
postgresql.JSONB(astext_type=sa.Text()),
nullable=False,
server_default="{}",
),
)
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("leaderboards", "columns_names")
op.drop_column("leaderboards", "wallet_connect")
op.drop_column("leaderboards", "blockchain_ids")
# ### end Alembic commands ###
60 changes: 58 additions & 2 deletions engineapi/engineapi/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,14 @@
from web3 import Web3
from web3.types import ChecksumAddress

from .data import Score, LeaderboardScore, LeaderboardConfigUpdate, LeaderboardConfig
from .data import (
Score,
LeaderboardScore,
LeaderboardConfigUpdate,
LeaderboardConfig,
LeaderboardPosition,
LeaderboardUnformattedPosition,
)
from .contracts import Dropper_interface, ERC20_interface, Terminus_interface
from .models import (
DropperClaimant,
Expand Down Expand Up @@ -101,6 +108,27 @@ class LeaderboardVersionNotFound(Exception):
logger = logging.getLogger(__name__)


def get_default_columns_names(columns_names: Optional[Dict[str, str]] = {}):
default_columns_names = {}

# Retrieve ordered list of field names from LeaderboardPosition
ordered_fields = list(LeaderboardPosition.__annotations__.keys())

# Mapping these to the corresponding columns in LeaderboardUnformattedPosition
for index, field_name in enumerate(ordered_fields, start=1):
# Construct the column name like "column_1", "column_2", etc.
column_name = f"column_{index}"

# If custom column name is provided in columns_names, use it
if columns_names and field_name in columns_names:
default_columns_names[column_name] = columns_names[field_name]
else:
# Otherwise, use the default field name in title case
default_columns_names[column_name] = field_name.replace("_", " ").title()

return default_columns_names


def create_dropper_contract(
db_session: Session,
blockchain: Optional[str],
Expand Down Expand Up @@ -1481,15 +1509,30 @@ def create_leaderboard(
title: str,
description: Optional[str],
token: Optional[Union[uuid.UUID, str]] = None,
wallet_connect: bool = False,
blockchain_ids: List[int] = [],
columns_names: Optional[Dict[str, str]] = {},
) -> Leaderboard:
"""
Create a leaderboard
"""

if len(columns_names) > 0:
columns_names = get_default_columns_names(columns_names)

if not token:
token = uuid.UUID(MOONSTREAM_ADMIN_ACCESS_TOKEN)
try:
leaderboard = Leaderboard(title=title, description=description)
# deduplicate and sort
blockchain_ids = sorted(list(set(blockchain_ids)))

leaderboard = Leaderboard(
title=title,
description=description,
wallet_connect=wallet_connect,
blockchain_ids=blockchain_ids,
columns_names=columns_names,
)
db_session.add(leaderboard)
db_session.commit()

Expand Down Expand Up @@ -1548,6 +1591,9 @@ def update_leaderboard(
leaderboard_id: uuid.UUID,
title: Optional[str],
description: Optional[str],
wallet_connect: Optional[bool],
blockchain_ids: Optional[List[int]],
columns_names: Optional[Dict[str, str]],
) -> Leaderboard:
"""
Update a leaderboard
Expand All @@ -1561,6 +1607,16 @@ def update_leaderboard(
leaderboard.title = title
if description is not None:
leaderboard.description = description
if wallet_connect is not None:
leaderboard.wallet_connect = wallet_connect
if blockchain_ids is not None:
# deduplicate and sort
blockchain_ids = sorted(list(set(blockchain_ids)))
leaderboard.blockchain_ids = blockchain_ids

if columns_names is not None:
columns_names = get_default_columns_names(columns_names)
leaderboard.columns_names = columns_names

db_session.commit()

Expand Down
28 changes: 28 additions & 0 deletions engineapi/engineapi/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,16 @@ class Score(BaseModel):
points_data: Dict[str, Any]


class LeaderboardUnformattedPosition(BaseModel):
column_1: str = Field(serialization_alias="address")
column_2: int = Field(serialization_alias="rank")
column_3: int = Field(serialization_alias="score")
column_4: Dict[str, Any] = Field(serialization_alias="points_data")

class Config:
orm_mode = True


class LeaderboardPosition(BaseModel):
address: str
rank: int
Expand Down Expand Up @@ -370,6 +380,9 @@ class Leaderboard(BaseModel):
title: str
description: Optional[str] = None
resource_id: Optional[UUID] = None
wallet_connect: bool = False
blockchain_ids: List[int] = Field(default_factory=list)
columns_names: Dict[str, str] = Field(default_factory=dict)
created_at: datetime
updated_at: datetime

Expand All @@ -385,13 +398,19 @@ class LeaderboardInfoResponse(BaseModel):
class LeaderboardCreateRequest(BaseModel):
title: str
description: Optional[str] = None
wallet_connect: bool = False
blockchain_ids: List[int] = Field(default_factory=list)
columns_names: Dict[str, str] = Field(default_factory=dict)


class LeaderboardCreatedResponse(BaseModel):
id: UUID
title: str
description: Optional[str] = None
resource_id: Optional[UUID] = None
wallet_connect: bool = False
blockchain_ids: List[int] = Field(default_factory=list)
columns_names: Dict[str, str] = Field(default_factory=dict)
created_at: datetime
updated_at: datetime

Expand All @@ -404,6 +423,9 @@ class LeaderboardUpdatedResponse(BaseModel):
title: str
description: Optional[str] = None
resource_id: Optional[UUID] = None
wallet_connect: bool = False
blockchain_ids: List[int] = Field(default_factory=list)
columns_names: Dict[str, str] = Field(default_factory=dict)
created_at: datetime
updated_at: datetime

Expand All @@ -414,13 +436,19 @@ class Config:
class LeaderboardUpdateRequest(BaseModel):
title: Optional[str] = None
description: Optional[str] = None
wallet_connect: bool = False
blockchain_ids: List[int] = Field(default_factory=list)
columns_names: Dict[str, str] = Field(default_factory=dict)


class LeaderboardDeletedResponse(BaseModel):
id: UUID
title: str
description: Optional[str] = None
resource_id: Optional[UUID] = None
wallet_connect: bool = False
blockchain_ids: List[int] = Field(default_factory=list)
columns_names: Dict[str, str] = Field(default_factory=dict)
created_at: datetime
updated_at: datetime

Expand Down
6 changes: 5 additions & 1 deletion engineapi/engineapi/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import uuid

from sqlalchemy import (
ARRAY,
DECIMAL,
VARCHAR,
BigInteger,
Expand Down Expand Up @@ -335,7 +336,6 @@ class CallRequest(Base):

class Leaderboard(Base): # type: ignore
__tablename__ = "leaderboards"
# __table_args__ = (UniqueConstraint("dropper_contract_id", "address"),)

id = Column(
UUID(as_uuid=True),
Expand All @@ -347,6 +347,10 @@ class Leaderboard(Base): # type: ignore
title = Column(VARCHAR(128), nullable=False)
description = Column(String, nullable=True)
resource_id = Column(UUID(as_uuid=True), nullable=True, index=True)
blockchain_ids = Column(ARRAY(Integer), nullable=False, default=[])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I sugest also add sort for add and update values to this list, so it always will be readable, for example when query returns few result:

    id               blockchain_ids
<uuid1>             80001, 1
<uuid2>             1, 80001


wallet_connect = Column(Boolean, default=False, nullable=False)
columns_names = Column(JSONB, nullable=False, default={})
created_at = Column(
DateTime(timezone=True), server_default=utcnow(), nullable=False
)
Expand Down
Loading
Loading