mirror of
https://github.com/nostr-protocol/nips.git
synced 2024-11-13 23:39:08 -05:00
398 lines
14 KiB
Markdown
398 lines
14 KiB
Markdown
NIP-11
|
|
======
|
|
|
|
Relay Information Document
|
|
--------------------------
|
|
|
|
`draft` `optional`
|
|
|
|
Relays may provide server metadata to clients to inform them of capabilities, administrative contacts, and various server attributes. This is made available as a JSON document over HTTP, on the same URI as the relay's websocket.
|
|
|
|
When a relay receives an HTTP(s) request with an `Accept` header of `application/nostr+json` to a URI supporting WebSocket upgrades, they SHOULD return a document with the following structure.
|
|
|
|
```json
|
|
{
|
|
"name": <string identifying relay>,
|
|
"description": <string with detailed information>,
|
|
"pubkey": <administrative contact pubkey>,
|
|
"contact": <administrative alternate contact>,
|
|
"supported_nips": <a list of NIP numbers supported by the relay>,
|
|
"software": <string identifying relay software URL>,
|
|
"version": <string version identifier>
|
|
}
|
|
```
|
|
|
|
Any field may be omitted, and clients MUST ignore any additional fields they do not understand. Relays MUST accept CORS requests by sending `Access-Control-Allow-Origin`, `Access-Control-Allow-Headers`, and `Access-Control-Allow-Methods` headers.
|
|
|
|
Field Descriptions
|
|
------------------
|
|
|
|
### Name
|
|
|
|
A relay may select a `name` for use in client software. This is a string, and SHOULD be less than 30 characters to avoid client truncation.
|
|
|
|
### Description
|
|
|
|
Detailed plain-text information about the relay may be contained in the `description` string. It is recommended that this contain no markup, formatting or line breaks for word wrapping, and simply use double newline characters to separate paragraphs. There are no limitations on length.
|
|
|
|
### Pubkey
|
|
|
|
An administrative contact may be listed with a `pubkey`, in the same format as the Nostr events (32-byte hex for a `secp256k1` public key). If a contact is listed, this provides clients with a recommended address to send encrypted direct messages (See [NIP-17](17.md)) to a system administrator. Expected uses of this address are to report abuse or illegal content, file bug reports, or request other technical assistance.
|
|
|
|
Relay operators have no obligation to respond to direct messages.
|
|
|
|
### Contact
|
|
|
|
An alternative contact may be listed under the `contact` field as well, with the same purpose as `pubkey`. Use of a Nostr public key and direct message SHOULD be preferred over this. Contents of this field SHOULD be a URI, using schemes such as `mailto` or `https` to provide users with a means of contact.
|
|
|
|
### Supported NIPs
|
|
|
|
As the Nostr protocol evolves, some functionality may only be available by relays that implement a specific `NIP`. This field is an array of the integer identifiers of `NIP`s that are implemented in the relay. Examples would include `1`, for `"NIP-01"` and `9`, for `"NIP-09"`. Client-side `NIPs` SHOULD NOT be advertised, and can be ignored by clients.
|
|
|
|
### Software
|
|
|
|
The relay server implementation MAY be provided in the `software` attribute. If present, this MUST be a URL to the project's homepage.
|
|
|
|
### Version
|
|
|
|
The relay MAY choose to publish its software version as a string attribute. The string format is defined by the relay implementation. It is recommended this be a version number or commit identifier.
|
|
|
|
Extra Fields
|
|
------------
|
|
|
|
### Server Limitations
|
|
|
|
These are limitations imposed by the relay on clients. Your client
|
|
should expect that requests which exceed these *practical* limitations
|
|
are rejected or fail immediately.
|
|
|
|
```jsonc
|
|
{
|
|
"limitation": {
|
|
"max_message_length": 16384,
|
|
"max_subscriptions": 20,
|
|
"max_filters": 100,
|
|
"max_limit": 5000,
|
|
"max_subid_length": 100,
|
|
"max_event_tags": 100,
|
|
"max_content_length": 8196,
|
|
"min_pow_difficulty": 30,
|
|
"auth_required": true,
|
|
"payment_required": true,
|
|
"restricted_writes": true,
|
|
"created_at_lower_limit": 31536000,
|
|
"created_at_upper_limit": 3
|
|
},
|
|
// ...
|
|
}
|
|
```
|
|
|
|
- `max_message_length`: this is the maximum number of bytes for incoming JSON that the relay
|
|
will attempt to decode and act upon. When you send large subscriptions, you will be
|
|
limited by this value. It also effectively limits the maximum size of any event. Value is
|
|
calculated from `[` to `]` and is after UTF-8 serialization (so some unicode characters
|
|
will cost 2-3 bytes). It is equal to the maximum size of the WebSocket message frame.
|
|
|
|
- `max_subscriptions`: total number of subscriptions that may be
|
|
active on a single websocket connection to this relay. It's possible
|
|
that authenticated clients with a (paid) relationship to the relay
|
|
may have higher limits.
|
|
|
|
- `max_filters`: maximum number of filter values in each subscription.
|
|
Must be one or higher.
|
|
|
|
- `max_subid_length`: maximum length of subscription id as a string.
|
|
|
|
- `max_limit`: the relay server will clamp each filter's `limit` value to this number.
|
|
This means the client won't be able to get more than this number
|
|
of events from a single subscription filter. This clamping is typically done silently
|
|
by the relay, but with this number, you can know that there are additional results
|
|
if you narrowed your filter's time range or other parameters.
|
|
|
|
- `max_event_tags`: in any event, this is the maximum number of elements in the `tags` list.
|
|
|
|
- `max_content_length`: maximum number of characters in the `content`
|
|
field of any event. This is a count of unicode characters. After
|
|
serializing into JSON it may be larger (in bytes), and is still
|
|
subject to the `max_message_length`, if defined.
|
|
|
|
- `min_pow_difficulty`: new events will require at least this difficulty of PoW,
|
|
based on [NIP-13](13.md), or they will be rejected by this server.
|
|
|
|
- `auth_required`: this relay requires [NIP-42](42.md) authentication
|
|
to happen before a new connection may perform any other action.
|
|
Even if set to False, authentication may be required for specific actions.
|
|
|
|
- `payment_required`: this relay requires payment before a new connection may perform any action.
|
|
|
|
- `restricted_writes`: this relay requires some kind of condition to be fulfilled in order to
|
|
accept events (not necessarily, but including `payment_required` and `min_pow_difficulty`).
|
|
This should only be set to `true` when users are expected to know the relay policy before trying
|
|
to write to it -- like belonging to a special pubkey-based whitelist or writing only events of
|
|
a specific niche kind or content. Normal anti-spam heuristics, for example, do not qualify.
|
|
|
|
- `created_at_lower_limit`: 'created_at' lower limit
|
|
|
|
- `created_at_upper_limit`: 'created_at' upper limit
|
|
|
|
### Event Retention
|
|
|
|
There may be a cost associated with storing data forever, so relays
|
|
may wish to state retention times. The values stated here are defaults
|
|
for unauthenticated users and visitors. Paid users would likely have
|
|
other policies.
|
|
|
|
Retention times are given in seconds, with `null` indicating infinity.
|
|
If zero is provided, this means the event will not be stored at
|
|
all, and preferably an error will be provided when those are received.
|
|
|
|
```jsonc
|
|
{
|
|
"retention":[
|
|
{
|
|
"kinds":[
|
|
0,
|
|
1,
|
|
[
|
|
5,
|
|
7
|
|
],
|
|
[
|
|
40,
|
|
49
|
|
]
|
|
],
|
|
"time":3600
|
|
},
|
|
{
|
|
"kinds":[
|
|
[
|
|
40000,
|
|
49999
|
|
]
|
|
],
|
|
"time":100
|
|
},
|
|
{
|
|
"kinds":[
|
|
[
|
|
30000,
|
|
39999
|
|
]
|
|
],
|
|
"count":1000
|
|
},
|
|
{
|
|
"time":3600,
|
|
"count":10000
|
|
}
|
|
],
|
|
// ...
|
|
}
|
|
```
|
|
|
|
- `retention` is a list of specifications: each will apply to either all kinds, or
|
|
a subset of kinds. Ranges may be specified for the kind field as a tuple of inclusive
|
|
start and end values. Events of indicated kind (or all) are then limited to a `count`
|
|
and/or time period.
|
|
|
|
It is possible to effectively blacklist Nostr-based protocols that rely on
|
|
a specific `kind` number, by giving a retention time of zero for those `kind` values.
|
|
While that is unfortunate, it does allow clients to discover servers that will
|
|
support their protocol quickly via a single HTTP fetch.
|
|
|
|
There is no need to specify retention times for _ephemeral events_ since they are not retained.
|
|
|
|
### Content Limitations
|
|
|
|
Some relays may be governed by the arbitrary laws of a nation state. This
|
|
may limit what content can be stored in clear-text on those relays. All
|
|
clients are encouraged to use encryption to work around this limitation.
|
|
|
|
It is not possible to describe the limitations of each country's laws
|
|
and policies which themselves are typically vague and constantly shifting.
|
|
|
|
Therefore, this field allows the relay operator to indicate which
|
|
countries' laws might end up being enforced on them, and then
|
|
indirectly on their users' content.
|
|
|
|
Users should be able to avoid relays in countries they don't like,
|
|
and/or select relays in more favorable zones. Exposing this
|
|
flexibility is up to the client software.
|
|
|
|
```jsonc
|
|
{
|
|
"relay_countries": [ "CA", "US" ],
|
|
// ...
|
|
}
|
|
```
|
|
|
|
- `relay_countries`: a list of two-level ISO country codes (ISO 3166-1 alpha-2) whose
|
|
laws and policies may affect this relay. `EU` may be used for European Union countries.
|
|
|
|
Remember that a relay may be hosted in a country which is not the
|
|
country of the legal entities who own the relay, so it's very
|
|
likely a number of countries are involved.
|
|
|
|
|
|
### Community Preferences
|
|
|
|
For public text notes at least, a relay may try to foster a
|
|
local community. This would encourage users to follow the global
|
|
feed on that relay, in addition to their usual individual follows.
|
|
To support this goal, relays MAY specify some of the following values.
|
|
|
|
```jsonc
|
|
{
|
|
"language_tags": ["en", "en-419"],
|
|
"tags": ["sfw-only", "bitcoin-only", "anime"],
|
|
"posting_policy": "https://example.com/posting-policy.html",
|
|
// ...
|
|
}
|
|
```
|
|
|
|
- `language_tags` is an ordered list
|
|
of [IETF language tags](https://en.wikipedia.org/wiki/IETF_language_tag) indicating
|
|
the major languages spoken on the relay. `"*"` wildcard can be used for global relays.
|
|
|
|
- `tags` is a list of limitations on the topics to be discussed.
|
|
For example `sfw-only` indicates that only *"Safe For Work"* content
|
|
is encouraged on this relay. This relies on assumptions of what the
|
|
"work" "community" feels "safe" talking about. In time, a common
|
|
set of tags may emerge that allow users to find relays that suit
|
|
their needs, and client software will be able to parse these tags easily.
|
|
The `bitcoin-only` tag indicates that any *"altcoin"*, *"crypto"* or *"blockchain"*
|
|
comments will be ridiculed without mercy.
|
|
|
|
- `posting_policy` is a link to a human-readable page which specifies the
|
|
community policies for the relay. In cases where `sfw-only` is True, it's
|
|
important to link to a page which gets into the specifics of your posting policy.
|
|
|
|
The `description` field should be used to describe your community
|
|
goals and values, in brief. The `posting_policy` is for additional
|
|
detail and legal terms. Use the `tags` field to signify limitations
|
|
on content, or topics to be discussed, which could be machine
|
|
processed by appropriate client software.
|
|
|
|
### Pay-to-Relay
|
|
|
|
Relays that require payments may want to expose their fee schedules.
|
|
|
|
```jsonc
|
|
{
|
|
"payments_url":"https://example.com/payments",
|
|
"fees":{
|
|
"admission":{
|
|
"amount":1000000,
|
|
"unit":"msats"
|
|
},
|
|
"subscription":[
|
|
{
|
|
"amount":5000000,
|
|
"unit":"msats",
|
|
"period":2592000 // 1 Month
|
|
},
|
|
{
|
|
"amount":50000000,
|
|
"unit":"msats",
|
|
"period":31536000 // 1 Year
|
|
}
|
|
],
|
|
"publication":[
|
|
{
|
|
"kinds":[
|
|
4
|
|
],
|
|
"amount":100,
|
|
"unit":"msats"
|
|
},
|
|
{
|
|
"kinds":[
|
|
30023 // Long-from content
|
|
],
|
|
"amount":300,
|
|
"unit":"msats"
|
|
}
|
|
]
|
|
},
|
|
// ...
|
|
}
|
|
```
|
|
|
|
The `subscription` and `publication` are fee models, their object value and `admission` are fee rules.
|
|
|
|
- `payments_url` is a link to a human-readable page which user can use to see and/or pay for fees on this relay.
|
|
|
|
- `fees` includes the list of different fees required for each mode on this relay:
|
|
|
|
- `admission` is the fee that user need to pay to access to relay, if only `admission` is presented that means only admission fee is required to get access to relay.
|
|
|
|
- `subscription` is the fee that user have to pay to access the relay for a fixed amount of time. The `period` field is the access time in seconds. If subscription and admission present at the same time, admission fee MUST get paid as well before subscribing. Otherwise only subscription need to get paid.
|
|
|
|
- `publication` is the fee that user needs to pay per event they publish on this relay. The `kinds` is an array of kinds that need a fee equal to `amount` to get published. A limited/not supported kind SHOULD NOT be presented and each kind or range of kinds can be presented in one or more publication fee rules. If publication and subscription models are present at the same time, subscription fee needs to get paid first.
|
|
|
|
- `unit` in each fee rule can be set to `BTC`, `sats` and `msats` and can be a float number for `BTC`.
|
|
|
|
Access means user can post anything on relay based on its limitation/policies document. The models/rules can be omitted as well.
|
|
|
|
### Icon
|
|
|
|
A URL pointing to an image to be used as an icon for the relay. Recommended to be squared in shape.
|
|
|
|
```jsonc
|
|
{
|
|
"icon": "https://nostr.build/i/53866b44135a27d624e99c6165cabd76ac8f72797209700acb189fce75021f47.jpg",
|
|
// ...
|
|
}
|
|
```
|
|
|
|
### Examples
|
|
|
|
As of 3 September 2024 the following command provided these results:
|
|
|
|
```bash
|
|
$ curl -H "Accept: application/nostr+json" https://eden.nostr.land | jq
|
|
```
|
|
|
|
```json
|
|
{
|
|
"description": "nostr.land family of relays (fi-01 [tiger])",
|
|
"name": "nostr.land",
|
|
"pubkey": "52b4a076bcbbbdc3a1aefa3735816cf74993b1b8db202b01c883c58be7fad8bd",
|
|
"software": "custom",
|
|
"supported_nips": [
|
|
1,
|
|
2,
|
|
4,
|
|
9,
|
|
11,
|
|
12,
|
|
16,
|
|
20,
|
|
22,
|
|
28,
|
|
33,
|
|
40
|
|
],
|
|
"version": "1.0.1",
|
|
"limitation": {
|
|
"payment_required": true,
|
|
"max_message_length": 65535,
|
|
"max_event_tags": 2000,
|
|
"max_subscriptions": 20,
|
|
"auth_required": false
|
|
},
|
|
"payments_url": "https://nostr.land",
|
|
"fees": {
|
|
"subscription": [
|
|
{
|
|
"amount": 4000000,
|
|
"unit": "msats",
|
|
"period": 2592000
|
|
}
|
|
]
|
|
},
|
|
"canonical_url": "wss://eden.nostr.land"
|
|
}
|
|
```
|