From 64bb88c83dbf56791a31720306f6100bf8334f08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Lo=CC=81pez=20Guevara?= Date: Thu, 22 Dec 2022 12:31:49 -0300 Subject: [PATCH 1/3] feat: add surveys / polls --- README.md | 1 + XX.md | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 XX.md diff --git a/README.md b/README.md index ddf022dc85..634efa3487 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh - [NIP-35: User Discovery](35.md) - [NIP-36: Sensitive Content](36.md) - [NIP-40: Expiration Timestamp](40.md) +- [NIP-XX: Surveys/Polls](XX.md) ## Event Kinds diff --git a/XX.md b/XX.md new file mode 100644 index 0000000000..503f67c3c4 --- /dev/null +++ b/XX.md @@ -0,0 +1,69 @@ +NIP-XX +====== + +Surveys / polls +----------------------------------- + +`draft` `optional` `require:nip-20` `author:fernandolguevara` + +The `surv` & `surv-resp` tags enables users to have surveys/polls experiences on the network. + + +#### Spec + +##### Message + +``` +tag: surv +options: + - allow others to reply with one or multiple options + - TTL (in seconds|timestamp) when surv expires, 0 TTL don't expire + - []: up to 4 choices each limited to 25 chars +```` + +``` +tag: surv-resp +options: + - []: based on surv type it can have one or multi +```` + +##### Relays + +One vote per key, relays needs to discard all subsequent votes, as well as invalid requests. + +##### Invalid responses +```json +["OK", , false, 'ALREADY_ANSWERED'], +["OK", , false, 'EXPIRED'], +["OK", , false, 'SINGLE_OPTION'], +["OK", , false, 'INVALID_OPTION', 'optionX', ...], +``` + +#### Example + +```json +{ + "pubkey": "", + "created_at": 1000000000, + "kind": 1, + "tags": [ + ["t", "hastag"], + ["surv", "", "", "option 1", "option 2", "option 3"] + ], + "content": "#hastag what is your favorite option?", + "id": "" + }, + { + "pubkey": "", + "created_at": 1000000000, + "kind": 1, + "tags": [ + ["p", "", "wss://..."], + ["e", "", "wss://...", "root"], + ["t", "tag"], + ["surv-resp", "option 1", "option 2"...] // based on root event surv type it can have one or multi + ], + "content": "hello #tag\n", + "id": "" + } +``` From 44a886e119e413b0907b1f8712bf5c976c722c73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Lo=CC=81pez=20Guevara?= Date: Thu, 22 Dec 2022 15:03:03 -0300 Subject: [PATCH 2/3] NIP-41 --- XX.md => 41.md | 0 README.md | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename XX.md => 41.md (100%) diff --git a/XX.md b/41.md similarity index 100% rename from XX.md rename to 41.md diff --git a/README.md b/README.md index 634efa3487..c51b4a2e18 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh - [NIP-35: User Discovery](35.md) - [NIP-36: Sensitive Content](36.md) - [NIP-40: Expiration Timestamp](40.md) -- [NIP-XX: Surveys/Polls](XX.md) +- [NIP-41: Surveys/Polls](41.md) ## Event Kinds From 1aa3ddf0e1209eed33f03c50fae658be7c841667 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Lo=CC=81pez=20Guevara?= Date: Fri, 3 Mar 2023 19:31:32 -0300 Subject: [PATCH 3/3] feat(surv): update nip & use parameterized replaceable events for surv-answer --- 41.md | 183 +++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 136 insertions(+), 47 deletions(-) diff --git a/41.md b/41.md index 503f67c3c4..c8409df8d8 100644 --- a/41.md +++ b/41.md @@ -1,69 +1,158 @@ -NIP-XX +NIP-41 ====== -Surveys / polls +# Surveys / polls / quizzes ----------------------------------- -`draft` `optional` `require:nip-20` `author:fernandolguevara` +`draft` `optional` `require:nip-13` `require:nip-57` `author:fernandolguevara` -The `surv` & `surv-resp` tags enables users to have surveys/polls experiences on the network. +The `surv` tag & `surv-answer` (kind: `30041`) enables users to have surveys/polls/quizzes experiences on the network. +## Spec -#### Spec +### surv -##### Message +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"] +]} ``` -tag: surv -options: - - allow others to reply with one or multiple options - - TTL (in seconds|timestamp) when surv expires, 0 TTL don't expire - - []: up to 4 choices each limited to 25 chars -```` +#### 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", ...] ``` -tag: surv-resp -options: - - []: based on surv type it can have one or multi -```` -##### Relays +```json +{ + "kind": 30041, + "tags":[ + ["e", "", "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`: `` 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. + -One vote per key, relays needs to discard all subsequent votes, as well as invalid requests. +## 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 -##### Invalid responses ```json -["OK", , false, 'ALREADY_ANSWERED'], -["OK", , false, 'EXPIRED'], -["OK", , false, 'SINGLE_OPTION'], -["OK", , false, 'INVALID_OPTION', 'optionX', ...], +{ + "pubkey": "", + "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": "" +}, +{ + "pubkey": "", + "created_at": 1000000000, + "kind": 30041, + "tags": [ + ["e", "", "wss://...", "root"], + ["t", "tag"], + ["surv-answer", "", "0"] + ], + "content": "here my favorite option is #option1 \n", + "id": "" +} ``` -#### Example +### Example surv multiple with expiration ```json { - "pubkey": "", - "created_at": 1000000000, - "kind": 1, - "tags": [ - ["t", "hastag"], - ["surv", "", "", "option 1", "option 2", "option 3"] - ], - "content": "#hastag what is your favorite option?", - "id": "" - }, - { - "pubkey": "", - "created_at": 1000000000, - "kind": 1, - "tags": [ - ["p", "", "wss://..."], - ["e", "", "wss://...", "root"], - ["t", "tag"], - ["surv-resp", "option 1", "option 2"...] // based on root event surv type it can have one or multi - ], - "content": "hello #tag\n", - "id": "" - } + "pubkey": "", + "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": "" +}, +{ + "pubkey": "", + "created_at": 1000000000, + "kind": 30041, + "tags": [ + ["e", "", "wss://...", "root"], + ["t", "tag"], + ["surv-answer", "", "0", "2"] + ], + "content": "here my favorite option is #option1 \n", + "id": "" +} ``` +### Example multiple surv + +```json +{ + "pubkey": "", + "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": "" +}, +{ + "pubkey": "", + "created_at": 1000000000, + "kind": 30041, + "tags": [ + ["e", "", "wss://...", "root"], + ["surv-answer", "0", "0"] + ["surv-answer", "1", "0", "2"] + ], + "content": "quis nostrud exercitation ullamco laboris!\n", + "id": "" +} +``` \ No newline at end of file