Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
13 changes: 13 additions & 0 deletions .cursor/commands/build.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# build mostro-cli using coding standards


## Overview

Build and test mostro-cli, fixing all errors reported by cargo and clippy.

## Steps

- execute cargo fmt --all
- execute cargo clippy --all-targets --all-features
- execute cargo test
- execute cargo build
31 changes: 31 additions & 0 deletions .cursor/commands/pull_request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Create PR

## Overview

Create a well-structured pull request with proper description, labels, and reviewers.

## Steps

1. **Prepare branch**
- Ensure all changes are committed
- Push branch to remote
- Verify branch is up to date with main

2. **Write PR description**
- Summarize changes clearly
- Include context and motivation
- List any breaking changes
- Add screenshots if UI changes

3. **Set up PR**
- Create PR with descriptive title
- Add appropriate labels
- Assign reviewers
- Link related issues

## PR Template

- [ ] Feature A
- [ ] Bug fix B
- [ ] Unit tests pass
- [ ] Manual testing completed
12 changes: 12 additions & 0 deletions .cursor/commands/update_docs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Update AI docs for automatic code generation with context

## Overview

Keep Markdown documents updated to provide AI context, improving the quality of generated code.

## Steps

- Identify the latest changes in Git history for files in the docs folder
- Analyze all new changes up to the latest commit
- Document new features, fixes, and refactorings in the docs
- Add contextual notes for structural changes (e.g., update DATABASE.md for DB schema changes)
5 changes: 5 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ path = "src/main.rs"
[dependencies]
anyhow = "1.0.99"
clap = { version = "4.5.46", features = ["derive"] }
nostr-sdk = { version = "0.43.0", features = ["nip06", "nip44", "nip59"] }
nostr-sdk = { version = "0.43.0", features = ["nip06", "nip44", "nip59", "nip98"] }
serde = "1.0.219"
serde_json = "1.0.143"
tokio = { version = "1.47.1", features = ["full"] }
Expand All @@ -47,6 +47,11 @@ pretty_env_logger = "0.5.0"
sqlx = { version = "0.8.6", features = ["sqlite", "runtime-tokio-rustls"] }
bip39 = { version = "2.2.0", features = ["rand"] }
dirs = "6.0.0"
chacha20poly1305 = "0.10.1"
rand_core = "0.6.4"
bitcoin = "0.32.2"
bitcoin_hashes = { version = "0.14", default-features = false }
base64 = "0.22"
Comment thread
arkanoider marked this conversation as resolved.

[package.metadata.release]
# (Default: true) Set to false to prevent automatically running `cargo publish`.
Expand Down
134 changes: 134 additions & 0 deletions docs/architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
## Architecture & Code Structure

This document describes the internal structure of `mostro-cli`, how major modules interact, and the main data/control flows. It is intentionally high-level to stay stable across refactors.

### Entry point and CLI wiring

- **`src/main.rs`**
- Initializes the async runtime and delegates to `cli::run()`.
- Very thin; most logic is in `src/cli.rs`.

- **`src/cli.rs`**
- Declares submodules for each logical command group: `add_invoice`, `adm_send_dm`, `conversation_key`, `dm_to_user`, `get_dm`, `get_dm_user`, `last_trade_index`, `list_disputes`, `list_orders`, `new_order`, `orders_info`, `rate_user`, `restore`, `send_dm`, `send_admin_dm_attach`, `send_msg`, `take_dispute`, `take_order`.
- Defines:
- `Context`: runtime dependencies required by commands (Nostr client, keys, trade index, DB pool, optional admin context keys, and Mostro pubkey).
- `Cli`: top-level arguments parsed by `clap` (subcommand, verbosity, Mostro pubkey override, relay list, PoW, secret mode).
- `Commands`: enum containing all subcommands and their structured arguments.
- `run()`:
- Parses CLI args via `Cli::parse()`.
- Constructs a `Context` using `init_context(&cli)`.
- Dispatches: `if let Some(cmd) = &cli.command { cmd.run(&ctx).await?; }`.
- `init_context()`:
- Sets environment variables from CLI flags (e.g. `MOSTRO_PUBKEY`, `RELAYS`, `POW`, `SECRET`).
- Connects to SQLite via `db::connect()`.
- Loads identity and per-trade keys from the local `users` table.
- Optionally loads `ADMIN_NSEC` into `context_keys` for admin commands.
- Resolves `MOSTRO_PUBKEY` via CLI flag or environment.
- Connects to Nostr relays via `util::connect_nostr()`.

### Utilities and shared infrastructure

- **`src/util/mod.rs`**
- Organizes utility modules:
- `events`: event filtering and retrieval from Nostr.
- `messaging`: higher-level DM helpers (gift-wrapped messages, admin keys, **shared-key derivation and custom wraps**).
- `misc`: small helpers such as `get_mcli_path` and string utilities.
- `net`: Nostr network connection setup.
- `storage`: thin storage helpers for orders and DMs.
- `types`: small shared enums/wrappers.
- Re-exports commonly used symbols (`create_filter`, `send_dm`, `connect_nostr`, `save_order`, **`derive_shared_keys`, `derive_shared_key_hex`, `keys_from_shared_hex`, `send_admin_chat_message_via_shared_key`**, etc.) so other modules can import from `crate::util` directly.

