Skip to content

Commit 778d8ab

Browse files
docs: add dispute chat documentation with NIP-59 Gift Wrap protocol
1 parent dda77a8 commit 778d8ab

3 files changed

Lines changed: 145 additions & 3 deletions

File tree

src/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
- [Rate user](./user_rating.md)
2121
- [Cancel](./cancel.md)
2222
- [Dispute](./dispute.md)
23+
- [Dispute Chat](./dispute_chat.md)
2324
- [Peer-to-peer Chat](./chat.md)
2425
- [List disputes](./list_disputes.md)
2526
- [Admin Settle order](./admin_settle_order.md)

src/dispute.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Dispute
22

3-
A use can start a dispute in an order with status `active` or `fiat-sent` sending action `dispute`, here is an example where the seller initiates a dispute:
3+
A user can start a dispute in an order with status `active` or `fiat-sent` sending action `dispute`, here is an example where the seller initiates a dispute:
44

55
```json
66
[
@@ -56,7 +56,7 @@ And here is the message to the buyer:
5656

5757
Mostro will not update the addressable event with `d` tag `<Order Id>` to change the status to `dispute`, this is because the order is still active, the dispute is just a way to let the admins and the other party know that there is a problem with the order.
5858

59-
## Mostro send a addressable event to show the dispute
59+
## Mostro sends an addressable event to show the dispute
6060

6161
Here is an example of the event sent by Mostro:
6262

@@ -128,7 +128,7 @@ Mostro will send a confirmation message to the admin with the order details:
128128
]
129129
```
130130

131-
Then mostrod send messages to each trade participat, the buyer and seller for them to know the pubkey of the admin who took the dispute, that way the client can start listening events from that specific pubkey, by default clients should discard any messages received from any pubkey different than Mostro node or dispute solver, the message looks like this:
131+
Then mostrod send messages to each trade participant, the buyer and seller for them to know the pubkey of the admin who took the dispute, that way the client can start listening events from that specific pubkey, by default clients should discard any messages received from any pubkey different than Mostro node or dispute solver, the message looks like this:
132132

133133
```json
134134
[

src/dispute_chat.md

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
# Dispute Chat
2+
3+
Once an admin takes a dispute, both the admin and the involved parties (buyer and seller) can communicate through an encrypted chat using Gift Wrap messages (NIP-59).
4+
5+
## Sending a message
6+
7+
Users and admins send messages using action `send-dm`. The message must be wrapped in a Gift Wrap event (kind 1059) to ensure privacy and encryption.
8+
9+
### User sending a message
10+
11+
Here is an example of a user sending a message to the admin:
12+
13+
```json
14+
[
15+
{
16+
"dm": {
17+
"version": 1,
18+
"action": "send-dm",
19+
"payload": {
20+
"text_message": "Hello, I need help with this order"
21+
}
22+
}
23+
},
24+
null
25+
]
26+
```
27+
28+
This content is wrapped in a RUMOR (kind 1, unsigned), then encrypted in a SEAL (kind 13), and finally wrapped in a Gift Wrap event (kind 1059) before being published to the relays.
29+
30+
### Admin sending a message
31+
32+
Admins use the same format to send messages to users:
33+
34+
```json
35+
[
36+
{
37+
"dm": {
38+
"version": 1,
39+
"action": "send-dm",
40+
"payload": {
41+
"text_message": "I'm reviewing the evidence, please wait"
42+
}
43+
}
44+
},
45+
null
46+
]
47+
```
48+
49+
## Gift Wrap structure
50+
51+
The Gift Wrap protocol (NIP-59) provides three layers of encryption:
52+
53+
### Layer 1: RUMOR (kind 1)
54+
55+
The original unsigned message containing the actual content:
56+
57+
```json
58+
{
59+
"kind": 1,
60+
"content": "[{\"dm\": {\"version\": 1, \"action\": \"send-dm\", \"payload\": {\"text_message\": \"Hello\"}}}, null]",
61+
"pubkey": "<Sender's trade pubkey>",
62+
"created_at": 1234567890,
63+
"tags": []
64+
}
65+
```
66+
67+
### Layer 2: SEAL (kind 13)
68+
69+
The RUMOR encrypted with NIP-44:
70+
71+
```json
72+
{
73+
"id": "<Seal event id>",
74+
"kind": 13,
75+
"content": "<Encrypted RUMOR with NIP-44>",
76+
"pubkey": "<Sender's trade pubkey>",
77+
"created_at": 1234567890,
78+
"tags": [],
79+
"sig": "<Signature>"
80+
}
81+
```
82+
83+
### Layer 3: GIFT WRAP (kind 1059)
84+
85+
The final layer using an ephemeral key:
86+
87+
```json
88+
{
89+
"id": "<Gift wrap event id>",
90+
"kind": 1059,
91+
"content": "<Encrypted SEAL with NIP-44>",
92+
"pubkey": "<Ephemeral pubkey>",
93+
"created_at": 1234567890,
94+
"tags": [
95+
["p", "<Receiver's pubkey>"]
96+
],
97+
"sig": "<Signature>"
98+
}
99+
```
100+
101+
## Receiving messages
102+
103+
To receive messages, clients must:
104+
105+
1. Subscribe to kind 1059 events with a `p` tag matching their pubkey
106+
2. Decrypt the Gift Wrap using their private key and the ephemeral pubkey
107+
3. Decrypt the SEAL using their private key and the sender's pubkey from the SEAL
108+
4. Extract the RUMOR content and parse the message
109+
110+
The sender's identity is preserved in the SEAL's pubkey field, allowing the receiver to identify who sent the message (admin or user) while maintaining privacy through the ephemeral key in the Gift Wrap layer.
111+
112+
## Message flow
113+
114+
```
115+
User writes message
116+
117+
Create RUMOR (kind 1)
118+
119+
Encrypt into SEAL (kind 13) with sender's key
120+
121+
Encrypt into Gift Wrap (kind 1059) with ephemeral key
122+
123+
Publish to relays
124+
125+
Receiver gets kind 1059 event
126+
127+
Decrypt Gift Wrap → SEAL
128+
129+
Decrypt SEAL → RUMOR
130+
131+
Parse and display message
132+
```
133+
134+
## Privacy features
135+
136+
The Gift Wrap protocol provides:
137+
138+
- **Double encryption**: SEAL + Gift Wrap layers
139+
- **Sender anonymity**: Ephemeral keys hide the real sender from relay observers
140+
- **Metadata obfuscation**: Randomized timestamps (±2 days)
141+
- **End-to-end encryption**: Only sender and receiver can read messages

0 commit comments

Comments
 (0)