Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
215 changes: 160 additions & 55 deletions 87.md
Original file line number Diff line number Diff line change
@@ -1,100 +1,105 @@
NIP-87
======

Ecash Mint Discoverability
--------------------------------
Nostr Service Discoverability
-----------------------------

`draft` `optional`

This NIP describes `kind:38173`, `kind:38172` and `kind:38000`: a way to discover ecash mints, their capabilities, and people who recommend them.
This NIP describes a standardized way to discover various Nostr services, their capabilities, and people who recommend them. It defines `kind:38000` as a general service recommendation event, and specific event kinds for different service types.

## Rationale

Nostr's discoverability and transparent event interaction is one of its most interesting/novel mechanics.
This NIP provides a simple way for users to discover ecash mints recommended by other users and to interact with them.
Nostr's discoverability and transparent event interaction is one of its most interesting/novel mechanics. This NIP provides a unified framework for users to discover various services recommended by other users and to interact with them.

## General Framework

### Parties involved

There are three actors to this workflow:
There are three actors in the service discovery workflow:

* A service operator, who announces their service and its capabilities
* Publishes a service-specific event kind, detailing how to connect to it and its capabilities
* User A, who recommends a service
* Publishes `kind:38000` with appropriate tags
* User B, who seeks a recommendation for a service
* Queries for `kind:38000` with filters, and based on results, queries for service-specific events

* An ecash mint operator, announces their mint and its capabilities.
* Publishes `kind:38173` or `kind:38172`, detailing how to connect to it and its capabilities.
* user A, who recommends an ecash mint
* Publishes `kind:38000`
* user B, who seeks a recommendation for an ecash mint
* Queries for `kind:38000` and, based on results, queries for `kind:38173`/`kind:38172`
### Service Recommendation Event

## Events
The recommendation event uses `kind:38000` as a general-purpose service recommendation event. Different services are distinguished by the `k` tag which specifies the event kind of the service being recommended.

### Recommendation event
```json
{
"kind": 38000,
"pubkey": <recommender-user-pubkey>,
"tags": [
["k", "38173"],
["k", "<service-event-kind>"],
["d", "<d-identifier>"],
["u", <recommended-fedimint-invite-code>],
["a", "38173:fedimint-pubkey:<d-identifier>", "wss://relay1"]
["u", "<service-connection-url>"],
["a", "<service-event-kind>:<service-pubkey>:<d-identifier>", "wss://relay"]
],
"content": "I trust this mint with my life"
"content": "Review or description of the service"
}
```

The recommendation event is a parameterized-replaceable event so that a user can change edit their recommendation without creating a new event.

The `d` tag in `kind:38000` is the `kind:38173`/`kind:38172` event identifier this event is recommending, if no event exists, the `d` tag can still be calculated from the mint's pubkey/id.
The `k` tag is the kind number that corresponds to the event kind that the user is recommending, in this case `kind:38173` for fedimints and `kind:38172` for cashu mints.
#### Required Tags

Optional `u` tags can be added to give a recommend way to connect to the mint.
The value of the tag is the URL or invite code of the ecash mint.
Multiple `u` tags can appear on the same `kind:38000`.
* `k` - The kind number of the service event being recommended
* `d` - The `d` identifier of the service event being recommended

`a` tags are used to point to the `kind:38173`/`kind:38172` event of the ecash mint.
The first value of the tag is the `kind:38173`/`kind:38172` event identifier, the second value of the tag is a relay hint.
This is used to correctly point to the mint's `kind:38173`/`kind:38172` event in case there are duplicates claiming to be the same mint.
#### Optional Tags

The content can be used to give a review.
* `u` - URLs or connection strings for the service (can have multiple)
* `a` - Reference to the service's announcement event with relay hints

## Ecash Mint Information
## Service Types

Cashu mints SHOULD publish `kind:38172` events to announce their capabilities and how to connect to them.
### Ecash Mints

For cashu mints, the `u` tag SHOULD be the URL to the cashu mint and it should list the nuts that the cashu mint supports.
Ecash mints use two event kinds:

The `d` tag SHOULD be the mint's pubkey (found when querying `/v1/info`), this way users can query by pubkey and find the mint announcement.
* `kind:38172` - Cashu mints
* `kind:38173` - Fedimints

An `n` tag SHOULD be added to signify the network the cashu mint is on (either `mainnet`, `testnet`, `signet`, or `regtest`)
#### Cashu Mint Information (`kind:38172`)

