diff --git a/engineapi/engineapi/contracts_actions.py b/engineapi/engineapi/contracts_actions.py index ceed9a13..7291eddc 100644 --- a/engineapi/engineapi/contracts_actions.py +++ b/engineapi/engineapi/contracts_actions.py @@ -3,9 +3,9 @@ import json import logging import uuid from datetime import datetime, timedelta -from typing import Any, Dict, List, Optional, Tuple +from typing import Any, Dict, List, Optional, Set, Tuple -from sqlalchemy import func, or_, text +from sqlalchemy import func, or_, text, tuple_ from sqlalchemy.dialects.postgresql import insert from sqlalchemy.engine import Row from sqlalchemy.exc import IntegrityError, NoResultFound @@ -431,6 +431,18 @@ def create_request_calls( return len(call_specs) +def get_call_request_from_tuple( + db_session: Session, registered_contract_id, requests: Set[Tuple[str, str]] +) -> List[CallRequest]: + existing_requests = ( + db_session.query(CallRequest) + .filter(CallRequest.registered_contract_id == registered_contract_id) + .filter(tuple_(CallRequest.caller, CallRequest.request_id).in_(requests)) + .all() + ) + return existing_requests + + def get_call_request( db_session: Session, request_id: uuid.UUID, diff --git a/engineapi/engineapi/routes/metatx.py b/engineapi/engineapi/routes/metatx.py index 23a14b26..642c28d4 100644 --- a/engineapi/engineapi/routes/metatx.py +++ b/engineapi/engineapi/routes/metatx.py @@ -5,8 +5,9 @@ Moonstream users can register contracts on Moonstream Engine. This allows them t as part of their chain-adjacent activities (like performing signature-based token distributions on the Dropper contract). """ + import logging -from typing import Dict, List, Optional +from typing import Dict, List, Optional, Set, Tuple from uuid import UUID from bugout.data import BugoutUser @@ -351,12 +352,30 @@ async def create_requests( data: data.CreateCallRequestsAPIRequest = Body(...), user: BugoutUser = Depends(request_user_auth), db_session: Session = Depends(db.yield_db_session), + verify: bool = Query(False), ) -> int: """ Allows API user to register call requests from given contract details, TTL, and call specifications. At least one of `contract_id` or `contract_address` must be provided in the request body. """ + if verify is True: + requests: Set[Tuple[str, str]] = { + (r.caller, r.request_id) for r in data.specifications + } + existing_requests = contracts_actions.get_call_request_from_tuple( + db_session=db_session, + registered_contract_id=data.contract_id, + requests=requests, + ) + + if len(existing_requests) != 0: + existing_request_ids = [str(r.request_id) for r in existing_requests] + raise EngineHTTPException( + status_code=409, + detail=f"Call request with request_id's: [{','.join(existing_request_ids)}] already registered", + ) + try: num_requests = contracts_actions.create_request_calls( db_session=db_session,