diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7e093f365..a964bd59a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,9 +19,6 @@ jobs: os: [ubuntu-latest] python-version: ["3.10"] poetry-version: ["2.3.2"] - # Wallet v0 / deprecated mint API support was removed in https://github.com/cashubtc/nutshell/pull/814; deprecated-only CI runs are no longer valid. - # mint-only-deprecated: ["false", "true"] - mint-only-deprecated: ["false"] mint-database: ["./test_data/test_mint", "postgres://cashu:cashu@localhost:5432/cashu"] backend-wallet-class: ["FakeWallet"] uses: ./.github/workflows/tests.yml @@ -29,7 +26,6 @@ jobs: os: ${{ matrix.os }} python-version: ${{ matrix.python-version }} poetry-version: ${{ matrix.poetry-version }} - mint-only-deprecated: ${{ matrix.mint-only-deprecated }} mint-database: ${{ matrix.mint-database }} tests_redis_cache: diff --git a/.github/workflows/regtest-mint.yml b/.github/workflows/regtest-mint.yml index 73fac68e7..f083d5c94 100644 --- a/.github/workflows/regtest-mint.yml +++ b/.github/workflows/regtest-mint.yml @@ -25,7 +25,12 @@ permissions: jobs: regtest-mint: runs-on: ${{ inputs.os-version }} - timeout-minutes: 10 + # Was 10m; job was cancelled mid-suite (e.g. postgres + CoreLightningRestWallet) while tests still ran. + # PR discussion / follow-ups: + # - Is this ceiling OK, or should we tune (measure worst matrix cell)? + # - Cheaper isolation than DROP SCHEMA per test in tests/conftest.py `ledger`? + # - Lighter regtest matrix on PR vs full matrix on main or nightly? + timeout-minutes: 120 steps: - name: Start PostgreSQL service if: contains(inputs.mint-database, 'postgres') diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index df76444cd..193f77b4f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -15,16 +15,13 @@ on: os: default: "ubuntu-latest" type: string - mint-only-deprecated: - default: "false" - type: string permissions: contents: read jobs: poetry: - name: Run (db ${{ inputs.mint-database }}, deprecated api ${{ inputs.mint-only-deprecated }}) + name: Run (db ${{ inputs.mint-database }}) runs-on: ${{ inputs.os }} steps: - name: Start PostgreSQL service @@ -45,7 +42,6 @@ jobs: MINT_HOST: localhost MINT_PORT: 3337 MINT_TEST_DATABASE: ${{ inputs.mint-database }} - DEBUG_MINT_ONLY_DEPRECATED: ${{ inputs.mint-only-deprecated }} TOR: false run: | make test diff --git a/.github/workflows/tests_redis_cache.yml b/.github/workflows/tests_redis_cache.yml index e01c90abe..e33fc4812 100644 --- a/.github/workflows/tests_redis_cache.yml +++ b/.github/workflows/tests_redis_cache.yml @@ -15,16 +15,13 @@ on: os: default: "ubuntu-latest" type: string - mint-only-deprecated: - default: "false" - type: string permissions: contents: read jobs: poetry: - name: Run (db ${{ inputs.mint-database }}, deprecated api ${{ inputs.mint-only-deprecated }}) + name: Run (db ${{ inputs.mint-database }}) runs-on: ${{ inputs.os }} steps: - name: Start PostgreSQL service diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1220c6dc1..b9920f241 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -93,7 +93,3 @@ MINT_CORELIGHTNING_REST_CERT=../cashu-regtest-enviroment/data/clightning-2-rest/ ### Profiling If you'd like to profile your code (measure how long steps take to execute), run the mint using `DEBUG_PROFILING=TRUE`. Make sure to turn this off again, as your application will be significantly slower with profiling enabled. - -### V0 API only - -To run the mint with only V0 API support (deprecated), use `DEBUG_MINT_ONLY_DEPRECATED=TRUE` diff --git a/cashu/core/settings.py b/cashu/core/settings.py index 5f13a608f..fe6f3af96 100644 --- a/cashu/core/settings.py +++ b/cashu/core/settings.py @@ -43,7 +43,6 @@ class EnvSettings(CashuSettings): log_level: str = Field(default="INFO") cashu_dir: str = Field(default=os.path.join(str(Path.home()), ".cashu")) debug_profiling: bool = Field(default=False) - debug_mint_only_deprecated: bool = Field(default=False) db_backup_path: Optional[str] = Field(default=None) db_connection_pool: bool = Field(default=True) diff --git a/cashu/mint/app.py b/cashu/mint/app.py index 152974c1f..eb4cc221b 100644 --- a/cashu/mint/app.py +++ b/cashu/mint/app.py @@ -15,7 +15,6 @@ from ..core.settings import settings from .auth.router import auth_router from .router import redis, router -from .router_deprecated import router_deprecated from .startup import ( shutdown_management_rpc, shutdown_mint, @@ -118,11 +117,7 @@ async def catch_exceptions(request: Request, call_next): app.add_exception_handler(RequestValidationError, request_validation_exception_handler) # type: ignore # Add routers -if settings.debug_mint_only_deprecated: - app.include_router(router=router_deprecated, tags=["Deprecated"], deprecated=True) -else: - app.include_router(router=router, tags=["Mint"]) - app.include_router(router=router_deprecated, tags=["Deprecated"], deprecated=True) +app.include_router(router=router, tags=["Mint"]) if settings.mint_require_auth: app.include_router(auth_router, tags=["Auth"]) diff --git a/cashu/mint/router_deprecated.py b/cashu/mint/router_deprecated.py deleted file mode 100644 index 7a2c8ecb1..000000000 --- a/cashu/mint/router_deprecated.py +++ /dev/null @@ -1,384 +0,0 @@ -from typing import Dict, List, Optional - -from fastapi import APIRouter, Request -from loguru import logger - -from ..core.base import BlindedMessage, BlindedSignature, Unit -from ..core.errors import CashuError -from ..core.models import ( - CheckFeesRequest_deprecated, - CheckFeesResponse_deprecated, - CheckSpendableRequest_deprecated, - CheckSpendableResponse_deprecated, - GetInfoResponse_deprecated, - GetMintResponse_deprecated, - KeysetsResponse_deprecated, - KeysResponse_deprecated, - PostMeltQuoteRequest, - PostMeltRequest_deprecated, - PostMeltResponse_deprecated, - PostMintQuoteRequest, - PostMintRequest_deprecated, - PostMintResponse_deprecated, - PostRestoreRequest_Deprecated, - PostRestoreResponse, - PostSwapRequest_Deprecated, - PostSwapResponse_Deprecated, - PostSwapResponse_Very_Deprecated, -) -from ..core.settings import settings -from .limit import limiter -from .startup import ledger - -router_deprecated: APIRouter = APIRouter() - - -@router_deprecated.get( - "/info", - name="Mint information", - summary="Mint information, operator contact information, and other info.", - response_model=GetInfoResponse_deprecated, - response_model_exclude_none=True, - deprecated=True, -) -async def info() -> GetInfoResponse_deprecated: - logger.trace("> GET /info") - return GetInfoResponse_deprecated( - name=settings.mint_info_name, - pubkey=ledger.pubkey.format().hex() if ledger.pubkey else None, - version=f"Nutshell/{settings.version}", - description=settings.mint_info_description, - description_long=settings.mint_info_description_long, - contact=settings.mint_info_contact, - nuts=["NUT-07", "NUT-08", "NUT-09"], - motd=settings.mint_info_motd, - ) - - -@router_deprecated.get( - "/keys", - name="Mint public keys", - summary="Get the public keys of the newest mint keyset", - response_description=( - "A dictionary of all supported token values of the mint and their associated" - " public key of the current keyset." - ), - response_model=KeysResponse_deprecated, - deprecated=True, -) -async def keys_deprecated() -> Dict[str, str]: - """This endpoint returns a dictionary of all supported token values of the mint and their associated public key.""" - logger.trace("> GET /keys") - keyset = ledger.get_keyset() - keys = KeysResponse_deprecated.model_validate( - {str(k): v for k, v in keyset.items()} - ) - return keys.root - - -@router_deprecated.get( - "/keys/{idBase64Urlsafe}", - name="Keyset public keys", - summary="Public keys of a specific keyset", - response_description=( - "A dictionary of all supported token values of the mint and their associated" - " public key for a specific keyset." - ), - response_model=Dict[str, str], - deprecated=True, -) -async def keyset_deprecated(idBase64Urlsafe: str) -> Dict[str, str]: - """ - Get the public keys of the mint from a specific keyset id. - The id is encoded in idBase64Urlsafe (by a wallet) and is converted back to - normal base64 before it can be processed (by the mint). - """ - logger.trace(f"> GET /keys/{idBase64Urlsafe}") - id = idBase64Urlsafe.replace("-", "+").replace("_", "/") - keyset = ledger.get_keyset(keyset_id=id) - keys = KeysResponse_deprecated.model_validate( - {str(k): v for k, v in keyset.items()} - ) - return keys.root - - -@router_deprecated.get( - "/keysets", - name="Active keysets", - summary="Get all active keyset id of the mind", - response_model=KeysetsResponse_deprecated, - response_description="A list of all active keyset ids of the mint.", - deprecated=True, -) -async def keysets_deprecated() -> KeysetsResponse_deprecated: - """This endpoint returns a list of keysets that the mint currently supports and will accept tokens from.""" - logger.trace("> GET /keysets") - sat_keysets = {k: v for k, v in ledger.keysets.items() if v.unit == Unit.sat} - keysets = KeysetsResponse_deprecated(keysets=list(sat_keysets.keys())) - return keysets - - -@router_deprecated.get( - "/mint", - name="Request mint", - summary="Request minting of new tokens", - response_model=GetMintResponse_deprecated, - response_description=( - "A Lightning invoice to be paid and a hash to request minting of new tokens" - " after payment." - ), - deprecated=True, -) -@limiter.limit(f"{settings.mint_transaction_rate_limit_per_minute}/minute") -async def request_mint_deprecated( - request: Request, amount: int = 0 -) -> GetMintResponse_deprecated: - """ - Request minting of new tokens. The mint responds with a Lightning invoice. - This endpoint can be used for a Lightning invoice UX flow. - - Call `POST /mint` after paying the invoice. - """ - logger.trace(f"> GET /mint: amount={amount}") - if amount > 21_000_000 * 100_000_000 or amount <= 0: - raise CashuError(code=0, detail="Amount must be a valid amount of sat.") - if settings.mint_bolt11_disable_mint: - raise CashuError(code=0, detail="Mint does not allow minting new tokens.") - quote = await ledger.mint_quote(PostMintQuoteRequest(amount=amount, unit="sat")) - resp = GetMintResponse_deprecated(pr=quote.request, hash=quote.quote) - logger.trace(f"< GET /mint: {resp}") - return resp - - -@router_deprecated.post( - "/mint", - name="Mint tokens", - summary="Mint tokens in exchange for a Bitcoin payment that the user has made", - response_model=PostMintResponse_deprecated, - response_description=( - "A list of blinded signatures that can be used to create proofs." - ), - deprecated=True, -) -@limiter.limit(f"{settings.mint_transaction_rate_limit_per_minute}/minute") -async def mint_deprecated( - request: Request, - payload: PostMintRequest_deprecated, - hash: Optional[str] = None, - payment_hash: Optional[str] = None, -) -> PostMintResponse_deprecated: - """ - Requests the minting of tokens belonging to a paid payment request. - - Call this endpoint after `GET /mint`. - """ - logger.trace(f"> POST /mint: {payload}") - - # BEGIN BACKWARDS COMPATIBILITY < 0.15 - # Mint expects "id" in outputs to know which keyset to use to sign them. - outputs: list[BlindedMessage] = [ - BlindedMessage(id=ledger.keyset.id, **o.model_dump(exclude={"id"})) - for o in payload.outputs - ] - # END BACKWARDS COMPATIBILITY < 0.15 - - # BEGIN: backwards compatibility < 0.12 where we used to lookup payments with payment_hash - # We use the payment_hash to lookup the hash from the database and pass that one along. - hash = payment_hash or hash - assert hash, "hash must be set." - # END: backwards compatibility < 0.12 - - promises = await ledger.mint(outputs=outputs, quote_id=hash) - blinded_signatures = PostMintResponse_deprecated(promises=promises) - - logger.trace(f"< POST /mint: {blinded_signatures}") - return blinded_signatures - - -@router_deprecated.post( - "/melt", - name="Melt tokens", - summary=( - "Melt tokens for a Bitcoin payment that the mint will make for the user in" - " exchange" - ), - response_model=PostMeltResponse_deprecated, - response_description=( - "The state of the payment, a preimage as proof of payment, and a list of" - " promises for change." - ), - deprecated=True, -) -@limiter.limit(f"{settings.mint_transaction_rate_limit_per_minute}/minute") -async def melt_deprecated( - request: Request, - payload: PostMeltRequest_deprecated, -) -> PostMeltResponse_deprecated: - """ - Requests tokens to be destroyed and sent out via Lightning. - """ - logger.trace(f"> POST /melt: {payload}") - # BEGIN BACKWARDS COMPATIBILITY < 0.14: add "id" to outputs - if payload.outputs: - outputs: list[BlindedMessage] = [ - BlindedMessage(id=ledger.keyset.id, **o.dict(exclude={"id"})) - for o in payload.outputs - ] - else: - outputs = [] - # END BACKWARDS COMPATIBILITY < 0.14 - quote = await ledger.melt_quote( - PostMeltQuoteRequest(request=payload.pr, unit="sat") - ) - melt_resp = await ledger.melt( - proofs=payload.proofs, quote=quote.quote, outputs=outputs - ) - resp = PostMeltResponse_deprecated( - paid=True, preimage=melt_resp.payment_preimage, change=melt_resp.change - ) - logger.trace(f"< POST /melt: {resp}") - return resp - - -@router_deprecated.post( - "/checkfees", - name="Check fees", - summary="Check fee reserve for a Lightning payment", - response_model=CheckFeesResponse_deprecated, - response_description="The fees necessary to pay a Lightning invoice.", - deprecated=True, -) -async def check_fees( - payload: CheckFeesRequest_deprecated, -) -> CheckFeesResponse_deprecated: - """ - Responds with the fees necessary to pay a Lightning invoice. - Used by wallets for figuring out the fees they need to supply together with the payment amount. - This is can be useful for checking whether an invoice is internal (Cashu-to-Cashu). - """ - logger.trace(f"> POST /checkfees: {payload}") - quote = await ledger.melt_quote( - PostMeltQuoteRequest(request=payload.pr, unit="sat") - ) - fees_sat = quote.fee_reserve - logger.trace(f"< POST /checkfees: {fees_sat}") - return CheckFeesResponse_deprecated(fee=fees_sat) - - -@router_deprecated.post( - "/split", - name="Split", - summary="Split proofs at a specified amount", - # response_model=Union[ - # PostSwapResponse_Very_Deprecated, PostSwapResponse_Deprecated - # ], - response_description=( - "A list of blinded signatures that can be used to create proofs." - ), - deprecated=True, -) -@limiter.limit(f"{settings.mint_transaction_rate_limit_per_minute}/minute") -async def split_deprecated( - request: Request, - payload: PostSwapRequest_Deprecated, - # ) -> Union[PostSwapResponse_Very_Deprecated, PostSwapResponse_Deprecated]: -): - """ - Requests a set of Proofs to be split into two a new set of BlindedSignatures. - - This endpoint is used by Alice to split a set of proofs before making a payment to Carol. - It is then used by Carol (by setting split=total) to redeem the tokens. - """ - logger.trace(f"> POST /split: {payload}") - assert payload.outputs, Exception("no outputs provided.") - # BEGIN BACKWARDS COMPATIBILITY < 0.14: add "id" to outputs - outputs: list[BlindedMessage] = [ - BlindedMessage(id=ledger.keyset.id, **o.model_dump(exclude={"id"})) - for o in payload.outputs - ] - # END BACKWARDS COMPATIBILITY < 0.14 - promises = await ledger.swap(proofs=payload.proofs, outputs=outputs) - - if payload.amount: - # BEGIN backwards compatibility < 0.13 - # old clients expect two lists of promises where the second one's amounts - # sum up to `amount`. The first one is the rest. - # The returned value `promises` has the form [keep1, keep2, ..., send1, send2, ...] - # The sum of the sendx is `amount`. We need to split this into two lists and keep the order of the elements. - frst_promises: List[BlindedSignature] = [] - scnd_promises: List[BlindedSignature] = [] - scnd_amount = 0 - for promise in promises[::-1]: # we iterate backwards - if scnd_amount < payload.amount: - scnd_promises.insert(0, promise) # and insert at the beginning - scnd_amount += promise.amount - else: - frst_promises.insert(0, promise) # and insert at the beginning - logger.trace( - f"Split into keep: {len(frst_promises)}:" - f" {sum([p.amount for p in frst_promises])} sat and send:" - f" {len(scnd_promises)}: {sum([p.amount for p in scnd_promises])} sat" - ) - return PostSwapResponse_Very_Deprecated(fst=frst_promises, snd=scnd_promises) - # END backwards compatibility < 0.13 - else: - return PostSwapResponse_Deprecated(promises=promises) - - -@router_deprecated.post( - "/check", - name="Check proof state", - summary="Check whether a proof is spent already or is pending in a transaction", - response_model=CheckSpendableResponse_deprecated, - response_description=( - "Two lists of booleans indicating whether the provided proofs " - "are spendable or pending in a transaction respectively." - ), - deprecated=True, -) -async def check_spendable_deprecated( - payload: CheckSpendableRequest_deprecated, -) -> CheckSpendableResponse_deprecated: - """Check whether a secret has been spent already or not.""" - logger.trace(f"> POST /check: {payload}") - proofs_state = await ledger.db_read.get_proofs_states([p.Y for p in payload.proofs]) - spendableList: List[bool] = [] - pendingList: List[bool] = [] - for proof_state in proofs_state: - if proof_state.unspent: - spendableList.append(True) - pendingList.append(False) - elif proof_state.spent: - spendableList.append(False) - pendingList.append(False) - elif proof_state.pending: - spendableList.append(True) - pendingList.append(True) - return CheckSpendableResponse_deprecated( - spendable=spendableList, pending=pendingList - ) - - -@router_deprecated.post( - "/restore", - name="Restore", - summary="Restores a blinded signature from a secret", - response_model=PostRestoreResponse, - response_description=( - "Two lists with the first being the list of the provided outputs that " - "have an associated blinded signature which is given in the second list." - ), - deprecated=True, -) -async def restore(payload: PostRestoreRequest_Deprecated) -> PostRestoreResponse: - assert payload.outputs, Exception("no outputs provided.") - if payload.outputs: - outputs: list[BlindedMessage] = [ - BlindedMessage(id=ledger.keyset.id, **o.dict(exclude={"id"})) - for o in payload.outputs - ] - else: - outputs = [] - - outputs, promises = await ledger.restore(outputs) - return PostRestoreResponse(outputs=outputs, signatures=promises) diff --git a/tests/fuzz/test_fuzz_mint_api.py b/tests/fuzz/test_fuzz_mint_api.py index ef6e6786b..b647054f1 100644 --- a/tests/fuzz/test_fuzz_mint_api.py +++ b/tests/fuzz/test_fuzz_mint_api.py @@ -10,7 +10,6 @@ Proof, ) from cashu.mint.app import app -from tests.helpers import is_deprecated_api_only ALLOWED_STATUS_CODES = [400, 404, 405, 422, 503] @@ -56,9 +55,6 @@ def client(): with TestClient(app) as c: yield c -# Apply skip marker to all tests in this module if deprecated API is enabled -pytestmark = pytest.mark.skipif(is_deprecated_api_only, reason="Deprecated API enabled") - # Fuzzers @hypothesis_settings(suppress_health_check=[HealthCheck.function_scoped_fixture], max_examples=50) diff --git a/tests/fuzz/test_fuzz_mint_api_deprecated.py b/tests/fuzz/test_fuzz_mint_api_deprecated.py deleted file mode 100644 index c43945769..000000000 --- a/tests/fuzz/test_fuzz_mint_api_deprecated.py +++ /dev/null @@ -1,160 +0,0 @@ -import pytest -from fastapi.testclient import TestClient -from hypothesis import HealthCheck, given -from hypothesis import settings as hypothesis_settings -from hypothesis import strategies as st - -from cashu.core.models import ( - BlindedMessage, - Proof, -) -from cashu.mint.app import app -from tests.helpers import is_deprecated_api_only - -# Apply skip marker to all tests in this module if deprecated API is NOT enabled -pytestmark = pytest.mark.skipif(not is_deprecated_api_only, reason="Deprecated API not enabled") - -@pytest.fixture -def client(): - with TestClient(app) as c: - yield c - -# Define strategies -def hex_string(min_len=66, max_len=66): - return st.text(alphabet="0123456789abcdef", min_size=min_len, max_size=max_len) - -def valid_unit(): - return st.sampled_from(["sat", "usd", "eur", "msat"]) - -def public_key(): - return st.builds(lambda a, b: a + b, st.just("02"), hex_string(64, 64)) - -def keyset_id(): - return st.builds(lambda a, b: a + b, st.just("00"), hex_string(14, 14)) - -def url_safe_text(min_len=1, max_len=20): - # Generates text that is safe for URLs (no control chars, no slashes, no #, no ?) - return st.text(alphabet=st.characters(blacklist_categories=("Cc", "Cs", "Zl", "Zp", "Cn")), min_size=min_len, max_size=max_len).filter(lambda x: "/" not in x and "\\" not in x and "#" not in x and "?" not in x) - -# Strategy for BlindedMessage -blinded_message_strategy = st.builds( - BlindedMessage, - amount=st.integers(min_value=1), - id=st.one_of(keyset_id(), hex_string(16, 16)), - B_=st.one_of(hex_string(), public_key()), - C_=st.one_of(st.none(), public_key(), hex_string()) -) - -# Strategy for Proof -proof_strategy = st.builds( - Proof, - id=st.one_of(keyset_id(), hex_string(16, 16)), - amount=st.integers(min_value=1), - secret=st.text(min_size=1, max_size=64), - C=st.one_of(hex_string(), public_key()), - Y=st.one_of(public_key(), hex_string()) -) - -# Fuzzers for Deprecated API - -# GET /mint -@hypothesis_settings(suppress_health_check=[HealthCheck.function_scoped_fixture], max_examples=50) -@given(amount=st.integers()) -def test_fuzz_deprecated_mint_get(client, amount): - response = client.get(f"/mint?amount={amount}") - # Expecting either success or valid error codes - assert response.status_code in [200, 400, 404, 422, 503] - -# POST /mint -@hypothesis_settings(suppress_health_check=[HealthCheck.function_scoped_fixture], max_examples=50) -@given( - outputs=st.lists(blinded_message_strategy, min_size=1, max_size=10), - hash=st.one_of(st.none(), st.text(min_size=1, max_size=64)) -) -def test_fuzz_deprecated_mint_post(client, outputs, hash): - outputs_json = [o.model_dump() for o in outputs] - payload = {"outputs": outputs_json} - params = {} - if hash: - params["hash"] = hash - - response = client.post("/mint", json=payload, params=params) - assert response.status_code in [400, 404, 422, 503] - -# POST /melt -@hypothesis_settings(suppress_health_check=[HealthCheck.function_scoped_fixture], max_examples=50) -@given( - pr=st.text(min_size=1, max_size=500), - proofs=st.lists(proof_strategy, min_size=1, max_size=10), - outputs=st.one_of(st.none(), st.lists(blinded_message_strategy, min_size=1, max_size=5)) -) -def test_fuzz_deprecated_melt(client, pr, proofs, outputs): - inputs_json = [p.model_dump(exclude={'dleq', 'witness'}) for p in proofs] - outputs_json = [o.model_dump() for o in outputs] if outputs else None - - payload = { - "pr": pr, - "proofs": inputs_json, - "outputs": outputs_json - } - response = client.post("/melt", json=payload) - assert response.status_code in [400, 404, 422, 503] - -# POST /check -@hypothesis_settings(suppress_health_check=[HealthCheck.function_scoped_fixture], max_examples=50) -@given( - proofs=st.lists(proof_strategy, min_size=1, max_size=10) -) -def test_fuzz_deprecated_check(client, proofs): - inputs_json = [p.model_dump(exclude={'dleq', 'witness'}) for p in proofs] - payload = {"proofs": inputs_json} - - response = client.post("/check", json=payload) - if response.status_code == 200: - data = response.json() - # For random proofs (unknown to mint), they are considered UNSPENT - # So spendable should be True, pending should be False - assert len(data["spendable"]) == len(proofs) - assert len(data["pending"]) == len(proofs) - assert all(data["spendable"]) - assert not any(data["pending"]) - else: - assert response.status_code in [400, 404, 422, 503] - -# POST /split -@hypothesis_settings(suppress_health_check=[HealthCheck.function_scoped_fixture], max_examples=50) -@given( - proofs=st.lists(proof_strategy, min_size=1, max_size=10), - outputs=st.lists(blinded_message_strategy, min_size=1, max_size=10), - amount=st.one_of(st.none(), st.integers(min_value=1)) -) -def test_fuzz_deprecated_split(client, proofs, outputs, amount): - inputs_json = [p.model_dump(exclude={'dleq', 'witness'}) for p in proofs] - outputs_json = [o.model_dump() for o in outputs] - - payload = { - "proofs": inputs_json, - "outputs": outputs_json - } - if amount is not None: - payload["amount"] = amount - - response = client.post("/split", json=payload) - assert response.status_code in [400, 404, 422, 503] - -# POST /restore -@hypothesis_settings(suppress_health_check=[HealthCheck.function_scoped_fixture], max_examples=50) -@given( - outputs=st.lists(blinded_message_strategy, min_size=1, max_size=20) -) -def test_fuzz_deprecated_restore(client, outputs): - outputs_json = [o.model_dump() for o in outputs] - payload = {"outputs": outputs_json} - - response = client.post("/restore", json=payload) - if response.status_code == 200: - data = response.json() - assert data["outputs"] == [] - assert data["signatures"] == [] - else: - assert response.status_code in [400, 404, 422, 503] diff --git a/tests/helpers.py b/tests/helpers.py index a69cb9e23..73a43aaa1 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -65,7 +65,6 @@ async def get_random_invoice_data(): WALLET = wallet_class() is_fake: bool = WALLET.__class__.__name__ == "FakeWallet" is_regtest: bool = not is_fake -is_deprecated_api_only = settings.debug_mint_only_deprecated is_github_actions = os.getenv("GITHUB_ACTIONS") == "true" is_postgres = settings.mint_database.startswith("postgres") SLEEP_TIME = 1 if not is_github_actions else 2 diff --git a/tests/mint/test_mint_api.py b/tests/mint/test_mint_api.py index 2ff3c4e8d..f899c9a29 100644 --- a/tests/mint/test_mint_api.py +++ b/tests/mint/test_mint_api.py @@ -16,7 +16,6 @@ ) from cashu.core.nuts import nut20 from cashu.core.nuts.nuts import MINT_NUT -from cashu.core.settings import settings from cashu.mint.ledger import Ledger from cashu.wallet.crud import bump_secret_derivation from cashu.wallet.wallet import Wallet @@ -37,10 +36,6 @@ async def wallet(ledger: Ledger): @pytest.mark.asyncio -@pytest.mark.skipif( - settings.debug_mint_only_deprecated, - reason="settings.debug_mint_only_deprecated is set", -) async def test_info(ledger: Ledger): response = httpx.get(f"{BASE_URL}/v1/info") assert response.status_code == 200, f"{response.url} {response.status_code}" @@ -57,10 +52,6 @@ async def test_info(ledger: Ledger): @pytest.mark.asyncio -@pytest.mark.skipif( - settings.debug_mint_only_deprecated, - reason="settings.debug_mint_only_deprecated is set", -) async def test_api_keys(ledger: Ledger): response = httpx.get(f"{BASE_URL}/v1/keys") assert response.status_code == 200, f"{response.url} {response.status_code}" @@ -85,10 +76,6 @@ async def test_api_keys(ledger: Ledger): @pytest.mark.asyncio -@pytest.mark.skipif( - settings.debug_mint_only_deprecated, - reason="settings.debug_mint_only_deprecated is set", -) async def test_api_keysets(ledger: Ledger): response = httpx.get(f"{BASE_URL}/v1/keysets") assert response.status_code == 200, f"{response.url} {response.status_code}" @@ -114,10 +101,6 @@ async def test_api_keysets(ledger: Ledger): @pytest.mark.asyncio -@pytest.mark.skipif( - settings.debug_mint_only_deprecated, - reason="settings.debug_mint_only_deprecated is set", -) async def test_api_keyset_keys(ledger: Ledger): response = httpx.get(f"{BASE_URL}/v1/keys/01d8a63077d0a51f9855f066409782ffcb322dc8a2265291865221ed06c039f6bc") assert response.status_code == 200, f"{response.url} {response.status_code}" @@ -141,10 +124,6 @@ async def test_api_keyset_keys(ledger: Ledger): @pytest.mark.asyncio -@pytest.mark.skipif( - settings.debug_mint_only_deprecated, - reason="settings.debug_mint_only_deprecated is set", -) async def test_api_keyset_keys_old_keyset_id(ledger: Ledger): response = httpx.get(f"{BASE_URL}/v1/keys/01d8a63077d0a51f9855f066409782ffcb322dc8a2265291865221ed06c039f6bc") assert response.status_code == 200, f"{response.url} {response.status_code}" @@ -168,10 +147,6 @@ async def test_api_keyset_keys_old_keyset_id(ledger: Ledger): @pytest.mark.asyncio -@pytest.mark.skipif( - settings.debug_mint_only_deprecated, - reason="settings.debug_mint_only_deprecated is set", -) async def test_swap(ledger: Ledger, wallet: Wallet): mint_quote = await wallet.request_mint(64) await pay_if_regtest(mint_quote.request) @@ -196,10 +171,6 @@ async def test_swap(ledger: Ledger, wallet: Wallet): @pytest.mark.asyncio -@pytest.mark.skipif( - settings.debug_mint_only_deprecated, - reason="settings.debug_mint_only_deprecated is set", -) async def test_mint_quote(ledger: Ledger): response = httpx.post( f"{BASE_URL}/v1/mint/quote/bolt11", @@ -250,10 +221,6 @@ async def test_mint_quote(ledger: Ledger): @pytest.mark.asyncio -@pytest.mark.skipif( - settings.debug_mint_only_deprecated, - reason="settings.debug_mint_only_deprecated is set", -) async def test_mint(ledger: Ledger, wallet: Wallet): mint_quote = await wallet.request_mint(64) await pay_if_regtest(mint_quote.request) @@ -283,10 +250,6 @@ async def test_mint(ledger: Ledger, wallet: Wallet): @pytest.mark.asyncio -@pytest.mark.skipif( - settings.debug_mint_only_deprecated, - reason="settings.debug_mint_only_deprecated is set", -) async def test_mint_bolt11_no_signature(ledger: Ledger, wallet: Wallet): """ For backwards compatibility, we do not require a NUT-20 signature @@ -321,10 +284,6 @@ async def test_mint_bolt11_no_signature(ledger: Ledger, wallet: Wallet): @pytest.mark.asyncio -@pytest.mark.skipif( - settings.debug_mint_only_deprecated, - reason="settings.debug_mint_only_deprecated is set", -) @pytest.mark.skipif( is_regtest, reason="regtest", @@ -384,10 +343,6 @@ async def test_melt_quote_internal(ledger: Ledger, wallet: Wallet): @pytest.mark.asyncio -@pytest.mark.skipif( - settings.debug_mint_only_deprecated, - reason="settings.debug_mint_only_deprecated is set", -) @pytest.mark.skipif( is_fake, reason="only works on regtest", @@ -409,10 +364,6 @@ async def test_melt_quote_external(ledger: Ledger, wallet: Wallet): @pytest.mark.asyncio -@pytest.mark.skipif( - settings.debug_mint_only_deprecated, - reason="settings.debug_mint_only_deprecated is set", -) async def test_melt_internal(ledger: Ledger, wallet: Wallet): # internal invoice mint_quote = await wallet.request_mint(64) @@ -461,10 +412,6 @@ async def test_melt_internal(ledger: Ledger, wallet: Wallet): assert resp_quote.request == invoice_payment_request @pytest.mark.asyncio -@pytest.mark.skipif( - settings.debug_mint_only_deprecated, - reason="settings.debug_mint_only_deprecated is set", -) @pytest.mark.skipif( is_fake, reason="only works on regtest", @@ -521,10 +468,6 @@ async def test_melt_external(ledger: Ledger, wallet: Wallet): assert resp_quote.state == MeltQuoteState.paid.value @pytest.mark.asyncio -@pytest.mark.skipif( - settings.debug_mint_only_deprecated, - reason="settings.debug_mint_only_deprecated is set", -) async def test_api_check_state(ledger: Ledger): payload = PostCheckStateRequest(Ys=["asdasdasd", "asdasdasd1"]) response = httpx.post( @@ -539,10 +482,6 @@ async def test_api_check_state(ledger: Ledger): @pytest.mark.asyncio -@pytest.mark.skipif( - settings.debug_mint_only_deprecated, - reason="settings.debug_mint_only_deprecated is set", -) async def test_api_restore(ledger: Ledger, wallet: Wallet): mint_quote = await wallet.request_mint(64) await pay_if_regtest(mint_quote.request) diff --git a/tests/mint/test_mint_api_deprecated.py b/tests/mint/test_mint_api_deprecated.py deleted file mode 100644 index 136cc516e..000000000 --- a/tests/mint/test_mint_api_deprecated.py +++ /dev/null @@ -1,320 +0,0 @@ -import httpx -import pytest -import pytest_asyncio - -from cashu.core.base import Proof, Unit -from cashu.core.models import ( - CheckSpendableRequest_deprecated, - CheckSpendableResponse_deprecated, - GetMintResponse_deprecated, -) -from cashu.mint.ledger import Ledger -from cashu.wallet.wallet import Wallet -from tests.helpers import get_real_invoice, is_fake, is_regtest, pay_if_regtest - -pytestmark = pytest.mark.skip(reason="Wallet v0 / deprecated mint API removed in https://github.com/cashubtc/nutshell/pull/814") - -BASE_URL = "http://localhost:3337" - - -@pytest_asyncio.fixture(scope="function") -async def wallet(ledger: Ledger): - wallet1 = await Wallet.with_db( - url=BASE_URL, - db="test_data/wallet_mint_api_deprecated", - name="wallet_mint_api_deprecated", - ) - await wallet1.load_mint() - yield wallet1 - - -@pytest.mark.asyncio -async def test_info(ledger: Ledger): - response = httpx.get(f"{BASE_URL}/info") - assert response.status_code == 200, f"{response.url} {response.status_code}" - assert ledger.pubkey - assert response.json()["pubkey"] == ledger.pubkey.format().hex() - - -@pytest.mark.asyncio -async def test_api_keys(ledger: Ledger): - response = httpx.get(f"{BASE_URL}/keys") - assert response.status_code == 200, f"{response.url} {response.status_code}" - assert ledger.keyset.public_keys - assert response.json() == { - str(k): v.format().hex() for k, v in ledger.keyset.public_keys.items() - } - - -@pytest.mark.asyncio -async def test_api_keysets(ledger: Ledger): - response = httpx.get(f"{BASE_URL}/keysets") - assert response.status_code == 200, f"{response.url} {response.status_code}" - assert ledger.keyset.public_keys - sat_keysets = {k: v for k, v in ledger.keysets.items() if v.unit == Unit.sat} - assert response.json()["keysets"] == list(sat_keysets.keys()) - - -@pytest.mark.asyncio -async def test_api_keyset_keys(ledger: Ledger): - response = httpx.get(f"{BASE_URL}/keys/01d8a63077d0a51f9855f066409782ffcb322dc8a2265291865221ed06c039f6bc") - assert response.status_code == 200, f"{response.url} {response.status_code}" - assert ledger.keyset.public_keys - assert response.json() == { - str(k): v.format().hex() for k, v in ledger.keyset.public_keys.items() - } - - -@pytest.mark.asyncio -async def test_split(ledger: Ledger, wallet: Wallet): - mint_quote = await wallet.request_mint(64) - await pay_if_regtest(mint_quote.request) - await wallet.mint(64, quote_id=mint_quote.quote) - assert wallet.balance == 64 - secrets, rs, derivation_paths = await wallet.generate_secrets_from_to(20000, 20001) - outputs, rs = wallet._construct_outputs([32, 32], secrets, rs) - # outputs = wallet._construct_outputs([32, 32], ["a", "b"], ["c", "d"]) - inputs_payload = [p.to_dict() for p in wallet.proofs] - outputs_payload = [o.model_dump() for o in outputs] - # strip "id" from outputs_payload, which is not used in the deprecated split endpoint - for o in outputs_payload: - o.pop("id") - payload = {"proofs": inputs_payload, "outputs": outputs_payload} - response = httpx.post(f"{BASE_URL}/split", json=payload, timeout=None) - assert response.status_code == 200, f"{response.url} {response.status_code}" - result = response.json() - assert result["promises"] - - -@pytest.mark.asyncio -async def test_split_deprecated_with_amount(ledger: Ledger, wallet: Wallet): - mint_quote = await wallet.request_mint(64) - await pay_if_regtest(mint_quote.request) - await wallet.mint(64, quote_id=mint_quote.quote) - assert wallet.balance == 64 - secrets, rs, derivation_paths = await wallet.generate_secrets_from_to(80000, 80001) - outputs, rs = wallet._construct_outputs([32, 32], secrets, rs) - # outputs = wallet._construct_outputs([32, 32], ["a", "b"], ["c", "d"]) - inputs_payload = [p.to_dict() for p in wallet.proofs] - outputs_payload = [o.model_dump() for o in outputs] - # strip "id" from outputs_payload, which is not used in the deprecated split endpoint - for o in outputs_payload: - o.pop("id") - # we supply an amount here, which should cause the very old deprecated split endpoint to be used - payload = {"proofs": inputs_payload, "outputs": outputs_payload, "amount": 32} - response = httpx.post(f"{BASE_URL}/split", json=payload, timeout=None) - assert response.status_code == 200, f"{response.url} {response.status_code}" - result = response.json() - # old deprecated output format - assert result["fst"] - assert result["snd"] - - -@pytest.mark.asyncio -async def test_api_mint_validation(ledger): - response = httpx.get(f"{BASE_URL}/mint?amount=-21") - assert "detail" in response.json() - response = httpx.get(f"{BASE_URL}/mint?amount=0") - assert "detail" in response.json() - response = httpx.get(f"{BASE_URL}/mint?amount=2100000000000001") - assert "detail" in response.json() - response = httpx.get(f"{BASE_URL}/mint?amount=1") - assert "detail" not in response.json() - - -@pytest.mark.asyncio -async def test_mint(ledger: Ledger, wallet: Wallet): - quote_response = httpx.get( - f"{BASE_URL}/mint", - params={"amount": 64}, - timeout=None, - ) - mint_quote = GetMintResponse_deprecated.model_validate(quote_response.json()) - await pay_if_regtest(mint_quote.pr) - secrets, rs, derivation_paths = await wallet.generate_secrets_from_to(10000, 10001) - outputs, rs = wallet._construct_outputs([32, 32], secrets, rs) - outputs_payload = [o.model_dump() for o in outputs] - response = httpx.post( - f"{BASE_URL}/mint", - json={"outputs": outputs_payload}, - params={"hash": mint_quote.hash}, - timeout=None, - ) - assert response.status_code == 200, f"{response.url} {response.status_code}" - result = response.json() - assert len(result["promises"]) == 2 - assert result["promises"][0]["amount"] == 32 - assert result["promises"][1]["amount"] == 32 - assert result["promises"][0]["id"] == "01d8a63077d0a51f9855f066409782ffcb322dc8a2265291865221ed06c039f6bc" - assert result["promises"][0]["dleq"] - assert "e" in result["promises"][0]["dleq"] - assert "s" in result["promises"][0]["dleq"] - - -@pytest.mark.asyncio -async def test_melt_internal(ledger: Ledger, wallet: Wallet): - # fill wallet - mint_quote = await wallet.request_mint(64) - await pay_if_regtest(mint_quote.request) - await wallet.mint(64, quote_id=mint_quote.quote) - assert wallet.balance == 64 - - # create invoice to melt to - mint_quote = await wallet.request_mint(64) - - invoice_payment_request = mint_quote.request - - quote = await wallet.melt_quote(invoice_payment_request) - assert quote.amount == 64 - assert quote.fee_reserve == 0 - - inputs_payload = [p.to_dict() for p in wallet.proofs] - - # outputs for change - secrets, rs, derivation_paths = await wallet.generate_n_secrets(1) - outputs, rs = wallet._construct_outputs([2], secrets, rs) - outputs_payload = [o.model_dump() for o in outputs] - - response = httpx.post( - f"{BASE_URL}/melt", - json={ - "pr": invoice_payment_request, - "proofs": inputs_payload, - "outputs": outputs_payload, - }, - timeout=None, - ) - assert response.status_code == 200, f"{response.url} {response.status_code}" - result = response.json() - assert result.get("preimage") is None - -@pytest.mark.asyncio -async def test_melt_internal_no_change_outputs(ledger: Ledger, wallet: Wallet): - # Clients without NUT-08 will not send change outputs - # internal invoice - mint_quote = await wallet.request_mint(64) - await pay_if_regtest(mint_quote.request) - await wallet.mint(64, quote_id=mint_quote.quote) - assert wallet.balance == 64 - - # create invoice to melt to - mint_quote = await wallet.request_mint(64) - invoice_payment_request = mint_quote.request - quote = await wallet.melt_quote(invoice_payment_request) - assert quote.amount == 64 - assert quote.fee_reserve == 0 - - inputs_payload = [p.to_dict() for p in wallet.proofs] - - # outputs for change - secrets, rs, derivation_paths = await wallet.generate_n_secrets(1) - outputs, rs = wallet._construct_outputs([2], secrets, rs) - - response = httpx.post( - f"{BASE_URL}/melt", - json={ - "pr": invoice_payment_request, - "proofs": inputs_payload, - }, - timeout=None, - ) - assert response.status_code == 200, f"{response.url} {response.status_code}" - result = response.json() - assert result.get("preimage") is None - -@pytest.mark.asyncio -@pytest.mark.skipif( - is_fake, - reason="only works on regtest", -) -async def test_melt_external(ledger: Ledger, wallet: Wallet): - # internal invoice - mint_quote = await wallet.request_mint(64) - await pay_if_regtest(mint_quote.request) - await wallet.mint(64, quote_id=mint_quote.quote) - assert wallet.balance == 64 - - # create invoice to melt to - # use 2 sat less because we need to pay the fee - invoice_dict = get_real_invoice(62) - invoice_payment_request = invoice_dict["payment_request"] - - quote = await wallet.melt_quote(invoice_payment_request) - assert quote.amount == 62 - assert quote.fee_reserve == 2 - - inputs_payload = [p.to_dict() for p in wallet.proofs] - - # outputs for change - secrets, rs, derivation_paths = await wallet.generate_n_secrets(1) - outputs, rs = wallet._construct_outputs([2], secrets, rs) - outputs_payload = [o.model_dump() for o in outputs] - - response = httpx.post( - f"{BASE_URL}/melt", - json={ - "pr": invoice_payment_request, - "proofs": inputs_payload, - "outputs": outputs_payload, - }, - timeout=None, - ) - assert response.status_code == 200, f"{response.url} {response.status_code}" - result = response.json() - assert result.get("preimage") is not None - assert result["change"] - # we get back 2 sats because Lightning was free to pay on regtest - assert result["change"][0]["amount"] == 2 - -@pytest.mark.asyncio -async def test_checkfees(ledger: Ledger, wallet: Wallet): - # internal invoice - mint_quote = await wallet.request_mint(64) - response = httpx.post( - f"{BASE_URL}/checkfees", - json={ - "pr": mint_quote.request, - }, - timeout=None, - ) - assert response.status_code == 200, f"{response.url} {response.status_code}" - result = response.json() - # internal invoice, so no fee - assert result["fee"] == 0 - - -@pytest.mark.asyncio -@pytest.mark.skipif(not is_regtest, reason="only works on regtest") -async def test_checkfees_external(ledger: Ledger, wallet: Wallet): - # external invoice - invoice_dict = get_real_invoice(62) - invoice_payment_request = invoice_dict["payment_request"] - response = httpx.post( - f"{BASE_URL}/checkfees", - json={"pr": invoice_payment_request}, - timeout=None, - ) - assert response.status_code == 200, f"{response.url} {response.status_code}" - result = response.json() - # external invoice, so fee - assert result["fee"] == 2 - - -@pytest.mark.asyncio -async def test_api_check_state(ledger: Ledger): - proofs = [ - Proof(id="1234", amount=0, secret="asdasdasd", C="asdasdasd"), - Proof(id="1234", amount=0, secret="asdasdasd1", C="asdasdasd1"), - ] - payload = CheckSpendableRequest_deprecated(proofs=proofs) - response = httpx.post( - f"{BASE_URL}/check", - json=payload.model_dump(), - ) - assert response.status_code == 200, f"{response.url} {response.status_code}" - states = CheckSpendableResponse_deprecated.model_validate(response.json()) - assert states.spendable - assert len(states.spendable) == 2 - assert states.pending - assert len(states.pending) == 2 - diff --git a/tests/mint/test_mint_db.py b/tests/mint/test_mint_db.py index 058adbe98..a98a38862 100644 --- a/tests/mint/test_mint_db.py +++ b/tests/mint/test_mint_db.py @@ -19,7 +19,6 @@ from tests.conftest import SERVER_ENDPOINT from tests.helpers import ( assert_err, - is_deprecated_api_only, is_github_actions, pay_if_regtest, ) @@ -325,7 +324,6 @@ async def test_db_update_mint_quote_state(wallet: Wallet, ledger: Ledger): @pytest.mark.asyncio -@pytest.mark.skipif(is_deprecated_api_only, reason=("Deprecated API")) async def test_db_update_melt_quote_state(wallet: Wallet, ledger: Ledger): melt_quote = await wallet.melt_quote(payment_request) await ledger.db_write._update_melt_quote_state( diff --git a/tests/mint/test_mint_melt.py b/tests/mint/test_mint_melt.py index 2ed913ab4..9b6f84526 100644 --- a/tests/mint/test_mint_melt.py +++ b/tests/mint/test_mint_melt.py @@ -17,7 +17,6 @@ from tests.conftest import SERVER_ENDPOINT from tests.helpers import ( get_real_invoice, - is_deprecated_api_only, is_fake, is_regtest, pay_if_regtest, @@ -92,8 +91,8 @@ async def create_pending_melts( @pytest.mark.asyncio @pytest.mark.skipif( - not is_fake or is_deprecated_api_only, - reason="only fakewallet and non-deprecated api", + not is_fake, + reason="only FakeWallet", ) async def test_pending_melt_quote_outputs_registration_regression( wallet, ledger: Ledger @@ -153,8 +152,8 @@ async def test_pending_melt_quote_outputs_registration_regression( @pytest.mark.asyncio @pytest.mark.skipif( - not is_fake or is_deprecated_api_only, - reason="only fakewallet and non-deprecated api", + not is_fake, + reason="only FakeWallet", ) async def test_settled_melt_quote_outputs_registration_regression( wallet, ledger: Ledger @@ -211,8 +210,8 @@ async def test_settled_melt_quote_outputs_registration_regression( @pytest.mark.asyncio @pytest.mark.skipif( - not is_fake or is_deprecated_api_only, - reason="only fakewallet and non-deprecated api", + not is_fake, + reason="only FakeWallet", ) async def test_melt_quote_reuse_same_outputs(wallet, ledger: Ledger): """Verify that if the same outputs are used in two melt requests, diff --git a/tests/mint/test_mint_operations.py b/tests/mint/test_mint_operations.py index caa9a925a..c52d1c5d8 100644 --- a/tests/mint/test_mint_operations.py +++ b/tests/mint/test_mint_operations.py @@ -6,7 +6,6 @@ from cashu.core.helpers import sum_proofs from cashu.core.models import PostMeltQuoteRequest, PostMintQuoteRequest from cashu.core.nuts import nut20 -from cashu.core.settings import settings from cashu.mint.ledger import Ledger from cashu.wallet.wallet import Wallet from cashu.wallet.wallet import Wallet as Wallet1 @@ -58,13 +57,12 @@ async def test_melt_internal(wallet1: Wallet, ledger: Ledger): assert melt_quote.amount == 64 assert melt_quote.fee_reserve == 0 - if not settings.debug_mint_only_deprecated: - melt_quote_response_pre_payment = await wallet1.get_melt_quote(melt_quote.quote) - assert melt_quote_response_pre_payment - assert ( - not melt_quote_response_pre_payment.state == MeltQuoteState.paid - ), "melt quote should not be paid" - assert melt_quote_response_pre_payment.amount == 64 + melt_quote_response_pre_payment = await wallet1.get_melt_quote(melt_quote.quote) + assert melt_quote_response_pre_payment + assert ( + not melt_quote_response_pre_payment.state == MeltQuoteState.paid + ), "melt quote should not be paid" + assert melt_quote_response_pre_payment.amount == 64 melt_quote_pre_payment = await ledger.get_melt_quote(melt_quote.quote) assert melt_quote_pre_payment.state != MeltQuoteState.paid, "melt quote should not be paid" @@ -100,13 +98,12 @@ async def test_melt_external(wallet1: Wallet, ledger: Ledger): PostMeltQuoteRequest(request=invoice_payment_request, unit="sat") ) - if not settings.debug_mint_only_deprecated: - melt_quote_response_pre_payment = await wallet1.get_melt_quote(melt_quote.quote) - assert melt_quote_response_pre_payment - assert ( - melt_quote_response_pre_payment.state == MeltQuoteState.unpaid - ), "melt quote should not be paid" - assert melt_quote_response_pre_payment.amount == melt_quote.amount + melt_quote_response_pre_payment = await wallet1.get_melt_quote(melt_quote.quote) + assert melt_quote_response_pre_payment + assert ( + melt_quote_response_pre_payment.state == MeltQuoteState.unpaid + ), "melt quote should not be paid" + assert melt_quote_response_pre_payment.amount == melt_quote.amount melt_quote_pre_payment = await ledger.get_melt_quote(melt_quote.quote) assert melt_quote_pre_payment.state != MeltQuoteState.paid, "melt quote should not be paid" @@ -129,9 +126,8 @@ async def test_mint_internal(wallet1: Wallet, ledger: Ledger): assert mint_quote.state == MintQuoteState.paid, "mint quote should be paid" - if not settings.debug_mint_only_deprecated: - mint_quote = await wallet1.get_mint_quote(mint_quote.quote) - assert mint_quote.state == MintQuoteState.paid, "mint quote should be paid" + mint_quote = await wallet1.get_mint_quote(mint_quote.quote) + assert mint_quote.state == MintQuoteState.paid, "mint quote should be paid" output_amounts = [128] secrets, rs, derivation_paths = await wallet1.generate_n_secrets( @@ -163,9 +159,8 @@ async def test_mint_external(wallet1: Wallet, ledger: Ledger): assert mint_quote.state != MintQuoteState.paid, "mint quote already paid" assert mint_quote.state == MintQuoteState.unpaid - if not settings.debug_mint_only_deprecated: - mint_quote = await wallet1.get_mint_quote(quote.quote) - assert mint_quote.state != MintQuoteState.paid, "mint quote should not be paid" + mint_quote = await wallet1.get_mint_quote(quote.quote) + assert mint_quote.state != MintQuoteState.paid, "mint quote should not be paid" await assert_err( wallet1.mint(128, quote_id=quote.quote), diff --git a/tests/test_mint_rpc_cli.py b/tests/test_mint_rpc_cli.py index 17b083b47..a9eea5eb3 100644 --- a/tests/test_mint_rpc_cli.py +++ b/tests/test_mint_rpc_cli.py @@ -7,7 +7,7 @@ from cashu.mint.management_rpc.cli.cli import cli from cashu.wallet.wallet import Wallet -from .helpers import is_deprecated_api_only, is_fake +from .helpers import is_fake payment_request = ( "lnbc10u1pjap7phpp50s9lzr3477j0tvacpfy2ucrs4q0q6cvn232ex7nt2zqxxxj8gxrsdpv2phhwetjv4jzqcneypqyc6t8dp6xu6twva2xjuzzda6qcqzzsxqrrsss" @@ -115,10 +115,6 @@ async def test_update_mint_quote(cli_prefix): assert "Successfully updated!" in result.output @pytest.mark.asyncio -@pytest.mark.skipif( - is_deprecated_api_only, - reason=("Deprecated API"), -) async def test_update_melt_quote(cli_prefix): wallet = await init_wallet() melt_quote = await wallet.melt_quote("lnbc1u1p5qefdgsp5xj5cl559ks226f3vf3d7x2ev2qadplmkswp4649h755cfekdufsspp5sxenacdev78ssuwn5vehycs7ch2ds23hhzytut4ncm27gywtv6rqdqqcqpjrzjqdgp5ar48c8k4cns58jw9lamcdlh57trvrn9psgjrsvwz94j9tqsvrqsvcqqvqsqqqqqqqlgqqqzwyqq2q9qxpqysgqzg8e75zkcxazmd0wqmre6xgkumt7sl4ftsw0q4c6zvz8hn6zjxwz9fmdmwpupw7tw79f7gmukyeeh8vusvt03pgwfud9shj849rvrnqpgcpusw") @@ -142,10 +138,6 @@ async def test_get_mint_quote(cli_prefix): assert "mint quote:" in result.output @pytest.mark.asyncio -@pytest.mark.skipif( - is_deprecated_api_only, - reason=("Deprecated API"), -) async def test_get_melt_quote(cli_prefix): wallet = await init_wallet() melt_quote = await wallet.melt_quote("lnbc1u1p5qefd7sp55l6kmcrnqz5rejy4lghmgf9de0ucmmn2s3lvkvtkrr0qkwk5r0espp5da4x63rspz5rcfretdh6573c6qlpnzpxc8yq26cyqjc4sk0srfwsdqqcqpjrzjqv3dpepm8kfdxrk3sl6wzqdf49s9c0h9ljtjrek6c08r6aejlwcnur2z3sqqrrgqqyqqqqqqqqqqfcsqjq9qxpqysgq4l5rfjd4h84w7prmtgzjvq79ddy266svuz0d7dg44jmnwjpxg0zxef6hn4j8nzfp4c67qjpe0c9aw63ghu7rtcdg6n4zka9hym69euqq8w5wmj") @@ -170,10 +162,6 @@ async def test_get_quote_ttl_mint_quote(cli_prefix): assert "Error:" in result.output @pytest.mark.asyncio -@pytest.mark.skipif( - is_deprecated_api_only, - reason=("Deprecated API"), -) async def test_get_quote_ttl_melt_quote(cli_prefix): """Melt quotes persist expiry; GetQuoteTtl should return the expiry timestamp.""" wallet = await init_wallet() diff --git a/tests/test_mint_watchdog.py b/tests/test_mint_watchdog.py index cf0753f92..7ddf738c8 100644 --- a/tests/test_mint_watchdog.py +++ b/tests/test_mint_watchdog.py @@ -77,12 +77,11 @@ async def test_balance_update_on_test_melt_internal(wallet: Wallet, ledger: Ledg PostMeltQuoteRequest(request=invoice_payment_request, unit="sat") ) - if not settings.debug_mint_only_deprecated: - melt_quote_response_pre_payment = await wallet.get_melt_quote(melt_quote.quote) - assert ( - not melt_quote_response_pre_payment.state == MeltQuoteState.paid.value - ), "melt quote should not be paid" - assert melt_quote_response_pre_payment.amount == payment_amount + melt_quote_response_pre_payment = await wallet.get_melt_quote(melt_quote.quote) + assert ( + not melt_quote_response_pre_payment.state == MeltQuoteState.paid.value + ), "melt quote should not be paid" + assert melt_quote_response_pre_payment.amount == payment_amount melt_quote_pre_payment = await ledger.get_melt_quote(melt_quote.quote) assert melt_quote_pre_payment.state != MeltQuoteState.paid, "melt quote should not be paid" @@ -140,12 +139,11 @@ async def test_balance_update_on_melt_external(wallet: Wallet, ledger: Ledger): PostMeltQuoteRequest(request=invoice_payment_request, unit="sat") ) - if not settings.debug_mint_only_deprecated: - melt_quote_response_pre_payment = await wallet.get_melt_quote(melt_quote.quote) - assert ( - melt_quote_response_pre_payment.state == MeltQuoteState.unpaid.value - ), "melt quote should not be paid" - assert melt_quote_response_pre_payment.amount == melt_quote.amount + melt_quote_response_pre_payment = await wallet.get_melt_quote(melt_quote.quote) + assert ( + melt_quote_response_pre_payment.state == MeltQuoteState.unpaid.value + ), "melt quote should not be paid" + assert melt_quote_response_pre_payment.amount == melt_quote.amount melt_quote_resp = await ledger.melt(proofs=send_proofs, quote=melt_quote.quote) fees_paid = melt_quote.fee_reserve - ( diff --git a/tests/wallet/test_wallet.py b/tests/wallet/test_wallet.py index 192f6335b..71500df56 100644 --- a/tests/wallet/test_wallet.py +++ b/tests/wallet/test_wallet.py @@ -21,7 +21,6 @@ from tests.conftest import SERVER_ENDPOINT from tests.helpers import ( get_real_invoice, - is_deprecated_api_only, is_fake, is_github_actions, is_regtest, @@ -178,10 +177,9 @@ async def test_request_mint(wallet1: Wallet): async def test_mint(wallet1: Wallet): mint_quote = await wallet1.request_mint(64) await pay_if_regtest(mint_quote.request) - if not settings.debug_mint_only_deprecated: - mint_quote = await wallet1.get_mint_quote(mint_quote.quote) - assert mint_quote.request == mint_quote.request - assert mint_quote.state == MintQuoteState.paid + mint_quote = await wallet1.get_mint_quote(mint_quote.quote) + assert mint_quote.request == mint_quote.request + assert mint_quote.state == MintQuoteState.paid expected_proof_amounts = wallet1.split_wallet_state(64) await wallet1.mint(64, quote_id=mint_quote.quote) @@ -317,10 +315,9 @@ async def test_melt(wallet1: Wallet): assert total_amount == 64 assert quote.fee_reserve == 0 - if not settings.debug_mint_only_deprecated: - quote_resp = await wallet1.get_melt_quote(quote.quote) - assert quote_resp - assert quote_resp.amount == quote.amount + quote_resp = await wallet1.get_melt_quote(quote.quote) + assert quote_resp + assert quote_resp.amount == quote.amount _, send_proofs = await wallet1.swap_to_send(wallet1.proofs, total_amount) @@ -346,15 +343,14 @@ async def test_melt(wallet1: Wallet): assert melt_quote_db, "No melt quote in db" # compare melt quote from API against db - if not settings.debug_mint_only_deprecated: - melt_quote_api_resp = await wallet1.get_melt_quote(melt_quote_db.quote) - assert melt_quote_api_resp, "No melt quote from API" - assert melt_quote_api_resp.quote == melt_quote_db.quote, "Wrong quote ID" - assert melt_quote_api_resp.amount == melt_quote_db.amount, "Wrong amount" - assert melt_quote_api_resp.fee_reserve == melt_quote_db.fee_reserve, "Wrong fee" - assert melt_quote_api_resp.request == melt_quote_db.request, "Wrong request" - assert melt_quote_api_resp.state == melt_quote_db.state, "Wrong state" - assert melt_quote_api_resp.unit == melt_quote_db.unit, "Wrong unit" + melt_quote_api_resp = await wallet1.get_melt_quote(melt_quote_db.quote) + assert melt_quote_api_resp, "No melt quote from API" + assert melt_quote_api_resp.quote == melt_quote_db.quote, "Wrong quote ID" + assert melt_quote_api_resp.amount == melt_quote_db.amount, "Wrong amount" + assert melt_quote_api_resp.fee_reserve == melt_quote_db.fee_reserve, "Wrong fee" + assert melt_quote_api_resp.request == melt_quote_db.request, "Wrong request" + assert melt_quote_api_resp.state == melt_quote_db.state, "Wrong state" + assert melt_quote_api_resp.unit == melt_quote_db.unit, "Wrong unit" proofs_used = await get_proofs( db=wallet1.db, melt_id=melt_quote_db.quote, table="proofs_used" @@ -369,7 +365,6 @@ async def test_melt(wallet1: Wallet): @pytest.mark.asyncio -@pytest.mark.skipif(is_deprecated_api_only, reason="Deprecated API only") async def test_get_melt_quote_state(wallet1: Wallet): mint_quote = await wallet1.request_mint(128) await pay_if_regtest(mint_quote.request) diff --git a/tests/wallet/test_wallet_cli.py b/tests/wallet/test_wallet_cli.py index c71611006..8f1e334dd 100644 --- a/tests/wallet/test_wallet_cli.py +++ b/tests/wallet/test_wallet_cli.py @@ -11,7 +11,6 @@ from cashu.wallet.wallet import Wallet from tests.helpers import ( get_real_invoice, - is_deprecated_api_only, is_fake, is_regtest, pay_if_regtest, @@ -135,9 +134,6 @@ def test_pay_invoice_regtest(mint, cli_prefix): @pytest.mark.skipif(is_regtest, reason="only works with FakeWallet") def test_invoice(mint, cli_prefix): - if settings.debug_mint_only_deprecated: - pytest.skip("only works with v1 API") - runner = CliRunner() result = runner.invoke( cli, @@ -151,9 +147,6 @@ def test_invoice(mint, cli_prefix): @pytest.mark.skipif(is_regtest, reason="only works with FakeWallet") def test_invoice_verbose(mint, cli_prefix): - if settings.debug_mint_only_deprecated: - pytest.skip("only works with v1 API") - runner = CliRunner() result = runner.invoke( cli, @@ -189,7 +182,6 @@ def test_invoice_return_immediately(mint, cli_prefix): assert result.exit_code == 0 -@pytest.mark.skipif(is_deprecated_api_only, reason="only works with v1 API") def test_invoice_with_memo(mint, cli_prefix): runner = CliRunner() result = runner.invoke( diff --git a/tests/wallet/test_wallet_lightning.py b/tests/wallet/test_wallet_lightning.py index b8b114762..d41df2e5d 100644 --- a/tests/wallet/test_wallet_lightning.py +++ b/tests/wallet/test_wallet_lightning.py @@ -10,7 +10,6 @@ from tests.conftest import SERVER_ENDPOINT from tests.helpers import ( get_real_invoice, - is_deprecated_api_only, is_fake, is_regtest, pay_if_regtest, @@ -66,7 +65,6 @@ async def test_create_invoice(wallet: LightningWallet): @pytest.mark.asyncio -@pytest.mark.skipif(is_deprecated_api_only, reason="only works with v1 API") async def test_create_invoice_with_description(wallet: LightningWallet): invoice = await wallet.create_invoice(64, "test description") assert invoice.payment_request diff --git a/tests/wallet/test_wallet_p2pk.py b/tests/wallet/test_wallet_p2pk.py index 1e12d3fed..951fe76ee 100644 --- a/tests/wallet/test_wallet_p2pk.py +++ b/tests/wallet/test_wallet_p2pk.py @@ -20,7 +20,7 @@ from cashu.wallet.wallet import Wallet as Wallet1 from cashu.wallet.wallet import Wallet as Wallet2 from tests.conftest import SERVER_ENDPOINT -from tests.helpers import is_deprecated_api_only, pay_if_regtest +from tests.helpers import pay_if_regtest async def assert_err(f, msg): @@ -85,12 +85,11 @@ async def test_p2pk(wallet1: Wallet, wallet2: Wallet): proof_states = await wallet2.check_proof_state(send_proofs) assert all([p.spent for p in proof_states.states]) - if not is_deprecated_api_only: - for state in proof_states.states: - assert state.witness is not None - witness_obj = json.loads(state.witness) - assert len(witness_obj["signatures"]) == 1 - assert len(witness_obj["signatures"][0]) == 128 + for state in proof_states.states: + assert state.witness is not None + witness_obj = json.loads(state.witness) + assert len(witness_obj["signatures"]) == 1 + assert len(witness_obj["signatures"][0]) == 128 @pytest.mark.asyncio