Skip to content

Commit

Permalink
make text more intelligible
Browse files Browse the repository at this point in the history
  • Loading branch information
arthurfranca committed May 10, 2024
1 parent c209e55 commit fc97c78
Showing 1 changed file with 39 additions and 102 deletions.
141 changes: 39 additions & 102 deletions 61.md
Original file line number Diff line number Diff line change
@@ -1,134 +1,71 @@
NIP-61
======

Unbounded List
Unbound List
--------------

`draft` `optional` `author:arthurfranca` `author:vitorpamplona`
`draft` `optional`

An unbounded list is a group of events with the same pubkey and `n` (name) tag.
An event can have many `n` tags, thus being member of many unbounded lists.
An unbound list is a group of events with the same pubkey and `n` (list "n"ame) tag.
An event can have many `n` tags, thus being member of many unbound lists.

An unbounded list itself is referenced by an `u` tag
or by an `nunb` [NIP-19](19.md) entity using [NIP-21](21.md) URI.
To add an event to the "Close Friends" list,
add a "close-friend" (prefer singular form with dash separator) `n` tag to the event.

To remove an event from a "Close Friends" list,
remove the "close-friend" `n` tag from the event.

An unbound list itself is referenced by an `u` tag
or by an `nlist` [NIP-19](19.md) entity using [NIP-21](21.md) URI.

## Use Cases

Unbounded lists are an option to hold a big number of items. In contrast, [NIP-51](51.md) lists
have a limit on the number of items depending on relay's event size restrictions.
Unbound lists can be used wherever a [NIP-51](51.md) list fits.

Public and encrypted data can coexist in unbounded list events similar to NIP-51 lists.
NIP-51 lists have a limit on the number of items they can hold depending on relay's event size restrictions.
While unbound lists can have any number of items.

In fact, an unbounded list can be made of different NIP-51 lists from the same author.
The downside of unbound lists is that migrating a list from one relay to another can be rate limited
due to saving many individual events during a small time window.

For example, the NIP-51 lists may be "close_friends" and "family" and both sharing the same `n` tag,
effectively making an unbounded list combining both sets of `p` tags.
Public and encrypted data can coexist in unbound list events, similar to NIP-51 lists.

## Referencing

An unbounded list is referenced by an `u` tag.
An unbound list is referenced by an `u` tag.
It references a set of events from an author instead of a single one:

`["u", "<32-bytes lowercase hex of a pubkey>:<n tag value>", "<recommended relay URL, optional>"]`

One may also use an `nunb` entity URI: `nostr:nunb1qqstn...794234d`.

## Unbounded List Event Kinds

Any event kind can be part of an unbounded list by just adding an `n` tag. Nevertheless,
there are reserved kinds for specific usage:

| kind | list type |
| ------ | ----------|
| 33118 | People |

Tags other than `d` and `n` may be encrypted with [NIP-44](#44.md) similar to NIP-51 lists.

### Unbounded People List
One may also use an `nlist` entity URI: `nostr:nlist1qqstn...794234d`.

An event with kind `33118` is defined as a parameterized replaceable unbounded list event for people.
The `n` tag(s) holds the list name(s) the event is currently part of.
The **single** `p` tag included in these list events MUST follow the format of kind 3 events as defined in [NIP-02 - Contact List and Petnames](02.md).
## Event Kinds

## Examples

### People List

```js
// Unbounded subscriber list event also part of the unbounded
// "private:5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36" list
{
"kind": 33118,
"tags": [
["d", "random6467362966154779"]
// This is enough to mark it as a "subscribers" unbounded list
["n", "subscribers"],
// This also adds this event to other unbounded list (e.g.: meant
// to hold all pubkeys who can access the
// 5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36 event)
// made of the "subscribers" unbounded list events
// and other events such as the above "close_friends" NIP-51 Categorized People list event
["n", "private:5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36"],
],
"content": "<NIP-44 encrypted Stringified TAG-List([
["p", "91cf9..4e5ca", "wss://alicerelay.com/"]
])>",
// ...other fields
}
```
The the same `n` tag can be applied to any event no matter the `kind` or structure.
However, it is better to add `n` tag(s) to parameterized replaceable events, because
such events can be removed from a list later by removing the corresponding `n` tag,
due to their editable nature.

### Private ACL
The following example is based on the unreleased
[Relationship Status](https://github.com/vitorpamplona/nips/blob/relationship-status/81.md) spec:

```js
// A NIP-51 list being part of the unbounded
// "private:5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36" list
{
"kind": 30000,
"kind": 30382, // This is a kind for public relationship info between the signer and another user
"pubkey": "<me>",
"tags": [
["d", "close_friends"]
// This event is added to an ubounded list meant to hold all pubkeys who can access the
// 5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36 event just like the event above
["n", "private:5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36"],
["d", "<another-user-pubkey>"],
["n", "follow"], // A "follow" "n" tag turns this event into a kind 3 equivalent entry
["n", "friend"], // He is part of may "Friends" list
["n", "close-friend"], // He is also part of the smaller "Close Friends" list
// ...other metadata describing the relationship
["T", "3:driver"] // This is using an unreleased spec to rate this user as a great driver
],
"content": "<NIP-44 encrypted Stringified TAG-List([
// This has multiple "p" tags because it is a NIP-51 Categorized People list
["p", "14aeb..8dad4", "wss://bobrelay.com/nostr"],
["p", "612ae..e610f", "ws://carolrelay.com/ws"]
])>",
"content": ""
// ...other fields
}
```

### Relationship Status
```js
// Unbounded contact lists can be made of
// thousands of events like this NIP-81 one below
{
"kind": 30382, // contact kind
"tags": [
["d", "91cf9..4e5ca"] // contact's pubkey
// Can fetch all Scammer List but no one else but the author knows
// The author should keep all n "relaltionship status names" to "random string" mapping
// in an encrypted NIP-51 list (see kind:10003 event below)
["n", "<random string mapped to 'Scammer' list>"],
["relay", "<recommended relay>"],
],
"content": "<NIP-44 encrypted Stringified TAG-List([
["nickname", "Big Joe"],
["summary", "<summary of the relationship>"],
["email", "[email protected]"]
])>",
// ...other fields
}
{
"kind": 10003,
"content": "<NIP-44 encrypted Stringified TAG-List([
["status", "Scammer", "3737815743613957"],
["status", "Great Friend", "9369453848773155"],
["status", "Ex-Girlfriend", "17740745702992977"]
])>",
// ...other fields
}
```
In the above example, when removing someone from an unbound list (considering a `kind:30382` event),
a client should only delete the event when all tags other
than the `d` one were removed and the content is an empty string.

0 comments on commit fc97c78

Please sign in to comment.