You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* Screen constructors handle errors internally via `MessageBanner` and return `Self` with degraded state. Keep `create_screen()` clean — no error handling at callsites.
68
68
***i18n-ready strings**: All user-facing strings (labels, messages, tooltips, errors) must be simple, complete sentences. Avoid concatenating fragments, positional assumptions, or grammar that breaks in other languages. Each string should be extractable as a single translation unit with named placeholders for dynamic values and no logic in the text itself. Current code uses standard Rust format specifiers (`{name}`, `{max}`). When i18n extraction happens later, these will become Fluent-style placeholders (`{ $name }`, `{ $max }`).
69
69
***Never parse error strings** to extract information. Always use the typed error chain (downcast, match on variants, access structured fields). If no typed variant exists for the information you need, define a new `TaskError` variant or extend the existing error type. String parsing is fragile, breaks on message changes, and bypasses the type system.
70
+
***Validation placement**: Pure input validation (format, length, character sets) lives in `model/` as stateless functions — single source of truth, unit-testable, no dependencies on `AppContext` or `Sdk`. Backend tasks are the authoritative enforcement layer: they call model validators for format checks AND perform stateful validation that requires network or database (existence checks, uniqueness, business rules). UI screens may call model validators for instant user feedback, but must never implement their own validation logic — always delegate to the model function.
70
71
71
72
### Error messages
72
73
@@ -109,13 +110,13 @@ User-facing error messages (shown in `MessageBanner` via `Display`) must follow
109
110
-**CLI ≠ MCP**: `src/bin/det_cli/` is a separate client that talks to the MCP server — it must work over HTTP too, not just in-process. Never put tool logic in the CLI binary; tools live in `src/mcp/tools/` and the CLI discovers them dynamically via `tools/list`.
110
111
-**Tool architecture**: each tool is a struct implementing `ToolBase` (metadata) + `AsyncTool<DashMcpService>` (invocation). Adding a tool requires only the struct + registering in `tool_router()` — zero CLI changes.
111
112
-**Tool naming**: `{domain}_{object}_{action}` — e.g. `core_address_create`, `platform_withdrawals_get`, `tool_describe`. CLI converts underscores to hyphens.
112
-
-**Context provider**: `ContextProvider::Shared(ArcSwap)` for HTTP mode (follows GUI network switches), `ContextProvider::Lazy(OnceCell)` for stdio (init on first tool call).
113
+
-**Context provider**: `ContextHolder::Shared(ArcSwap)` for HTTP mode (follows GUI network switches), `ContextHolder::Standalone(ArcSwapOption)` for stdio (init on first tool call).
113
114
-**Network safety**: tools accept optional `network` param — request fails if it doesn't match the active network. Exempt: `network_info`, `tool_describe`.
114
115
-**SPV sync**: wallet tools call `resolve::ensure_spv_synced()` before operating — polls SPV status with 1s interval, 10min timeout.
115
116
-**Backend dispatch**: tools reuse the app's `BackendTask` system via `dispatch::dispatch_task()` — creates a throwaway channel, calls `app_context.run_backend_task()`.
116
117
-**Schema quirk**: `schemars` v1 derives bare `true` for `serde_json::Value` fields — some MCP clients reject this. Use `#[schemars(transform)]` to override.
117
118
-**Error type**: `McpToolError` enum (InvalidParam, WalletNotFound, SpvSyncFailed, TaskFailed, Internal) converts to `rmcp::ErrorData` via `From`.
118
-
-**Docs**: `docs/MCP.md` (server config, tool reference), `docs/CLI.md` (usage, examples), `docs/EXPOSING_BACKEND_TASKS.md` (checklist for adding new MCP tools).
119
+
-**Docs**: `docs/MCP.md` (server config, tool reference), `docs/CLI.md` (usage, examples), `docs/MCP_TOOL_DEVELOPMENT.md` (checklist for adding new MCP tools).
Copy file name to clipboardExpand all lines: CONTRIBUTING.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -76,7 +76,7 @@ The default `cargo build` produces only the `dash-evo-tool` GUI binary. Optional
76
76
77
77
### Adding MCP tools
78
78
79
-
To expose a `BackendTask` as a new MCP/CLI tool, follow the step-by-step checklist in [docs/EXPOSING_BACKEND_TASKS.md](docs/EXPOSING_BACKEND_TASKS.md). It covers architecture rules, the standard invocation pattern, registration, and common pitfalls.
79
+
To expose a `BackendTask` as a new MCP/CLI tool, follow the step-by-step checklist in [docs/MCP_TOOL_DEVELOPMENT.md](docs/MCP_TOOL_DEVELOPMENT.md). It covers architecture rules, the standard invocation pattern, registration, and common pitfalls.
|`network_info`| — |`det-cli network-info`| Show active network and available configured networks |
71
+
|`network_reinit_sdk`|`network`|`det-cli network-reinit-sdk`| Rebuild Core RPC client and Platform SDK with current config (use after changing credentials) |
72
+
|`network_switch`|`network`|`det-cli network-switch`| Switch the active network (creates context if needed, may take a few seconds) |
71
73
|`core_wallets_list`|`network`? |`det-cli core-wallets-list`| List wallets loaded in the app (alias + seed hash) |
72
74
|`core_address_create`|`wallet_id`, `network`? |`det-cli core-address-create`| Generate a new receive address for a wallet |
73
75
|`core_balances_get`|`wallet_id`, `network`? |`det-cli core-balances-get`| Show wallet balances (total, confirmed, unconfirmed) in duffs |
@@ -88,6 +90,12 @@ Set these in the app's `.env` file (see `.env.example`) or as environment variab
88
90
89
91
Parameters marked `?` are optional. The `det-cli` column shows the equivalent CLI command (underscores become hyphens).
90
92
93
+
### SPV requirements
94
+
95
+
All wallet-facing tools wait for SPV to fully sync before executing. This includes both core-chain tools (`core_address_create`, `core_balances_get`, `core_funds_send`) and platform tools (`platform_addresses_list`, `identity_credits_topup`, `shielded_shield_from_core`). Even DAPI-only operations need SPV because the SDK verifies DAPI proofs against quorum and masternode list data from the synced chain. When another DET instance is already running, SPV falls back to a temporary directory and must sync from scratch.
96
+
97
+
Only metadata tools that make no network calls (`core_wallets_list`, `network_info`, `tool_describe`) skip the SPV gate.
98
+
91
99
## CLI interface (det-cli)
92
100
93
101
`det-cli` is the command-line interface for interacting with MCP tools. It can operate in two modes:
// 4. Wait for SPV sync if tool needs wallet/chain data
77
+
// 4. Wait for SPV sync (see SPV gate rule below)
78
78
resolve::ensure_spv_synced(&ctx).await?;
79
79
80
80
// 5. Build and dispatch the backend task
@@ -97,7 +97,7 @@ impl AsyncTool<DashMcpService> for MyNewTool {
97
97
- Skip `verify_network` only for `network_info` and `tool_describe`.
98
98
- For destructive tools (`read_only: false`), the `network` parameter **must be required** (not optional with `#[serde(default)]`). Use `resolve::require_network()` instead of `resolve::verify_network()` to prevent accidental cross-network operations that could spend funds on the wrong network.
99
99
- Skip wallet resolution if the tool doesn't operate on a wallet.
100
-
-Skip `ensure_spv_synced`if the tool reads only from the database or Platform SDK (no SPV-dependent data). For tools that only dispatch Platform state transitions (not Core UTXO spends), add an `// INTENTIONAL: no SPV sync needed` comment explaining why.
100
+
-**SPV gate rule**: Call `ensure_spv_synced`for **all wallet-facing tools** — both core-chain and platform/DAPI. The SDK verifies DAPI proofs against quorum and masternode list data from the synced SPV chain, so even platform-only queries fail without it. Skip only for metadata tools that make no network calls (`core_wallets_list`, `network_info`, `tool_describe`).
0 commit comments