upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArc <33088785+arcbtc@users.noreply.github.com>2023-04-13 11:13:04 +0100
committerGitHub <noreply@github.com>2023-04-13 07:13:04 -0300
commitbf0a0da6a48b96467172414d8e41dc72b0ca379c (patch)
tree6c09aac40cf91ee1032aabb153064b74b51add19
parentfb39455804cf772337616072a24dc5598ebefcbe (diff)
NIP-15 Nostr marketplace (#330)
Co-authored-by: Andrew Camilleri <evilkukka@gmail.com> Co-authored-by: Vlad Stan <stan.v.vlad@gmail.com>
-rw-r--r--15.md214
1 files changed, 214 insertions, 0 deletions
diff --git a/15.md b/15.md
new file mode 100644
index 0000000..a3d105d
--- /dev/null
+++ b/15.md
@@ -0,0 +1,214 @@
1NIP-15
2======
3
4Nostr Marketplace (for resilient marketplaces)
5-----------------------------------
6
7`draft` `optional` `author:fiatjaf` `author:benarc` `author:motorina0` `author:talvasconcelos`
8
9> Based on https://github.com/lnbits/Diagon-Alley
10
11> Implemented here https://github.com/lnbits/nostrmarket
12
13## Terms
14
15- `merchant` - seller of products with NOSTR key-pair
16- `customer` - buyer of products with NOSTR key-pair
17- `product` - item for sale by the `merchant`
18- `stall` - list of products controlled by `merchant` (a `merchant` can have multiple stalls)
19- `marketplace` - clientside software for searching `stalls` and purchasing `products`
20
21## Nostr Marketplace Clients
22
23### Merchant admin
24
25Where the `merchant` creates, updates and deletes `stalls` and `products`, as well as where they manage sales, payments and communication with `customers`.
26
27The `merchant` admin software can be purely clientside, but for `convenience` and uptime, implementations will likely have a server client listening for NOSTR events.
28
29### Marketplace
30
31`Marketplace` software should be entirely clientside, either as a stand-alone app, or as a purely frontend webpage. A `customer` subscribes to different merchant NOSTR public keys, and those `merchants` `stalls` and `products` become listed and searchable. The marketplace client is like any other ecommerce site, with basket and checkout. `Marketplaces` may also wish to include a `customer` support area for direct message communication with `merchants`.
32
33## `Merchant` publishing/updating products (event)
34
35A merchant can publish these events:
36| Kind | | Description | NIP |
37|---------|------------------|---------------------------------------------------------------------------------------------------------------|-----------------------------------------|
38| `0 ` | `set_meta` | The merchant description (similar with any `nostr` public key). | [NIP01 ](https://github.com/nostr-protocol/nips/blob/master/01.md) |
39| `30017` | `set_stall` | Create or update a stall. | [NIP33](https://github.com/nostr-protocol/nips/blob/master/33.md) (Parameterized Replaceable Event) |
40| `30018` | `set_product` | Create or update a product. | [NIP33](https://github.com/nostr-protocol/nips/blob/master/33.md) (Parameterized Replaceable Event) |
41| `4 ` | `direct_message` | Communicate with the customer. The messages can be plain-text or JSON. | [NIP09](https://github.com/nostr-protocol/nips/blob/master/09.md) |
42| `5 ` | `delete` | Delete a product or a stall. | [NIP05](https://github.com/nostr-protocol/nips/blob/master/05.md) |
43
44### Event `30017`: Create or update a stall.
45
46**Event Content**:
47```json
48{
49 "id": <String, UUID generated by the merchant. Sequential IDs (`0`, `1`, `2`...) are discouraged>,
50 "name": <String, stall name>,
51 "description": <String (optional), stall description>,
52 "currency": <String, currency used>,
53 "shipping": [
54 {
55 "id": <String, UUID of the shipping zone, generated by the merchant>,
56 "name": <String (optional), zone name>,
57 "cost": <float, cost for shipping. The currency is defined at the stall level>,
58 "countries": [<String, countries included in this zone>],
59 }
60 ]
61}
62```
63
64Fields that are not self-explanatory:
65 - `shipping`:
66 - an array with possible shipping zones for this stall. The customer MUST choose exactly one shipping zone.
67 - shipping to different zones can have different costs. For some goods (digital for examle) the cost can be zero.
68 - the `id` is an internal value used by the merchant. This value must be sent back as the customer selection.
69
70**Event Tags**:
71```json
72 "tags": [["d", <String, id of stall]]
73```
74 - the `d` tag is required by [NIP33](https://github.com/nostr-protocol/nips/blob/master/33.md). Its value MUST be the same as the stall `id`.
75
76### Event `30018`: Create or update a product
77
78**Event Content**:
79```json
80{
81 "id": <String, UUID generated by the merchant.Sequential IDs (`0`, `1`, `2`...) are discouraged>,
82 "stall_id": <String, UUID of the stall to which this product belong to>,
83 "name": <String, product name>,
84 "description": <String (optional), product description>,
85 "images": <[String], array of image URLs, optional>,
86 "currency": <String, currency used>,
87 "price": <float, cost of product>,
88 "quantity": <int, available items>,
89 "specs": [
90 [ <String, spec key>, <String, spec value>]
91 ]
92}
93```
94
95Fields that are not self-explanatory:
96 - `specs`:
97 - an array of key pair values. It allows for the Customer UI to present present product specifications in a structure mode. It also allows comparison between products
98 - eg: `[["operating_system", "Android 12.0"], ["screen_size", "6.4 inches"], ["connector_type", "USB Type C"]]`
99
100_Open_: better to move `spec` in the `tags` section of the event?
101
102**Event Tags**:
103```json
104 "tags": [
105 ["d", <String, id of product],
106 ["t", <String (optional), product category],
107 ["t", <String (optional), product category],
108 ...
109 ]
110```
111
112 - the `d` tag is required by [NIP33](https://github.com/nostr-protocol/nips/blob/master/33.md). Its value MUST be the same as the product `id`.
113 - the `t` tag is as searchable tag ([NIP12](https://github.com/nostr-protocol/nips/blob/master/12.md)). It represents different categories that the product can be part of (`food`, `fruits`). Multiple `t` tags can be present.
114
115## Checkout events
116
117All checkout events are sent as JSON strings using ([NIP04](https://github.com/nostr-protocol/nips/blob/master/04.md)).
118
119The `merchant` and the `customer` can exchange JSON messages that represent different actions. Each `JSON` message `MUST` have a `type` field indicating the what the JSON represents. Possible types:
120
121| Message Type | Sent By | Description |
122|--------------|----------|---------------------|
123| 0 | Customer | New Order |
124| 1 | Merchant | Payment Request |
125| 2 | Merchant | Order Status Update |
126
127
128### Step 1: `customer` order (event)
129The below json goes in content of [NIP04](https://github.com/nostr-protocol/nips/blob/master/04.md).
130
131```json
132{
133 "id": <String, UUID generated by the customer>,
134 "type": 0,
135 "name": <String (optional), ???>,
136 "address": <String (optional), for physical goods an address should be provided>
137 "message": "<String (optional), message for merchant>,
138 "contact": {
139 "nostr": <32-bytes hex of a pubkey>,
140 "phone": <String (optional), if the customer whats to be contacted by phone>,
141 "email": <String (optional), if the customer whats to be contacted by email>,
142 },
143 "items": [
144 {
145 "product_id": <String, UUID of the product>,
146 "quantity": <int, how many products have been ordered>
147 }
148 ],
149 "shipping_id": <String, UUID of the shipping zone>
150}
151
152```
153
154_Open_: is `contact.nostr` required?
155
156
157### Step 2: `merchant` request payment (event)
158
159Sent back from the merchant for payment. Any payment option is valid that the merchant can check.
160
161The below json goes in `content` of [NIP04](https://github.com/nostr-protocol/nips/blob/master/04.md).
162
163`payment_options`/`type` include:
164
165- `url` URL to a payment page, stripe, paypal, btcpayserver, etc
166- `btc` onchain bitcoin address
167- `ln` bitcoin lightning invoice
168- `lnurl` bitcoin lnurl-pay
169
170```json
171{
172 "id": <String, UUID of the order>,
173 "type": 1,
174 "message": <String, message to customer, optional>,
175 "payment_options": [
176 {
177 "type": <String, option type>,
178 "link": <String, url, btc address, ln invoice, etc>
179 },
180 {
181 "type": <String, option type>,
182 "link": <String, url, btc address, ln invoice, etc>
183 },
184 {
185 "type": <String, option type>,
186 "link": <String, url, btc address, ln invoice, etc>
187 }
188 ]
189}
190```
191
192### Step 3: `merchant` verify payment/shipped (event)
193
194Once payment has been received and processed.
195
196The below json goes in `content` of [NIP04](https://github.com/nostr-protocol/nips/blob/master/04.md).
197
198```json
199{
200 "id": <String, UUID of the order>,
201 "type": 2,
202 "message": <String, message to customer>,
203 "paid": <Bool, true/false has received payment>,
204 "shipped": <Bool, true/false has been shipped>,
205}
206```
207
208## Customer support events
209
210Customer support is handled over whatever communication method was specified. If communicating via nostr, NIP-04 is used https://github.com/nostr-protocol/nips/blob/master/04.md.
211
212## Additional
213
214Standard data models can be found here <a href="https://raw.githubusercontent.com/lnbits/nostrmarket/main/models.py">here</a>