Repository: rotki/rotki

Issue:
Add sorting support to `/names/addressbook/`
Enable the support in the backend and adjust the frontend to sort by `name` or `address`


Discussion:

Resolving patch:
diff --git a/rotkehlchen/api/v1/schemas.py b/rotkehlchen/api/v1/schemas.py
--- a/rotkehlchen/api/v1/schemas.py
+++ b/rotkehlchen/api/v1/schemas.py
@@ -2830,6 +2830,7 @@ class QueryAddressbookSchema(
     BaseAddressbookSchema,
     OptionalAddressesWithBlockchainsListSchema,
     DBPaginationSchema,
+    DBOrderBySchema,
 ):
     """Schema for querying addressbook entries"""
     name_substring = fields.String(load_default=None)
@@ -2847,6 +2848,7 @@ def make_get_addressbook_query(
             blockchain=data['blockchain'],
             substring_search=data['name_substring'],
             optional_chain_addresses=data['addresses'],
+            order_by_rules=create_order_by_rules_list(data=data),
         )
         return {
             'filter_query': filter_query,
diff --git a/rotkehlchen/db/filtering.py b/rotkehlchen/db/filtering.py
--- a/rotkehlchen/db/filtering.py
+++ b/rotkehlchen/db/filtering.py
@@ -1445,11 +1445,13 @@ def make(
             blockchain: SupportedBlockchain | None = None,
             optional_chain_addresses: list[OptionalChainAddress] | None = None,
             substring_search: str | None = None,
+            order_by_rules: list[tuple[str, bool]] | None = None,
     ) -> 'AddressbookFilterQuery':
         filter_query = cls.create(
             and_op=and_op,
             limit=limit,
             offset=offset,
+            order_by_rules=order_by_rules,
         )
         filters: list[DBFilter] = []
         if substring_search is not None:


Test patch:
diff --git a/rotkehlchen/tests/api/test_addressbook.py b/rotkehlchen/tests/api/test_addressbook.py
--- a/rotkehlchen/tests/api/test_addressbook.py
+++ b/rotkehlchen/tests/api/test_addressbook.py
@@ -66,6 +66,7 @@ def test_get_addressbook(
     result = assert_proper_response_with_result(response)
     deserialized_entries = [AddressbookEntry.deserialize(data=raw_entry) for raw_entry in result['entries']]  # noqa: E501
     assert deserialized_entries == entries_set
+    assert deserialized_entries != sorted(deserialized_entries, key=lambda x: x.name)  # not sorted
     assert result['entries_found'] == len(entries_set)
     assert result['entries_total'] == len(entries_set)
 
@@ -200,6 +201,23 @@ def test_get_addressbook(
     assert result['entries_found'] == 3
     assert result['entries_total'] == len(entries_set)
 
+    # order by name/address in ascending order
+    for attribute in ('name', 'address'):
+        response = requests.post(
+            api_url_for(
+                rotkehlchen_api_server,
+                'addressbookresource',
+                book_type=book_type,
+            ),
+            json={
+                'order_by_attributes': [attribute],
+                'ascending': [True],
+            },
+        )
+        result = assert_proper_response_with_result(response=response)
+        entries = [raw_entry[attribute] for raw_entry in result['entries']]
+        assert entries == sorted(entries)
+
 
 @pytest.mark.parametrize('empty_global_addressbook', [True])
 @pytest.mark.parametrize('book_type', [AddressbookType.GLOBAL, AddressbookType.PRIVATE])