- **`src/util/storage.rs`**
- `save_order(order, trade_keys, request_id, trade_index, pool)`:
- Wraps `Order::new` to insert/update an order row.
- Logs created order IDs.
- Updates the `User`'s `last_trade_index` in the `users` table.
- `run_simple_order_msg(command, order_id, ctx)`:
- Convenience wrapper that forwards to `cli::send_msg::execute_send_msg(...)` for simple order messages (e.g. `FiatSent`, `Release`, `Cancel`, `Dispute`).
- `admin_send_dm(ctx, msg)`:
- Uses `util::messaging::get_admin_keys` and `util::send_dm` to send an admin DM via Nostr.

- **`src/util/types.rs`**
- `Event` enum:
- Wraps `SmallOrder`, `Dispute`, and a `Message` tuple `(Message, u64, PublicKey)` for use in parsers and event handling.
- `ListKind` enum:
- Identifies what is being listed: `Orders`, `Disputes`, `DirectMessagesUser`, `DirectMessagesAdmin`, `PrivateDirectMessagesUser`.
- `MessageType` (internal to `util`) distinguishes DM/gift-wrap styles.

### Database layer

- **`src/db.rs`**
- Connection:
- `connect()` creates or opens `mcli.db` in the CLI data directory from `get_mcli_path()`.
- On first run, it creates the `orders` and `users` tables via raw SQL.
- On subsequent runs, it applies a small migration to drop legacy `buyer_token`/`seller_token` columns if present.
- Models:
- `User`:
- Represents the local identity (mnemonic, root pubkey, last trade index).
- Handles creation (`User::new`), loading (`User::get`), updating (`save`), and key derivation helpers (identity keys and per-trade keys using `nip06`).
- `Order`:
- Represents cached orders with fields mapped to the `orders` table.
- Provides `new`, `insert_db`, `update_db`, fluent setters, `save`, `save_new_id`, `get_by_id`, `get_all_trade_keys`, **`get_all_trade_and_counterparty_keys`** (distinct `(trade_keys, counterparty_pubkey)` pairs for orders where both are set), and `delete_by_id`.
- See `database.md` for schema details.

### Parsers and protocol types

- **`src/parser/*`**
- Interpret raw Nostr events into higher-level `Event` variants based on `mostro_core` types.
- Responsibility split:
- `orders.rs`: parsing order-related events.
- `disputes.rs`: parsing dispute events.
- `dms.rs`: parsing direct messages.
- `common.rs`: shared parsing helpers.
- `mod.rs`: module glue.

- **Shared-key custom wraps** (`src/util/messaging.rs`):
- **Sending**: `derive_shared_keys(local_keys, counterparty_pubkey)` yields a `Keys` whose public key is used as the NIP-59 gift-wrap recipient; inner content is a signed text note encrypted with NIP-44 to that pubkey. Used by `dmtouser` and `sendadmindmattach`.
- **Receiving**: `unwrap_giftwrap_with_shared_key(shared_keys, event)` decrypts with NIP-44 and returns `(content, timestamp, sender_pubkey)`; `fetch_gift_wraps_for_shared_key(client, shared_keys)` fetches Kind::GiftWrap events with `#p` = shared key pubkey and unwraps them. Use when implementing flows that read shared-key DMs.

### Lightning integration

- **`src/lightning/mod.rs`**
- Houses Lightning Network–specific helpers used by order flows and invoice handling (exact functions depend on the current version of the file).
- Typically used by `add_invoice`, `new_order`, and `take_order` modules.

### Command modules

Each file in `src/cli/` encapsulates the logic of a specific feature or a group of related commands:

- Order-related: `add_invoice.rs`, `list_orders.rs`, `new_order.rs`, `take_order.rs`, `orders_info.rs`, `rate_user.rs`, `restore.rs`, `last_trade_index.rs`.
- Disputes and admin: `list_disputes.rs`, `take_dispute.rs`, `adm_send_dm.rs`.
- Messaging: `send_dm.rs`, `send_msg.rs`, `dm_to_user.rs`, `get_dm.rs`, `get_dm_user.rs`, `send_admin_dm_attach.rs`, `conversation_key.rs`.

Each module exports an `execute_*` function that `Commands::run` calls. This keeps `src/cli.rs` as a central router while pushing feature logic into focused files.

### Typical flow: creating a new order

1. User runs `mostro-cli neworder ...`.
2. `clap` parses CLI arguments into `Cli` and `Commands::NewOrder { ... }`.
3. `cli::run()` calls `init_context()` to build `Context` (DB, keys, Nostr client, Mostro pubkey).
4. `Commands::run` matches `Commands::NewOrder` and calls `execute_new_order(...)`.
5. The handler:
- Uses `mostro_core` types to construct an order message.
- Sends it to the Mostro backend over Nostr via `util::connect_nostr`/messaging helpers.
- Persists or updates the local representation via `util::save_order` and `db::Order`.

### Extension guidelines

When adding new features:

- **New command**:
- Add a variant to `Commands` in `src/cli.rs`.
- Add the corresponding `execute_*` function in a `src/cli/*.rs` module.
- Extend the `Commands::run` match arm.
- Update `docs/commands.md` to keep documentation in sync.

- **New database fields / tables**:
- Update `connect()` schema creation and migrations in `src/db.rs`.
- Extend the relevant model structs and methods.
- Update `docs/database.md`.

- **New protocol/event type**:
- Extend `util::types::Event` and the relevant parser module in `src/parser/*`.
- Adjust listing or DM flows as needed.

Loading
Loading