Request type PK name and default set to dropper if not specified

pull/882/head
kompotkot 2023-08-08 12:17:49 +00:00
rodzic 1bd2f3706b
commit ba78712cc5
4 zmienionych plików z 67 dodań i 86 usunięć

Wyświetl plik

@ -50,26 +50,19 @@ def upgrade():
# Types # Types
op.create_table('call_request_types', op.create_table('call_request_types',
sa.Column('id', sa.UUID(), nullable=False), sa.Column('name', sa.VARCHAR(length=128), nullable=False),
sa.Column('request_type', sa.VARCHAR(length=128), nullable=False),
sa.Column('description', sa.String(), nullable=True), sa.Column('description', sa.String(), nullable=True),
sa.Column('required_params', postgresql.ARRAY(sa.String()), nullable=True), sa.PrimaryKeyConstraint('name', name=op.f('pk_call_request_types')),
sa.Column('method', sa.String(), nullable=True), sa.UniqueConstraint('name', name=op.f('uq_call_request_types_name'))
sa.PrimaryKeyConstraint('id', name=op.f('pk_call_request_types')),
sa.UniqueConstraint('id', name=op.f('uq_call_request_types_id'))
) )
op.create_index(op.f('ix_call_request_types_request_type'), 'call_request_types', ['request_type'], unique=True) op.add_column('call_requests', sa.Column('call_request_type_name', sa.VARCHAR(length=128), nullable=True))
op.create_foreign_key(op.f('fk_call_requests_call_request_type_name_call_request_types'), 'call_requests', 'call_request_types', ['call_request_type_name'], ['name'], ondelete='CASCADE')
op.add_column('call_requests', sa.Column('call_request_type_id', sa.UUID(), nullable=True))
op.create_foreign_key(op.f('fk_call_requests_call_request_type_id_call_request_types'), 'call_requests', 'call_request_types', ['call_request_type_id'], ['id'], ondelete='CASCADE')
# Manual - Start # Manual - Start
op.execute(f"INSERT INTO call_request_types (id, request_type, description, required_params, method) VALUES ('{str(uuid.uuid4())}', 'raw', 'A generic smart contract. You can ask users to submit arbitrary calldata to this contract.',ARRAY ['calldata'],''),('{str(uuid.uuid4())}', 'dropper-v0.2.0', 'A Dropper v0.2.0 contract. You can authorize users to submit claims against this contract.',ARRAY ['dropId','requestID','blockDeadline','amount','signer','signature'],'claim');") op.execute(f"INSERT INTO call_request_types (name, description) VALUES ('raw','A generic smart contract. You can ask users to submit arbitrary calldata to this contract.'),('dropper-v0.2.0','A Dropper v0.2.0 contract. You can authorize users to submit claims against this contract.');")
op.execute("UPDATE call_requests SET call_request_type_id = (SELECT call_request_types.id FROM call_request_types INNER JOIN registered_contracts ON call_requests.registered_contract_id = registered_contracts.id WHERE call_request_types.request_type = registered_contracts.contract_type);") op.execute("UPDATE call_requests SET call_request_type_name = (SELECT call_request_types.name FROM call_request_types INNER JOIN registered_contracts ON call_requests.registered_contract_id = registered_contracts.id WHERE call_request_types.name = registered_contracts.contract_type);")
op.alter_column("call_requests", "call_request_type_id", nullable=False) op.alter_column("call_requests", "call_request_type_name", nullable=False)
op.alter_column("call_request_types", "required_params", nullable=False)
op.alter_column("call_request_types", "method", nullable=False)
# Manual - End # Manual - End
op.drop_index('ix_registered_contracts_contract_type', table_name='registered_contracts') op.drop_index('ix_registered_contracts_contract_type', table_name='registered_contracts')
@ -105,10 +98,10 @@ def upgrade():
# Other # Other
op.create_unique_constraint(op.f('uq_registered_contracts_blockchain_id'), 'registered_contracts', ['blockchain_id', 'metatx_requester_id', 'address']) op.create_unique_constraint(op.f('uq_registered_contracts_blockchain_id'), 'registered_contracts', ['blockchain_id', 'metatx_requester_id', 'address'])
op.create_unique_constraint(op.f('uq_call_requests_id'), 'call_requests', ['id']) # op.create_unique_constraint(op.f('uq_call_requests_id'), 'call_requests', ['id'])
op.create_unique_constraint(op.f('uq_registered_contracts_id'), 'registered_contracts', ['id']) # op.create_unique_constraint(op.f('uq_registered_contracts_id'), 'registered_contracts', ['id'])
op.create_unique_constraint(op.f('uq_leaderboard_scores_id'), 'leaderboard_scores', ['id']) # op.create_unique_constraint(op.f('uq_leaderboard_scores_id'), 'leaderboard_scores', ['id'])
op.create_unique_constraint(op.f('uq_leaderboards_id'), 'leaderboards', ['id']) # op.create_unique_constraint(op.f('uq_leaderboards_id'), 'leaderboards', ['id'])
# ### end Alembic commands ### # ### end Alembic commands ###

