nips/88.md

132 lines
4.3 KiB
Markdown
Raw Normal View History

2024-09-20 03:04:21 -04:00
# NIP-88
## Polls
`draft` `optional`
This NIP defines the event scheme that describe Polls on nostr.
## Events
### Poll Event
The poll event is defined as a `kind:1068` event.
- **content** key holds the label for the poll.
Major tags in the poll event are:
- **option**: The option tags contain an OptionId(any alphanumeric) field, followed by an option label field.
- **relay**: One or multiple tags that the poll is expecting respondents to respond on.
- **polltype**: can be "singlechoice", "multiplechoice", or "rankedchoice". Polls that do not have a polltype should be considered a "singlechoice" poll.
2024-09-20 03:30:02 -04:00
- **endsAt**: signifying at which unix timestamp the poll is meant to end.
2024-09-20 03:04:21 -04:00
Example Event
```json
{
2024-09-20 03:30:02 -04:00
"content": "Pineapple on pizza",
2024-09-20 03:04:21 -04:00
"created_at": 1719888496,
"id": "9d1b6b9562e66f2ecf35eb0a3c2decc736c47fddb13d6fb8f87185a153ea3634",
"kind": 1068,
"pubkey": "dee45a23c4f1d93f3a2043650c5081e4ac14a778e0acbef03de3768e4f81ac7b",
"sig": "7fa93bf3c430eaef784b0dacc217d3cd5eff1c520e7ef5d961381bc0f014dde6286618048d924808e54d1be03f2f2c2f0f8b5c9c2082a4480caf45a565ca9797",
"tags": [
["option", "qj518h583", "Yay"],
["option", "gga6cdnqj", "Nay"],
["relay", "<relay url1>"],
["relay", "<relay url2>"],
2024-09-20 03:30:02 -04:00
["polltype", "singlechoice"],
["endsAt", "<unix timestamp in seconds>"]
2024-09-20 03:04:21 -04:00
]
}
```
### Responses
2024-09-20 03:30:02 -04:00
The response event is a `kind:1018` event. It contains an e tag with the poll event it is referencing, followed by one or more response tags.
2024-09-20 03:04:21 -04:00
- **response** : The tag contains "response" as it's first positional argument followed by the option Id selected.
2024-09-20 03:30:02 -04:00
The responses are meant to be published to the relays specified in the poll event.
2024-09-20 03:04:21 -04:00
Example Response Event
```json
{
"content": "",
"created_at": 1720097117,
"id": "60a005e32e9596c3f544a841a9bc4e46d3020ca3650d6a739c95c1568e33f6d8",
"kind": 1018,
2024-09-20 03:04:21 -04:00
"pubkey": "1bc70a0148b3f316da33fe7e89f23e3e71ac4ff998027ec712b905cd24f6a411",
"sig": "30071a633c65db8f3a075c7a8de757fbd8ce65e3607f4ba287fe6d7fbf839a380f94ff4e826fbba593f6faaa13683b7ea9114ade140720ecf4927010ebf3e44f",
"tags": [
2024-09-20 03:30:02 -04:00
["e", "1fc80cf813f1af33d5a435862b7ef7fb96b47e68a48f1abcadf8081f5a545550"],
2024-09-20 03:04:21 -04:00
["response", "gga6cdnqj"],
["response", "m3agjsdq1"]
]
}
```
### Poll Types
2024-09-20 03:30:02 -04:00
The polltype setting dictates how multiple response tags are handled in the `kind:1018` event.
2024-09-20 03:04:21 -04:00
2024-09-20 03:30:02 -04:00
- **polltype: singlechoice**: The first response tag is to be considered the actual response.
- **polltype: multiplechoice**: The first response tag pointing to each id is considered the actual response, without considering the order of the response tags.
- **polltype: rankedchoice**: The first response tag pointing to each id is the considered the actual response, while also taking into account the order of the response tags.
2024-09-20 03:04:21 -04:00
### Counting Results
2024-09-20 03:30:02 -04:00
Results can be queried by fetching `kind:1018` events from the relays specified in the poll.
2024-09-20 03:04:21 -04:00
The results displayed should only be 1 vote event per pubkey.
2024-09-20 03:30:02 -04:00
In case of multiple events for a pubkey, the event with the largest timestamp within the poll limits should be considered.
Example for querying polls.
```ts
const fetchVoteEvents = (filterPubkeys: string[]) => {
let resultFilter: Filter = {
"#e": [pollEvent.id],
2024-09-21 02:44:14 -04:00
kinds: [1018],
2024-09-20 03:30:02 -04:00
};
if (filterPubkeys?.length) {
resultFilter.authors = filterPubkeys;
}
if (pollExpiration) {
resultFilter.until = Number(pollExpiration);
}
2024-09-21 02:44:14 -04:00
pool.subscribeMany(relays, [resultFilter], {
2024-09-20 03:30:02 -04:00
onevent: handleResultEvent,
});
};
```
Example for maintaining OneVotePerPubkey
```ts
const oneVotePerPubkey = (events: Event[]) => {
const eventMap = new Map<string, Event>();
events.forEach((event) => {
if (
!eventMap.has(event.pubkey) ||
event.created_at > eventMap.get(event.pubkey)!.created_at
) {
eventMap.set(event.pubkey, event);
}
});
return Array.from(eventMap.values());
};
```
### Relays
2024-09-27 23:20:49 -04:00
It is advisable for poll authors to use relays that do not allow backdated events and do not honor kind:5 (delete) requests for vote events to maintain the integrity of poll results after the poll has ended.
2024-09-20 03:04:21 -04:00
### Curation
The clients may configure fetching results by specific people. This can be achieved by creating `kind:30000` follow sets, and fetching results only from the follow set.
Clients can also employ other curation algorithms, like Proof Of Work and Web of Trust scores for result curations.