Sergei Sumarokov 2024-05-02 16:52:20 +00:00 zatwierdzone przez GitHub
commit 07aeb52c51
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
3 zmienionych plików z 105 dodań i 10 usunięć

Wyświetl plik

@ -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
@ -71,6 +71,12 @@ class CallRequestAlreadyRegistered(Exception):
"""
class CallRequestIdDuplicates(Exception):
"""
Raised when same call request IDs passed in one request.
"""
def parse_registered_contract_response(
obj: Tuple[RegisteredContract, Blockchain]
) -> data.RegisteredContractResponse:
@ -431,6 +437,38 @@ def create_request_calls(
return len(call_specs)
def get_call_request_from_tuple(
db_session: Session,
metatx_requester_id: uuid.UUID,
requests: Set[Tuple[str, str]],
contract_id: Optional[uuid.UUID] = None,
contract_address: Optional[str] = None,
) -> List[CallRequest]:
if contract_id is None and contract_address is None:
raise ValueError(
"At least one of contract_id or contract_address must be specified"
)
query = (
db_session.query(CallRequest)
.join(
RegisteredContract,
CallRequest.registered_contract_id == RegisteredContract.id,
)
.filter(RegisteredContract.metatx_requester_id == metatx_requester_id)
.filter(tuple_(CallRequest.caller, CallRequest.request_id).in_(requests))
)
if contract_id is not None:
query = query.filter(RegisteredContract.id == contract_id)
if contract_address is not None:
query = query.filter(
RegisteredContract.address == Web3.toChecksumAddress(contract_address)
)
existing_requests = query.all()
return existing_requests
def get_call_request(
db_session: Session,
request_id: uuid.UUID,

Wyświetl plik

@ -1,6 +1,6 @@
from datetime import datetime
from enum import Enum
from typing import Any, Dict, List, Optional, Set
from typing import Any, Dict, List, Optional, Set, Tuple
from uuid import UUID
from bugout.data import BugoutResource
@ -329,6 +329,10 @@ class CallRequestResponse(BaseModel):
return Web3.toChecksumAddress(v)
class CallRequestsCheck(BaseModel):
existing_requests: Set[Tuple[str, str]] = Field(default_factory=set)
class CompleteCallRequestsAPIRequest(BaseModel):
tx_hash: str

Wyświetl plik

@ -5,14 +5,16 @@ 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
from fastapi import Body, Depends, FastAPI, Form, Path, Query, Request
from sqlalchemy.exc import NoResultFound
from sqlalchemy.orm import Session
from web3 import Web3
from .. import contracts_actions, data, db
from ..middleware import (
@ -316,6 +318,57 @@ async def list_requests_route(
return [contracts_actions.parse_call_request_response(r) for r in requests]
@app.get(
"/requests/check",
response_model=data.CallRequestsCheck,
)
async def check_requests_route(
request_data: data.CreateCallRequestsAPIRequest = Body(...),
user: BugoutUser = Depends(request_user_auth),
db_session: Session = Depends(db.yield_db_session),
) -> data.CallRequestsCheck:
"""
Implemented for pre-check until list of requests to be pushed into database.
"""
try:
incoming_requests: Set[Tuple[str, str]] = set()
incoming_request_ids: List[str] = []
for r in request_data.specifications:
caller_addr = Web3.toChecksumAddress(r.caller)
incoming_requests.add((caller_addr, r.request_id))
incoming_request_ids.append(r.request_id)
if len(incoming_requests) != len(incoming_request_ids):
raise contracts_actions.CallRequestIdDuplicates(
"There are same call_request_id's in one request"
)
existing_requests = contracts_actions.get_call_request_from_tuple(
db_session=db_session,
metatx_requester_id=user.id,
requests=incoming_requests,
contract_id=request_data.contract_id,
contract_address=request_data.contract_address,
)
except contracts_actions.CallRequestIdDuplicates:
raise EngineHTTPException(
status_code=400, detail="There are same call_request_id's in one request"
)
except Exception as err:
logger.error(repr(err))
raise EngineHTTPException(status_code=500)
existing_requests_set: Set[Tuple[str, str]] = set()
if len(existing_requests) != 0:
existing_requests_set = {
(er.caller, str(er.request_id)) for er in existing_requests
}
return data.CallRequestsCheck(
existing_requests=existing_requests_set,
)
@app.get(
"/requests/{request_id}", tags=["requests"], response_model=data.CallRequestResponse
)
@ -348,7 +401,7 @@ async def get_request(
@app.post("/requests", tags=["requests"], response_model=int)
async def create_requests(
data: data.CreateCallRequestsAPIRequest = Body(...),
request_data: data.CreateCallRequestsAPIRequest = Body(...),
user: BugoutUser = Depends(request_user_auth),
db_session: Session = Depends(db.yield_db_session),
) -> int:
@ -361,11 +414,11 @@ async def create_requests(
num_requests = contracts_actions.create_request_calls(
db_session=db_session,
metatx_requester_id=user.id,
registered_contract_id=data.contract_id,
contract_address=data.contract_address,
call_specs=data.specifications,
ttl_days=data.ttl_days,
live_at=data.live_at,
registered_contract_id=request_data.contract_id,
contract_address=request_data.contract_address,
call_specs=request_data.specifications,
ttl_days=request_data.ttl_days,
live_at=request_data.live_at,
)
except contracts_actions.InvalidAddressFormat as err:
raise EngineHTTPException(