Skip to content

Commit

Permalink
Add result_set for pagination to token holders API
Browse files Browse the repository at this point in the history
  • Loading branch information
purplesmoke05 committed Nov 29, 2023
1 parent 1ad67e7 commit 43163a5
Show file tree
Hide file tree
Showing 6 changed files with 1,665 additions and 351 deletions.
2 changes: 1 addition & 1 deletion app/model/schema/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
ListAllFilesResponse,
UploadFileRequest,
)
from .holder import HolderCountResponse, HolderResponse
from .holder import HolderCountResponse, HolderResponse, HoldersResponse
from .index import BlockNumberResponse, E2EEResponse
from .issue_redeem import IssueRedeemEvent, IssueRedeemHistoryResponse
from .ledger import (
Expand Down
9 changes: 9 additions & 0 deletions app/model/schema/holder.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@

from pydantic import BaseModel

from app.model.schema.base import ResultSet

from .personal_info import PersonalInfo


Expand All @@ -40,6 +42,13 @@ class HolderResponse(BaseModel):
modified: Optional[datetime]


class HoldersResponse(BaseModel):
"""Holders schema (Response)"""

result_set: ResultSet
holders: list[HolderResponse]


class HolderCountResponse(BaseModel):
"""Holder count schema (Response)"""

Expand Down
36 changes: 33 additions & 3 deletions app/routers/bond.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
GetBatchRegisterPersonalInfoResponse,
HolderCountResponse,
HolderResponse,
HoldersResponse,
IbetStraightBondAdditionalIssue,
IbetStraightBondCreate,
IbetStraightBondRedeem,
Expand Down Expand Up @@ -1654,13 +1655,16 @@ def delete_scheduled_event(
# GET: /bond/tokens/{token_address}/holders
@router.get(
"/tokens/{token_address}/holders",
response_model=List[HolderResponse],
response_model=HoldersResponse,
responses=get_routers_responses(422, InvalidParameterError, 404),
)
def list_all_holders(
db: DBSession,
token_address: str,
include_former_holder: bool = False,
sort_order: int = Query(0, ge=0, le=1, description="0:asc, 1:desc (created)"),
offset: Optional[int] = Query(None),
limit: Optional[int] = Query(None),
issuer_address: str = Header(...),
):
"""List all bond token holders"""
Expand Down Expand Up @@ -1715,6 +1719,8 @@ def list_all_holders(
)
)

total = db.scalar(select(func.count()).select_from(stmt.subquery()))

if not include_former_holder:
stmt = stmt.where(
or_(
Expand All @@ -1726,8 +1732,22 @@ def list_all_holders(
)
)

count = db.scalar(select(func.count()).select_from(stmt.subquery()))

# Sort
if sort_order == 0: # ASC
stmt = stmt.order_by(IDXPosition.id)
else: # DESC
stmt = stmt.order_by(desc(IDXPosition.id))

# Pagination
if limit is not None:
stmt = stmt.limit(limit)
if offset is not None:
stmt = stmt.offset(offset)

_holders: Sequence[tuple[IDXPosition, int, datetime | None]] = (
db.execute(stmt.order_by(IDXPosition.id)).tuples().all()
db.execute(stmt).tuples().all()
)

# Get personal information
Expand Down Expand Up @@ -1780,7 +1800,17 @@ def list_all_holders(
}
)

return json_response(holders)
return json_response(
{
"result_set": {
"count": count,
"total": total,
"limit": limit,
"offset": offset,
},
"holders": holders,
}
)


# GET: /bond/tokens/{token_address}/holders/count
Expand Down
37 changes: 34 additions & 3 deletions app/routers/share.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
GetBatchRegisterPersonalInfoResponse,
HolderCountResponse,
HolderResponse,
HoldersResponse,
IbetShareAdditionalIssue,
IbetShareCreate,
IbetShareRedeem,
Expand Down Expand Up @@ -1640,13 +1641,16 @@ def delete_scheduled_event(
# GET: /share/tokens/{token_address}/holders
@router.get(
"/tokens/{token_address}/holders",
response_model=List[HolderResponse],
response_model=HoldersResponse,
responses=get_routers_responses(422, InvalidParameterError, 404),
)
def list_all_holders(
db: DBSession,
token_address: str,
include_former_holder: bool = False,
sort_order: int = Query(0, ge=0, le=1, description="0:asc, 1:desc (created)"),
offset: Optional[int] = Query(None),
limit: Optional[int] = Query(None),
issuer_address: str = Header(...),
):
"""List all share token holders"""
Expand Down Expand Up @@ -1701,6 +1705,8 @@ def list_all_holders(
)
)

total = db.scalar(select(func.count()).select_from(stmt.subquery()))

if not include_former_holder:
stmt = stmt.where(
or_(
Expand All @@ -1712,8 +1718,22 @@ def list_all_holders(
)
)

count = db.scalar(select(func.count()).select_from(stmt.subquery()))

# Sort
if sort_order == 0: # ASC
stmt = stmt.order_by(IDXPosition.id)
else: # DESC
stmt = stmt.order_by(desc(IDXPosition.id))

# Pagination
if limit is not None:
stmt = stmt.limit(limit)
if offset is not None:
stmt = stmt.offset(offset)

_holders: Sequence[tuple[IDXPosition, int, datetime | None]] = (
db.execute(stmt.order_by(IDXPosition.id)).tuples().all()
db.execute(stmt).tuples().all()
)

# Get personal information
Expand Down Expand Up @@ -1752,6 +1772,7 @@ def list_all_holders(
if (_position.modified > _lock_event_latest_created)
else _lock_event_latest_created
)

holders.append(
{
"account_address": _position.account_address,
Expand All @@ -1765,7 +1786,17 @@ def list_all_holders(
}
)

return json_response(holders)
return json_response(
{
"result_set": {
"count": count,
"total": total,
"limit": limit,
"offset": offset,
},
"holders": holders,
}
)


# GET: /share/tokens/{token_address}/holders/count
Expand Down
Loading

0 comments on commit 43163a5

Please sign in to comment.