Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 45 additions & 12 deletions kaleido_cli/commands/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
DEFAULT_INDEXER_URL,
DEFAULT_NETWORK,
DEFAULT_PROXY_ENDPOINT,
DEFAULT_REGTEST_BITCOIND_RPC_HOST,
DEFAULT_REGTEST_BITCOIND_RPC_PASSWORD,
DEFAULT_REGTEST_BITCOIND_RPC_PORT,
DEFAULT_REGTEST_BITCOIND_RPC_USERNAME,
DEFAULT_REGTEST_INDEXER_URL,
DEFAULT_REGTEST_PROXY_ENDPOINT,
)
from kaleido_cli.context import get_client, state
from kaleido_cli.docker_manager import (
Expand Down Expand Up @@ -105,6 +111,22 @@ def _resolve_name(name: str | None) -> str:
raise typer.Exit(1)


def _prompt_unlock_service_profile() -> str:
while True:
raw = typer.prompt(
"Bitcoin services profile: [S]ignet defaults, [R]egtest defaults, [C]ustom",
default="S",
)
choice = raw.strip().lower()
if choice in {"s", "signet", "mutinynet", "signetcustom"}:
return "signet"
if choice in {"r", "regtest"}:
return "regtest"
if choice in {"c", "custom", "o", "other"}:
return "custom"
print_error("Choose S for signet, R for regtest, or C for custom.")


# ---------------------------------------------------------------------------
# Environment management
# ---------------------------------------------------------------------------
Expand Down Expand Up @@ -558,8 +580,14 @@ async def _node_init(password: str, mnemonic: str | None) -> None:
"unlock",
epilog=(
"[bold]Examples[/bold]\n\n"
" Simple unlock (uses Kaleidoswap mutinynet defaults):\n"
" Simple unlock (choose signet, regtest, or custom services):\n"
" [cyan]kaleido node unlock[/cyan]\n\n"
" Non-interactive signet defaults:\n"
" [cyan]kaleido --agent node unlock --password mysecret[/cyan]\n\n"
" Regtest defaults:\n"
" [cyan]kaleido node unlock --bitcoind-user user --bitcoind-pass password \\\n"
" --bitcoind-host regtest-bitcoind.rgbtools.org --bitcoind-port 80 \\\n"
" --indexer-url electrum.rgbtools.org:50041[/cyan]\n\n"
" Override bitcoind credentials:\n"
" [cyan]kaleido node unlock --bitcoind-user alice --bitcoind-pass hunter2[/cyan]\n\n"
" Full custom override:\n"
Expand Down Expand Up @@ -630,10 +658,22 @@ def node_unlock(
resolved_password = typer.prompt("Wallet password", hide_input=True)

if is_interactive():
use_defaults = typer.confirm(
"Use default Kaleidoswap mutinynet services (bitcoind, indexer, proxy)?", default=True
)
if not use_defaults:
profile = _prompt_unlock_service_profile()
if profile == "signet":
bitcoind_user = DEFAULT_BITCOIND_RPC_USERNAME
bitcoind_pass = DEFAULT_BITCOIND_RPC_PASSWORD
bitcoind_host = DEFAULT_BITCOIND_RPC_HOST
bitcoind_port = DEFAULT_BITCOIND_RPC_PORT
indexer_url = DEFAULT_INDEXER_URL
proxy_endpoint = DEFAULT_PROXY_ENDPOINT
elif profile == "regtest":
bitcoind_user = DEFAULT_REGTEST_BITCOIND_RPC_USERNAME
bitcoind_pass = DEFAULT_REGTEST_BITCOIND_RPC_PASSWORD
bitcoind_host = DEFAULT_REGTEST_BITCOIND_RPC_HOST
bitcoind_port = DEFAULT_REGTEST_BITCOIND_RPC_PORT
indexer_url = DEFAULT_REGTEST_INDEXER_URL
proxy_endpoint = DEFAULT_REGTEST_PROXY_ENDPOINT
else:
bitcoind_user = typer.prompt("bitcoind RPC username", default=bitcoind_user)
bitcoind_pass = typer.prompt(
"bitcoind RPC password", default=bitcoind_pass, hide_input=True
Expand All @@ -642,13 +682,6 @@ def node_unlock(
bitcoind_port = typer.prompt("bitcoind RPC port", default=bitcoind_port, type=int)
indexer_url = typer.prompt("Electrs indexer URL", default=indexer_url)
proxy_endpoint = typer.prompt("RGB proxy endpoint", default=proxy_endpoint)
else:
bitcoind_user = DEFAULT_BITCOIND_RPC_USERNAME
bitcoind_pass = DEFAULT_BITCOIND_RPC_PASSWORD
bitcoind_host = DEFAULT_BITCOIND_RPC_HOST
bitcoind_port = DEFAULT_BITCOIND_RPC_PORT
indexer_url = DEFAULT_INDEXER_URL
proxy_endpoint = DEFAULT_PROXY_ENDPOINT
raw = typer.prompt("[OPTIONAL] Lightning announce alias (Enter to skip)", default="")
if raw.strip():
announce_alias = raw.strip()
Expand Down
7 changes: 7 additions & 0 deletions kaleido_cli/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@
DEFAULT_INDEXER_URL = "electrum.signet.kaleidoswap.com:60601"
DEFAULT_PROXY_ENDPOINT = "rpcs://proxy.iriswallet.com/0.2/json-rpc"

DEFAULT_REGTEST_BITCOIND_RPC_USERNAME = "user"
DEFAULT_REGTEST_BITCOIND_RPC_PASSWORD = "password"
DEFAULT_REGTEST_BITCOIND_RPC_HOST = "regtest-bitcoind.rgbtools.org"
DEFAULT_REGTEST_BITCOIND_RPC_PORT = 80
DEFAULT_REGTEST_INDEXER_URL = "electrum.rgbtools.org:50041"
DEFAULT_REGTEST_PROXY_ENDPOINT = "rpcs://proxy.iriswallet.com/0.2/json-rpc"


def normalize_network_name(network: str) -> str:
"""Normalize friendly CLI aliases to the network value expected by RLN."""
Expand Down
1 change: 1 addition & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ def mock_client(mocker):
rln.list_transactions = AsyncMock()
rln.estimate_fee = AsyncMock()
rln.shutdown = AsyncMock()
rln.unlock_wallet = AsyncMock()
rln.backup = AsyncMock()
rln.restore = AsyncMock()
rln.change_password = AsyncMock()
Expand Down
88 changes: 88 additions & 0 deletions tests/test_cmd_node.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
"""Tests for `kaleido node` CLI commands."""

from __future__ import annotations

from kaleido_cli.app import app
from kaleido_cli.config import (
DEFAULT_BITCOIND_RPC_HOST,
DEFAULT_BITCOIND_RPC_PASSWORD,
DEFAULT_BITCOIND_RPC_PORT,
DEFAULT_BITCOIND_RPC_USERNAME,
DEFAULT_INDEXER_URL,
DEFAULT_PROXY_ENDPOINT,
DEFAULT_REGTEST_BITCOIND_RPC_HOST,
DEFAULT_REGTEST_BITCOIND_RPC_PASSWORD,
DEFAULT_REGTEST_BITCOIND_RPC_PORT,
DEFAULT_REGTEST_BITCOIND_RPC_USERNAME,
DEFAULT_REGTEST_INDEXER_URL,
DEFAULT_REGTEST_PROXY_ENDPOINT,
)


def _unlock_request(mock_client):
return mock_client.rln.unlock_wallet.await_args.args[0]


def test_node_unlock_interactive_signet_defaults(runner, mocker, mock_client):
mocker.patch("kaleido_cli.commands.node.is_interactive", return_value=True)

result = runner.invoke(app, ["node", "unlock"], input="walletpw\ns\n\n\n")

assert result.exit_code == 0
req = _unlock_request(mock_client)
assert req.password == "walletpw"
assert req.bitcoind_rpc_username == DEFAULT_BITCOIND_RPC_USERNAME
assert req.bitcoind_rpc_password == DEFAULT_BITCOIND_RPC_PASSWORD
assert req.bitcoind_rpc_host == DEFAULT_BITCOIND_RPC_HOST
assert req.bitcoind_rpc_port == DEFAULT_BITCOIND_RPC_PORT
assert req.indexer_url == DEFAULT_INDEXER_URL
assert req.proxy_endpoint == DEFAULT_PROXY_ENDPOINT


def test_node_unlock_interactive_regtest_defaults(runner, mocker, mock_client):
mocker.patch("kaleido_cli.commands.node.is_interactive", return_value=True)

result = runner.invoke(app, ["node", "unlock"], input="walletpw\nr\n\n\n")

assert result.exit_code == 0
req = _unlock_request(mock_client)
assert req.password == "walletpw"
assert req.bitcoind_rpc_username == DEFAULT_REGTEST_BITCOIND_RPC_USERNAME
assert req.bitcoind_rpc_password == DEFAULT_REGTEST_BITCOIND_RPC_PASSWORD
assert req.bitcoind_rpc_host == DEFAULT_REGTEST_BITCOIND_RPC_HOST
assert req.bitcoind_rpc_port == DEFAULT_REGTEST_BITCOIND_RPC_PORT
assert req.indexer_url == DEFAULT_REGTEST_INDEXER_URL
assert req.proxy_endpoint == DEFAULT_REGTEST_PROXY_ENDPOINT


def test_node_unlock_interactive_custom_services(runner, mocker, mock_client):
mocker.patch("kaleido_cli.commands.node.is_interactive", return_value=True)

result = runner.invoke(
app,
["node", "unlock"],
input=(
"walletpw\n"
"c\n"
"alice\n"
"secret\n"
"127.0.0.1\n"
"18443\n"
"tcp://127.0.0.1:50001\n"
"rpc://127.0.0.1:3000/json-rpc\n"
"alias\n"
"127.0.0.1:9735\n"
),
)

assert result.exit_code == 0
req = _unlock_request(mock_client)
assert req.password == "walletpw"
assert req.bitcoind_rpc_username == "alice"
assert req.bitcoind_rpc_password == "secret"
assert req.bitcoind_rpc_host == "127.0.0.1"
assert req.bitcoind_rpc_port == 18443
assert req.indexer_url == "tcp://127.0.0.1:50001"
assert req.proxy_endpoint == "rpc://127.0.0.1:3000/json-rpc"
assert req.announce_alias == "alias"
assert req.announce_addresses == ["127.0.0.1:9735"]