Skip to content
Merged
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
14 changes: 9 additions & 5 deletions kaleido_cli/commands/channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
print_panel,
print_success,
)
from kaleido_cli.utils.prompts import resolve_required_text

channel_app = typer.Typer(
no_args_is_help=True,
Expand Down Expand Up @@ -691,14 +692,17 @@ async def _channel_order_create(params) -> None:
),
)
def channel_order_get(
order_id: Annotated[str, typer.Argument(help="LSP order ID.")],
order_id: Annotated[str | None, typer.Argument(help="LSP order ID.")] = None,
access_token: Annotated[
str,
typer.Option("--access-token", help="Optional access token returned for the order."),
] = "",
str | None,
typer.Option("--access-token", help="Access token returned for the order."),
] = None,
) -> None:
"""Get the status and details of an LSP channel order."""
asyncio.run(_channel_order_get(order_id, access_token))
resolved_order_id = resolve_required_text(order_id, "LSP order ID", "ORDER_ID argument")
resolved_access_token = resolve_required_text(access_token, "Access token", "--access-token")

asyncio.run(_channel_order_get(resolved_order_id, resolved_access_token))


async def _channel_order_get(order_id: str, access_token: str) -> None:
Expand Down
81 changes: 46 additions & 35 deletions kaleido_cli/commands/market.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@
resolve_quote_layers,
resolve_trading_pair,
)
from kaleido_cli.utils.prompts import (
display_amount_to_raw,
resolve_amount_pair,
resolve_pair,
)

market_app = typer.Typer(
no_args_is_help=True,
Expand Down Expand Up @@ -95,10 +100,10 @@ async def _market_pairs() -> None:
"quote",
epilog=(
"[bold]Examples[/bold]\n\n"
" Quote: send 100 000 msat via Lightning, receive USDT via RGB Lightning:\n"
" [cyan]kaleido market quote BTC/USDT --from-amount 100000[/cyan]\n\n"
" Quote: send BTC via Lightning, receive USDT via RGB Lightning:\n"
" [cyan]kaleido market quote BTC/USDT --from-amount 0.001[/cyan]\n\n"
" Quote with explicit layers:\n"
" [cyan]kaleido market quote BTC/USDT --from-amount 100000 --from-layer BTC_LN --to-layer RGB_LN[/cyan]\n\n"
" [cyan]kaleido market quote BTC/USDT --from-amount 0.001 --from-layer BTC_LN --to-layer RGB_LN[/cyan]\n\n"
" Quote how much BTC is needed to receive 500 USDT:\n"
" [cyan]kaleido market quote BTC/USDT --to-amount 500 --from-layer BTC_LN --to-layer RGB_LN[/cyan]\n\n"
"[bold]Available layers[/bold]: [green]BTC_LN[/green] [green]RGB_LN[/green] [green]BTC_ONCHAIN[/green]\n"
Expand All @@ -113,17 +118,17 @@ def market_quote(
),
] = None,
from_amount: Annotated[
int | None,
str | None,
typer.Option(
"--from-amount",
help="Amount to send (raw units of the base asset). Provide this OR --to-amount.",
help="Amount to send in display units. Provide this OR --to-amount.",
),
] = None,
to_amount: Annotated[
int | None,
str | None,
typer.Option(
"--to-amount",
help="Amount to receive (raw units of the quote asset). Provide this OR --from-amount.",
help="Amount to receive in display units. Provide this OR --from-amount.",
),
] = None,
from_layer: Annotated[
Expand All @@ -142,37 +147,23 @@ def market_quote(
] = None,
) -> None:
"""Get a swap quote for a trading pair."""
resolved_pair: str
if pair is not None:
resolved_pair = pair
elif is_interactive():
resolved_pair = typer.prompt("Trading pair (e.g. BTC/USDT)")
else:
print_error("PAIR argument is required in non-interactive mode.")
raise typer.Exit(1)

if from_amount is None and to_amount is None:
if is_interactive():
choice = typer.prompt("Quote by [S]end amount or [R]eceive amount?", default="S")
if choice.strip().upper().startswith("R"):
to_amount = typer.prompt("Amount to receive (raw units)", type=int)
else:
from_amount = typer.prompt("Amount to send (raw units)", type=int)
else:
print_error("Provide --from-amount or --to-amount in non-interactive mode.")
raise typer.Exit(1)
elif from_amount is not None and to_amount is not None:
print_error("Provide exactly one of --from-amount or --to-amount.")
raise typer.Exit(1)
resolved_pair = resolve_pair(pair)
resolved_from_amount, resolved_to_amount = resolve_amount_pair(
from_amount,
to_amount,
prompt_prefix="Quote",
default_choice="R",
pair=resolved_pair,
)

resolved_from_layer, resolved_to_layer = resolve_quote_layers(
resolved_pair, from_layer, to_layer
)
asyncio.run(
_market_quote(
resolved_pair,
from_amount,
to_amount,
resolved_from_amount,
resolved_to_amount,
resolved_from_layer,
resolved_to_layer,
)
Expand All @@ -181,8 +172,8 @@ def market_quote(

async def _market_quote(
pair: str,
from_amount: int | None,
to_amount: int | None,
from_amount: str | None,
to_amount: str | None,
from_layer: str,
to_layer: str,
) -> None:
Expand All @@ -205,17 +196,37 @@ async def _market_quote(
except ValueError as exc:
print_error(str(exc))
raise typer.Exit(1)
resolved_from_amount = (
display_amount_to_raw(
from_amount,
precision=from_asset.precision,
asset_label=from_asset.ticker,
option_name="--from-amount",
)
if from_amount is not None
else None
)
resolved_to_amount = (
display_amount_to_raw(
to_amount,
precision=to_asset.precision,
asset_label=to_asset.ticker,
option_name="--to-amount",
)
if to_amount is not None
else None
)

body = PairQuoteRequest(
from_asset=SwapLegInput(
asset_id=from_asset_id,
layer=Layer(from_layer),
amount=from_amount,
amount=resolved_from_amount,
),
to_asset=SwapLegInput(
asset_id=to_asset_id,
layer=Layer(to_layer),
amount=to_amount,
amount=resolved_to_amount,
),
)
quote = await client.maker.get_quote(body)
Expand Down
20 changes: 20 additions & 0 deletions kaleido_cli/commands/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"[bold]After starting:[/bold]\n"
" [cyan]kaleido node init[/cyan] — initialize node wallet (once)\n"
" [cyan]kaleido node unlock[/cyan] — unlock wallet after restart\n"
" [cyan]kaleido node shutdown[/cyan] — gracefully shut down the node process\n"
" [cyan]kaleido node info[/cyan] — check node reachability and details\n"
),
)
Expand Down Expand Up @@ -418,6 +419,25 @@ def node_stop(
raise typer.Exit(rc)


@node_app.command(
"shutdown",
epilog=" [cyan]kaleido node shutdown[/cyan] Gracefully shut down the configured node process.",
)
def node_shutdown() -> None:
"""Gracefully shut down the configured node."""
asyncio.run(_node_shutdown())


async def _node_shutdown() -> None:
try:
client = get_client(require_node=True)
await client.rln.shutdown()
print_success("Node shutdown initiated.")
except Exception as e:
print_error(f"Error: {e}")
raise typer.Exit(1)


@node_app.command(
"down",
epilog=" [cyan]kaleido node down <name>[/cyan] Stop and remove containers + networks.",
Expand Down
Loading