diff --git a/src/aleph/sdk/chains/common.py b/src/aleph/sdk/chains/common.py index 9f6b45f4..3c7e634e 100644 --- a/src/aleph/sdk/chains/common.py +++ b/src/aleph/sdk/chains/common.py @@ -27,9 +27,9 @@ def get_verification_buffer(message: Dict) -> bytes: # Convert Enum values to strings return "\n".join( ( - enum_as_str(message["chain"]), + enum_as_str(message["chain"]) or "", message["sender"], - enum_as_str(message["type"]), + enum_as_str(message["type"]) or "", message["item_hash"], ) ).encode() diff --git a/src/aleph/sdk/query/filters.py b/src/aleph/sdk/query/filters.py index 17c4a8cd..4caee5f5 100644 --- a/src/aleph/sdk/query/filters.py +++ b/src/aleph/sdk/query/filters.py @@ -1,9 +1,24 @@ from datetime import datetime +from enum import Enum from typing import Dict, Iterable, Optional, Union from aleph_message.models import MessageType -from ..utils import _date_field_to_timestamp, serialize_list +from ..utils import _date_field_to_timestamp, enum_as_str, serialize_list + + +class SortBy(str, Enum): + """Supported SortBy types""" + + TIME = "time" + TX_TIME = "tx-time" + + +class SortOrder(str, Enum): + """Supported SortOrder types""" + + ASCENDING = "1" + DESCENDING = "-1" class MessageFilter: @@ -20,6 +35,8 @@ class MessageFilter: :param chains: Filter by sender address chain :param start_date: Earliest date to fetch messages from :param end_date: Latest date to fetch messages from + :param sort_by: Sort by time or tx-time + :param sort_order: Sort by ascending or descending order """ message_types: Optional[Iterable[MessageType]] @@ -33,6 +50,8 @@ class MessageFilter: chains: Optional[Iterable[str]] start_date: Optional[Union[datetime, float]] end_date: Optional[Union[datetime, float]] + sort_by: Optional[SortBy] + sort_order: Optional[SortOrder] def __init__( self, @@ -47,6 +66,8 @@ def __init__( chains: Optional[Iterable[str]] = None, start_date: Optional[Union[datetime, float]] = None, end_date: Optional[Union[datetime, float]] = None, + sort_by: Optional[SortBy] = None, + sort_order: Optional[SortOrder] = None, ): self.message_types = message_types self.content_types = content_types @@ -59,6 +80,8 @@ def __init__( self.chains = chains self.start_date = start_date self.end_date = end_date + self.sort_by = sort_by + self.sort_order = sort_order def as_http_params(self) -> Dict[str, str]: """Convert the filters into a dict that can be used by an `aiohttp` client @@ -66,7 +89,7 @@ def as_http_params(self) -> Dict[str, str]: """ partial_result = { - "msgType": serialize_list( + "msgTypes": serialize_list( [type.value for type in self.message_types] if self.message_types else None @@ -81,6 +104,8 @@ def as_http_params(self) -> Dict[str, str]: "chains": serialize_list(self.chains), "startDate": _date_field_to_timestamp(self.start_date), "endDate": _date_field_to_timestamp(self.end_date), + "sortBy": enum_as_str(self.sort_by), + "sortOrder": enum_as_str(self.sort_order), } # Ensure all values are strings. @@ -110,6 +135,8 @@ class PostFilter: chains: Optional[Iterable[str]] start_date: Optional[Union[datetime, float]] end_date: Optional[Union[datetime, float]] + sort_by: Optional[SortBy] + sort_order: Optional[SortOrder] def __init__( self, @@ -122,6 +149,8 @@ def __init__( chains: Optional[Iterable[str]] = None, start_date: Optional[Union[datetime, float]] = None, end_date: Optional[Union[datetime, float]] = None, + sort_by: Optional[SortBy] = None, + sort_order: Optional[SortOrder] = None, ): self.types = types self.refs = refs @@ -132,6 +161,8 @@ def __init__( self.chains = chains self.start_date = start_date self.end_date = end_date + self.sort_by = sort_by + self.sort_order = sort_order def as_http_params(self) -> Dict[str, str]: """Convert the filters into a dict that can be used by an `aiohttp` client @@ -148,6 +179,8 @@ def as_http_params(self) -> Dict[str, str]: "chains": serialize_list(self.chains), "startDate": _date_field_to_timestamp(self.start_date), "endDate": _date_field_to_timestamp(self.end_date), + "sortBy": enum_as_str(self.sort_by), + "sortOrder": enum_as_str(self.sort_order), } # Ensure all values are strings. diff --git a/src/aleph/sdk/utils.py b/src/aleph/sdk/utils.py index 51bb04e5..ab17f44a 100644 --- a/src/aleph/sdk/utils.py +++ b/src/aleph/sdk/utils.py @@ -115,12 +115,14 @@ async def copy_async_readable_to_buffer( buffer.write(chunk) -def enum_as_str(obj: Union[str, Enum]) -> str: +def enum_as_str(obj: Optional[Union[str, Enum]]) -> Optional[str]: """Returns the value of an Enum, or the string itself when passing a string. Python 3.11 adds a new formatting of string enums. `str(MyEnum.value)` becomes `MyEnum.value` instead of `value`. """ + if not obj: + return None if not isinstance(obj, str): raise TypeError(f"Unsupported enum type: {type(obj)}")