Overview
See also: User Guide (English) | Guía de Usuario (Español) | Run Your Own Node
Mostro uses Addressable Events to publish different types of information. Each event type has its own kind:
| Event Type | Kind | Description |
|---|---|---|
| Orders | 38383 | P2P order events for the shared order book |
| Ratings | 38384 | User rating events |
| Info | 38385 | Mostro instance status and information |
| Disputes | 38386 | Dispute events |
You can find more details about the order event here
The Message
Transports
Mostro messages travel over one of two interchangeable wire transports. A
given node speaks exactly one of them — there is no dual mode — and
advertises which in its instance-info event
(kind 38385) through the protocol_version tag ("1" or "2"):
| Protocol | Transport | Event kind | Status |
|---|---|---|---|
| v1 | NIP-59 Gift Wrap | 1059 | DEPRECATED (default through v0.18.x) |
| v2 | NIP-44 direct message | 14 | current (default from v0.19.0) |
Both transports carry the same logical message and, once unwrapped,
yield the same structure to the daemon's handlers — only the envelope and
how the identity key is proven differ. Client developers should support
both during the transition and pick per node from the protocol_version
tag; see the client migration guide.
The logical message itself (the first tuple element described below) is
identical across transports, except for the version field: 1 on the
gift-wrap transport, 2 on the NIP-44 direct transport.
The logical message
In protocol v1 all messages from/to Mostro are
Gift wrap Nostr events;
the content of the rumor event is a JSON-serialized array as a string
(with no white space or line breaks), the first element is the message, the
second element is the signature of the sha256 hash of the serialized
first element. In protocol v2 the same array travels NIP-44 encrypted
inside a signed kind-14 event and gains a third element (the identity
proof) — see Keys management
for the v2 wire format. Here the structure of the first element (the
logical message, shared by both transports):
- Wrapper: Wrapper of the Message
- <
versioninteger>: Version of the protocol —1on the gift-wrap transport,2on the NIP-44 direct transport - [
idinteger]: (optional) Wrapper Id - [
request_idinteger]: (optional) Mostro daemon should send back this same id in the response - [
trade_indexinteger]: (optional) This field is used by users who wants to maintain reputation, it should be the index of the trade in the user's trade history - <
actionstring>: Action to be performed by Mostro daemon - [
payloadstring]: (optional) Payload of the message, it should be a JSON-serialized string. The content of this field depends on theactionfield.
- <
Here an example of a new-order order message:
{
"order": {
"version": 1,
"id": "<Order id>",
"request_id": 123456,
"trade_index": 1,
"action": "new-order",
"payload": {
"order": {
"id": "<Order id>",
"kind": "sell",
"status": "pending",
"amount": 0,
"fiat_code": "VES",
"fiat_amount": 100,
"payment_method": "face to face",
"premium": 1,
"created_at": 1698870173
}
}
}
}
The content array (v1 vs v2)
The first element above is the logical message. The array that actually
travels in the content differs by transport:
Protocol v1 (gift wrap) — a 2-element array:
[
{ "order": { "version": 1, "...": "..." } },
"<trade-key signature, or null>"
]
Protocol v2 (NIP-44 direct) — a 3-element array, the v1 pair plus an
identity proof, NIP-44 encrypted inside a signed kind-14 event:
[
{ "order": { "version": 2, "...": "..." } },
"<trade-key signature, or null>",
["<identity pubkey>", "<identity signature>"]
]
| element | meaning |
|---|---|
| 1 | the logical message (the version: 2 wrapper shown above) |
| 2 | the trade key's signature over the serialized first element, or null (Mostro replies and full-privacy mode set this element to null; the outer kind-14 event is still signed, as in v1) |
| 3 | the identity proof ["<identity pubkey>", "<identity signature>"], or null for full-privacy mode (where the identity is the trade key itself) |
In v1 the identity key is carried, authenticated, by the gift-wrap seal. v2 has no seal, so the identity instead travels inside the ciphertext as element 3 — never visible at the event level, exactly as private as before. The full v2 envelope and identity-proof signing rule are documented in Keys management.
Payment Request Array Structure
The payment_request field in the payload can have different structures depending on the use case:
-
Lightning invoice from buyer/seller to Mostro (action:
add-invoice):- With amount:
[null, "lnbc..."] - Without amount (0-amount invoice):
[null, "lnbc...", amount_in_sats]
- With amount:
-
Lightning address:
- Taking a sell order with fixed amount:
[null, "[email protected]"] - Taking a sell Range order:
[null, "[email protected]", fiat_amount]
- Taking a sell order with fixed amount:
Optional Fields
Some fields in order objects may be null or omitted depending on the context:
request_id: Optional field that clients can include to correlate responses with requests. Mostro will echo this value back in responses.trade_index: Required for users maintaining reputation, omitted when using full privacy mode.expires_at: Unix timestamp when the order expires. Present in order confirmations and updates, but set to0ornullwhen creating new orders.created_at: Unix timestamp when the order was created. Set to0or current time when creating orders; Mostro will set the actual timestamp.- Signature (second array element): Required for reputation mode (signs the first element with trade key), set to
nullin full privacy mode or for Mostro responses.
Payment Method Format
Payment methods can be specified like this:
["pm", "face to face", "bank transfer", "mobile"]