diff --git a/src/lumino/api_sdk/whitelist.py b/src/lumino/api_sdk/whitelist.py new file mode 100644 index 0000000..ba5f205 --- /dev/null +++ b/src/lumino/api_sdk/whitelist.py @@ -0,0 +1,93 @@ +# Add to lumino/api_sdk/models.py +from enum import Enum +from typing import Optional +from pydantic import BaseModel, EmailStr + + +class WhitelistRequestCreate(BaseModel): + """ + Request model for creating a new whitelist request. + """ + name: str + email: EmailStr + phone_number: str + + +class WhitelistRequestResponse(BaseModel): + """ + Response model for whitelist request data. + """ + id: str + user_id: str + name: str + email: EmailStr + phone_number: str + is_whitelisted: bool + has_signed_nda: bool + created_at: str + updated_at: str + +class WhitelistClient: + """ + Client for whitelist operations. + """ + + def __init__(self, http_client): + self.http_client = http_client + + async def request_to_be_whitelisted(self, request: WhitelistRequestCreate) -> WhitelistRequestResponse: + """ + Submit a new whitelist request. + + Args: + request: The whitelist request data. + + Returns: + The created whitelist request. + """ + response = await self.http_client.post("/whitelist", request.dict()) + return WhitelistRequestResponse(**response) + + async def get_whitelist_status(self) -> WhitelistRequestResponse: + """ + Get the current user's whitelist status. + + Returns: + The whitelist status. + """ + response = await self.http_client.get("/whitelist") + return WhitelistRequestResponse(**response) + + async def add_computing_providers_batch(self, addresses: List[str]) -> Dict[str, Any]: + """ + Add multiple computing providers to the whitelist in a batch. + + Args: + addresses: List of computing provider addresses to whitelist + + Returns: + Dictionary with operation results including transaction hash + """ + payload = {"addresses": addresses} + response = await self.http_client.post("/whitelist/computing-providers/batch", payload) + return response + + + async def remove_computing_providers_batch(self, addresses: List[str]) -> Dict[str, Any]: + """ + Remove multiple computing providers from the whitelist in a batch. + + Args: + addresses: List of computing provider addresses to remove + + Returns: + Dictionary with operation results including transaction hash + """ + payload = {"addresses": addresses} + response = await self.http_client.delete("/whitelist/computing-providers/batch", json=payload) + return response + + +@property +def whitelist(self) -> WhitelistClient: + return WhitelistClient(self.http_client) \ No newline at end of file diff --git a/tests_e2e/test_runner.py b/tests_e2e/test_runner.py index 4d9db2d..f2a3fec 100644 --- a/tests_e2e/test_runner.py +++ b/tests_e2e/test_runner.py @@ -131,6 +131,7 @@ async def run_tests(self) -> bool: from test_fine_tuning import test_fine_tuning_operations from test_usage import test_usage_operations from test_billing import test_billing_operations + from test_whitelist import test_whitelist_operations, test_duplicate_whitelist_request console.print("=== Running tests ===") @@ -142,7 +143,9 @@ async def run_tests(self) -> bool: test_model_operations, test_fine_tuning_operations, test_usage_operations, - test_billing_operations + test_billing_operations, + test_whitelist_operations, + test_duplicate_whitelist_request ] # Create progress display diff --git a/tests_e2e/test_whitelist.py b/tests_e2e/test_whitelist.py new file mode 100644 index 0000000..aa0d6d8 --- /dev/null +++ b/tests_e2e/test_whitelist.py @@ -0,0 +1,110 @@ +import asyncio +from typing import TYPE_CHECKING + +from logger import get_logger +from lumino.api_sdk.models import WhitelistRequestCreate +from utils import TestData, generate_test_name + +if TYPE_CHECKING: + from test_runner import TestRunner + +logger = get_logger(__name__) +test_data = TestData() + + +async def test_whitelist_operations(runner: 'TestRunner') -> None: + """ + Test whitelist operations. + + Tests: + - Submit a whitelist request + - Get current whitelist status + """ + logger.info("Starting whitelist operations test") + + # Generate test data for the whitelist request + test_name = generate_test_name("whitelist-user") + test_email = f"{test_name}@example.com" + test_phone = "1234567890" + + # Create a whitelist request + logger.info(f"Submitting whitelist request for {test_name}") + + whitelist_request = WhitelistRequestCreate( + name=test_name, + email=test_email, + phone_number=test_phone + ) + + whitelist = await runner.sdk.whitelist.request_to_be_whitelisted(whitelist_request) + + # Store the whitelist request ID for potential cleanup + test_data.set('test_whitelist_id', str(whitelist.id)) + + # Verify the whitelist request was created successfully + assert whitelist.name == test_name, f"Whitelist name mismatch. Expected: {test_name}, got: {whitelist.name}" + assert whitelist.email == test_email, f"Whitelist email mismatch" + assert whitelist.phone_number == test_phone, f"Whitelist phone number mismatch" + assert whitelist.is_whitelisted is False, "New whitelist request should not be pre-approved" + assert whitelist.has_signed_nda is False, "New whitelist request should not have NDA signed" + + logger.info(f"Successfully created whitelist request with ID: {whitelist.id}") + + # Retrieve whitelist status + logger.info("Retrieving whitelist status") + status = await runner.sdk.whitelist.get_whitelist_status() + + # Verify the retrieved status matches what we created + assert status.id == whitelist.id, "Whitelist ID mismatch in status response" + assert status.name == test_name, "Whitelist name mismatch in status response" + assert status.is_whitelisted is False, "Whitelist approval status mismatch" + assert status.has_signed_nda is False, "NDA status mismatch" + + logger.info("Whitelist operations test completed successfully") + + +async def test_duplicate_whitelist_request(runner: 'TestRunner') -> None: + """ + Test that submitting a duplicate whitelist request fails appropriately. + This test should run after test_whitelist_operations. + """ + logger.info("Starting duplicate whitelist request test") + + # Generate new test data + test_name = generate_test_name("duplicate-whitelist") + test_email = f"{test_name}@example.com" + test_phone = "9876543210" + + whitelist_request = WhitelistRequestCreate( + name=test_name, + email=test_email, + phone_number=test_phone + ) + + try: + # This should fail since a whitelist request already exists for this user + await runner.sdk.whitelist.request_to_be_whitelisted(whitelist_request) + # If we get here, the test failed + assert False, "Duplicate whitelist request should have been rejected" + except Exception as e: + # Verify the error is about a duplicate request + logger.info(f"Received expected error for duplicate request: {str(e)}") + assert "already has a whitelist request" in str(e).lower(), "Unexpected error message" + + logger.info("Duplicate whitelist request test completed successfully") + + +if __name__ == "__main__": + # For manual testing + from test_runner import TestRunner + + async def run_test(): + runner = TestRunner() + try: + await runner.setup() + await test_whitelist_operations(runner) + await test_duplicate_whitelist_request(runner) + finally: + await runner.cleanup() + + asyncio.run(run_test()) \ No newline at end of file