Cashu mints SHOULD publish `kind:38172` events to announce their capabilities and how to connect to them.

```json
{
"kind": 38172,
"pubkey": "<application-pubkey>",
"content": "<optional-kind:0-style-metadata>",
"tags": [
["d", <cashu mint pubkey>],
["d", "<cashu-mint-pubkey>"],
["u", "https://cashu.example.com"],
["nuts", "1,2,3,4,5,6,7"],
["n", "mainnet"]
]
}
```

Fedimints SHOULD publish `kind:38173` events to announce their capabilities and how to connect to them.
Tags:

For fedimints, it should list all known fedimint invite codes in `u` tags and it should list the modules it supports.
* `d` - The mint's pubkey (found when querying `/v1/info`)
* `u` - URL to the cashu mint
* `nuts` - Supported NUT specifications
* `n` - Network (`mainnet`, `testnet`, `signet`, or `regtest`)

The `d` tag SHOULD be the federation id, this way users can query by federation id and find the fedimint announcement.
#### Fedimint Information (`kind:38173`)

An `n` tag SHOULD be added to signify the network the fedimint is on (either `mainnet`, `testnet`, `signet`, or `regtest`)
Fedimints SHOULD publish `kind:38173` events to announce their capabilities and how to connect to them.

```json
{
"kind": 38173,
"pubkey": "<application-pubkey>",
"content": "<optional-kind:0-style-metadata>",
"tags": [
["d", <federation-id>],
["d", "<federation-id>"],
["u", "fed11abc.."],
["u", "fed11xyz.."],
["modules", "lightning,wallet,mint"],
Expand All @@ -103,40 +108,140 @@ An `n` tag SHOULD be added to signify the network the fedimint is on (either `ma
}
```

* `content` is an optional `metadata`-like stringified JSON object, as described in NIP-01. This content is useful when the pubkey creating the `kind:38173` is not a normal user. If `content` is empty, the `kind:0` of the pubkey should be used to display mint information (e.g. name, picture, web, LUD16, etc.)
Tags:

* `d` - The federation ID
* `u` - Fedimint invite codes (can have multiple)
* `modules` - Supported modules
* `n` - Network (`mainnet`, `testnet`, `signet`, or `regtest`)

### Routstr Providers

Routstr provides a way to access AI models through Nostr, offering privacy-preserving access to various language models. Routstr providers use `kind:38421`.

#### Routstr Provider Information (`kind:38421`)

Routstr providers SHOULD publish `kind:38421` events to announce their capabilities and how to connect to them.

```json
{
"kind": 38421,
"pubkey": "<routstr-provider-pubkey>",
"content": "<optional-kind:0-style-metadata>",
"tags": [
["d", "<unique-provider-identifier>"],
["u", "https://api.routstr.com/"],
["u", "fhxpl22punqhmmgcldhbusmxrmxa36gx2hbrr7yz4trq5wwthwbxucqd.onion"],
["models", "gpt-4o-mini", "gpt-4o", "claude-3-5-sonnet", "claude-3-5-haiku", "mistral-large", "llama-3.3-70b"],
["mint", "https://mint.example.com"],
["version", "0.0.1"]
]
}
```

Tags:

## Example
* `d` - Unique identifier for the provider instance (e.g., domain name)
* `u` - URLs to connect to the Routstr provider (HTTP endpoints)
* `models` - List of supported AI models
* `mint` - (Optional) Associated ecash mint for payments
* `version` - Provider software version

### User A recommends some mints
User A might be a user of a cashu mint. Using a client, user A publishes an event recommending the cashu mint they use.
#### Model Capabilities

Providers MAY include additional tags to describe model-specific capabilities:

```json
{
"tags": [
["model-cap", "gpt-4o", "max_tokens:128000,vision:true,tools:true"],
["model-cap", "claude-3-5-sonnet", "max_tokens:200000,vision:true,tools:true"],
["model-cap", "llama-3.3-70b", "max_tokens:32768,vision:false,tools:true"]
]
}
```

## Common Patterns

### Content Field

For all service announcement events, the `content` field is an optional `metadata`-like stringified JSON object, as described in NIP-01. This content is useful when the pubkey creating the service event is not a normal user. If `content` is empty, the `kind:0` of the pubkey should be used to display service information (e.g. name, picture, web, LUD16, etc.)

### Discovery Examples

#### Example: User A recommends a Cashu mint

```json
{
"kind": 38000,
"tags": [
["u", "fed11abc..", "fedimint"],
["u", "https://cashu.example.com", "cashu"],
["a", "38173:fedimint-pubkey:<d-identifier>", "wss://relay1", "fedimint"],
["a", "38172:cashu-mint-pubkey:<d-identifier>", "wss://relay2", "cashu"]
["k", "38172"],
["d", "<cashu-mint-pubkey>"],
["u", "https://cashu.example.com"],
["a", "38172:<cashu-mint-pubkey>:<cashu-mint-pubkey>", "wss://relay1"]
],
...
"content": "Reliable mint with low fees"
}
```

### User B finds a mint
User B wants to use an ecash wallet, they need to find a mint.
#### Example: User A recommends a Routstr provider

User B's wallet client queries for `kind:38000` events, looking for recommendations for ecash mints.
```json
{
"kind": 38000,
"tags": [
["k", "38421"],
["d", "api.routstr.com"],
["u", "https://api.routstr.com/"],
["u", "fhxpl22punqhmmgcldhbusmxrmxa36gx2hbrr7yz4trq5wwthwbxucqd.onion"],
["a", "38421:routstr-provider-pubkey:api.routstr.com", "wss://relay1"]
],
"content": "Fast and reliable AI proxy with great model selection"
}
```

#### Example: User B finds services

User B's client queries for `kind:38000` events, filtering by the service kind they're interested in:

```json
// Finding ecash mints
["REQ", <id>, [{ "kinds": [38000], "authors": [<user>, <users-contact-list>], "#k": ["38172", "38173"] }]]

