diff --git a/cashu/core/settings.py b/cashu/core/settings.py index 55f8e0c..3dab28e 100644 --- a/cashu/core/settings.py +++ b/cashu/core/settings.py @@ -216,6 +216,7 @@ class WalletSettings(CashuSettings): wallet_name: str = Field(default="wallet") wallet_unit: str = Field(default="sat") wallet_use_deprecated_h2c: bool = Field(default=False) + wallet_verbose_requests: bool = Field(default=False) api_port: int = Field(default=4448) api_host: str = Field(default="127.0.0.1") diff --git a/cashu/wallet/cli/cli.py b/cashu/wallet/cli/cli.py index 242a82f..0d36272 100644 --- a/cashu/wallet/cli/cli.py +++ b/cashu/wallet/cli/cli.py @@ -148,9 +148,16 @@ def init_auth_wallet(func): default=False, help="Run in test mode (don't ask for CLI inputs)", ) +@click.option( + "--verbose", + "-v", + is_flag=True, + default=False, + help="Enable verbose mode to show all requests to the mint", +) @click.pass_context @coro -async def cli(ctx: Context, host: str, walletname: str, unit: str, tests: bool): +async def cli(ctx: Context, host: str, walletname: str, unit: str, tests: bool, verbose: bool): if settings.debug: configure_logger() if settings.tor and not TorProxy().check_platform(): @@ -184,6 +191,8 @@ async def cli(ctx: Context, host: str, walletname: str, unit: str, tests: bool): unit = ctx.obj["UNIT"] ctx.obj["WALLET_NAME"] = walletname settings.wallet_name = walletname + settings.wallet_verbose_requests = verbose + ctx.obj["VERBOSE"] = verbose db_path = os.path.join(settings.cashu_dir, walletname) # if the command is "restore" we don't want to ask the user for a mnemonic diff --git a/cashu/wallet/v1_api.py b/cashu/wallet/v1_api.py index ff09730..3e944e6 100644 --- a/cashu/wallet/v1_api.py +++ b/cashu/wallet/v1_api.py @@ -188,7 +188,26 @@ class LedgerAPI(LedgerAPIDeprecated, SupportsAuth): } ) - return await self.httpx.request(method, path, **kwargs) + # Verbose logging of requests when enabled + if settings.wallet_verbose_requests: + request_info = f"{method} {self.url.rstrip('/')}/{path}" + if "json" in kwargs: + request_info += f"\nPayload: {json.dumps(kwargs['json'], indent=2)}" + print(f"Request: {request_info}") + + resp = await self.httpx.request(method, path, **kwargs) + + # Verbose logging of responses when enabled + if settings.wallet_verbose_requests: + response_info = f"Response: {resp.status_code}" + try: + json_response = resp.json() + response_info += f"\n{json.dumps(json_response, indent=2)}" + except json.JSONDecodeError: + response_info += f"\n{resp.text}" + print(response_info) + + return resp """ ENDPOINTS diff --git a/cashu/wallet/wallet_deprecated.py b/cashu/wallet/wallet_deprecated.py index f8fb0a5..fbd8025 100644 --- a/cashu/wallet/wallet_deprecated.py +++ b/cashu/wallet/wallet_deprecated.py @@ -253,6 +253,20 @@ class LedgerAPIDeprecated(SupportsHttpxClient, SupportsMintURL): """ logger.warning("Using deprecated API call: Requesting mint: GET /mint") resp = await self.httpx.get(f"{self.url}/mint", params={"amount": amount}) + + # Verbose logging of requests and responses when enabled + if settings.wallet_verbose_requests: + request_info = f"Request: GET {self.url}/mint?amount={amount}" + print(request_info) + + response_info = f"Response: {resp.status_code}" + try: + json_response = resp.json() + response_info += f"\n{json.dumps(json_response, indent=2)}" + except json.JSONDecodeError: + response_info += f"\n{resp.text}" + print(response_info) + self.raise_on_error(resp) return_dict = resp.json() mint_response = GetMintResponse_deprecated.parse_obj(return_dict) @@ -308,6 +322,22 @@ class LedgerAPIDeprecated(SupportsHttpxClient, SupportsMintURL): "payment_hash": hash, # backwards compatibility pre 0.12.0 }, ) + + # Verbose logging of requests and responses when enabled + if settings.wallet_verbose_requests: + request_info = f"Request: POST {self.url}/mint?hash={hash}" + if payload: + request_info += f"\nPayload: {json.dumps(payload, indent=2)}" + print(request_info) + + response_info = f"Response: {resp.status_code}" + try: + json_response = resp.json() + response_info += f"\n{json.dumps(json_response, indent=2)}" + except json.JSONDecodeError: + response_info += f"\n{resp.text}" + print(response_info) + self.raise_on_error(resp) response_dict = resp.json() logger.trace("Lightning invoice checked. POST /mint") diff --git a/tests/wallet/test_wallet_cli.py b/tests/wallet/test_wallet_cli.py index 25fdf2e..f64ea76 100644 --- a/tests/wallet/test_wallet_cli.py +++ b/tests/wallet/test_wallet_cli.py @@ -149,6 +149,23 @@ def test_invoice(mint, cli_prefix): assert result.exit_code == 0 +@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, + [*cli_prefix, "-v", "invoice", "1000"], + ) + + wallet = asyncio.run(init_wallet()) + assert wallet.available_balance >= 1000 + assert "Request: POST" in result.output + assert "Response: 200" in result.output + + def test_invoice_return_immediately(mint, cli_prefix): runner = CliRunner() result = runner.invoke(