Basic call requests endpoints to work with updated db

pull/882/head
kompotkot 2023-08-03 14:12:06 +00:00
rodzic 1589c8c65d
commit 927eb85c94
3 zmienionych plików z 90 dodań i 93 usunięć

Wyświetl plik

@ -48,6 +48,40 @@ class ContractAlreadyRegistered(Exception):
pass
def parse_registered_contract_response(
obj: Tuple[RegisteredContract, Blockchain]
) -> data.RegisteredContractResponse:
return data.RegisteredContractResponse(
id=obj[0].id,
blockchain=obj[1].name,
address=obj[0].address,
metatx_holder_id=obj[0].metatx_holder_id,
title=obj[0].title,
description=obj[0].description,
image_uri=obj[0].image_uri,
created_at=obj[0].created_at,
updated_at=obj[0].updated_at,
)
def parse_call_request_response(
obj: Tuple[CallRequest, RegisteredContract, CallRequestType, CallRequestType]
) -> data.CallRequestResponse:
return data.CallRequestResponse(
id=obj[0].id,
contract_id=obj[0].registered_contract_id,
contract_address=obj[1].address,
metatx_holder_id=obj[0].metatx_holder_id,
call_request_type=obj[2].request_type,
caller=obj[0].caller,
method=obj[0].method,
parameters=obj[0].parameters,
expires_at=obj[0].expires_at,
created_at=obj[0].created_at,
updated_at=obj[0].updated_at,
)
def validate_method_and_params(
contract_type: ContractType, method: str, parameters: Dict[str, Any]
) -> None:
@ -259,7 +293,7 @@ def delete_registered_contract(
def request_calls(
db_session: Session,
moonstream_user_id: uuid.UUID,
metatx_holder_id: uuid.UUID,
registered_contract_id: Optional[uuid.UUID],
contract_address: Optional[str],
call_specs: List[data.CallSpecification],
@ -283,7 +317,7 @@ def request_calls(
# Check that the moonstream_user_id matches a RegisteredContract with the given id or address
query = db_session.query(RegisteredContract).filter(
RegisteredContract.moonstream_user_id == moonstream_user_id
RegisteredContract.metatx_holder_id == metatx_holder_id
)
if registered_contract_id is not None:
@ -297,7 +331,7 @@ def request_calls(
try:
registered_contract = query.one()
except NoResultFound:
raise ValueError("Invalid registered_contract_id or moonstream_user_id")
raise ValueError("Invalid registered_contract_id or metatx_holder_id")
# Normalize the caller argument using Web3.toChecksumAddress
contract_type = ContractType(registered_contract.contract_type)
@ -343,16 +377,20 @@ def request_calls(
def get_call_requests(
db_session: Session,
request_id: uuid.UUID,
) -> data.CallRequest:
) -> Tuple[CallRequest, RegisteredContract, CallRequestType, CallRequestType]:
"""
Get call request by ID.
"""
results = (
db_session.query(CallRequest, RegisteredContract)
db_session.query(CallRequest, RegisteredContract, CallRequestType)
.join(
RegisteredContract,
CallRequest.registered_contract_id == RegisteredContract.id,
)
.join(
CallRequestType,
CallRequest.call_request_type_id == CallRequestType.id,
)
.filter(CallRequest.id == request_id)
.all()
)
@ -360,11 +398,12 @@ def get_call_requests(
raise CallRequestNotFound("Call request with given ID not found")
elif len(results) != 1:
raise Exception(
f"Incorrect number of results found for moonstream_user_id {moonstream_user_id} and request_id {request_id}"
f"Incorrect number of results found for request_id {request_id}"
)
return data.CallRequest(
contract_address=results[0][1].address, **results[0][0].__dict__
)
call_request, registered_contract, call_request_type = results[0]
return (call_request, registered_contract, call_request_type)
def list_blockchains(
@ -389,7 +428,7 @@ def list_call_requests(
limit: int = 10,
offset: Optional[int] = None,
show_expired: bool = False,
) -> List[data.CallRequest]:
) -> List[Row[Tuple[CallRequest, RegisteredContract, CallRequestType]]]:
"""
List call requests for the given moonstream_user_id
"""
@ -403,11 +442,15 @@ def list_call_requests(
# If show_expired is False, filter out expired requests using current time on database server
query = (
db_session.query(CallRequest, RegisteredContract)
db_session.query(CallRequest, RegisteredContract, CallRequestType)
.join(
RegisteredContract,
CallRequest.registered_contract_id == RegisteredContract.id,
)
.join(
CallRequestType,
CallRequest.call_request_type_id == CallRequestType.id,
)
.filter(CallRequest.caller == Web3.toChecksumAddress(caller))
)
@ -429,12 +472,7 @@ def list_call_requests(
query = query.limit(limit)
results = query.all()
return [
data.CallRequest(
contract_address=registered_contract.address, **call_request.__dict__
)
for call_request, registered_contract in results
]
return results
# TODO(zomglings): What should the delete functionality for call requests look like?
@ -449,7 +487,7 @@ def list_call_requests(
def delete_requests(
db_session: Session,
moonstream_user_id: uuid.UUID,
metatx_holder_id: uuid.UUID,
request_ids: List[uuid.UUID] = [],
) -> int:
"""
@ -458,7 +496,7 @@ def delete_requests(
try:
requests_to_delete_query = (
db_session.query(CallRequest)
.filter(CallRequest.moonstream_user_id == moonstream_user_id)
.filter(CallRequest.metatx_holder_id == metatx_holder_id)
.filter(CallRequest.id.in_(request_ids))
)
requests_to_delete_num: int = requests_to_delete_query.delete(

Wyświetl plik

@ -299,22 +299,23 @@ class CreateCallRequestsAPIRequest(BaseModel):
return values
class CallRequest(BaseModel):
class CallRequestResponse(BaseModel):
id: UUID
contract_id: UUID = Field(alias="registered_contract_id")
contract_id: UUID
contract_address: Optional[str] = None
moonstream_user_id: UUID
metatx_holder_id: UUID
call_request_type: Optional[str] = None
caller: str
method: str
parameters: Dict[str, Any]
expires_at: Optional[datetime]
expires_at: Optional[datetime] = None
created_at: datetime
updated_at: datetime
class Config:
orm_mode = True
@validator("id", "contract_id", "moonstream_user_id")
@validator("id", "contract_id", "metatx_holder_id")
def validate_uuids(cls, v):
return str(v)

Wyświetl plik

@ -115,18 +115,8 @@ async def list_registered_contracts_route(
raise EngineHTTPException(status_code=500)
return [
data.RegisteredContractResponse(
id=rc_with_b[0].id,
blockchain=rc_with_b[1].name,
address=rc_with_b[0].address,
metatx_holder_id=rc_with_b[0].metatx_holder_id,
title=rc_with_b[0].title,
description=rc_with_b[0].description,
image_uri=rc_with_b[0].image_uri,
created_at=rc_with_b[0].created_at,
updated_at=rc_with_b[0].updated_at,
)
for rc_with_b in registered_contracts_with_blockchain
contracts_actions.parse_registered_contract_response(rc)
for rc in registered_contracts_with_blockchain
]
@ -158,16 +148,8 @@ async def get_registered_contract_route(
logger.error(repr(err))
raise EngineHTTPException(status_code=500)
return data.RegisteredContractResponse(
id=contract_with_blockchain[0].id,
blockchain=contract_with_blockchain[1].name,
address=contract_with_blockchain[0].address,
metatx_holder_id=contract_with_blockchain[0].metatx_holder_id,
title=contract_with_blockchain[0].title,
description=contract_with_blockchain[0].description,
image_uri=contract_with_blockchain[0].image_uri,
created_at=contract_with_blockchain[0].created_at,
updated_at=contract_with_blockchain[0].updated_at,
return contracts_actions.parse_registered_contract_response(
contract_with_blockchain
)
@ -205,16 +187,8 @@ async def register_contract_route(
logger.error(repr(err))
raise EngineHTTPException(status_code=500)
return data.RegisteredContractResponse(
id=contract_with_blockchain[0].id,
blockchain=contract_with_blockchain[1].name,
address=contract_with_blockchain[0].address,
metatx_holder_id=contract_with_blockchain[0].metatx_holder_id,
title=contract_with_blockchain[0].title,
description=contract_with_blockchain[0].description,
image_uri=contract_with_blockchain[0].image_uri,
created_at=contract_with_blockchain[0].created_at,
updated_at=contract_with_blockchain[0].updated_at,
return contracts_actions.parse_registered_contract_response(
contract_with_blockchain
)
@ -248,16 +222,8 @@ async def update_contract_route(
logger.error(repr(err))
raise EngineHTTPException(status_code=500)
return data.RegisteredContractResponse(
id=contract_with_blockchain[0].id,
blockchain=contract_with_blockchain[1].name,
address=contract_with_blockchain[0].address,
metatx_holder_id=contract_with_blockchain[0].metatx_holder_id,
title=contract_with_blockchain[0].title,
description=contract_with_blockchain[0].description,
image_uri=contract_with_blockchain[0].image_uri,
created_at=contract_with_blockchain[0].created_at,
updated_at=contract_with_blockchain[0].updated_at,
return contracts_actions.parse_registered_contract_response(
contract_with_blockchain
)
@ -284,27 +250,21 @@ async def delete_contract_route(
logger.error(repr(err))
raise EngineHTTPException(status_code=500)
return data.RegisteredContractResponse(
id=deleted_contract_with_blockchain[0].id,
blockchain=deleted_contract_with_blockchain[1].name,
address=deleted_contract_with_blockchain[0].address,
metatx_holder_id=deleted_contract_with_blockchain[0].metatx_holder_id,
title=deleted_contract_with_blockchain[0].title,
description=deleted_contract_with_blockchain[0].description,
image_uri=deleted_contract_with_blockchain[0].image_uri,
created_at=deleted_contract_with_blockchain[0].created_at,
updated_at=deleted_contract_with_blockchain[0].updated_at,
return contracts_actions.parse_registered_contract_response(
deleted_contract_with_blockchain
)
# TODO(kompotkot): route `/contracts/types` deprecated
@app.get("/contracts/types", tags=["contracts"])
@app.get(
"/requests/types", tags=["requests"], response_model=data.CallRequestTypesResponse
"/requests/types",
tags=["requests"],
response_model=List[data.CallRequestTypeResponse],
)
async def call_request_types_route(
db_session: Session = Depends(db.yield_db_read_only_session),
) -> data.CallRequestTypesResponse:
) -> List[data.CallRequestTypeResponse]:
"""
Describes the call_request_types that users can register call requests as against this API.
"""
@ -315,15 +275,11 @@ async def call_request_types_route(
except Exception as e:
logger.error(repr(e))
raise EngineHTTPException(status_code=500)
return data.CallRequestTypesResponse(
call_request_types=[
call_request_type for call_request_type in call_request_types
]
)
return call_request_types
@app.get("/requests", tags=["requests"], response_model=List[data.CallRequest])
async def list_requests(
@app.get("/requests", tags=["requests"], response_model=List[data.CallRequestResponse])
async def list_requests_route(
contract_id: Optional[UUID] = Query(None),
contract_address: Optional[str] = Query(None),
caller: str = Query(...),
@ -331,7 +287,7 @@ async def list_requests(
offset: Optional[int] = Query(None),
show_expired: Optional[bool] = Query(False),
db_session: Session = Depends(db.yield_db_read_only_session),
) -> List[data.CallRequest]:
) -> List[data.CallRequestResponse]:
"""
Allows API user to see all unexpired call requests for a given caller against a given contract.
@ -354,21 +310,23 @@ async def list_requests(
logger.error(repr(e))
raise EngineHTTPException(status_code=500)
return requests
return [contracts_actions.parse_call_request_response(r) for r in requests]
@app.get("/requests/{request_id}", tags=["requests"], response_model=data.CallRequest)
@app.get(
"/requests/{request_id}", tags=["requests"], response_model=data.CallRequestResponse
)
async def get_request(
request_id: UUID = Path(...),
db_session: Session = Depends(db.yield_db_read_only_session),
) -> List[data.CallRequest]:
) -> List[data.CallRequestResponse]:
"""
Allows API user to see call request.
At least one of `contract_id` or `contract_address` must be provided as query parameters.
"""
try:
result = contracts_actions.get_call_requests(
request = contracts_actions.get_call_requests(
db_session=db_session,
request_id=request_id,
)
@ -381,7 +339,7 @@ async def get_request(
logger.error(repr(e))
raise EngineHTTPException(status_code=500)
return result
return contracts_actions.parse_call_request_response(request)
@app.post("/requests", tags=["requests"], response_model=int)
@ -398,7 +356,7 @@ async def create_requests(
try:
num_requests = contracts_actions.request_calls(
db_session=db_session,
moonstream_user_id=request.state.user.id,
metatx_holder_id=request.state.user.id,
registered_contract_id=data.contract_id,
contract_address=data.contract_address,
call_specs=data.specifications,
@ -428,7 +386,7 @@ async def delete_requests(
try:
deleted_requests = contracts_actions.delete_requests(
db_session=db_session,
moonstream_user_id=request.state.user.id,
metatx_holder_id=request.state.user.id,
request_ids=request_ids,
)
except Exception as err: