Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
5c6f16c
docs(mn-cli): requirements + UX spec for masternode CLI withdrawals
lklimek Jun 18, 2026
351a705
docs(mn-cli): test-case specification for masternode CLI withdrawals
lklimek Jun 18, 2026
9826ead
docs(mn-cli): development plan for masternode CLI withdrawals
lklimek Jun 18, 2026
2784ba3
feat(mcp): add masternode input validators (Task 1)
lklimek Jun 18, 2026
0283ce8
feat(mcp): add Tool A load params with redacting Debug (Task 2)
lklimek Jun 18, 2026
9907539
feat(mcp): implement Tool A invoke + register identity_masternode_loa…
lklimek Jun 18, 2026
7c1adb4
feat(mcp): add Tool B masternode credit withdraw (Tasks 4+5)
lklimek Jun 18, 2026
f00eb68
test(mcp): cross-cutting discoverability + key-redaction guards (Task 6)
lklimek Jun 18, 2026
1c931ed
test(e2e): masternode load + withdraw backend-e2e suite (Task 7)
lklimek Jun 18, 2026
6d82378
docs(mcp): document masternode load + withdraw tools (Task 8)
lklimek Jun 18, 2026
b127a05
fix(mcp): owner-mode withdrawal dispatches None, not Some(payout) (QA…
lklimek Jun 18, 2026
5102615
fix(mcp): decode_identity_id error states what to do (M-01)
lklimek Jun 18, 2026
1e86bfd
fix(mcp): blank network yields a clear "required" message (QA-004)
lklimek Jun 18, 2026
eaa8a7c
test(e2e): fill missing masternode backend-e2e cases (PROJ-001/QA-005…
lklimek Jun 18, 2026
3c9a0f9
docs(mcp): doc accuracy + comment hygiene (DOC-001..005, QA-010)
lklimek Jun 18, 2026
c527c26
style(mcp): trim the redacting-Debug rationale comment to 3 lines (QA…
lklimek Jun 18, 2026
b9cb11b
chore: merge docs/platform-wallet-migration-design (#860, incl. overl…
lklimek Jun 19, 2026
ec98360
fix(mcp): gracefully stop wallet backend before standalone det-cli exits
lklimek Jun 19, 2026
7b5353f
fix(mcp): wait for cold-start storage migration before dispatching wa…
lklimek Jun 19, 2026
acb06b1
fix(mcp): wire wallet backend before resolving identity in masternode…
lklimek Jun 19, 2026
98e9638
fix(mcp): wait for coordinator threads to exit before runtime shutdown
lklimek Jun 19, 2026
74cf43a
fix(mcp): hard-exit CLI after flush to avoid coordinator thread panics
lklimek Jun 19, 2026
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
41 changes: 41 additions & 0 deletions docs/CLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,47 @@ det-cli core-funds-send wallet-id=savings address=yXyz... amount-duffs=1000000 n
det-cli serve
```

## Masternode / evonode credit withdrawal (headless)

Withdraw a masternode/evonode identity's Platform credits without the GUI:
first load the identity by ProTxHash + keys, then withdraw in either key mode.
The keys are accepted as inline `key=value` arguments (WIF or 64-char hex) — see
the private-key handling note in `MCP.md` and keep the HTTP endpoint loopback-only
for key-bearing calls. Inline `key=value` arguments are visible to other local
users (`ps`, `/proc/<pid>/cmdline`) and are saved to shell history. On a shared or
untrusted host, prefer the deferred env-var/stdin entry path once available, or
clear your shell history afterward. In transfer mode, `to-address` must be a Core
address — Platform (bech32m `dash1…`/`tdash1…`) addresses are rejected.

```bash
# 1. Load an evonode identity (testnet). Provide at least one of the owner or
# payout key; voting key and alias are optional.
det-cli identity-masternode-load \
pro-tx-hash=<64-hex protx> \
node-type=evonode \
owner-private-key=<WIF> \
payout-private-key=<WIF> \
network=testnet
# -> { "identity_id": "...", "available_withdrawal_keys": ["owner","transfer"],
# "payout_address": "y...", ... }

# 2a. Owner key — destination is forced to the registered payout address.
# Supplying to-address is rejected.
det-cli identity-masternode-credits-withdraw \
identity-id=<base58> \
key-mode=owner \
amount-credits=100000 \
network=testnet

# 2b. Payout/transfer key — withdraw to any Core address.
det-cli identity-masternode-credits-withdraw \
identity-id=<base58> \
key-mode=transfer \
to-address=y... \
amount-credits=100000 \
network=testnet
```

## Shielded self-verification loop (testnet)

The shielded read/control tools let an agent drive and verify a full shielded
Expand Down
12 changes: 11 additions & 1 deletion docs/MCP.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ Set these in the app's `.env` file (see `.env.example`) or as environment variab
| `identity_credits_transfer` | `wallet_id`, `from_identity_id`, `to_identity_id`, `amount_credits`, `network` | `det-cli identity-credits-transfer` | Transfer credits between identities |
| `identity_credits_withdraw` | `wallet_id`, `identity_id`, `to_address`, `amount_credits`, `network` | `det-cli identity-credits-withdraw` | Withdraw identity credits to a Core address |
| `identity_credits_to_address` | `wallet_id`, `identity_id`, `to_address`, `amount_credits`, `network` | `det-cli identity-credits-to-address` | Transfer identity credits to a Platform address |
| `identity_masternode_load` | `pro_tx_hash`, `node_type`, `owner_private_key`?, `voting_private_key`?, `payout_private_key`?, `alias`?, `network` | `det-cli identity-masternode-load` | Load a masternode/evonode identity by ProTxHash and bind its owner/voting/payout keys. Returns which keys loaded, the available withdrawal modes, and the payout address. Requires at least one of the owner or payout key |
| `identity_masternode_credits_withdraw` | `identity_id`, `key_mode`, `to_address`?, `amount_credits`, `network` | `det-cli identity-masternode-credits-withdraw` | Withdraw a masternode/evonode identity's credits. `key_mode=owner` forces the registered payout address (no `to_address`); `key_mode=transfer` withdraws to any Core address. Platform addresses (bech32m) are rejected for both modes |
| `shielded_shield_from_core` | `wallet_id`, `amount_duffs`, `network` | `det-cli shielded-shield-from-core` | Shield DASH from Core wallet into shielded pool (via asset lock, ~30s) |
| `shielded_shield_from_platform` | `wallet_id`, `amount_credits`, `network` | `det-cli shielded-shield-from-platform` | Shield credits from Platform address into shielded pool |
| `shielded_transfer` | `wallet_id`, `to_address`, `amount_credits`, `network` | `det-cli shielded-transfer` | Private shielded-to-shielded transfer |
Expand All @@ -101,6 +103,14 @@ All wallet-facing tools wait for SPV to fully sync before executing. This includ

Tools that make no network calls skip the SPV gate: the metadata tools (`core_wallets_list`, `network_info`, `tool_describe`), the local wallet import (`core_wallet_import`), and the shielded snapshot read `shielded_balance_get` (a pure in-memory read of the last synced balance). `shielded_address_get` also skips the SPV gate, but it reads through the wallet backend, so the backend must already be wired — run `shielded_init` (or any SPV-gated tool) first in standalone mode. `shielded_init` and `shielded_sync` still wait for SPV — they wire the wallet backend and drive a coordinator sync.

`identity_masternode_credits_withdraw` waits for SPV before dispatching: a withdrawal does proof-verified Platform reads, so it gates like every other proof-verifying tool. (`identity_credits_withdraw` historically skipped this gate; the masternode tool deliberately adds it.)

### Private-key handling

`identity_masternode_load` accepts the masternode owner/voting/payout private keys as plain string parameters (WIF or 64-char hex), mirroring `core_wallet_import`. The keys are moved into a zeroizing, best-effort page-locked `Secret` on receipt and are never echoed back: the tool output reports only which keys loaded (booleans), validation errors name the key by role and never its value, and the parameter struct's `Debug` renders each key as `<redacted>` so it cannot leak into logs or the MCP error `data` payload.

Over the MCP **HTTP** transport these keys traverse the request body. The HTTP endpoint is bearer-authenticated and binds to loopback by default; do not send live mainnet masternode keys over a non-loopback MCP HTTP endpoint. (HTTP transport-layer key handling is not separately enforced in code — keep the endpoint loopback-only for key-bearing calls.)

## CLI interface (det-cli)

`det-cli` is the command-line interface for interacting with MCP tools. It can operate in two modes:
Expand Down Expand Up @@ -135,7 +145,7 @@ See [CLI.md](CLI.md) for full documentation.

Tools accept a `network` parameter (e.g. `"mainnet"`, `"testnet"`, `"devnet"`, `"local"`). When provided, the request fails immediately if it does not match the server's active network. This prevents accidentally operating on the wrong network.

For **destructive tools** (those that spend funds or modify state — all identity tools, `core_funds_send`, `core_wallet_import`, and the fund-moving shielded tools `shielded_shield_from_core`, `shielded_shield_from_platform`, `shielded_transfer`, `shielded_unshield`, `shielded_withdraw`), `network` is **required**. The tool will reject the request if `network` is omitted or does not match the active network. This is a safety measure to prevent accidentally spending funds on the wrong network.
For **destructive tools** (those that spend funds or modify state — the fund-moving identity tools `identity_credits_topup`, `identity_credits_topup_from_platform`, `identity_credits_transfer`, `identity_credits_withdraw`, `identity_credits_to_address`, `identity_masternode_credits_withdraw`, plus `core_funds_send`, `core_wallet_import`, and the fund-moving shielded tools `shielded_shield_from_core`, `shielded_shield_from_platform`, `shielded_transfer`, `shielded_unshield`, `shielded_withdraw`), `network` is **required**. The tool will reject the request if `network` is omitted or does not match the active network. This is a safety measure to prevent accidentally spending funds on the wrong network. Note: `identity_masternode_load` is non-destructive (it does not move funds) but also requires `network`, because the private keys it binds are chain-scoped.

For **read-only tools** (e.g. `core_wallets_list`, `core_balances_get`) and the shielded control/read tools (`shielded_init`, `shielded_sync`, `shielded_balance_get`, `shielded_address_get`), `network` is optional. When omitted, the tool operates on whatever network is currently active.

Expand Down
Loading
Loading