NIP-15 ====== Nostr Marketplace (for resilient marketplaces) ----------------------------------- `draft` `optional` `author:fiatjaf` `author:benarc` `author:motorina0` `author:talvasconcelos` > Based on https://github.com/lnbits/Diagon-Alley > Implemented in [NostrMarket](https://github.com/lnbits/nostrmarket) and [Plebeian Market](https://github.com/PlebeianTech/plebeian-market) ## 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 | | --------- | ------------------ | --------------------------------------------------------------------------------------------------------------- | | `0 ` | `set_meta` | The merchant description (similar with any `nostr` public key). | | `30017` | `set_stall` | Create or update a stall. | | `30018` | `set_product` | Create or update a product. | | `4 ` | `direct_message` | Communicate with the customer. The messages can be plain-text or JSON. | | `5 ` | `delete` | Delete a product or a stall. | ### Event `30017`: Create or update a stall. **Event Content**: ```json { "id": , "name": , "description": , "currency": , "shipping": [ { "id": , "name": , "cost": , "regions": [], } ] } ``` Fields that are not self-explanatory: - `shipping`: - an array with possible shipping zones for this stall. - the customer MUST choose exactly one of those shipping zones. - shipping to different zones can have different costs. For some goods (digital for example) 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. - each shipping zone contains the base cost for orders made to that shipping zone, but a specific shipping cost per product can also be specified if the shipping cost for that product is higher than what's specified by the base cost. **Event Tags**: ```json "tags": [["d", , "stall_id": , "name": , "description": , "images": <[String], array of image URLs, optional>, "currency": , "price": , "quantity": , "specs": [ [, ] ], "shipping": [ { "id": , "cost": , } ] } ``` Fields that are not self-explanatory: - `specs`: - an optional array of key pair values. It allows for the Customer UI to 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? - `shipping`: - an _optional_ array of extra costs to be used per shipping zone, only for products that require special shipping costs to be added to the base shipping cost defined in the stall - the `id` should match the id of the shipping zone, as defined in the `shipping` field of the stall - to calculate the total cost of shipping for an order, the user will choose a shipping option during checkout, and then the client must consider this costs: - the `base cost from the stall` for the chosen shipping option - the result of multiplying the product units by the `shipping costs specified in the product`, if any. **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": , } ``` ## Customize Marketplace Create a customized user experience using the `naddr` from [NIP-19](https://github.com/nostr-protocol/nips/blob/master/19.md#shareable-identifiers-with-extra-metadata). The use of `naddr` enables easy sharing of marketplace events while incorporating a rich set of metadata. This metadata can include relays, merchant profiles, and more. Subsequently, it allows merchants to be grouped into a market, empowering the market creator to configure the marketplace's user interface and user experience, and share that marketplace. This customization can encompass elements such as market name, description, logo, banner, themes, and even color schemes, offering a tailored and unique marketplace experience. ### Event `30019`: Create or update marketplace UI/UX **Event Content**: ```json { "name": , "about": , "ui": { "picture": , "banner": , "theme": , "darkMode": }, "merchants": <[String] (optional), array of pubkeys>, ... } ``` This event leverages naddr to enable comprehensive customization and sharing of marketplace configurations, fostering a unique and engaging marketplace environment. ## 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