From 503e8616215ccc3bdbf41775ab19bd45bd1b3c7b Mon Sep 17 00:00:00 2001 From: Shroominic Date: Sat, 9 Aug 2025 14:55:26 -0300 Subject: [PATCH] change dir 'router' -> 'routstr' --- Dockerfile | 3 +- Makefile | 8 +- README.md | 2 +- compose.testing.yml | 9 +- compose.yml | 6 +- migrations/env.py | 4 +- pyproject.toml | 12 ++- {router => routstr}/__init__.py | 0 {router => routstr}/auth.py | 0 {router => routstr}/balance.py | 0 {router => routstr}/core/__init__.py | 0 {router => routstr}/core/admin.py | 0 {router => routstr}/core/db.py | 0 {router => routstr}/core/logging.py | 23 ++--- {router => routstr}/core/main.py | 0 {router => routstr}/discovery.py | 0 {router => routstr}/payment/__init__.py | 0 .../payment/cost_caculation.py | 0 {router => routstr}/payment/helpers.py | 0 {router => routstr}/payment/models.py | 0 {router => routstr}/payment/price.py | 0 {router => routstr}/payment/x_cashu.py | 0 {router => routstr}/proxy.py | 0 {router => routstr}/wallet.py | 0 setup.py | 19 ---- tests/integration/conftest.py | 42 ++++---- tests/integration/run_performance_tests.py | 2 +- tests/integration/test_background_tasks.py | 62 ++++++------ .../integration/test_database_consistency.py | 8 +- .../test_error_handling_edge_cases.py | 10 +- tests/integration/test_performance_load.py | 2 +- tests/integration/test_provider_management.py | 95 +++++++++++-------- tests/integration/test_proxy_get_endpoints.py | 2 +- .../integration/test_wallet_authentication.py | 2 +- tests/integration/test_wallet_information.py | 2 +- tests/integration/test_wallet_refund.py | 12 +-- tests/integration/test_wallet_topup.py | 10 +- tests/integration/utils.py | 2 +- tests/integration/verify_setup.py | 4 +- tests/unit/README.md | 2 +- tests/unit/test_payment_helpers.py | 14 +-- tests/unit/test_wallet.py | 26 ++--- uv.lock | 4 +- 43 files changed, 193 insertions(+), 194 deletions(-) rename {router => routstr}/__init__.py (100%) rename {router => routstr}/auth.py (100%) rename {router => routstr}/balance.py (100%) rename {router => routstr}/core/__init__.py (100%) rename {router => routstr}/core/admin.py (100%) rename {router => routstr}/core/db.py (100%) rename {router => routstr}/core/logging.py (96%) rename {router => routstr}/core/main.py (100%) rename {router => routstr}/discovery.py (100%) rename {router => routstr}/payment/__init__.py (100%) rename {router => routstr}/payment/cost_caculation.py (100%) rename {router => routstr}/payment/helpers.py (100%) rename {router => routstr}/payment/models.py (100%) rename {router => routstr}/payment/price.py (100%) rename {router => routstr}/payment/x_cashu.py (100%) rename {router => routstr}/proxy.py (100%) rename {router => routstr}/wallet.py (100%) delete mode 100644 setup.py diff --git a/Dockerfile b/Dockerfile index ba15bfb8..b17f1ed8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,6 +12,7 @@ RUN apk add --no-cache \ RUN apk add git COPY uv.lock pyproject.toml ./ +COPY routstr ./routstr RUN uv add git+https://github.com/saschanaz/secp256k1-py.git#branch=upgrade060 # RUN uv sync @@ -25,4 +26,4 @@ ENV PYTHONUNBUFFERED=1 EXPOSE 8000 -CMD ["/.venv/bin/fastapi", "run", "router", "--host", "0.0.0.0"] +CMD ["/.venv/bin/fastapi", "run", "routstr", "--host", "0.0.0.0"] diff --git a/Makefile b/Makefile index b965ef57..79215dec 100644 --- a/Makefile +++ b/Makefile @@ -92,7 +92,7 @@ docker-down: lint: @echo "🔍 Running linting checks..." $(RUFF) check . - $(MYPY) router/ --ignore-missing-imports + $(MYPY) routstr/ --ignore-missing-imports format: @echo "✨ Formatting code..." @@ -101,7 +101,7 @@ format: type-check: @echo "🔎 Running type checks..." - $(MYPY) router/ --ignore-missing-imports + $(MYPY) routstr/ --ignore-missing-imports # Development setup dev-setup: @@ -209,7 +209,7 @@ db-clean: # Advanced testing options test-coverage: @echo "📊 Running tests with coverage..." - $(PYTEST) --cov=router --cov-report=html --cov-report=term + $(PYTEST) --cov=routstr --cov-report=html --cov-report=term @echo "Coverage report generated in htmlcov/" test-watch: @@ -228,7 +228,7 @@ ci-test: ci-lint: @echo "🤖 Running CI linting..." $(RUFF) check . --exit-non-zero-on-fix - $(MYPY) router/ --ignore-missing-imports --no-error-summary + $(MYPY) routstr/ --ignore-missing-imports --no-error-summary # Debug helpers test-debug: diff --git a/README.md b/README.md index b762a208..25fc25c2 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ cp .env.example .env ### Running Locally ```bash -fastapi run router --host 0.0.0.0 --port 8000 +fastapi run routstr --host 0.0.0.0 --port 8000 ``` The service forwards requests to `UPSTREAM_BASE_URL`. Supply the upstream API key via the `UPSTREAM_API_KEY` environment variable if required. diff --git a/compose.testing.yml b/compose.testing.yml index cb85d55b..36532d91 100644 --- a/compose.testing.yml +++ b/compose.testing.yml @@ -1,9 +1,9 @@ version: '3.8' services: - router: + routstr: build: . - command: ["/.venv/bin/fastapi", "dev", "router", "--host", "0.0.0.0", "--port", "8000"] + command: ["/.venv/bin/fastapi", "dev", "routstr", "--host", "0.0.0.0", "--port", "8000"] ports: - "8000:8000" environment: @@ -27,9 +27,6 @@ services: - "REFUND_PROCESSING_INTERVAL=3600" - "MINIMUM_PAYOUT=1000" - "PAYOUT_INTERVAL=86400" - volumes: - - ./:/app - - ./logs:/app/logs depends_on: - mock-mint - mock-openai @@ -40,8 +37,6 @@ services: restart: unless-stopped ports: - "8088:8080" # host:container - volumes: - - ./relay-data:/usr/src/app/db environment: - LISTEN_ADDR=0.0.0.0 - LISTEN_PORT=8080 diff --git a/compose.yml b/compose.yml index 8b0f67f2..65b22c31 100644 --- a/compose.yml +++ b/compose.yml @@ -1,7 +1,7 @@ version: '3.8' services: - router: + routstr: build: . volumes: - .:/app @@ -21,9 +21,9 @@ services: - tor-data:/var/lib/tor environment: # Format: HS_=:: - - HS_ROUTER=router:8000:80 + - HS_ROUTER=routstr:8000:80 depends_on: - - router + - routstr volumes: tor-data: diff --git a/migrations/env.py b/migrations/env.py index e62499fa..180c259a 100644 --- a/migrations/env.py +++ b/migrations/env.py @@ -9,10 +9,10 @@ from sqlalchemy.engine import Connection from sqlalchemy.ext.asyncio import create_async_engine from sqlmodel import SQLModel -# Add the parent directory to the Python path so we can import router modules +# Add the parent directory to the Python path so we can import routstr modules sys.path.insert(0, str(pathlib.Path(__file__).resolve().parents[1])) -from router.core.db import DATABASE_URL +from routstr.core.db import DATABASE_URL config = context.config if config.config_file_name is None: diff --git a/pyproject.toml b/pyproject.toml index 7d25a6c2..50ddaf1f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -58,6 +58,13 @@ markers = [ "performance: marks tests that measure performance metrics", ] +[build-system] +requires = ["setuptools", "wheel"] +build-backend = "setuptools.build_meta" + +[tool.setuptools] +packages = ["routstr"] + [tool.ruff.lint] select = ["E", "F", "I"] ignore = ["E501"] @@ -72,8 +79,5 @@ disallow_incomplete_defs = true disallow_untyped_decorators = true [tool.uv.sources] -secp256k1 = { git = "https://github.com/saschanaz/secp256k1-py", branch = "upgrade060" } routstr = { workspace = true } - -[tool.uv.workspace] -members = ["."] +secp256k1 = { git = "https://github.com/saschanaz/secp256k1-py", branch = "upgrade060" } diff --git a/router/__init__.py b/routstr/__init__.py similarity index 100% rename from router/__init__.py rename to routstr/__init__.py diff --git a/router/auth.py b/routstr/auth.py similarity index 100% rename from router/auth.py rename to routstr/auth.py diff --git a/router/balance.py b/routstr/balance.py similarity index 100% rename from router/balance.py rename to routstr/balance.py diff --git a/router/core/__init__.py b/routstr/core/__init__.py similarity index 100% rename from router/core/__init__.py rename to routstr/core/__init__.py diff --git a/router/core/admin.py b/routstr/core/admin.py similarity index 100% rename from router/core/admin.py rename to routstr/core/admin.py diff --git a/router/core/db.py b/routstr/core/db.py similarity index 100% rename from router/core/db.py rename to routstr/core/db.py diff --git a/router/core/logging.py b/routstr/core/logging.py similarity index 96% rename from router/core/logging.py rename to routstr/core/logging.py index 9820b747..79690ac7 100644 --- a/router/core/logging.py +++ b/routstr/core/logging.py @@ -89,7 +89,7 @@ def get_package_version() -> str: return version current_path = current_path.parent - # Fallback: try the simple path resolution (3 levels up for router/logging/logging_config.py) + # Fallback: try the simple path resolution (3 levels up for routstr/logging/logging_config.py) pyproject_path = Path(__file__).parent.parent.parent / "pyproject.toml" if pyproject_path.exists(): with open(pyproject_path, "rb") as f: @@ -229,27 +229,22 @@ def setup_logging() -> None: }, }, "loggers": { - "router": { + "routstr": { + "level": log_level, + "handlers": handlers, + "propagate": True, + }, + "routstr.payment": { "level": log_level, "handlers": handlers, "propagate": False, }, - "router.payment": { + "routstr.proxy": { "level": log_level, "handlers": handlers, "propagate": False, }, - "router.cashu": { - "level": log_level, - "handlers": handlers, - "propagate": False, - }, - "router.proxy": { - "level": log_level, - "handlers": handlers, - "propagate": False, - }, - "router.auth": { + "routstr.auth": { "level": log_level, "handlers": handlers, "propagate": False, diff --git a/router/core/main.py b/routstr/core/main.py similarity index 100% rename from router/core/main.py rename to routstr/core/main.py diff --git a/router/discovery.py b/routstr/discovery.py similarity index 100% rename from router/discovery.py rename to routstr/discovery.py diff --git a/router/payment/__init__.py b/routstr/payment/__init__.py similarity index 100% rename from router/payment/__init__.py rename to routstr/payment/__init__.py diff --git a/router/payment/cost_caculation.py b/routstr/payment/cost_caculation.py similarity index 100% rename from router/payment/cost_caculation.py rename to routstr/payment/cost_caculation.py diff --git a/router/payment/helpers.py b/routstr/payment/helpers.py similarity index 100% rename from router/payment/helpers.py rename to routstr/payment/helpers.py diff --git a/router/payment/models.py b/routstr/payment/models.py similarity index 100% rename from router/payment/models.py rename to routstr/payment/models.py diff --git a/router/payment/price.py b/routstr/payment/price.py similarity index 100% rename from router/payment/price.py rename to routstr/payment/price.py diff --git a/router/payment/x_cashu.py b/routstr/payment/x_cashu.py similarity index 100% rename from router/payment/x_cashu.py rename to routstr/payment/x_cashu.py diff --git a/router/proxy.py b/routstr/proxy.py similarity index 100% rename from router/proxy.py rename to routstr/proxy.py diff --git a/router/wallet.py b/routstr/wallet.py similarity index 100% rename from router/wallet.py rename to routstr/wallet.py diff --git a/setup.py b/setup.py deleted file mode 100644 index 4d7fd57a..00000000 --- a/setup.py +++ /dev/null @@ -1,19 +0,0 @@ -from setuptools import find_packages, setup - -setup( - name="routstr", - version="0.1.0", - packages=find_packages(), - install_requires=[ - "fastapi[standard]>=0.115", - "aiosqlite>=0.20", - "sqlmodel>=0.0.24", - "httpx[socks]>=0.25.2", - "greenlet>=3.2.1", - "python-json-logger>=2.0.0", - "cashu", - "secp256k1", - "marshmallow>=3.13,<4.0", - ], - python_requires=">=3.11", -) \ No newline at end of file diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index bc9f8d13..16344318 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -11,7 +11,7 @@ from httpx import AsyncClient from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine from sqlmodel import select -from router.core.logging import get_logger +from routstr.core.logging import get_logger logger = get_logger(__name__) @@ -25,7 +25,7 @@ if use_local_services: "DATABASE_URL": "sqlite+aiosqlite:///:memory:", "UPSTREAM_BASE_URL": "http://localhost:3000", # Mock OpenAI service "UPSTREAM_API_KEY": "test-upstream-key", - "CASHU_MINTS": "http://mint:3338", # Docker service name for router validation + "CASHU_MINTS": "http://mint:3338", # Docker service name for routstr validation "MINT": "http://mint:3338", "MINT_URL": "http://mint:3338", "NOSTR_RELAY_URL": "ws://localhost:8088", @@ -63,8 +63,8 @@ else: # Set test environment variables before importing the app os.environ.update(test_env) -from router.core.db import ApiKey, get_session # noqa: E402 -from router.core.main import app, lifespan # noqa: E402 +from routstr.core.db import ApiKey, get_session # noqa: E402 +from routstr.core.main import app, lifespan # noqa: E402 @pytest.fixture(scope="session") @@ -157,7 +157,7 @@ class TestmintWallet: mint_response = await wallet.mint(amount=amount, hash=quote) token = mint_response.token - # Replace connection URL with Docker service name for router validation + # Replace connection URL with Docker service name for routstr validation if self.connection_url != self.mint_url: token = token.replace(self.connection_url, self.mint_url) @@ -251,7 +251,7 @@ class TestmintWallet: async def send_token( self, amount: int, unit: str, mint_url: Optional[str] = None ) -> str: - """Send token with compatible signature for mocking router.wallet.send_token""" + """Send token with compatible signature for mocking routstr.wallet.send_token""" return await self.send(amount) async def send_to_lnurl(self, lnurl: str, amount: int) -> int: @@ -501,25 +501,25 @@ async def integration_app( if use_real_mint: # Use real mint - no wallet patches needed - with patch("router.core.db.engine", integration_engine): + with patch("routstr.core.db.engine", integration_engine): yield test_app else: # Use testmint with wallet patches for all integration tests mint_url = os.environ.get("CASHU_MINTS", "http://localhost:3338") with ( - patch("router.core.db.engine", integration_engine), - patch("router.wallet.TRUSTED_MINTS", [mint_url]), - patch("router.wallet.PRIMARY_MINT_URL", mint_url), - patch("router.auth.credit_balance", testmint_wallet.credit_balance), - patch("router.wallet.credit_balance", testmint_wallet.credit_balance), - patch("router.balance.credit_balance", testmint_wallet.credit_balance), - patch("router.wallet.send_token", testmint_wallet.send_token), - patch("router.balance.send_token", testmint_wallet.send_token), - patch("router.wallet.recieve_token", testmint_wallet.redeem_token), - patch("router.wallet.get_balance", testmint_wallet.get_balance), + patch("routstr.core.db.engine", integration_engine), + patch("routstr.wallet.TRUSTED_MINTS", [mint_url]), + patch("routstr.wallet.PRIMARY_MINT_URL", mint_url), + patch("routstr.auth.credit_balance", testmint_wallet.credit_balance), + patch("routstr.wallet.credit_balance", testmint_wallet.credit_balance), + patch("routstr.balance.credit_balance", testmint_wallet.credit_balance), + patch("routstr.wallet.send_token", testmint_wallet.send_token), + patch("routstr.balance.send_token", testmint_wallet.send_token), + patch("routstr.wallet.recieve_token", testmint_wallet.redeem_token), + patch("routstr.wallet.get_balance", testmint_wallet.get_balance), patch("websockets.connect") as mock_websockets, - patch("router.payment.price.btc_usd_ask_price", return_value=50000.0), - patch("router.payment.price.sats_usd_ask_price", return_value=0.0005), + patch("routstr.payment.price.btc_usd_ask_price", return_value=50000.0), + patch("routstr.payment.price.sats_usd_ask_price", return_value=0.0005), ): # Configure the WebSocket mock for discovery service - fast failure for performance tests async def mock_websocket_connect(*args: Any, **kwargs: Any) -> None: @@ -689,8 +689,8 @@ async def background_tasks_controller() -> AsyncGenerator[Any, None]: original_periodic_payout: Optional[Callable] = None try: - from router.payment.models import update_sats_pricing - from router.wallet import periodic_payout + from routstr.payment.models import update_sats_pricing + from routstr.wallet import periodic_payout async def controlled_update_pricing() -> None: while not controller.cancelled: diff --git a/tests/integration/run_performance_tests.py b/tests/integration/run_performance_tests.py index 5fcec67b..d41b6690 100755 --- a/tests/integration/run_performance_tests.py +++ b/tests/integration/run_performance_tests.py @@ -139,7 +139,7 @@ async def main() -> None: print("WARNING: Proxy server may not be running properly") except Exception: print("ERROR: Proxy server is not running!") - print("Please start the server with: uvicorn router.main:app") + print("Please start the server with: uvicorn routstr.main:app") sys.exit(1) # Run performance tests diff --git a/tests/integration/test_background_tasks.py b/tests/integration/test_background_tasks.py index 3f87603f..de387286 100644 --- a/tests/integration/test_background_tasks.py +++ b/tests/integration/test_background_tasks.py @@ -9,9 +9,9 @@ from unittest.mock import AsyncMock, patch import pytest -from router.core.db import ApiKey -from router.payment.models import MODELS, Model, Pricing, update_sats_pricing -from router.wallet import periodic_payout +from routstr.core.db import ApiKey +from routstr.payment.models import MODELS, Model, Pricing, update_sats_pricing +from routstr.wallet import periodic_payout @pytest.mark.asyncio @@ -24,7 +24,7 @@ class TestPricingUpdateTask: mock_sats_usd = 0.00002 # 1 sat = $0.00002 (BTC at $50,000) with patch( - "router.payment.price.sats_usd_ask_price", + "routstr.payment.price.sats_usd_ask_price", AsyncMock(return_value=mock_sats_usd), ): # Create a test model @@ -114,7 +114,7 @@ class TestPricingUpdateTask: raise Exception("Price API error") return 0.00002 - with patch("router.payment.price.sats_usd_ask_price", mock_price_func): + with patch("routstr.payment.price.sats_usd_ask_price", mock_price_func): # Test the retry behavior directly # First call should fail try: @@ -122,7 +122,7 @@ class TestPricingUpdateTask: assert False, "Expected exception on first call" except Exception: pass - + # Second call should succeed result = await mock_price_func() assert result == 0.00002 @@ -165,7 +165,7 @@ class TestPricingUpdateTask: try: with patch( - "router.payment.price.sats_usd_ask_price", + "routstr.payment.price.sats_usd_ask_price", AsyncMock(return_value=0.00002), ): # Initialize pricing once to ensure consistent state @@ -214,9 +214,9 @@ class TestRefundCheckTask: # Mock the wallet send_to_lnurl method and get_session with ( patch( - "router.wallet.send_to_lnurl", AsyncMock(return_value=5) + "routstr.wallet.send_to_lnurl", AsyncMock(return_value=5) ) as mock_send_to_lnurl, - patch("router.core.db.get_session") as mock_get_session, + patch("routstr.core.db.get_session") as mock_get_session, ): # Make get_session return our integration session async def get_test_session() -> Any: @@ -279,9 +279,9 @@ class TestRefundCheckTask: with ( patch( - "router.wallet.send_to_lnurl", mock_send_to_lnurl + "routstr.wallet.send_to_lnurl", mock_send_to_lnurl ) as mock_send_to_lnurl_patch, - patch("router.core.db.get_session") as mock_get_session, + patch("routstr.core.db.get_session") as mock_get_session, ): # Make get_session return our integration session async def get_test_session() -> Any: @@ -366,9 +366,9 @@ class TestRefundCheckTask: with ( patch( - "router.wallet.send_to_lnurl", AsyncMock(return_value=1) + "routstr.wallet.send_to_lnurl", AsyncMock(return_value=1) ) as mock_send_to_lnurl, - patch("router.core.db.get_session") as mock_get_session, + patch("routstr.core.db.get_session") as mock_get_session, ): # Make get_session return our integration session async def get_test_session() -> Any: @@ -424,7 +424,7 @@ class TestRefundCheckTask: # async def test_refund_check_disabled(self) -> None: # """Test that refund check can be disabled by setting interval to 0""" # # Patch the constant directly to disable refunds - # with patch.object(router.wallet, "REFUND_PROCESSING_INTERVAL", 0): + # with patch.object(routstr.wallet, "REFUND_PROCESSING_INTERVAL", 0): # # Task should exit immediately # task = asyncio.create_task(check_for_refunds()) # await task # Should complete without hanging @@ -466,9 +466,9 @@ class TestPeriodicPayoutTask: wallet_balance = 200000 # 200 sats total with ( - patch("router.wallet.get_balance", AsyncMock(return_value=wallet_balance)), + patch("routstr.wallet.get_balance", AsyncMock(return_value=wallet_balance)), patch( - "router.wallet.send_to_lnurl", AsyncMock(return_value=None) + "routstr.wallet.send_to_lnurl", AsyncMock(return_value=None) ) as mock_send_to_lnurl, ): # Mock environment variables @@ -481,7 +481,7 @@ class TestPeriodicPayoutTask: }, ): # Call periodic_payout directly (pay_out was renamed/refactored) - from router.wallet import periodic_payout + from routstr.wallet import periodic_payout await periodic_payout() @@ -506,7 +506,7 @@ class TestPeriodicPayoutTask: # integration_session.add(key) # await integration_session.commit() - # with patch("router.cashu.wallet") as mock_wallet: + # with patch("routstr.cashu.wallet") as mock_wallet: # mock_wallet_instance = AsyncMock() # mock_wallet_instance.balance = AsyncMock( # return_value=100000 @@ -522,7 +522,7 @@ class TestPeriodicPayoutTask: # "DEV_LN_ADDRESS": "dev@test.com", # }, # ): - # from router.cashu import pay_out + # from routstr.cashu import pay_out # await pay_out() @@ -543,7 +543,7 @@ class TestPeriodicPayoutTask: # integration_session.add(key) # await integration_session.commit() - # with patch("router.cashu.wallet") as mock_wallet: + # with patch("routstr.cashu.wallet") as mock_wallet: # mock_wallet_instance = AsyncMock() # mock_wallet_instance.balance = AsyncMock( # return_value=96000 @@ -552,7 +552,7 @@ class TestPeriodicPayoutTask: # mock_wallet.return_value = mock_wallet_instance # with patch.dict(os.environ, {"MINIMUM_PAYOUT": "10"}): # 10 sats minimum - # from router.cashu import pay_out + # from routstr.cashu import pay_out # await pay_out() @@ -571,9 +571,9 @@ class TestTaskInteractions: # """Test that all tasks can run concurrently without issues""" # # Mock all external dependencies # with ( - # patch("router.payment.price.sats_usd_ask_price", AsyncMock(return_value=0.00002)), - # patch("router.cashu.wallet") as mock_wallet, - # patch("router.cashu.pay_out", AsyncMock()), + # patch("routstr.payment.price.sats_usd_ask_price", AsyncMock(return_value=0.00002)), + # patch("routstr.cashu.wallet") as mock_wallet, + # patch("routstr.cashu.pay_out", AsyncMock()), # ): # mock_wallet_instance = AsyncMock() # mock_wallet_instance.send_to_lnurl = AsyncMock(return_value=1) @@ -587,7 +587,7 @@ class TestTaskInteractions: # tasks.append(pricing_task) # # Refund task (disabled to avoid interference) - # with patch.object(router.wallet, "REFUND_PROCESSING_INTERVAL", 0): + # with patch.object(routstr.wallet, "REFUND_PROCESSING_INTERVAL", 0): # refund_task = asyncio.create_task(check_for_refunds()) # tasks.append(refund_task) @@ -621,7 +621,7 @@ class TestTaskInteractions: processing.set() await asyncio.sleep(2) # Simulate long operation - with patch("router.payment.price.sats_usd_ask_price", slow_task): + with patch("routstr.payment.price.sats_usd_ask_price", slow_task): # Start the pricing task task = asyncio.create_task(update_sats_pricing()) @@ -708,11 +708,15 @@ class TestTaskInteractions: # Patch the actual task functions with ( patch( - "router.payment.models.update_sats_pricing", + "routstr.payment.models.update_sats_pricing", lambda: task_with_cleanup("pricing"), ), - patch("router.wallet.periodic_payout", lambda: task_with_cleanup("refund")), - patch("router.wallet.periodic_payout", lambda: task_with_cleanup("payout")), + patch( + "routstr.wallet.periodic_payout", lambda: task_with_cleanup("refund") + ), + patch( + "routstr.wallet.periodic_payout", lambda: task_with_cleanup("payout") + ), ): # Start all tasks tasks = [ diff --git a/tests/integration/test_database_consistency.py b/tests/integration/test_database_consistency.py index d4abcb61..526811a3 100644 --- a/tests/integration/test_database_consistency.py +++ b/tests/integration/test_database_consistency.py @@ -11,7 +11,7 @@ from sqlalchemy.exc import IntegrityError from sqlalchemy.ext.asyncio import AsyncSession from sqlmodel import select -from router.core.db import ApiKey +from routstr.core.db import ApiKey class TestTransactionAtomicity: @@ -114,7 +114,7 @@ class TestTransactionAtomicity: initial_balance = api_key.balance # Mock wallet to fail after token validation - with patch("router.wallet.send_token") as mock_wallet_func: + with patch("routstr.wallet.send_token") as mock_wallet_func: mock_proof = MagicMock() mock_proof.amount = 1000 mock_wallet = AsyncMock() @@ -256,7 +256,7 @@ class TestConcurrentOperations: await integration_session.commit() # Mock wallet for topup - with patch("router.wallet.send_token") as mock_wallet_func: + with patch("routstr.wallet.send_token") as mock_wallet_func: mock_proof = MagicMock() mock_proof.amount = 2000 mock_wallet = AsyncMock() @@ -521,7 +521,7 @@ class TestPerformance: operation_times["select"].append((end - start) * 1000) # Convert to ms # Test UPDATE performance (via topup) - with patch("router.wallet.send_token") as mock_wallet_func: + with patch("routstr.wallet.send_token") as mock_wallet_func: mock_proof = MagicMock() mock_proof.amount = 100 mock_wallet = AsyncMock() diff --git a/tests/integration/test_error_handling_edge_cases.py b/tests/integration/test_error_handling_edge_cases.py index 53e74630..8d519f14 100644 --- a/tests/integration/test_error_handling_edge_cases.py +++ b/tests/integration/test_error_handling_edge_cases.py @@ -10,7 +10,7 @@ from httpx import AsyncClient, ConnectError from sqlalchemy.ext.asyncio import AsyncSession from sqlmodel import select -from router.core.db import ApiKey +from routstr.core.db import ApiKey class TestNetworkFailureScenarios: @@ -26,11 +26,11 @@ class TestNetworkFailureScenarios: # Patch the wallet send function to simulate failure across all modules with ( patch( - "router.wallet.send_token", + "routstr.wallet.send_token", AsyncMock(side_effect=ConnectError("Mint service unavailable")), ), patch( - "router.balance.send_token", + "routstr.balance.send_token", AsyncMock(side_effect=ConnectError("Mint service unavailable")), ), ): @@ -46,8 +46,8 @@ class TestNetworkFailureScenarios: integration_session: AsyncSession, ) -> None: """Test proxy behavior when upstream LLM service is down""" - # Mock at the router level to simulate upstream being down - with patch("router.proxy.httpx.AsyncClient") as mock_client_class: + # Mock at the routstr level to simulate upstream being down + with patch("routstr.proxy.httpx.AsyncClient") as mock_client_class: # Create a mock client instance mock_client = AsyncMock() mock_client_class.return_value = mock_client diff --git a/tests/integration/test_performance_load.py b/tests/integration/test_performance_load.py index d75340fa..581553b9 100644 --- a/tests/integration/test_performance_load.py +++ b/tests/integration/test_performance_load.py @@ -149,7 +149,7 @@ class TestPerformanceBaseline: """Test database operation performance""" from sqlmodel import select - from router.core.db import ApiKey + from routstr.core.db import ApiKey # Create test data for i in range(100): diff --git a/tests/integration/test_provider_management.py b/tests/integration/test_provider_management.py index a2b0aff5..1ea5a321 100644 --- a/tests/integration/test_provider_management.py +++ b/tests/integration/test_provider_management.py @@ -43,9 +43,9 @@ async def test_providers_endpoint_default_response( } with patch( - "router.discovery.query_nostr_relay_for_providers", return_value=mock_events + "routstr.discovery.query_nostr_relay_for_providers", return_value=mock_events ): - with patch("router.discovery.fetch_provider_health") as mock_fetch: + with patch("routstr.discovery.fetch_provider_health") as mock_fetch: # Configure mock to return appropriate responses mock_fetch.side_effect = lambda url: mock_fetch_responses.get( url, {"status_code": 500, "json": {"error": "Unknown provider"}} @@ -100,9 +100,9 @@ async def test_providers_endpoint_with_include_json( } with patch( - "router.discovery.query_nostr_relay_for_providers", return_value=mock_events + "routstr.discovery.query_nostr_relay_for_providers", return_value=mock_events ): - with patch("router.discovery.fetch_provider_health") as mock_fetch: + with patch("routstr.discovery.fetch_provider_health") as mock_fetch: mock_fetch.return_value = { "status_code": 200, "json": mock_provider_response, @@ -155,7 +155,7 @@ async def test_providers_data_structure_validation( ["description", "A comprehensive AI provider"], ["model", "gpt-3.5-turbo"], ["model", "gpt-4"], - ] + ], } ] @@ -165,15 +165,15 @@ async def test_providers_data_structure_validation( "json": { "data": [ {"id": "gpt-3.5-turbo", "object": "model"}, - {"id": "gpt-4", "object": "model"} + {"id": "gpt-4", "object": "model"}, ] - } + }, } with patch( - "router.discovery.query_nostr_relay_for_providers", return_value=mock_events + "routstr.discovery.query_nostr_relay_for_providers", return_value=mock_events ): - with patch("router.discovery.fetch_provider_health") as mock_fetch: + with patch("routstr.discovery.fetch_provider_health") as mock_fetch: mock_fetch.return_value = mock_health_response response = await integration_client.get("/v1/providers/?include_json=true") @@ -188,7 +188,7 @@ async def test_providers_data_structure_validation( # Should have provider and health keys based on actual implementation assert "provider" in provider_data assert "health" in provider_data - + provider_info = provider_data["provider"] # Expected fields from RIP-02 parser expected_fields = ["id", "name", "endpoint_url", "supported_models"] @@ -215,7 +215,7 @@ async def test_providers_endpoint_no_providers_found( mock_events: list[dict[str, Any]] = [] with patch( - "router.discovery.query_nostr_relay_for_providers", return_value=mock_events + "routstr.discovery.query_nostr_relay_for_providers", return_value=mock_events ): response = await integration_client.get("/v1/providers/") @@ -245,33 +245,41 @@ async def test_providers_endpoint_offline_providers( ["d", "healthy-provider"], ["endpoint", "http://healthy-provider.onion"], ["name", "Healthy Provider"], - ] + ], }, { "id": "event2", - "pubkey": "offline_provider_pubkey", + "pubkey": "offline_provider_pubkey", "created_at": 1234567891, "content": "Offline provider announcement", "tags": [ ["d", "offline-provider"], ["endpoint", "http://offline-provider.onion"], ["name", "Offline Provider"], - ] + ], }, ] # Mock one healthy and one offline provider def mock_fetch_provider_health(url: str) -> dict[str, Any]: if "healthy" in url: - return {"status_code": 200, "endpoint": "root", "json": {"status": "online"}} + return { + "status_code": 200, + "endpoint": "root", + "json": {"status": "online"}, + } else: - return {"status_code": 500, "endpoint": "error", "json": {"error": "Service unavailable"}} + return { + "status_code": 500, + "endpoint": "error", + "json": {"error": "Service unavailable"}, + } with patch( - "router.discovery.query_nostr_relay_for_providers", return_value=mock_events + "routstr.discovery.query_nostr_relay_for_providers", return_value=mock_events ): with patch( - "router.discovery.fetch_provider_health", + "routstr.discovery.fetch_provider_health", side_effect=mock_fetch_provider_health, ): response = await integration_client.get("/v1/providers/?include_json=true") @@ -286,10 +294,10 @@ async def test_providers_endpoint_offline_providers( for provider_data in data["providers"]: assert "provider" in provider_data assert "health" in provider_data - + provider_info = provider_data["provider"] health_info = provider_data["health"] - + if "offline" in provider_info["endpoint_url"]: # Offline provider should have error information in health assert health_info["status_code"] == 500 @@ -297,7 +305,10 @@ async def test_providers_endpoint_offline_providers( else: # Healthy provider should have successful health check assert health_info["status_code"] == 200 - assert "status" in health_info["json"] or "error" not in health_info["json"] + assert ( + "status" in health_info["json"] + or "error" not in health_info["json"] + ) @pytest.mark.integration @@ -318,7 +329,7 @@ async def test_providers_endpoint_duplicate_urls( ["d", "provider-1"], ["endpoint", "http://provider.onion"], ["name", "Provider"], - ] + ], }, { "id": "event2", @@ -329,15 +340,19 @@ async def test_providers_endpoint_duplicate_urls( ["d", "other-provider"], ["endpoint", "http://other-provider.onion"], ["name", "Other Provider"], - ] + ], }, ] with patch( - "router.discovery.query_nostr_relay_for_providers", return_value=mock_events + "routstr.discovery.query_nostr_relay_for_providers", return_value=mock_events ): - with patch("router.discovery.fetch_provider_health") as mock_fetch: - mock_fetch.return_value = {"status_code": 200, "endpoint": "root", "json": {"status": "online"}} + with patch("routstr.discovery.fetch_provider_health") as mock_fetch: + mock_fetch.return_value = { + "status_code": 200, + "endpoint": "root", + "json": {"status": "online"}, + } response = await integration_client.get("/v1/providers/") @@ -352,7 +367,7 @@ async def test_providers_endpoint_duplicate_urls( endpoint_urls = [] for provider_data in providers: endpoint_urls.append(provider_data["endpoint_url"]) - + unique_endpoints = set(endpoint_urls) assert len(unique_endpoints) == len(endpoint_urls) @@ -369,7 +384,7 @@ async def test_providers_endpoint_nostr_relay_failures( raise Exception("Connection to relay failed") with patch( - "router.discovery.query_nostr_relay_for_providers", side_effect=failing_query + "routstr.discovery.query_nostr_relay_for_providers", side_effect=failing_query ): response = await integration_client.get("/v1/providers/") @@ -407,9 +422,9 @@ async def test_providers_endpoint_malformed_urls( ] with patch( - "router.discovery.query_nostr_relay_for_providers", return_value=mock_events + "routstr.discovery.query_nostr_relay_for_providers", return_value=mock_events ): - with patch("router.discovery.fetch_provider_health") as mock_fetch: + with patch("routstr.discovery.fetch_provider_health") as mock_fetch: mock_fetch.return_value = {"status_code": 200, "json": {"status": "online"}} response = await integration_client.get("/v1/providers/") @@ -440,9 +455,9 @@ async def test_providers_endpoint_response_format( ] with patch( - "router.discovery.query_nostr_relay_for_providers", return_value=mock_events + "routstr.discovery.query_nostr_relay_for_providers", return_value=mock_events ): - with patch("router.discovery.fetch_provider_health") as mock_fetch: + with patch("routstr.discovery.fetch_provider_health") as mock_fetch: mock_fetch.return_value = {"status_code": 200, "json": {"status": "online"}} # Test default format @@ -490,9 +505,9 @@ async def test_providers_endpoint_performance(integration_client: AsyncClient) - validator = PerformanceValidator() with patch( - "router.discovery.query_nostr_relay_for_providers", return_value=mock_events + "routstr.discovery.query_nostr_relay_for_providers", return_value=mock_events ): - with patch("router.discovery.fetch_provider_health") as mock_fetch: + with patch("routstr.discovery.fetch_provider_health") as mock_fetch: mock_fetch.return_value = {"status_code": 200, "json": {"status": "online"}} # Test multiple requests @@ -530,9 +545,9 @@ async def test_providers_endpoint_concurrent_requests( ] with patch( - "router.discovery.query_nostr_relay_for_providers", return_value=mock_events + "routstr.discovery.query_nostr_relay_for_providers", return_value=mock_events ): - with patch("router.discovery.fetch_provider_health") as mock_fetch: + with patch("routstr.discovery.fetch_provider_health") as mock_fetch: mock_fetch.return_value = {"status_code": 200, "json": {"status": "online"}} # Create concurrent requests @@ -566,9 +581,9 @@ async def test_providers_endpoint_parameter_validation( ] with patch( - "router.discovery.query_nostr_relay_for_providers", return_value=mock_events + "routstr.discovery.query_nostr_relay_for_providers", return_value=mock_events ): - with patch("router.discovery.fetch_provider_health") as mock_fetch: + with patch("routstr.discovery.fetch_provider_health") as mock_fetch: mock_fetch.return_value = {"status_code": 200, "json": {"status": "online"}} # Test various parameter values @@ -617,9 +632,9 @@ async def test_no_database_changes_during_provider_operations( ] with patch( - "router.discovery.query_nostr_relay_for_providers", return_value=mock_events + "routstr.discovery.query_nostr_relay_for_providers", return_value=mock_events ): - with patch("router.discovery.fetch_provider_health") as mock_fetch: + with patch("routstr.discovery.fetch_provider_health") as mock_fetch: mock_fetch.return_value = {"status_code": 200, "json": {"status": "online"}} # Make multiple requests with different parameters diff --git a/tests/integration/test_proxy_get_endpoints.py b/tests/integration/test_proxy_get_endpoints.py index 777a26b7..3434b151 100644 --- a/tests/integration/test_proxy_get_endpoints.py +++ b/tests/integration/test_proxy_get_endpoints.py @@ -14,7 +14,7 @@ import pytest from httpx import AsyncClient from sqlmodel import select -from router.core.db import ApiKey +from routstr.core.db import ApiKey from .utils import ( ConcurrencyTester, diff --git a/tests/integration/test_wallet_authentication.py b/tests/integration/test_wallet_authentication.py index 504308dc..21a26f3b 100644 --- a/tests/integration/test_wallet_authentication.py +++ b/tests/integration/test_wallet_authentication.py @@ -11,7 +11,7 @@ import pytest from httpx import AsyncClient from sqlmodel import select -from router.core.db import ApiKey +from routstr.core.db import ApiKey from .utils import ( CashuTokenGenerator, diff --git a/tests/integration/test_wallet_information.py b/tests/integration/test_wallet_information.py index bae84cb4..6f24e895 100644 --- a/tests/integration/test_wallet_information.py +++ b/tests/integration/test_wallet_information.py @@ -11,7 +11,7 @@ import pytest from httpx import AsyncClient from sqlmodel import select, update -from router.core.db import ApiKey +from routstr.core.db import ApiKey from .utils import ConcurrencyTester, ResponseValidator diff --git a/tests/integration/test_wallet_refund.py b/tests/integration/test_wallet_refund.py index 17b4f965..db4f0177 100644 --- a/tests/integration/test_wallet_refund.py +++ b/tests/integration/test_wallet_refund.py @@ -13,8 +13,8 @@ import pytest from httpx import AsyncClient from sqlmodel import select -from router.core.db import ApiKey -from router.wallet import CurrencyUnit +from routstr.core.db import ApiKey +from routstr.wallet import CurrencyUnit @pytest.mark.integration @@ -207,12 +207,12 @@ async def test_refund_with_lightning_address( await db_snapshot.capture() # Mock send_to_lnurl function directly - with patch("router.balance.send_to_lnurl") as mock_send_to_lnurl: + with patch("routstr.balance.send_to_lnurl") as mock_send_to_lnurl: mock_send_to_lnurl.return_value = { "amount_sent": balance, "unit": "msat", "lnurl": refund_address, - "status": "completed" + "status": "completed", } # Request refund @@ -411,7 +411,7 @@ async def test_mint_unavailability_handling( # Make the send_token method raise an exception with patch( - "router.balance.send_token", + "routstr.balance.send_token", side_effect=Exception("Mint unavailable: Connection refused"), ): # The exception should propagate as a 503 error (Service Unavailable) @@ -534,7 +534,7 @@ async def test_refund_with_expired_key( integration_client.headers["Authorization"] = f"Bearer {api_key}" # Mock the refund to LN address - with patch("router.wallet.send_token") as mock_wallet_func: + with patch("routstr.wallet.send_token") as mock_wallet_func: mock_wallet = AsyncMock() mock_wallet.send_to_lnurl = AsyncMock(return_value=500) # type: ignore[method-assign] mock_wallet_func.return_value = mock_wallet diff --git a/tests/integration/test_wallet_topup.py b/tests/integration/test_wallet_topup.py index 90befdfd..6f4d5c29 100644 --- a/tests/integration/test_wallet_topup.py +++ b/tests/integration/test_wallet_topup.py @@ -11,7 +11,7 @@ import pytest from httpx import AsyncClient from sqlmodel import select -from router.core.db import ApiKey +from routstr.core.db import ApiKey from .utils import ( CashuTokenGenerator, @@ -425,7 +425,7 @@ async def test_network_failure_during_token_verification( # type: ignore[no-unt token = await testmint_wallet.mint_tokens(300) # Mock credit_balance to simulate network failure during token verification - with patch("router.balance.credit_balance") as mock_credit_balance: + with patch("routstr.balance.credit_balance") as mock_credit_balance: mock_credit_balance.side_effect = Exception("Network error: Connection timeout") response = await authenticated_client.post( @@ -470,7 +470,11 @@ async def test_topup_with_zero_amount_token( # type: ignore[no-untyped-def] # Create a token with 0 amount (edge case) # The testmint wallet should handle this - with patch.object(testmint_wallet, "redeem_token", return_value=(0, "sat", testmint_wallet.mint_url)): + with patch.object( + testmint_wallet, + "redeem_token", + return_value=(0, "sat", testmint_wallet.mint_url), + ): token = await testmint_wallet.mint_tokens(0) response = await authenticated_client.post( diff --git a/tests/integration/utils.py b/tests/integration/utils.py index 6adcd8d3..dd1fcf3d 100644 --- a/tests/integration/utils.py +++ b/tests/integration/utils.py @@ -9,7 +9,7 @@ import httpx from sqlalchemy.ext.asyncio import AsyncSession from sqlmodel import select -from router.core.db import ApiKey +from routstr.core.db import ApiKey class CashuTokenGenerator: diff --git a/tests/integration/verify_setup.py b/tests/integration/verify_setup.py index c828fe58..992da14c 100644 --- a/tests/integration/verify_setup.py +++ b/tests/integration/verify_setup.py @@ -43,8 +43,8 @@ def check_imports() -> bool: print("Conftest fixtures imported successfully") - # Check router modules - imports are for verification only - from router.core.db import ApiKey + # Check routstr modules - imports are for verification only + from routstr.core.db import ApiKey del ApiKey diff --git a/tests/unit/README.md b/tests/unit/README.md index 72280342..914eb173 100644 --- a/tests/unit/README.md +++ b/tests/unit/README.md @@ -21,7 +21,7 @@ pytest To run tests with coverage: ```bash -pytest --cov=router --cov-report=html +pytest --cov=routstr --cov-report=html ``` To run specific test files: diff --git a/tests/unit/test_payment_helpers.py b/tests/unit/test_payment_helpers.py index c167486b..5bd782e4 100644 --- a/tests/unit/test_payment_helpers.py +++ b/tests/unit/test_payment_helpers.py @@ -5,7 +5,7 @@ from unittest.mock import Mock, patch os.environ["UPSTREAM_BASE_URL"] = "http://test" os.environ["UPSTREAM_API_KEY"] = "test" -from router.payment.helpers import get_max_cost_for_model # noqa: E402 +from routstr.payment.helpers import get_max_cost_for_model # noqa: E402 def test_get_max_cost_for_model_known() -> None: @@ -14,21 +14,21 @@ def test_get_max_cost_for_model_known() -> None: mock_model.sats_pricing = Mock() mock_model.sats_pricing.max_cost = 500 - with patch("router.payment.helpers.MODELS", [mock_model]): - with patch("router.payment.helpers.MODEL_BASED_PRICING", True): + with patch("routstr.payment.helpers.MODELS", [mock_model]): + with patch("routstr.payment.helpers.MODEL_BASED_PRICING", True): cost = get_max_cost_for_model("gpt-4") assert cost == 500000 # 500 sats * 1000 = msats def test_get_max_cost_for_model_unknown() -> None: - with patch("router.payment.helpers.MODELS", []): - with patch("router.payment.helpers.COST_PER_REQUEST", 100): + with patch("routstr.payment.helpers.MODELS", []): + with patch("routstr.payment.helpers.COST_PER_REQUEST", 100): cost = get_max_cost_for_model("unknown-model") assert cost == 100 def test_get_max_cost_for_model_disabled() -> None: - with patch("router.payment.helpers.MODEL_BASED_PRICING", False): - with patch("router.payment.helpers.COST_PER_REQUEST", 200): + with patch("routstr.payment.helpers.MODEL_BASED_PRICING", False): + with patch("routstr.payment.helpers.COST_PER_REQUEST", 200): cost = get_max_cost_for_model("any-model") assert cost == 200 diff --git a/tests/unit/test_wallet.py b/tests/unit/test_wallet.py index fb5425e7..f0f21203 100644 --- a/tests/unit/test_wallet.py +++ b/tests/unit/test_wallet.py @@ -4,7 +4,7 @@ from unittest.mock import AsyncMock, Mock, patch import pytest -from router.wallet import credit_balance, get_balance, recieve_token, send_token +from routstr.wallet import credit_balance, get_balance, recieve_token, send_token @pytest.mark.asyncio @@ -13,7 +13,7 @@ async def test_get_balance() -> None: mock_wallet.available_balance = Mock(amount=50000) mock_wallet.load_proofs = AsyncMock() - with patch("router.wallet.Wallet.with_db", return_value=mock_wallet): + with patch("routstr.wallet.Wallet.with_db", return_value=mock_wallet): balance = await get_balance("sat") assert balance == 50000 @@ -38,8 +38,8 @@ async def test_recieve_token_valid() -> None: mock_wallet = Mock() mock_wallet.redeem = AsyncMock() - with patch("router.wallet.TRUSTED_MINTS", ["http://mint:3338"]): - with patch("router.wallet.deserialize_token_from_string") as mock_deserialize: + with patch("routstr.wallet.TRUSTED_MINTS", ["http://mint:3338"]): + with patch("routstr.wallet.deserialize_token_from_string") as mock_deserialize: mock_token = Mock() mock_token.keysets = ["keyset1"] mock_token.mint = "http://mint:3338" @@ -48,7 +48,7 @@ async def test_recieve_token_valid() -> None: mock_token.proofs = [{"amount": 1000}] mock_deserialize.return_value = mock_token - with patch("router.wallet.Wallet.with_db", return_value=mock_wallet): + with patch("routstr.wallet.Wallet.with_db", return_value=mock_wallet): mock_wallet.load_mint = AsyncMock() amount, unit, mint = await recieve_token(token_str) @@ -61,8 +61,8 @@ async def test_recieve_token_valid() -> None: async def test_send_token() -> None: mock_wallet = Mock() - with patch("router.wallet.Wallet.with_db", return_value=mock_wallet): - with patch("router.wallet.send", return_value=(1000, "test_token")): + with patch("routstr.wallet.Wallet.with_db", return_value=mock_wallet): + with patch("routstr.wallet.send", return_value=(1000, "test_token")): token = await send_token(1000, "sat", "http://mint:3338") assert token == "test_token" @@ -81,9 +81,9 @@ async def test_credit_balance() -> None: mock_key.balance = 5000000 mock_session = AsyncMock() - with patch("router.wallet.PRIMARY_MINT_URL", "http://mint:3338"): + with patch("routstr.wallet.PRIMARY_MINT_URL", "http://mint:3338"): with patch( - "router.wallet.recieve_token", + "routstr.wallet.recieve_token", return_value=(1000, "sat", "http://mint:3338"), ): amount = await credit_balance(token_str, mock_key, mock_session) @@ -99,7 +99,7 @@ async def test_credit_balance_invalid_mint() -> None: mock_session = AsyncMock() with patch( - "router.wallet.recieve_token", return_value=(1000, "sat", "http://other:3338") + "routstr.wallet.recieve_token", return_value=(1000, "sat", "http://other:3338") ): with pytest.raises(ValueError, match="Mint URL is not supported"): await credit_balance("test_token", mock_key, mock_session) @@ -109,7 +109,7 @@ async def test_credit_balance_invalid_mint() -> None: async def test_recieve_token_untrusted_mint() -> None: mock_wallet = Mock() - with patch("router.wallet.deserialize_token_from_string") as mock_deserialize: + with patch("routstr.wallet.deserialize_token_from_string") as mock_deserialize: mock_token = Mock() mock_token.keysets = ["keyset1"] mock_token.mint = "http://untrusted:3338" @@ -117,10 +117,10 @@ async def test_recieve_token_untrusted_mint() -> None: mock_token.amount = 1000 mock_deserialize.return_value = mock_token - with patch("router.wallet.Wallet.with_db", return_value=mock_wallet): + with patch("routstr.wallet.Wallet.with_db", return_value=mock_wallet): mock_wallet.load_mint = AsyncMock() with patch( - "router.wallet.swap_to_primary_mint", + "routstr.wallet.swap_to_primary_mint", return_value=(900, "sat", "http://mint:3338"), ): amount, unit, mint = await recieve_token("test_token") diff --git a/uv.lock b/uv.lock index 642223ea..9276ccdd 100644 --- a/uv.lock +++ b/uv.lock @@ -1768,7 +1768,7 @@ wheels = [ [[package]] name = "routstr" version = "0.1.0" -source = { virtual = "." } +source = { editable = "." } dependencies = [ { name = "aiosqlite" }, { name = "alembic" }, @@ -1822,7 +1822,7 @@ dev = [ { name = "pytest-asyncio", specifier = ">=0.24.0" }, { name = "pytest-benchmark", specifier = ">=4.0.0" }, { name = "pytest-cov", specifier = ">=6.1.1" }, - { name = "routstr", virtual = "." }, + { name = "routstr", editable = "." }, { name = "ruff", specifier = ">=0.11.6" }, ]