Wyświetl plik

@ -82,14 +82,14 @@ def parse_registered_contract_response(
def parse_call_request_response( def parse_call_request_response(
obj: Tuple[CallRequest, RegisteredContract, CallRequestType, CallRequestType] obj: Tuple[CallRequest, RegisteredContract]
) -> data.CallRequestResponse: ) -> data.CallRequestResponse:
return data.CallRequestResponse( return data.CallRequestResponse(
id=obj[0].id, id=obj[0].id,
contract_id=obj[0].registered_contract_id, contract_id=obj[0].registered_contract_id,
contract_address=obj[1].address, contract_address=obj[1].address,
metatx_requester_id=obj[0].metatx_requester_id, metatx_requester_id=obj[0].metatx_requester_id,
call_request_type=obj[2].request_type, call_request_type=obj[0].call_request_type_name,
caller=obj[0].caller, caller=obj[0].caller,
method=obj[0].method, method=obj[0].method,
parameters=obj[0].parameters, parameters=obj[0].parameters,
@ -100,38 +100,48 @@ def parse_call_request_response(
def validate_method_and_params( def validate_method_and_params(
call_request_type: str, method: str, parameters: Dict[str, Any], call_request_type: Optional[str] = None
method: str, ) -> str:
parameters: Dict[str, Any],
request_types: List[CallRequestType],
) -> CallRequestType:
""" """
Validate the given method and parameters for the specified contract_type. Validate the given method and parameters for the specified contract_type.
""" """
for rt in request_types: if call_request_type is None or call_request_type == "dropper-v0.2.0":
if rt.request_type == call_request_type: call_request_type = "dropper-v0.2.0"
if method != rt.method: if method != "claim":
raise CallRequestMethodValueError( raise CallRequestMethodValueError(
f"Method must be {rt.method} for {rt.request_type} request type" "Method must be 'claim' for dropper contract type"
) )
required_params = {
required_params_set = set(rt.required_params) "dropId",
if set(parameters.keys()) != required_params_set: "requestID",
"blockDeadline",
"amount",
"signer",
"signature",
}
if set(parameters.keys()) != required_params:
raise CallRequestRequiredParamsValueError( raise CallRequestRequiredParamsValueError(
f"Parameters must have only {rt.required_params} key for {rt.request_type} request type" f"Parameters must have {required_params} keys for dropper contract type"
) )
if "signer" in parameters:
try: try:
Web3.toChecksumAddress(parameters["signer"]) Web3.toChecksumAddress(parameters["signer"])
except: except:
raise InvalidAddressFormat( raise InvalidAddressFormat("Parameter signer must be a valid address")
"Parameter signer must be a valid address"
elif call_request_type == "raw":
if method != "":
raise CallRequestMethodValueError(
"Method must be empty string for raw contract type"
)
if set(parameters.keys()) != {"calldata"}:
raise CallRequestRequiredParamsValueError(
"Parameters must have only 'calldata' key for raw contract type"
) )
return rt else:
raise UnsupportedCallRequestType(f"Unknown contract type {call_request_type}")
raise UnsupportedCallRequestType(f"Unknown request type {call_request_type}") return call_request_type
def register_contract( def register_contract(
@ -353,8 +363,6 @@ def request_calls(
except NoResultFound: except NoResultFound:
raise ValueError("Invalid registered_contract_id or metatx_requester_id") raise ValueError("Invalid registered_contract_id or metatx_requester_id")
request_types = db_session.query(CallRequestType).all()
# Normalize the caller argument using Web3.toChecksumAddress # Normalize the caller argument using Web3.toChecksumAddress
for specification in call_specs: for specification in call_specs:
normalized_caller = Web3.toChecksumAddress(specification.caller) normalized_caller = Web3.toChecksumAddress(specification.caller)
@ -362,10 +370,9 @@ def request_calls(
# Validate the method and parameters for the contract_type # Validate the method and parameters for the contract_type
try: try:
call_request_type = validate_method_and_params( call_request_type = validate_method_and_params(
specification.call_request_type, method=specification.method,
specification.method, parameters=specification.parameters,
specification.parameters, call_request_type=specification.call_request_type,
request_types,
) )
except UnsupportedCallRequestType as err: except UnsupportedCallRequestType as err:
raise UnsupportedCallRequestType(err) raise UnsupportedCallRequestType(err)
@ -379,6 +386,7 @@ def request_calls(
logger.error( logger.error(
f"Unhandled error occurred during methods and parameters validation, err: {err}" f"Unhandled error occurred during methods and parameters validation, err: {err}"
) )
raise Exception()
expires_at = None expires_at = None
if ttl_days is not None: if ttl_days is not None:
@ -386,7 +394,7 @@ def request_calls(
request = CallRequest( request = CallRequest(
registered_contract_id=registered_contract.id, registered_contract_id=registered_contract.id,
call_request_type_id=call_request_type.id, call_request_type_name=call_request_type,
metatx_requester_id=metatx_requester_id, metatx_requester_id=metatx_requester_id,
caller=normalized_caller, caller=normalized_caller,
method=specification.method, method=specification.method,
@ -408,20 +416,16 @@ def request_calls(
def get_call_requests( def get_call_requests(
db_session: Session, db_session: Session,
request_id: uuid.UUID, request_id: uuid.UUID,
) -> Tuple[CallRequest, RegisteredContract, CallRequestType, CallRequestType]: ) -> Tuple[CallRequest, RegisteredContract]:
""" """
Get call request by ID. Get call request by ID.
""" """
results = ( results = (
db_session.query(CallRequest, RegisteredContract, CallRequestType) db_session.query(CallRequest, RegisteredContract)
.join( .join(
RegisteredContract, RegisteredContract,
CallRequest.registered_contract_id == RegisteredContract.id, CallRequest.registered_contract_id == RegisteredContract.id,
) )
.join(
CallRequestType,
CallRequest.call_request_type_id == CallRequestType.id,
)
.filter(CallRequest.id == request_id) .filter(CallRequest.id == request_id)
.all() .all()
) )
@ -432,9 +436,9 @@ def get_call_requests(
f"Incorrect number of results found for request_id {request_id}" f"Incorrect number of results found for request_id {request_id}"
) )
call_request, registered_contract, call_request_type = results[0] call_request, registered_contract = results[0]
return (call_request, registered_contract, call_request_type) return (call_request, registered_contract)
def list_blockchains( def list_blockchains(
@ -473,15 +477,11 @@ def list_call_requests(
# If show_expired is False, filter out expired requests using current time on database server # If show_expired is False, filter out expired requests using current time on database server
query = ( query = (
db_session.query(CallRequest, RegisteredContract, CallRequestType) db_session.query(CallRequest, RegisteredContract)
.join( .join(
RegisteredContract, RegisteredContract,
CallRequest.registered_contract_id == RegisteredContract.id, CallRequest.registered_contract_id == RegisteredContract.id,
) )
.join(
CallRequestType,
CallRequest.call_request_type_id == CallRequestType.id,
)
.filter(CallRequest.caller == Web3.toChecksumAddress(caller)) .filter(CallRequest.caller == Web3.toChecksumAddress(caller))
) )

Wyświetl plik

@ -204,8 +204,7 @@ class DropUpdatedResponse(BaseModel):
class CallRequestTypeResponse(BaseModel): class CallRequestTypeResponse(BaseModel):
id: UUID name: str
request_type: str
description: str description: str
class Config: class Config:
@ -271,7 +270,7 @@ class RegisteredContractResponse(BaseModel):
class CallSpecification(BaseModel): class CallSpecification(BaseModel):
caller: str caller: str
method: str method: str
call_request_type: str call_request_type: Optional[str] = None
parameters: Dict[str, Any] parameters: Dict[str, Any]
@validator("caller") @validator("caller")

Wyświetl plik

@ -165,22 +165,12 @@ class CallRequestType(Base): # type: ignore
__tablename__ = "call_request_types" __tablename__ = "call_request_types"
id = Column( name = Column(
UUID(as_uuid=True), VARCHAR(128),
primary_key=True, primary_key=True,
default=uuid.uuid4,
unique=True, unique=True,
) )
request_type = Column(VARCHAR(128), nullable=False, unique=True, index=True)
description = Column(String, nullable=True) description = Column(String, nullable=True)
required_params = Column(ARRAY(String), nullable=False)
method = Column(String, nullable=False)
call_requests = relationship(
"CallRequest",
back_populates="call_request_type",
cascade="all, delete, delete-orphan",
)
class MetatxRequester(Base): # type: ignore class MetatxRequester(Base): # type: ignore
@ -301,9 +291,9 @@ class CallRequest(Base):
ForeignKey("registered_contracts.id", ondelete="CASCADE"), ForeignKey("registered_contracts.id", ondelete="CASCADE"),
nullable=False, nullable=False,
) )
call_request_type_id = Column( call_request_type_name = Column(
UUID(as_uuid=True), VARCHAR(128),
ForeignKey("call_request_types.id", ondelete="CASCADE"), ForeignKey("call_request_types.name", ondelete="CASCADE"),
nullable=False, nullable=False,
) )
metatx_requester_id = Column( metatx_requester_id = Column(
@ -332,7 +322,6 @@ class CallRequest(Base):
registered_contract = relationship( registered_contract = relationship(
"RegisteredContract", back_populates="call_requests" "RegisteredContract", back_populates="call_requests"
) )
call_request_type = relationship("CallRequestType", back_populates="call_requests")
metatx_requester = relationship("MetatxRequester", back_populates="call_requests") metatx_requester = relationship("MetatxRequester", back_populates="call_requests")