mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-08-09 08:04:45 +00:00
docs: document cashu, admin, serve, fetch code mode, key validate
Update the amy docs to reflect the new command surface:
- cli/README.md — add the Cashu (NIP-60/61), Relay management (NIP-86
admin), and Run-a-relay (serve) sections; document fetch's nip19/nip05
code mode and key validate.
- cli/DEVELOPMENT.md — add cashu.json to the on-disk layout and pin the
command-family --json contracts (cashu keys/error codes + pointer to the
cashu plan, admin {relay,method,result}, serve startup object).
- .claude/skills/amy-expert/SKILL.md — extend the "where things live" tree
with AdminCommand/ServeCommand/cashu/, the commons/cashu + relayManagement
shared modules, and the allowed :geode dependency.
- .claude/CLAUDE.md — note cli may depend on :geode (for serve), never on
:amethyst/:desktopApp.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011SapGdtAc1j7woifoCZ9fY
This commit is contained in:
+3
-1
@@ -76,7 +76,9 @@ amethyst/
|
||||
- `nestsClient/` = MoQ + audio-rooms client; takes `:quic` as transport,
|
||||
Quartz for crypto, `MediaCodec` / `AudioRecord` / `AudioTrack` for audio.
|
||||
- `amethyst/` & `desktopApp/` = Platform-native layouts and navigation
|
||||
- `cli/` = Thin assembly layer over `quartz/` + `commons/` (no new logic allowed)
|
||||
- `cli/` = Thin assembly layer over `quartz/` + `commons/` (no new logic
|
||||
allowed). May also depend on `:geode` (for `amy serve`, which embeds the
|
||||
standalone relay); never on `:amethyst` or `:desktopApp`.
|
||||
|
||||
**Plans per module:** design docs for new subsystems live in the owning
|
||||
module's `plans/YYYY-MM-DD-<slug>.md` (e.g. `cli/plans/`, `commons/plans/`).
|
||||
|
||||
@@ -189,15 +189,30 @@ cli/
|
||||
├── MessageCommands.kt
|
||||
├── MarmotResetCommand.kt
|
||||
├── AwaitCommands.kt
|
||||
└── StoreCommands.kt
|
||||
├── StoreCommands.kt
|
||||
├── AdminCommand.kt # `amy admin RELAY METHOD` (NIP-86)
|
||||
├── ServeCommand.kt # `amy serve` (embeds :geode)
|
||||
└── cashu/ # `amy cashu …` (NIP-60/61) — thin wrappers
|
||||
├── CashuCommands.kt # over commons CashuWalletOps / CashuWalletReader
|
||||
├── CashuWalletCommands.kt + CashuBalanceCommand.kt + CashuMintCommands.kt
|
||||
└── CashuReceiveCommands.kt + CashuSendCommands.kt
|
||||
+ CashuMaintenanceCommands.kt + CashuMintRecCommands.kt
|
||||
```
|
||||
|
||||
Shared logic consumed by Amy lives in `commons/`:
|
||||
- `commons/account/` — account bootstrap
|
||||
- `commons/marmot/` — MLS / group state
|
||||
- `commons/cashu/` — `ops/CashuWalletOps` (jvmAndroid) + `CashuWalletReader`
|
||||
+ `CashuKeysetCounterStore`; the NIP-60/61 wallet, shared with Android.
|
||||
- `commons/relayManagement/Nip86Retriever` — NIP-86 HTTP client, shared with
|
||||
the Android relay-management screen.
|
||||
- `commons/defaults/` — default relays, kinds
|
||||
- Consult `commons/plans/` for cross-cutting design work in flight.
|
||||
|
||||
A few amy verbs lean on modules beyond `quartz`/`commons`: `amy serve`
|
||||
depends on `:geode` (the standalone relay) — the one allowed extra module
|
||||
dependency. `:amethyst` / `:desktopApp` remain forbidden (Rule 5).
|
||||
|
||||
## Common mistakes to refuse
|
||||
|
||||
- **Adding protocol logic to `cli/`.** Push back, offer to extract.
|
||||
|
||||
@@ -227,6 +227,22 @@ contract.
|
||||
- Errors via `Output.error("code","detail")` — single lower_snake
|
||||
code, free-form detail.
|
||||
|
||||
**Command-family schemas:**
|
||||
|
||||
- **Cashu** (`amy cashu …`, NIP-60/61): the full per-verb `--json` key table
|
||||
and the `cashu.json` NUT-13 counter layout are pinned in
|
||||
[`plans/2026-05-28-cashu-cli.md`](./plans/2026-05-28-cashu-cli.md). Common
|
||||
keys: `wallet_event_id`, `mint_url`, `amount_sats` (Long), `proofs_count`,
|
||||
`token_event_id`, `history_event_id`, `quote_id`, `p2pk_pubkey`. Error codes
|
||||
include `no_wallet`, `no_mint`, `insufficient_funds`, `mint_unreachable`,
|
||||
`mint_http_<status>`, `mint_proofs_spent`, `mint_quote_gone`.
|
||||
- **Admin** (`amy admin …`, NIP-86): `{relay, method, result}` where `result`
|
||||
is the relay's raw JSON-RPC result (list/boolean/null). Relay-side failures
|
||||
surface as `error: relay_error`.
|
||||
- **Serve** (`amy serve`): a single startup object `{listening, host, port,
|
||||
path, persistent, admin_pubkeys[]}`, then the process blocks (it embeds
|
||||
geode; teardown is on SIGINT).
|
||||
|
||||
---
|
||||
|
||||
## Testing
|
||||
@@ -360,6 +376,7 @@ events.
|
||||
│ ├── identity.json # nsec/npub/hex — the account
|
||||
│ ├── state.json # sync cursors (giftWrapSince, groupSince)
|
||||
│ ├── aliases.json # local name → npub map (init writes a self-entry)
|
||||
│ ├── cashu.json # NIP-60 NUT-13 counters: {"keyset_counters":{"<id>":<long>}}
|
||||
│ └── marmot/
|
||||
│ ├── keypackages.bundle # MLS KeyPackage bundles (NostrSignerInternal)
|
||||
│ └── groups/
|
||||
|
||||
@@ -215,6 +215,7 @@ Army-knife verbs that operate purely on their arguments. They never touch
|
||||
| `amy key public NSEC\|HEX` | Derive the public key from a secret key. |
|
||||
| `amy key encrypt NSEC\|HEX --password X` | NIP-49 encrypt a secret key to an `ncryptsec1…`. |
|
||||
| `amy key decrypt NCRYPTSEC --password X` | NIP-49 decrypt back to nsec/hex/npub. |
|
||||
| `amy key validate NPUB\|HEX` | Parse-check a public key. Prints `{valid, pubkey, npub}` or `{valid:false}` — never errors, so scripts branch on the field. |
|
||||
| `amy filter [filter flags]` | Assemble and print a NIP-01 filter JSON from the same flags `fetch`/`subscribe` use — no query is sent. |
|
||||
| `amy nip N` / `amy nip list` | Look up a NIP — the `nostr-protocol/nips` repo first, then a Nostr wiki/long-form fallback. `list` fetches the index. |
|
||||
| `amy kind N` / `amy kind NAME` | Look up an event kind's label + defining NIP (number), or search labels by name. Backed by quartz's `KindNames` registry. |
|
||||
@@ -264,6 +265,7 @@ Filter flags are shared by `fetch` and `subscribe`: `--kind K[,K]`, `--author U[
|
||||
| Command | What it does |
|
||||
|---|---|
|
||||
| `amy fetch [filter flags] [--timeout SECS]` | One-shot query — collect until every relay sends EOSE (or `--timeout`, default 8s), dedupe, sort newest-first, print and exit. `--limit` defaults to 100. |
|
||||
| `amy fetch CODE [--timeout SECS]` | Code mode — pass a single `nevent`/`naddr`/`nprofile`/`npub`/`note` or `name@domain`. Resolves relays the outbox way: the hints embedded in the code **plus** the author's NIP-65 write relays (draining their kind:10002 on a cache miss), exactly how the app opens a shared link. |
|
||||
| `amy subscribe [filter flags] [--timeout SECS]` | Live stream — print each matching event as it arrives (NDJSON under `--json`). Runs until `--timeout` SECS or until interrupted. |
|
||||
| `amy count [filter flags] [--timeout SECS]` | NIP-45 COUNT — per-relay match counts, no event download. |
|
||||
| `amy outbox USER [--refresh] [--timeout SECS]` | Show USER's NIP-65 read/write relays (outbox model). Cache-first; `--refresh` forces a relay drain. |
|
||||
@@ -308,6 +310,55 @@ nak's `clone`/`push`/`pull` (git-packfile transport over relays/GRASP) are out o
|
||||
| `amy blossom check --server URL HASH[,HASH]` | HEAD-check the server has each blob; exit 1 if any is missing. |
|
||||
| `amy blossom mirror --server URL SOURCE-URL` | Ask the server to mirror a blob from SOURCE-URL (BUD-04). |
|
||||
|
||||
### Cashu wallet (NIP-60 / NIP-61)
|
||||
|
||||
A NIP-60 ecash wallet + NIP-61 nutzaps, driven by the **same** shared
|
||||
`commons` `CashuWalletOps` / `CashuWalletReader` the Android wallet runs — so
|
||||
amy's on-relay events match the app's. NUT-13 counters persist in
|
||||
`~/.amy/<account>/cashu.json`. `mint ping`/`info` are stateless (no account).
|
||||
|
||||
| Command | What it does |
|
||||
|---|---|
|
||||
| `amy cashu wallet create [--mint URL] [--mints a,b] [--privkey HEX] [--relay r1,r2]` | Publish a kind:17375 wallet + kind:10019 nutzap info. Advertises your outbox relays for nutzaps unless `--relay` overrides. |
|
||||
| `amy cashu wallet show` | P2PK pubkey, mints, balance, per-mint balances, proof/history/pending counts. |
|
||||
| `amy cashu wallet export-key` | Decrypt and print the wallet's P2PK private key. |
|
||||
| `amy cashu wallet destroy` | Withdraw the nutzap advertisement and NIP-09 delete the wallet (leaves token events — the ecash still lives at the mint). |
|
||||
| `amy cashu balance [--mint URL]` | Spendable balance from the local store (optionally one mint). |
|
||||
| `amy cashu mint ping URL` / `info URL` | Stateless `/v1/info` probe (name/pubkey/version) / full DTO. |
|
||||
| `amy cashu receive ln SATS [--mint URL]` | Request a mint quote; prints the bolt11 + kind:7374 quote. |
|
||||
| `amy cashu receive complete QUOTE_ID` / `resume QUOTE_ID` | Poll the quote; once the invoice is settled, mint proofs (kind:7375 + kind:7376). |
|
||||
| `amy cashu receive token TOKEN` | Redeem a `cashuB…` token into the wallet. |
|
||||
| `amy cashu receive nutzap-sweep [--mint URL]` | Redeem inbound NIP-61 nutzaps locked to your wallet key. |
|
||||
| `amy cashu send ln INVOICE [--mint URL]` | Melt proofs to pay a bolt11 (scrubs stale proofs first). |
|
||||
| `amy cashu send token SATS [--mint URL] [--memo S]` | Export a `cashuB…` token of SATS. |
|
||||
| `amy cashu send nutzap USER SATS [--zapped EVENT_ID] [--message S]` | Send a P2PK-locked nutzap to USER (resolves their kind:10019). |
|
||||
| `amy cashu maintenance scrub [--mint URL]` | NUT-07 + NIP-09 prune of spent proofs. |
|
||||
| `amy cashu maintenance restore MINT_URL` | NUT-09 restore unspent proofs from the wallet seed. |
|
||||
| `amy cashu maintenance migrate-keysets [--mint URL]` | Consolidate proofs onto each mint's active keyset. |
|
||||
| `amy cashu mint-rec show [--author NPUB]` / `add URL [--dtag X] [--review T]` / `remove EVENT_ID` | NIP-87 mint recommendations (kind:38000). |
|
||||
|
||||
### Relay management — admin (NIP-86)
|
||||
|
||||
Signs a NIP-98 request with the active account and POSTs it to the relay's
|
||||
HTTP endpoint. Reuses quartz's `Nip86Client` and the shared `Nip86Retriever`
|
||||
(the same path Amethyst's relay-management screen runs).
|
||||
|
||||
| Command | What it does |
|
||||
|---|---|
|
||||
| `amy admin RELAY supported-methods` | List the NIP-86 methods the relay implements. |
|
||||
| `amy admin RELAY ban-pubkey HEX [--reason R]` / `unban-pubkey HEX` / `list-banned-pubkeys` | Pubkey ban list. |
|
||||
| `amy admin RELAY allow-pubkey HEX [--reason R]` / `unallow-pubkey HEX` / `list-allowed-pubkeys` | Pubkey allow list. |
|
||||
| `amy admin RELAY ban-event ID [--reason R]` / `allow-event ID` / `list-banned-events` / `list-needing-moderation` | Event moderation. |
|
||||
| `amy admin RELAY allow-kind N` / `disallow-kind N` / `list-allowed-kinds` | Kind allow list. |
|
||||
| `amy admin RELAY block-ip IP [--reason R]` / `unblock-ip IP` / `list-blocked-ips` | IP block list. |
|
||||
| `amy admin RELAY change-name S` / `change-description S` / `change-icon URL` | Relay metadata. |
|
||||
|
||||
### Run a relay — serve
|
||||
|
||||
| Command | What it does |
|
||||
|---|---|
|
||||
| `amy serve [--host H] [--port N] [--path P] [--db FILE] [--admin NPUBS]` | Run a Nostr relay by embedding **geode** (the standalone Ktor relay on quartz's relay-server code). In-memory by default; `--db FILE` for SQLite. The active account is always an admin, so `amy admin ws://host:port …` works against it. Blocks until interrupted. |
|
||||
|
||||
### Identity
|
||||
|
||||
| Command | What it does |
|
||||
|
||||
Reference in New Issue
Block a user