-`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`.
- 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
- 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 `d` tag is required, its value MUST be the same as the product `id`.
- the `t` tag is as searchable tag, it represents different categories that the product can be part of (`food`, `fruits`). Multiple `t` tags can be present.
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:
In the Merchant Delegation paradigm, a different Nostr account effectively controls all commerce-related events on behalf of the Merchant. The delegated account creates every Stall and Product, receives all Checkout events, and handles checkout-related communication with the Customer.
Clients implementing Merchant Delegation automatically re-target non-checkout events to the Merchant Root Account (aka Delegator).
By using Merchant Delegation, the Merchant's Root Account remains free to engage solely in social graph activities (ie. posting short-form / long-form content creation and engagement, non-checkout communications with Customers, etc), without the checkout-related events spamming their inbox.
The Merchant signs a Merchant Delegate Token, which is placed in a tag on every event signed by the delegate account. Clients parse the tag, verify the signature is valid, and cause non-checkout events (ie. follows, zaps, direct messages, etc.) to target the Merchant Root Account (aka Delegator) automatically.
As an extra layer of validation, a NIP-05 identifier may be included. When an identifier is present, clients will verify its validity, and reject delegation if the Npub is not properly identified. This provides the ability to invalidate the delegation, if need be.
To use Merchant Delegation Tags:
- Clients MUST treat events with a `merchant-delegation` tag in the following manner:
- Validate the `delegation token` signature
- If `retarget_while<` and/or `retarget_while>` is present in the conditions query string, only perform event re-targeting within the given time window
- If `nip_05_identifier` is present in the conditions query string, only perform re-targeting if the Npub of the event's creator is verifiable as-per the NIP-05 spec
- Clients SHOULD display a relevant visual indicator that a Stall and/or Product's Checkout process is handled by a Merchant Delegate.
Merchant Delegation tags are described as follows:
The following fields and operators are supported in the above query string:
*Fields*:
1.`retarget_while`
-*Operators*:
-`<${TIMESTAMP}` - clients must only redirect event targets for events created ***before*** the specified timestamp
-`>${TIMESTAMP}` - clients must only redirect event targets for events created ***after*** the specified timestamp
2.`nip_05_identifier`
-*Operators*:
-`<${TIMESTAMP}` - clients must only redirect event targets for events created ***before*** the specified timestamp
-`>${TIMESTAMP}` - clients must only redirect event targets for events created ***after*** the specified timestamp
In order to create a single condition, you must use a supported field and operator. Multiple conditions can be used in a single query string, including on the same field. Conditions must be combined with `&`.
For example, the following condition strings are valid:
*Note: This is closely inspired by the [NIP-26: Delegated Event Signing](https://github.com/nostr-protocol/nips/blob/master/26.md) tag specification. However, the NIP-26 implementation is NOT chosen for this use case. Delegating event signing ability as per NIP-26 would be superfluous because the Merchant Delegate will not possess the ability to decrypt incoming order messages from Customers.
Create a customized user experience using the `naddr` from [NIP-19](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.
This event leverages naddr to enable comprehensive customization and sharing of marketplace configurations, fostering a unique and engaging marketplace environment.
> Items sold as an auction are very similar in structure to fixed-price items, with some important differences worth noting.
* The `start_date` can be set to a date in the future if the auction is scheduled to start on that date, or can be omitted if the start date is unknown/hidden. If the start date is not specified, the auction will have to be edited later to set an actual date.
* The auction runs for an initial number of seconds after the `start_date`, specified by `duration`.
> Auctions can be edited as many times as desired (they are "addressable events") by the author - even after the start_date, but they cannot be edited after they have received the first bid! This is enforced by the fact that bids reference the event ID of the auction (rather than the product UUID), which changes with every new version of the auctioned product. So a bid is always attached to one "version". Editing the auction after a bid would result in the new product losing the bid!
Bids should be confirmed by the merchant before being considered as valid by other clients. So clients should subscribe to *bid confirmation* events (kind `1022`) for every auction that they follow, in addition to the actual bids and should check that the pubkey of the bid confirmation matches the pubkey of the merchant (in addition to checking the signature).
The `content` field is a JSON which includes *at least* a `status`. `winner` is how the *winning bid* is replied to after the auction ends and the winning bid is picked by the merchant.
The reasons for which a bid can be marked as `rejected` or `pending` are up to the merchant's implementation and configuration - they could be anything from basic validation errors (amount too low) to the bidder being blacklisted or to the bidder lacking sufficient *trust*, which could lead to the bid being marked as `pending` until sufficient verification is performed. The difference between the two is that `pending` bids *might* get approved after additional steps are taken by the bidder, whereas `rejected` bids can not be later approved.
An additional `message` field can appear in the `content` JSON to give further context as of why a bid is `rejected` or `pending`.
Another thing that can happen is - if bids happen very close to the end date of the auction - for the merchant to decide to extend the auction duration for a few more minutes. This is done by passing a `duration_extended` field as part of a bid confirmation, which would contain a number of seconds by which the initial duration is extended. So the actual end date of an auction is always `start_date + duration + (SUM(c.duration_extended) FOR c in all confirmations`.