// Finding Routstr providers
["REQ", <id>, [{ "kinds": [38000], "authors": [<user>, <users-contact-list>], "#k": ["38421"] }]]
```

After finding recommendations, the client queries for the specific service events:

```json
["REQ", <id>, [{ "kinds": [38000], "authors": [<user>, <users-contact-list>], "#k": ["38173"] }]]
// Query for specific service
["REQ", <id>, [{ "kinds": [38421], "#d": ["api.routstr.com"] }]]
```

User B, who follows User A, sees that `kind:38000` event and tries to connect to the corresponding mints.
### Alternative Direct Query

### Alternative query bypassing `kind:38000`
Alternatively, users might choose to query directly for `kind:38173` for an event kind. Clients SHOULD be careful doing this and use spam-prevention mechanisms or querying high-quality restricted relays to avoid directing users to malicious handlers.
Users might choose to query directly for service events. Clients SHOULD be careful doing this and use spam-prevention mechanisms or query high-quality restricted relays to avoid directing users to malicious services.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider expanding this into a "Security Considerations" section, mandating clients to:

  1. Cross-verify a tags against recommended events
  2. Require pubkey signatures for service announcements
  3. Integrate with NIP-05 or kind:0 for provider identity


```json
["REQ", <id>, [{ "kinds": [38173], "authors": [...] }]]
// Direct query for Routstr providers
["REQ", <id>, [{ "kinds": [38421] }]]

// Direct query for Cashu mints
["REQ", <id>, [{ "kinds": [38172] }]]
```

## Future Service Types

This framework can be extended to support additional service types by:

1. Defining a new event kind for the service
2. Specifying required and optional tags for that service type
3. Using `kind:38000` with the appropriate `k` tag for recommendations

Service operators should follow the patterns established above, including:

* Using parameterized-replaceable events
* Including connection information in `u` tags
* Providing capability information through specific tags
* Using the `content` field for metadata when appropriate
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
- [NIP-C7: Chats](C7.md)

## Event Kinds

| kind | description | NIP |
| ------------- | ------------------------------- | -------------------------------------- |
| `0` | User Metadata | [01](01.md) |
Expand Down Expand Up @@ -258,10 +259,12 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
| `31990` | Handler information | [89](89.md) |
| `32267` | Software Application | |
| `34550` | Community Definition | [72](72.md) |
| `38000` | Service Recommendation | [87](87.md) |
| `38172` | Cashu Mint Announcement | [87](87.md) |
| `38173` | Fedimint Announcement | [87](87.md) |
| `37516` | Geocache listing | [geocaching](geocaching) |
| `38383` | Peer-to-peer Order events | [69](69.md) |
| `38421` | Routstr Provider Announcement | [87](87.md) |
| `39000-9` | Group metadata events | [29](29.md) |
| `39089` | Starter packs | [51](51.md) |
| `39092` | Media starter packs | [51](51.md) |
Expand Down