From 604f6e397dc7fb524cf41d20126802a7bcde4f49 Mon Sep 17 00:00:00 2001 From: Arc <33088785+arcbtc@users.noreply.github.com> Date: Mon, 6 Mar 2023 10:25:32 +0000 Subject: [PATCH 01/30] NIP45 Nostr marketplace Based on Diagon Alley https://github.com/lnbits/Diagon-Alley --- 45.md | 269 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 269 insertions(+) create mode 100644 45.md diff --git a/45.md b/45.md new file mode 100644 index 000000000..b4a3b6491 --- /dev/null +++ b/45.md @@ -0,0 +1,269 @@ +## Nostr Marketplace (for resilient marketplaces) + +> Based on https://github.com/lnbits/Diagon-Alley + +## Terms + +- `merchant` - seller of products with NOSTR key-pair +- `customer` - buyer of products with NOSTR key-pair +- `product` - item for sale by the `merchant` +- `stall` - list of products controlled by `merchant` (a `merchant` can have multiple stalls) +- `marketplace` - clientside software for searching `stalls` and purchasing `products` + +## Nostr Marketplace Clients + +### Merchant admin + +Where the `merchant` creates, updates and deletes `stalls` and `products`, as well as where they manage sales, payments and communication with `customers`. + +The `merchant` admin software can be purely clientside, but for `convenience` and uptime, implementations will likely have a server listening for NOSTR events. + +### Marketplace + +`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`. + +## `Merchant` publishing/updating products (event) + +NIP-01 https://github.com/nostr-protocol/nips/blob/master/01.md uses the basic NOSTR event type. + +The `merchant` event that publishes and updates product lists + +The below json goes in `content` of NIP-01. + +Data from newer events should replace data from older events. + +`action` types (used to indicate changes): + +- `update` element has changed +- `delete` element should be deleted +- `suspend` element is suspended +- `unsuspend` element is unsuspended + +``` +{ + "name": , + "description": , + "currency": , + "action": , + "shipping": [ + { + "id": , + "zones": , + "price": , + }, + { + "id": , + "zones": , + "price": , + }, + { + "id": , + "zones": , + "price": , + } + ], + "stalls": [ + { + "id": , + "name": , + "description": , + "categories": , + "shipping": , + "action": , + "products": [ + { + "id": , + "name": , + "description": , + "categories": , + "amount": , + "price": , + "images": [ + { + "id": , + "name": , + "link": + } + ], + "action": , + }, + { + "id": , + "name": , + "description": , + "categories": , + "amount": , + "price": , + "images": [ + { + "id": , + "name": , + "link": + }, + { + "id": , + "name": , + "link": + } + ], + "action": , + }, + ] + }, + { + "id": , + "name": , + "description": , + "categories": , + "shipping": , + "action": , + "products": [ + { + "id": , + "name": , + "categories": , + "amount": , + "price": , + "images": [ + { + "id": , + "name": , + "link": + } + ], + "action": , + } + ] + } + ] +} + +``` + +As all elements are optional, an `update` `action` to a `product` `image`, may look as simple as: + +``` +{ + "stalls": [ + { + "id": , + "products": [ + { + "id": , + "images": [ + { + "id": , + "name": , + "link": + } + ], + "action": , + }, + ] + } + ] +} + +``` + +## Checkout events + +NIP-04 https://github.com/nostr-protocol/nips/blob/master/04.md, all checkout events are encrypted + +The below json goes in `content` of NIP-04. + +### Step 1: `customer` order (event) + +``` +{ + "id": , + "name": , + "description": , + "address": , + "message": , + "contact": [ + "nostr": , + "phone": , + "email": + ], + "items": [ + { + "id": , + "quantity": , + "message": + }, + { + "id": , + "quantity": , + "message": + }, + { + "id": , + "quantity": , + "message": + } + ] + +} + +``` + +Merchant should verify the sum of product ids + timestamp. + +### Step 2: `merchant` request payment (event) + +Sent back from the merchant for payment. Any payment option is valid that the merchant can check. + +The below json goes in `content` of NIP-04. + +`payment_options`/`type` include: + +- `url` URL to a payment page, stripe, paypal, btcpayserver, etc +- `btc` onchain bitcoin address +- `ln` bitcoin lightning invoice +- `lnurl` bitcoin lnurl-pay + +``` +{ + "id": , + "message": , + "payment_options": [ + { + "type": , + "link": + }, + { + "type": , + "link": + }, + { + "type": , + "link": + } +} + +``` + +### Step 3: `merchant` verify payment/shipped (event) + +Once payment has been received and processed. + +The below json goes in `content` of NIP-04. + +``` +{ + "id": , + "message": , + "paid": , + "shipped": , +} + +``` + +## Customer support events + +Customer support is handle over whatever communication method was specified. If communicationg via nostr, NIP-04 is used https://github.com/nostr-protocol/nips/blob/master/04.md. + +## Additional + +Standard data models can be found here here From 5fa3da03be753af64e48de7749f8b4413529656f Mon Sep 17 00:00:00 2001 From: ben Date: Mon, 6 Mar 2023 11:04:49 +0000 Subject: [PATCH 02/30] Added correct header --- 45.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/45.md b/45.md index b4a3b6491..48be2e87c 100644 --- a/45.md +++ b/45.md @@ -1,4 +1,10 @@ -## Nostr Marketplace (for resilient marketplaces) +NIP-45 +====== + +Nostr Marketplace (for resilient marketplaces) +----------------------------------- + +`draft` `optional` `author:benarc` `author:motorina0` `author:talvasconcelos` > Based on https://github.com/lnbits/Diagon-Alley @@ -16,7 +22,7 @@ Where the `merchant` creates, updates and deletes `stalls` and `products`, as well as where they manage sales, payments and communication with `customers`. -The `merchant` admin software can be purely clientside, but for `convenience` and uptime, implementations will likely have a server listening for NOSTR events. +The `merchant` admin software can be purely clientside, but for `convenience` and uptime, implementations will likely have a server client listening for NOSTR events. ### Marketplace From b3adbc6e8769364a200d0df652b3e40e9b102a62 Mon Sep 17 00:00:00 2001 From: ben Date: Mon, 6 Mar 2023 11:06:15 +0000 Subject: [PATCH 03/30] Added fiatjaf as author, for his comments in the previous repo we folllowed --- 45.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/45.md b/45.md index 48be2e87c..f30be6334 100644 --- a/45.md +++ b/45.md @@ -4,7 +4,7 @@ NIP-45 Nostr Marketplace (for resilient marketplaces) ----------------------------------- -`draft` `optional` `author:benarc` `author:motorina0` `author:talvasconcelos` +`draft` `optional` `author:fiatjaf` `author:benarc` `author:motorina0` `author:talvasconcelos` > Based on https://github.com/lnbits/Diagon-Alley From 8e03a42941d04a6215531e2b719da31ff7150dce Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Thu, 23 Mar 2023 12:23:59 +0200 Subject: [PATCH 04/30] doc: add events table --- 45.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/45.md b/45.md index f30be6334..03e1fcf50 100644 --- a/45.md +++ b/45.md @@ -30,6 +30,17 @@ The `merchant` admin software can be purely clientside, but for `convenience` an ## `Merchant` publishing/updating products (event) +A merchant can publish these events: +| Kind | | Description | NIP | +|---------|------------------|---------------------------------------------------------------------------------------------------------------|-----------------------------------------| +| `0 ` | `set_meta` | The merchant description (similar with any `nostr` public key) | NIP01 | +| `30017` | `set_stall` | Create or update a stall. | NIP33 (Parameterized Replaceable Event) | +| `30018` | `set_product` | Create or update a product. | NIP33 (Parameterized Replaceable Event) | +| `4 ` | `direct_message` | Communicate with the customer. The messages can be plain-text or JSON (for automatically generated responses) | | +| `5 ` | `delete` | Delete a product or a stall. | NIP09 | + + + NIP-01 https://github.com/nostr-protocol/nips/blob/master/01.md uses the basic NOSTR event type. The `merchant` event that publishes and updates product lists From 1e46b3fdc6b7ba0e12475f695825a73580071db7 Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Thu, 23 Mar 2023 13:54:51 +0200 Subject: [PATCH 05/30] doc: add data structures --- 45.md | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/45.md b/45.md index 03e1fcf50..eff3a18e8 100644 --- a/45.md +++ b/45.md @@ -39,7 +39,44 @@ A merchant can publish these events: | `4 ` | `direct_message` | Communicate with the customer. The messages can be plain-text or JSON (for automatically generated responses) | | | `5 ` | `delete` | Delete a product or a stall. | NIP09 | +**Event `30017`** +Create or update a stall +Data Structure: +```json +{ + "name": "Demo Stall", + "description": "Stall with all kind of products", + "currency": "EUR", + "shipping": [ + { + "name": "ZoneB", + "currency": "EUR", + "cost": 2.0, + "countries": [ + "Belgium" + ], + "id": "jKdBUwXfp3wbynKJU2Z3bV" + } + ] +} +``` + +**Event `30018`** +Create or update a product + +Data Structure: +```json +{ + "stall_id": "huLUPnMmWfNbPhkkH6b529", + "name": "oranges", + "description": "fresh oranges", + "image": "https://upload.wikimedia.org/wikipedia/commons/b/b0/OrangeBloss_wb.jpg", + "currency": "EUR", + "price": 5.0, + "quantity": 20 +} +`` NIP-01 https://github.com/nostr-protocol/nips/blob/master/01.md uses the basic NOSTR event type. From a73d7095cd1db3f7ebc6bd8566380a21af21954e Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Thu, 23 Mar 2023 14:20:56 +0200 Subject: [PATCH 06/30] doc: update links --- 45.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/45.md b/45.md index eff3a18e8..d94ff8ab4 100644 --- a/45.md +++ b/45.md @@ -33,18 +33,22 @@ The `merchant` admin software can be purely clientside, but for `convenience` an A merchant can publish these events: | Kind | | Description | NIP | |---------|------------------|---------------------------------------------------------------------------------------------------------------|-----------------------------------------| -| `0 ` | `set_meta` | The merchant description (similar with any `nostr` public key) | NIP01 | -| `30017` | `set_stall` | Create or update a stall. | NIP33 (Parameterized Replaceable Event) | -| `30018` | `set_product` | Create or update a product. | NIP33 (Parameterized Replaceable Event) | +| `0 ` | `set_meta` | The merchant description (similar with any `nostr` public key) | [NIP01 ](https://github.com/nostr-protocol/nips/blob/master/01.md) | +| `30017` | `set_stall` | Create or update a stall. | [NIP33](https://github.com/nostr-protocol/nips/blob/master/33.md) (Parameterized Replaceable Event) | +| `30018` | `set_product` | Create or update a product. | [NIP33](https://github.com/nostr-protocol/nips/blob/master/33.md) (Parameterized Replaceable Event) | | `4 ` | `direct_message` | Communicate with the customer. The messages can be plain-text or JSON (for automatically generated responses) | | -| `5 ` | `delete` | Delete a product or a stall. | NIP09 | +| `5 ` | `delete` | Delete a product or a stall. | [NIP09](https://github.com/nostr-protocol/nips/blob/master/09.md) | **Event `30017`** -Create or update a stall +Create or update a stall. + +- the stall `id` SHOULD be random generated one. Sequential IDs (`0`, `1`, `2`...) are discouraged. +- the stall `id` MUST be used as the `d` tag for the event (see [NIP33](https://github.com/nostr-protocol/nips/blob/master/33.md)) Data Structure: ```json { + "id": "huLUPnMmWfNbPhkkH6b529", "name": "Demo Stall", "description": "Stall with all kind of products", "currency": "EUR", @@ -62,12 +66,14 @@ Data Structure: } ``` + **Event `30018`** Create or update a product Data Structure: ```json { + "id": "YUfhcprkMSXLZtB5RCaGu2", "stall_id": "huLUPnMmWfNbPhkkH6b529", "name": "oranges", "description": "fresh oranges", @@ -76,7 +82,7 @@ Data Structure: "price": 5.0, "quantity": 20 } -`` +``` NIP-01 https://github.com/nostr-protocol/nips/blob/master/01.md uses the basic NOSTR event type. From c9f96018a0f9eb2f64effd0da51c8a213af7d8f4 Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Thu, 23 Mar 2023 14:37:14 +0200 Subject: [PATCH 07/30] doc: shipping zones --- 45.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/45.md b/45.md index d94ff8ab4..a9645657a 100644 --- a/45.md +++ b/45.md @@ -36,8 +36,8 @@ A merchant can publish these events: | `0 ` | `set_meta` | The merchant description (similar with any `nostr` public key) | [NIP01 ](https://github.com/nostr-protocol/nips/blob/master/01.md) | | `30017` | `set_stall` | Create or update a stall. | [NIP33](https://github.com/nostr-protocol/nips/blob/master/33.md) (Parameterized Replaceable Event) | | `30018` | `set_product` | Create or update a product. | [NIP33](https://github.com/nostr-protocol/nips/blob/master/33.md) (Parameterized Replaceable Event) | -| `4 ` | `direct_message` | Communicate with the customer. The messages can be plain-text or JSON (for automatically generated responses) | | -| `5 ` | `delete` | Delete a product or a stall. | [NIP09](https://github.com/nostr-protocol/nips/blob/master/09.md) | +| `4 ` | `direct_message` | Communicate with the customer. The messages can be plain-text or JSON (for automatically generated responses) | [NIP09](https://github.com/nostr-protocol/nips/blob/master/09.md) | +| `5 ` | `delete` | Delete a product or a stall. | [NIP05](https://github.com/nostr-protocol/nips/blob/master/05.md) | **Event `30017`** Create or update a stall. @@ -55,7 +55,6 @@ Data Structure: "shipping": [ { "name": "ZoneB", - "currency": "EUR", "cost": 2.0, "countries": [ "Belgium" @@ -66,6 +65,10 @@ Data Structure: } ``` + - `shipping`: + - a list with possible shipping zones for this stall. The customer MUST choose exactly one shipping zone. + - shipping to different zones can have different costs. For some goods (digital for examle) the cost can be zero. + - **Event `30018`** Create or update a product From 750f25791cf500151441f5845da39147c28e0deb Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Thu, 23 Mar 2023 14:42:03 +0200 Subject: [PATCH 08/30] doc: clean-up --- 45.md | 145 +--------------------------------------------------------- 1 file changed, 2 insertions(+), 143 deletions(-) diff --git a/45.md b/45.md index a9645657a..470fa4e4c 100644 --- a/45.md +++ b/45.md @@ -68,7 +68,7 @@ Data Structure: - `shipping`: - a list with possible shipping zones for this stall. The customer MUST choose exactly one shipping zone. - shipping to different zones can have different costs. For some goods (digital for examle) the cost can be zero. - - + - the `id` is an internal value used by the merchant. This value must be sent back as the customer selection. **Event `30018`** Create or update a product @@ -84,151 +84,10 @@ Data Structure: "currency": "EUR", "price": 5.0, "quantity": 20 + "specs": [[]] } ``` -NIP-01 https://github.com/nostr-protocol/nips/blob/master/01.md uses the basic NOSTR event type. - -The `merchant` event that publishes and updates product lists - -The below json goes in `content` of NIP-01. - -Data from newer events should replace data from older events. - -`action` types (used to indicate changes): - -- `update` element has changed -- `delete` element should be deleted -- `suspend` element is suspended -- `unsuspend` element is unsuspended - -``` -{ - "name": , - "description": , - "currency": , - "action": , - "shipping": [ - { - "id": , - "zones": , - "price": , - }, - { - "id": , - "zones": , - "price": , - }, - { - "id": , - "zones": , - "price": , - } - ], - "stalls": [ - { - "id": , - "name": , - "description": , - "categories": , - "shipping": , - "action": , - "products": [ - { - "id": , - "name": , - "description": , - "categories": , - "amount": , - "price": , - "images": [ - { - "id": , - "name": , - "link": - } - ], - "action": , - }, - { - "id": , - "name": , - "description": , - "categories": , - "amount": , - "price": , - "images": [ - { - "id": , - "name": , - "link": - }, - { - "id": , - "name": , - "link": - } - ], - "action": , - }, - ] - }, - { - "id": , - "name": , - "description": , - "categories": , - "shipping": , - "action": , - "products": [ - { - "id": , - "name": , - "categories": , - "amount": , - "price": , - "images": [ - { - "id": , - "name": , - "link": - } - ], - "action": , - } - ] - } - ] -} - -``` - -As all elements are optional, an `update` `action` to a `product` `image`, may look as simple as: - -``` -{ - "stalls": [ - { - "id": , - "products": [ - { - "id": , - "images": [ - { - "id": , - "name": , - "link": - } - ], - "action": , - }, - ] - } - ] -} - -``` - ## Checkout events NIP-04 https://github.com/nostr-protocol/nips/blob/master/04.md, all checkout events are encrypted From a5b4833899db82b4de7c5d86a456dc25b0af1687 Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Thu, 23 Mar 2023 15:11:35 +0200 Subject: [PATCH 09/30] doc: product fields --- 45.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/45.md b/45.md index 470fa4e4c..768a25aae 100644 --- a/45.md +++ b/45.md @@ -65,8 +65,9 @@ Data Structure: } ``` +Fields that are not self-explanatory: - `shipping`: - - a list with possible shipping zones for this stall. The customer MUST choose exactly one shipping zone. + - an array with possible shipping zones for this stall. The customer MUST choose exactly one shipping zone. - shipping to different zones can have different costs. For some goods (digital for examle) the cost can be zero. - the `id` is an internal value used by the merchant. This value must be sent back as the customer selection. @@ -80,14 +81,19 @@ Data Structure: "stall_id": "huLUPnMmWfNbPhkkH6b529", "name": "oranges", "description": "fresh oranges", - "image": "https://upload.wikimedia.org/wikipedia/commons/b/b0/OrangeBloss_wb.jpg", + "images": ["https://upload.wikimedia.org/wikipedia/commons/b/b0/OrangeBloss_wb.jpg"] "currency": "EUR", "price": 5.0, "quantity": 20 - "specs": [[]] + "specs": [["feature", "value"]] } ``` +Fields that are not self-explanatory: + - `specs`: + - an array of key pair values. It allows for the Customer UI to present present product specifications in a structure mode. It alsow allows comparison between products + - eg: `[["operating_system", "Android 12.0"], ["screen_size", "6.4 inches"], ["connector_type", "USB Type C"]]` + ## Checkout events NIP-04 https://github.com/nostr-protocol/nips/blob/master/04.md, all checkout events are encrypted From 98448e83d3cdb7031547e6f5fa5f53003358252e Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Thu, 23 Mar 2023 15:49:50 +0200 Subject: [PATCH 10/30] doc: update Step 1: `customer` order (event) --- 45.md | 46 +++++++++++++++++++--------------------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/45.md b/45.md index 768a25aae..e71a3fa9f 100644 --- a/45.md +++ b/45.md @@ -96,47 +96,39 @@ Fields that are not self-explanatory: ## Checkout events -NIP-04 https://github.com/nostr-protocol/nips/blob/master/04.md, all checkout events are encrypted - -The below json goes in `content` of NIP-04. +All checkout events are sent as JSON strings using ([NIP04](https://github.com/nostr-protocol/nips/blob/master/04.md)). ### Step 1: `customer` order (event) -``` +```json { - "id": , - "name": , - "description": , - "address": , - "message": , - "contact": [ - "nostr": , - "phone": , - "email": - ], + "id": "60ff080d5f3eb9692e5c9899766df988d0f6470c2c58f70ec560026ab2234061", + "name": "Some Customer", + "address": "To my door step", + "message": "Please use paper bags", + "contact": { + "nostr": "480bf053affbb9069e44a3fd72f86e2d7e5c29508ab1da8f2230c8b604642fb6", + "phone": null, + "email": "abc@example.com" + }, "items": [ { - "id": , - "quantity": , - "message": - }, - { - "id": , - "quantity": , - "message": + "product_id": "YUfhcprkMSXLZtB5RCaGu2", + "quantity": 1 }, { - "id": , - "quantity": , - "message": + "product_id": "6AMSx8mwV2n7U5ia2VWNKo", + "quantity": 3 } ] - } ``` +Optional Fields: `name`, `address`, `message`, `contact` (the objet itself and any property of it is optional) -Merchant should verify the sum of product ids + timestamp. +_Open_: is `contact.nostr` required? + + ### Step 2: `merchant` request payment (event) From 0f705f5f5fc63d0889f13ae808dd150bd3fa7a52 Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Thu, 23 Mar 2023 16:15:54 +0200 Subject: [PATCH 11/30] doc: stuff --- 45.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/45.md b/45.md index e71a3fa9f..8872f3958 100644 --- a/45.md +++ b/45.md @@ -99,10 +99,12 @@ Fields that are not self-explanatory: All checkout events are sent as JSON strings using ([NIP04](https://github.com/nostr-protocol/nips/blob/master/04.md)). ### Step 1: `customer` order (event) +The below json goes in content of [NIP04](https://github.com/nostr-protocol/nips/blob/master/04.md). ```json { - "id": "60ff080d5f3eb9692e5c9899766df988d0f6470c2c58f70ec560026ab2234061", + "id": , + "type": ###, "name": "Some Customer", "address": "To my door step", "message": "Please use paper bags", @@ -134,7 +136,7 @@ _Open_: is `contact.nostr` required? Sent back from the merchant for payment. Any payment option is valid that the merchant can check. -The below json goes in `content` of NIP-04. +The below json goes in `content` of [NIP04](https://github.com/nostr-protocol/nips/blob/master/04.md). `payment_options`/`type` include: @@ -145,8 +147,8 @@ The below json goes in `content` of NIP-04. ``` { - "id": , - "message": , + "id": , + "message": , "payment_options": [ { "type": , @@ -168,7 +170,7 @@ The below json goes in `content` of NIP-04. Once payment has been received and processed. -The below json goes in `content` of NIP-04. +The below json goes in `content` of [NIP04](https://github.com/nostr-protocol/nips/blob/master/04.md). ``` { From f7a75527a7e3613042faff1148a4d20f9188d969 Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Thu, 23 Mar 2023 16:25:59 +0200 Subject: [PATCH 12/30] doc: replace hard-coded values with spec --- 45.md | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/45.md b/45.md index 8872f3958..ee2e8fda6 100644 --- a/45.md +++ b/45.md @@ -48,18 +48,16 @@ Create or update a stall. Data Structure: ```json { - "id": "huLUPnMmWfNbPhkkH6b529", - "name": "Demo Stall", - "description": "Stall with all kind of products", - "currency": "EUR", + "id": , + "name": , + "description": , + "currency": , "shipping": [ { - "name": "ZoneB", - "cost": 2.0, - "countries": [ - "Belgium" - ], - "id": "jKdBUwXfp3wbynKJU2Z3bV" + "id": , + "name": , + "cost": , + "countries": [], } ] } @@ -77,14 +75,14 @@ Create or update a product Data Structure: ```json { - "id": "YUfhcprkMSXLZtB5RCaGu2", - "stall_id": "huLUPnMmWfNbPhkkH6b529", - "name": "oranges", - "description": "fresh oranges", - "images": ["https://upload.wikimedia.org/wikipedia/commons/b/b0/OrangeBloss_wb.jpg"] - "currency": "EUR", - "price": 5.0, - "quantity": 20 + "id": , + "stall_id": , + "name": , + "description": , + "images": <[String], array of image URLs>, + "currency": , + "price": , + "quantity": , "specs": [["feature", "value"]] } ``` From 8edc3577722219fd27c7047a30c23d284303246b Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Fri, 24 Mar 2023 11:21:29 +0200 Subject: [PATCH 13/30] doc: replace concrete values with placeholders --- 45.md | 42 +++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/45.md b/45.md index ee2e8fda6..8edcfffd4 100644 --- a/45.md +++ b/45.md @@ -54,10 +54,10 @@ Data Structure: "currency": , "shipping": [ { - "id": , - "name": , - "cost": , - "countries": [], + "id": , + "name": , + "cost": , + "countries": [], } ] } @@ -76,20 +76,22 @@ Data Structure: ```json { "id": , - "stall_id": , + "stall_id": , "name": , "description": , - "images": <[String], array of image URLs>, + "images": <[String], array of image URLs, optional>, "currency": , "price": , "quantity": , - "specs": [["feature", "value"]] + "specs": [ + [ , ] + ] } ``` Fields that are not self-explanatory: - `specs`: - - an array of key pair values. It allows for the Customer UI to present present product specifications in a structure mode. It alsow allows comparison between products + - 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 - eg: `[["operating_system", "Android 12.0"], ["screen_size", "6.4 inches"], ["connector_type", "USB Type C"]]` ## Checkout events @@ -102,33 +104,27 @@ The below json goes in content of [NIP04](https://github.com/nostr-protocol/nips ```json { "id": , - "type": ###, - "name": "Some Customer", - "address": "To my door step", - "message": "Please use paper bags", + "type": + "name": , + "address": + "message": ", "contact": { - "nostr": "480bf053affbb9069e44a3fd72f86e2d7e5c29508ab1da8f2230c8b604642fb6", - "phone": null, - "email": "abc@example.com" + "nostr": <32-bytes hex of a pubkey>, + "phone": , + "email": , }, "items": [ { - "product_id": "YUfhcprkMSXLZtB5RCaGu2", - "quantity": 1 - }, - { - "product_id": "6AMSx8mwV2n7U5ia2VWNKo", - "quantity": 3 + "product_id": , + "quantity": } ] } ``` -Optional Fields: `name`, `address`, `message`, `contact` (the objet itself and any property of it is optional) _Open_: is `contact.nostr` required? - ### Step 2: `merchant` request payment (event) From 7ae38f6330725155598c10efd63a2afadb2925f4 Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Fri, 24 Mar 2023 11:34:24 +0200 Subject: [PATCH 14/30] doc: add message type table --- 45.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/45.md b/45.md index 8edcfffd4..e827f2231 100644 --- a/45.md +++ b/45.md @@ -98,6 +98,15 @@ Fields that are not self-explanatory: All checkout events are sent as JSON strings using ([NIP04](https://github.com/nostr-protocol/nips/blob/master/04.md)). +The `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: + +| Message Type | Sent By | Description | +|--------------|----------|---------------------| +| 0 | Customer | New Order | +| 1 | Merchant | Payment Request | +| 2 | Merchant | Order Status Update | + + ### Step 1: `customer` order (event) The below json goes in content of [NIP04](https://github.com/nostr-protocol/nips/blob/master/04.md). @@ -115,7 +124,7 @@ The below json goes in content of [NIP04](https://github.com/nostr-protocol/nips }, "items": [ { - "product_id": , + "product_id": , "quantity": } ] From 0605320c7b706b2798b204b40c0e4ab530e86b7e Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Fri, 24 Mar 2023 11:40:00 +0200 Subject: [PATCH 15/30] doc: add type to messages --- 45.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/45.md b/45.md index e827f2231..ef65e8d24 100644 --- a/45.md +++ b/45.md @@ -48,7 +48,7 @@ Create or update a stall. Data Structure: ```json { - "id": , + "id": , "name": , "description": , "currency": , @@ -75,8 +75,8 @@ Create or update a product Data Structure: ```json { - "id": , - "stall_id": , + "id": , + "stall_id": , "name": , "description": , "images": <[String], array of image URLs, optional>, @@ -112,8 +112,8 @@ The below json goes in content of [NIP04](https://github.com/nostr-protocol/nips ```json { - "id": , - "type": + "id": , + "type": 0, "name": , "address": "message": ", @@ -124,7 +124,7 @@ The below json goes in content of [NIP04](https://github.com/nostr-protocol/nips }, "items": [ { - "product_id": , + "product_id": , "quantity": } ] @@ -150,7 +150,8 @@ The below json goes in `content` of [NIP04](https://github.com/nostr-protocol/ni ``` { - "id": , + "id": , + "type": 1, "message": , "payment_options": [ { @@ -177,7 +178,8 @@ The below json goes in `content` of [NIP04](https://github.com/nostr-protocol/ni ``` { - "id": , + "id": , + "type": 2, "message": , "paid": , "shipped": , From 9b20e0a97991adc2a56f65966ad43c33d3014bd9 Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Fri, 24 Mar 2023 11:41:14 +0200 Subject: [PATCH 16/30] doc: clean-up --- 45.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/45.md b/45.md index ef65e8d24..f812bea2c 100644 --- a/45.md +++ b/45.md @@ -36,7 +36,7 @@ A merchant can publish these events: | `0 ` | `set_meta` | The merchant description (similar with any `nostr` public key) | [NIP01 ](https://github.com/nostr-protocol/nips/blob/master/01.md) | | `30017` | `set_stall` | Create or update a stall. | [NIP33](https://github.com/nostr-protocol/nips/blob/master/33.md) (Parameterized Replaceable Event) | | `30018` | `set_product` | Create or update a product. | [NIP33](https://github.com/nostr-protocol/nips/blob/master/33.md) (Parameterized Replaceable Event) | -| `4 ` | `direct_message` | Communicate with the customer. The messages can be plain-text or JSON (for automatically generated responses) | [NIP09](https://github.com/nostr-protocol/nips/blob/master/09.md) | +| `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) | | `5 ` | `delete` | Delete a product or a stall. | [NIP05](https://github.com/nostr-protocol/nips/blob/master/05.md) | **Event `30017`** From 752a2c408242ab0b36ccbc87a8c9b3a6384239f1 Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Fri, 24 Mar 2023 11:42:03 +0200 Subject: [PATCH 17/30] doc: punctuation --- 45.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/45.md b/45.md index f812bea2c..9bff4b6d0 100644 --- a/45.md +++ b/45.md @@ -33,10 +33,10 @@ The `merchant` admin software can be purely clientside, but for `convenience` an A merchant can publish these events: | Kind | | Description | NIP | |---------|------------------|---------------------------------------------------------------------------------------------------------------|-----------------------------------------| -| `0 ` | `set_meta` | The merchant description (similar with any `nostr` public key) | [NIP01 ](https://github.com/nostr-protocol/nips/blob/master/01.md) | +| `0 ` | `set_meta` | The merchant description (similar with any `nostr` public key). | [NIP01 ](https://github.com/nostr-protocol/nips/blob/master/01.md) | | `30017` | `set_stall` | Create or update a stall. | [NIP33](https://github.com/nostr-protocol/nips/blob/master/33.md) (Parameterized Replaceable Event) | | `30018` | `set_product` | Create or update a product. | [NIP33](https://github.com/nostr-protocol/nips/blob/master/33.md) (Parameterized Replaceable Event) | -| `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) | +| `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) | | `5 ` | `delete` | Delete a product or a stall. | [NIP05](https://github.com/nostr-protocol/nips/blob/master/05.md) | **Event `30017`** From e0ac74331f1a33a056de1d5d362bd85b5e482752 Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Fri, 24 Mar 2023 11:50:46 +0200 Subject: [PATCH 18/30] doc: fix UUID --- 45.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/45.md b/45.md index 9bff4b6d0..46dc63123 100644 --- a/45.md +++ b/45.md @@ -54,7 +54,7 @@ Data Structure: "currency": , "shipping": [ { - "id": , + "id": , "name": , "cost": , "countries": [], From 14c7e815184544dd08e688edaf00dfcaa12059e0 Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Fri, 24 Mar 2023 11:52:45 +0200 Subject: [PATCH 19/30] doc: add code type --- 45.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/45.md b/45.md index 46dc63123..9c1932013 100644 --- a/45.md +++ b/45.md @@ -148,7 +148,7 @@ The below json goes in `content` of [NIP04](https://github.com/nostr-protocol/ni - `ln` bitcoin lightning invoice - `lnurl` bitcoin lnurl-pay -``` +```json { "id": , "type": 1, @@ -176,7 +176,7 @@ Once payment has been received and processed. The below json goes in `content` of [NIP04](https://github.com/nostr-protocol/nips/blob/master/04.md). -``` +```json { "id": , "type": 2, From cebceccd4a3516535a4dbccc0e6cde3694def045 Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Fri, 24 Mar 2023 11:54:22 +0200 Subject: [PATCH 20/30] doc: fix JSON --- 45.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/45.md b/45.md index 9c1932013..83b2fb20d 100644 --- a/45.md +++ b/45.md @@ -166,8 +166,8 @@ The below json goes in `content` of [NIP04](https://github.com/nostr-protocol/ni "type": , "link": } + ] } - ``` ### Step 3: `merchant` verify payment/shipped (event) @@ -184,7 +184,6 @@ The below json goes in `content` of [NIP04](https://github.com/nostr-protocol/ni "paid": , "shipped": , } - ``` ## Customer support events From ed6e3aed151e950a8dbb784300fb83c3e27ffdd5 Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Fri, 24 Mar 2023 12:08:58 +0200 Subject: [PATCH 21/30] doc: add tags --- 45.md | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/45.md b/45.md index 83b2fb20d..660606144 100644 --- a/45.md +++ b/45.md @@ -45,7 +45,7 @@ Create or update a stall. - the stall `id` SHOULD be random generated one. Sequential IDs (`0`, `1`, `2`...) are discouraged. - the stall `id` MUST be used as the `d` tag for the event (see [NIP33](https://github.com/nostr-protocol/nips/blob/master/33.md)) -Data Structure: +Event Content: ```json { "id": , @@ -69,10 +69,16 @@ Fields that are not self-explanatory: - shipping to different zones can have different costs. For some goods (digital for examle) the cost can be zero. - the `id` is an internal value used by the merchant. This value must be sent back as the customer selection. +Event Tags: +```json + "tags": [["d", , @@ -94,6 +100,19 @@ Fields that are not self-explanatory: - 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 - eg: `[["operating_system", "Android 12.0"], ["screen_size", "6.4 inches"], ["connector_type", "USB Type C"]]` +Event Tags: +```json + "tags": [ + ["d", Date: Fri, 24 Mar 2023 12:10:49 +0200 Subject: [PATCH 22/30] doc: update titles --- 45.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/45.md b/45.md index 660606144..379604b2b 100644 --- a/45.md +++ b/45.md @@ -39,13 +39,12 @@ A merchant can publish these events: | `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) | | `5 ` | `delete` | Delete a product or a stall. | [NIP05](https://github.com/nostr-protocol/nips/blob/master/05.md) | -**Event `30017`** -Create or update a stall. +### Event `30017`: Create or update a stall. - the stall `id` SHOULD be random generated one. Sequential IDs (`0`, `1`, `2`...) are discouraged. - the stall `id` MUST be used as the `d` tag for the event (see [NIP33](https://github.com/nostr-protocol/nips/blob/master/33.md)) -Event Content: +**Event Content**: ```json { "id": , @@ -69,16 +68,15 @@ Fields that are not self-explanatory: - shipping to different zones can have different costs. For some goods (digital for examle) the cost can be zero. - the `id` is an internal value used by the merchant. This value must be sent back as the customer selection. -Event Tags: +**Event Tags**: ```json "tags": [["d", , @@ -100,7 +98,7 @@ Fields that are not self-explanatory: - 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 - eg: `[["operating_system", "Android 12.0"], ["screen_size", "6.4 inches"], ["connector_type", "USB Type C"]]` -Event Tags: +**Event Tags**: ```json "tags": [ ["d", Date: Fri, 24 Mar 2023 12:11:50 +0200 Subject: [PATCH 23/30] doc: clean-up --- 45.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/45.md b/45.md index 379604b2b..5f9f087f9 100644 --- a/45.md +++ b/45.md @@ -41,13 +41,10 @@ A merchant can publish these events: ### Event `30017`: Create or update a stall. -- the stall `id` SHOULD be random generated one. Sequential IDs (`0`, `1`, `2`...) are discouraged. -- the stall `id` MUST be used as the `d` tag for the event (see [NIP33](https://github.com/nostr-protocol/nips/blob/master/33.md)) - **Event Content**: ```json { - "id": , + "id": , "name": , "description": , "currency": , @@ -79,7 +76,7 @@ Fields that are not self-explanatory: **Event Content**: ```json { - "id": , + "id": , "stall_id": , "name": , "description": , From 545e0175ebca155b26e03d7ad55227754f989d83 Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Fri, 24 Mar 2023 12:33:05 +0200 Subject: [PATCH 24/30] doc: add __Open__ topic --- 45.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/45.md b/45.md index 5f9f087f9..6e626243c 100644 --- a/45.md +++ b/45.md @@ -90,6 +90,8 @@ Fields that are not self-explanatory: } ``` +_Open_: better to move `spec` in the `tags` section of the event? + Fields that are not self-explanatory: - `specs`: - 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 From f55a9c21625a70b1ea3dddb23e0704781c751c4f Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Fri, 24 Mar 2023 12:33:52 +0200 Subject: [PATCH 25/30] doc: re-order --- 45.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/45.md b/45.md index 6e626243c..77ba368d8 100644 --- a/45.md +++ b/45.md @@ -90,13 +90,13 @@ Fields that are not self-explanatory: } ``` -_Open_: better to move `spec` in the `tags` section of the event? - Fields that are not self-explanatory: - `specs`: - 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 - eg: `[["operating_system", "Android 12.0"], ["screen_size", "6.4 inches"], ["connector_type", "USB Type C"]]` +_Open_: better to move `spec` in the `tags` section of the event? + **Event Tags**: ```json "tags": [ From 9af7652529a46341bfa6013209fa9cd7ef065e37 Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Thu, 30 Mar 2023 14:20:27 +0300 Subject: [PATCH 26/30] doc: add `shipping_id` --- 45.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/45.md b/45.md index 77ba368d8..82702df08 100644 --- a/45.md +++ b/45.md @@ -143,7 +143,8 @@ The below json goes in content of [NIP04](https://github.com/nostr-protocol/nips "product_id": , "quantity": } - ] + ], + "shipping_id": } ``` From cf1d1c6e2e283d69e1e283930115d5f346f38dbf Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Mon, 3 Apr 2023 09:37:45 +0300 Subject: [PATCH 27/30] fix: typo Co-authored-by: Andrew Camilleri --- 45.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/45.md b/45.md index 82702df08..fd08dbd7c 100644 --- a/45.md +++ b/45.md @@ -131,7 +131,7 @@ The below json goes in content of [NIP04](https://github.com/nostr-protocol/nips "id": , "type": 0, "name": , - "address": + "address": "message": ", "contact": { "nostr": <32-bytes hex of a pubkey>, From a8076e928e521a0a89d90f5635d88e3e8aeb2b6b Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Mon, 3 Apr 2023 09:38:11 +0300 Subject: [PATCH 28/30] fix: typo Co-authored-by: Andrew Camilleri --- 45.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/45.md b/45.md index fd08dbd7c..3dfec8e4f 100644 --- a/45.md +++ b/45.md @@ -205,7 +205,7 @@ The below json goes in `content` of [NIP04](https://github.com/nostr-protocol/ni ## Customer support events -Customer support is handle over whatever communication method was specified. If communicationg via nostr, NIP-04 is used https://github.com/nostr-protocol/nips/blob/master/04.md. +Customer 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. ## Additional From 1e3ec27e4832148e1b26202d96a35030f25302be Mon Sep 17 00:00:00 2001 From: ben Date: Wed, 12 Apr 2023 12:46:05 +0100 Subject: [PATCH 29/30] Renamed to 15 --- 15.md | 213 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 45.md | 212 --------------------------------------------------------- 2 files changed, 202 insertions(+), 223 deletions(-) delete mode 100644 45.md diff --git a/15.md b/15.md index 081a97d92..4b512c385 100644 --- a/15.md +++ b/15.md @@ -1,21 +1,212 @@ NIP-15 ====== -End of Stored Events Notice ---------------------------- +Nostr Marketplace (for resilient marketplaces) +----------------------------------- -`final` `optional` `author:Semisol` +`draft` `optional` `author:fiatjaf` `author:benarc` `author:motorina0` `author:talvasconcelos` -Relays may support notifying clients when all stored events have been sent. +> Based on https://github.com/lnbits/Diagon-Alley -If a relay supports this NIP, the relay SHOULD send the client a `EOSE` message in the format `["EOSE", ]` after it has sent all the events it has persisted and it indicates all the events that come after this message are newly published. +## Terms -Client Behavior ---------------- +- `merchant` - seller of products with NOSTR key-pair +- `customer` - buyer of products with NOSTR key-pair +- `product` - item for sale by the `merchant` +- `stall` - list of products controlled by `merchant` (a `merchant` can have multiple stalls) +- `marketplace` - clientside software for searching `stalls` and purchasing `products` -Clients SHOULD use the `supported_nips` field to learn if a relay supports end of stored events notices. +## Nostr Marketplace Clients -Motivation ----------- +### Merchant admin -The motivation for this proposal is to reduce uncertainty when all events have been sent by a relay to make client code possibly less complex. +Where the `merchant` creates, updates and deletes `stalls` and `products`, as well as where they manage sales, payments and communication with `customers`. + +The `merchant` admin software can be purely clientside, but for `convenience` and uptime, implementations will likely have a server client listening for NOSTR events. + +### Marketplace + +`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`. + +## `Merchant` publishing/updating products (event) + +A merchant can publish these events: +| Kind | | Description | NIP | +|---------|------------------|---------------------------------------------------------------------------------------------------------------|-----------------------------------------| +| `0 ` | `set_meta` | The merchant description (similar with any `nostr` public key). | [NIP01 ](https://github.com/nostr-protocol/nips/blob/master/01.md) | +| `30017` | `set_stall` | Create or update a stall. | [NIP33](https://github.com/nostr-protocol/nips/blob/master/33.md) (Parameterized Replaceable Event) | +| `30018` | `set_product` | Create or update a product. | [NIP33](https://github.com/nostr-protocol/nips/blob/master/33.md) (Parameterized Replaceable Event) | +| `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) | +| `5 ` | `delete` | Delete a product or a stall. | [NIP05](https://github.com/nostr-protocol/nips/blob/master/05.md) | + +### Event `30017`: Create or update a stall. + +**Event Content**: +```json +{ + "id": , + "name": , + "description": , + "currency": , + "shipping": [ + { + "id": , + "name": , + "cost": , + "countries": [], + } + ] +} +``` + +Fields that are not self-explanatory: + - `shipping`: + - an array with possible shipping zones for this stall. The customer MUST choose exactly one shipping zone. + - shipping to different zones can have different costs. For some goods (digital for examle) the cost can be zero. + - the `id` is an internal value used by the merchant. This value must be sent back as the customer selection. + +**Event Tags**: +```json + "tags": [["d", , + "stall_id": , + "name": , + "description": , + "images": <[String], array of image URLs, optional>, + "currency": , + "price": , + "quantity": , + "specs": [ + [ , ] + ] +} +``` + +Fields that are not self-explanatory: + - `specs`: + - 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 + - eg: `[["operating_system", "Android 12.0"], ["screen_size", "6.4 inches"], ["connector_type", "USB Type C"]]` + +_Open_: better to move `spec` in the `tags` section of the event? + +**Event Tags**: +```json + "tags": [ + ["d", , + "type": 0, + "name": , + "address": + "message": ", + "contact": { + "nostr": <32-bytes hex of a pubkey>, + "phone": , + "email": , + }, + "items": [ + { + "product_id": , + "quantity": + } + ], + "shipping_id": +} + +``` + +_Open_: is `contact.nostr` required? + + +### Step 2: `merchant` request payment (event) + +Sent back from the merchant for payment. Any payment option is valid that the merchant can check. + +The below json goes in `content` of [NIP04](https://github.com/nostr-protocol/nips/blob/master/04.md). + +`payment_options`/`type` include: + +- `url` URL to a payment page, stripe, paypal, btcpayserver, etc +- `btc` onchain bitcoin address +- `ln` bitcoin lightning invoice +- `lnurl` bitcoin lnurl-pay + +```json +{ + "id": , + "type": 1, + "message": , + "payment_options": [ + { + "type": , + "link": + }, + { + "type": , + "link": + }, + { + "type": , + "link": + } + ] +} +``` + +### Step 3: `merchant` verify payment/shipped (event) + +Once payment has been received and processed. + +The below json goes in `content` of [NIP04](https://github.com/nostr-protocol/nips/blob/master/04.md). + +```json +{ + "id": , + "type": 2, + "message": , + "paid": , + "shipped": , +} +``` + +## Customer support events + +Customer 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. + +## Additional + +Standard data models can be found here here diff --git a/45.md b/45.md deleted file mode 100644 index 3dfec8e4f..000000000 --- a/45.md +++ /dev/null @@ -1,212 +0,0 @@ -NIP-45 -====== - -Nostr Marketplace (for resilient marketplaces) ------------------------------------ - -`draft` `optional` `author:fiatjaf` `author:benarc` `author:motorina0` `author:talvasconcelos` - -> Based on https://github.com/lnbits/Diagon-Alley - -## Terms - -- `merchant` - seller of products with NOSTR key-pair -- `customer` - buyer of products with NOSTR key-pair -- `product` - item for sale by the `merchant` -- `stall` - list of products controlled by `merchant` (a `merchant` can have multiple stalls) -- `marketplace` - clientside software for searching `stalls` and purchasing `products` - -## Nostr Marketplace Clients - -### Merchant admin - -Where the `merchant` creates, updates and deletes `stalls` and `products`, as well as where they manage sales, payments and communication with `customers`. - -The `merchant` admin software can be purely clientside, but for `convenience` and uptime, implementations will likely have a server client listening for NOSTR events. - -### Marketplace - -`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`. - -## `Merchant` publishing/updating products (event) - -A merchant can publish these events: -| Kind | | Description | NIP | -|---------|------------------|---------------------------------------------------------------------------------------------------------------|-----------------------------------------| -| `0 ` | `set_meta` | The merchant description (similar with any `nostr` public key). | [NIP01 ](https://github.com/nostr-protocol/nips/blob/master/01.md) | -| `30017` | `set_stall` | Create or update a stall. | [NIP33](https://github.com/nostr-protocol/nips/blob/master/33.md) (Parameterized Replaceable Event) | -| `30018` | `set_product` | Create or update a product. | [NIP33](https://github.com/nostr-protocol/nips/blob/master/33.md) (Parameterized Replaceable Event) | -| `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) | -| `5 ` | `delete` | Delete a product or a stall. | [NIP05](https://github.com/nostr-protocol/nips/blob/master/05.md) | - -### Event `30017`: Create or update a stall. - -**Event Content**: -```json -{ - "id": , - "name": , - "description": , - "currency": , - "shipping": [ - { - "id": , - "name": , - "cost": , - "countries": [], - } - ] -} -``` - -Fields that are not self-explanatory: - - `shipping`: - - an array with possible shipping zones for this stall. The customer MUST choose exactly one shipping zone. - - shipping to different zones can have different costs. For some goods (digital for examle) the cost can be zero. - - the `id` is an internal value used by the merchant. This value must be sent back as the customer selection. - -**Event Tags**: -```json - "tags": [["d", , - "stall_id": , - "name": , - "description": , - "images": <[String], array of image URLs, optional>, - "currency": , - "price": , - "quantity": , - "specs": [ - [ , ] - ] -} -``` - -Fields that are not self-explanatory: - - `specs`: - - 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 - - eg: `[["operating_system", "Android 12.0"], ["screen_size", "6.4 inches"], ["connector_type", "USB Type C"]]` - -_Open_: better to move `spec` in the `tags` section of the event? - -**Event Tags**: -```json - "tags": [ - ["d", , - "type": 0, - "name": , - "address": - "message": ", - "contact": { - "nostr": <32-bytes hex of a pubkey>, - "phone": , - "email": , - }, - "items": [ - { - "product_id": , - "quantity": - } - ], - "shipping_id": -} - -``` - -_Open_: is `contact.nostr` required? - - -### Step 2: `merchant` request payment (event) - -Sent back from the merchant for payment. Any payment option is valid that the merchant can check. - -The below json goes in `content` of [NIP04](https://github.com/nostr-protocol/nips/blob/master/04.md). - -`payment_options`/`type` include: - -- `url` URL to a payment page, stripe, paypal, btcpayserver, etc -- `btc` onchain bitcoin address -- `ln` bitcoin lightning invoice -- `lnurl` bitcoin lnurl-pay - -```json -{ - "id": , - "type": 1, - "message": , - "payment_options": [ - { - "type": , - "link": - }, - { - "type": , - "link": - }, - { - "type": , - "link": - } - ] -} -``` - -### Step 3: `merchant` verify payment/shipped (event) - -Once payment has been received and processed. - -The below json goes in `content` of [NIP04](https://github.com/nostr-protocol/nips/blob/master/04.md). - -```json -{ - "id": , - "type": 2, - "message": , - "paid": , - "shipped": , -} -``` - -## Customer support events - -Customer 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. - -## Additional - -Standard data models can be found here here From e660b257567299a95802533d4fc8fca023188c61 Mon Sep 17 00:00:00 2001 From: ben Date: Wed, 12 Apr 2023 12:50:07 +0100 Subject: [PATCH 30/30] Added link to implementation --- 15.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/15.md b/15.md index 4b512c385..a3d105da5 100644 --- a/15.md +++ b/15.md @@ -8,6 +8,8 @@ Nostr Marketplace (for resilient marketplaces) > Based on https://github.com/lnbits/Diagon-Alley +> Implemented here https://github.com/lnbits/nostrmarket + ## Terms - `merchant` - seller of products with NOSTR key-pair