Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add surveys / polls #111

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
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
158 changes: 158 additions & 0 deletions 41.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
NIP-41
======

# Surveys / polls / quizzes
-----------------------------------

`draft` `optional` `require:nip-13` `require:nip-57` `author:fernandolguevara`

The `surv` tag & `surv-answer` (kind: `30041`) enables users to have surveys/polls/quizzes experiences on the network.

## Spec

### surv

To start a survey on the network, an event with one or many 'surv' tags may be created.

```json
{"tags":[
["surv", "{single|multiple}", "ttl", "(label)", "option 1", "option 2", "option 3", "option 4"]
["nonce", "1", "32"]
["amount", "milli-satoshi value"]
]}
```

fernandolguevara marked this conversation as resolved.
Show resolved Hide resolved
#### tags
- `surv`:
- `{single|multiple}`: allow others to reply with single or multiple choice.
- `ttl:unix-time`: when survey expires, `0` don't expire.
- `(label):string`: if present, clients should use it as surv label.
- `option:string`: survey options
- `nonce`: if present, pow is mandatory for answer. ref: [13](13.md)
- `amount`: if present, zap is mandatory for answer. ref: [57](57.md)

### surv-answer

To reply to a survey on the network, an event of kind `30041` is created.

```meta
["surv-answer", "surv-index", "option-index", ...]
```

```json
{
"kind": 30041,
"tags":[
["e", "<event-id-root>", "wss://...", "root"]
["d", "surv-answer/{event-id-root}"]
["surv-answer", "0", "option-index:int", "{...}"]
["nonce", "1", "32"],
["amount", "milli-satoshi value"],
]
}
```
at least one selected option index should present on the answer event the tag `surv-answer`

tags:
- `e`: `<event-id-root>` origin event.
- `d`: the value should be an string formed using origin `event-id-root` for the survey.
- `surv-answer`:
- `surv-index:int`: starting at 0.
- `option-index:int`: starting at 0.
- `nonce`: if present, pow is mandatory for answer.
- `amount`: if present, zap is mandatory for answer.


## Relay and client recommendations
- `surv` tag:
- Should have at least `two` options.
- The value of the `label` field should allow enough characters to express the questions.
- The `options` items should be limited up to 4.
- Each `option` should be 25 chars limited.

## Examples

### Example surv single

```json
{
"pubkey": "<pub-key>",
"created_at": 1000000000,
"kind": 1,
"tags": [
["t", "hastag"],
["surv", "single", "0", "", "option 1", "option 2", "options 3"],
],
"content": "#hastag what is your favorite option?",
"id": "<event-id>"
},
{
"pubkey": "<pub-key>",
"created_at": 1000000000,
"kind": 30041,
"tags": [
["e", "<event-id-root>", "wss://...", "root"],
["t", "tag"],
["surv-answer", "", "0"]
],
"content": "here my favorite option is #option1 \n",
"id": "<event-id>"
}
```

### Example surv multiple with expiration

```json
{
"pubkey": "<pub-key>",
"created_at": 1000000000,
"kind": 1,
"tags": [
["t", "hastag"],
["surv", "multiple", "1684599600"],
["options", "option 1", "option 2", "options 3"],
],
"content": "#hastag what are your favorite options?",
"id": "<event-id>"
},
{
"pubkey": "<pub-key>",
"created_at": 1000000000,
"kind": 30041,
"tags": [
["e", "<event-id-root>", "wss://...", "root"],
["t", "tag"],
["surv-answer", "", "0", "2"]
],
"content": "here my favorite option is #option1 \n",
"id": "<event-id>"
}
```
### Example multiple surv

```json
{
"pubkey": "<pub-key>",
"created_at": 1000000000,
"kind": 1,
"tags": [
["t", "hastag"],
["surv", "single", "0", "surv 1?", "option 1", "option 2", "options 3"],
["surv", "multiple", "0", "surv 2?", "option 1", "option 2", "options 3"],
],
"content": "#hastag Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do?",
"id": "<event-id>"
},
{
"pubkey": "<pub-key>",
"created_at": 1000000000,
"kind": 30041,
"tags": [
["e", "<event-id-root>", "wss://...", "root"],
["surv-answer", "0", "0"]
["surv-answer", "1", "0", "2"]
],
"content": "quis nostrud exercitation ullamco laboris!\n",
"id": "<event-id>"
}
```
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh
- [NIP-33: Parameterized Replaceable Events](33.md)
- [NIP-36: Sensitive Content](36.md)
- [NIP-40: Expiration Timestamp](40.md)
- [NIP-41: Surveys/Polls/Quizzes](41.md)
- [NIP-42: Authentication of clients to relays](42.md)
- [NIP-46: Nostr Connect](46.md)
- [NIP-50: Keywords filter](50.md)
Expand Down