Compare commits

..

72 Commits

Author SHA1 Message Date
Alex Gleason
fcc1b0baf6 Link r tag in the README 2024-06-02 16:38:01 -05:00
hodlbod
81a0e0036e Merge pull request #868 from greenart7c3/master
Android Signer Application
2024-06-01 07:23:18 -07:00
Asai Toshiya
30a5723f88 BREAKING.md: add NIP-71 change 2024-05-31 12:43:13 +09:00
Asai Toshiya
5c796c19fd NIP-38: move description of content to Live Statuses section 2024-05-29 13:08:31 +09:00
hodlbod
57fcad3e13 Merge pull request #1264 from coracle-social/client-implementation-requirements
Raise bar for NIP implementation
2024-05-28 11:38:17 -07:00
Basanta Goswami
244666ed0d small nitpicks 2024-05-28 10:13:12 -03:00
Jon Staab
8199b79571 Raise bar for NIP implementation 2024-05-27 08:31:29 -07:00
Alex Gleason
85df9b0e89 Merge pull request #1260 from AsaiToshiya/AsaiToshiya-patch-13
README: add `nonce` tag difficulty
2024-05-26 22:43:53 -05:00
Asai Toshiya
deb0073493 README: add nonce tag difficulty 2024-05-27 12:40:01 +09:00
Asai Toshiya
a649a75e5a README: fix order of kinds 2024-05-26 23:57:05 +09:00
/dev/fd0
765c731397 add joinstr event kind in README (#1257)
* add joinstr event kind

* remove extra spaces

* change kind number

Co-authored-by: fiatjaf_ <fiatjaf@gmail.com>

---------

Co-authored-by: fiatjaf_ <fiatjaf@gmail.com>
2024-05-26 07:58:14 -03:00
fiatjaf
92d5837b0c nip54: clarify wikilink format. 2024-05-25 09:46:46 -03:00
Asai Toshiya
5d1d1c178e NIP-71: remove aes-256-gcm tag 2024-05-24 22:02:13 -03:00
hodlbod
58c76f04e8 Merge pull request #1255 from patrickReiis/master
Mention extra metadata fields may be set
2024-05-24 13:19:40 -07:00
hodlbod
092da0a463 Update 01.md
Co-authored-by: Asai Toshiya <to.asai.60@gmail.com>
2024-05-24 13:19:31 -07:00
P. Reis
ca6dddde80 nip01: mention extra metadata fields may be set 2024-05-24 15:04:45 -03:00
hodlbod
58c1ab2a9b Merge pull request #1252 from aidik/patch-1
NIP-13: Fix of otherwise unverifiable example event
2024-05-24 09:02:19 -07:00
Václav Navrátil
f5be59b052 Fix of otherwise unverifiable event
I'm reverting a change made by @arkin0x in commit: 6fb9e54f7b (diff-cb504c91ef546f76741fb8fd4c13b1f97e4b5ce2a9d78afa545fb6ec799e06c2L39) which renders the example event unverifiable because of a changed hash.
2024-05-24 16:20:25 +02:00
hodlbod
0cb9b60519 Add CIP-01 (#1251)
* Add CIP-01

* Rename cip to nud

---------

Co-authored-by: Jon Staab <shtaab@gmail.com>
2024-05-24 00:31:36 -03:00
Kieran
ec3c417086 Merge pull request #1250 from AsaiToshiya/AsaiToshiya-patch-11
README: add NIP-35 and e tag pubkey
2024-05-22 14:27:23 +01:00
Asai Toshiya
12655c739c Format tags table 2024-05-22 21:28:00 +09:00
Asai Toshiya
744b788427 README: add NIP-35 and e tag pubkey 2024-05-22 21:21:44 +09:00
Kieran
5971aa2fbe Merge pull request #1175 from nostr-protocol/feat/nip35
NIP-35: Torrents
2024-05-22 09:36:56 +01:00
kieran
d68899881c pubkey on e tags 2024-05-20 17:26:56 -03:00
hodlbod
67e870d95a Merge pull request #923 from zmeyer44/patch-1
Create NIP 71 for Video Events
2024-05-20 09:01:52 -07:00
hodlbod
d85c347813 Merge pull request #1245 from AsaiToshiya/AsaiToshiya-patch-10
README: add missing kinds of NIP-54
2024-05-18 07:29:36 -07:00
Asai Toshiya
b151a28fe3 README: add missing kinds of NIP-54 2024-05-18 22:02:14 +09:00
Braydon Fuller
a59ce8970a Fix connection string protocol description. (#1243)
* Fix connection string protocol description.

* Update `nostr+walletconnect` reference.
2024-05-18 04:02:21 +09:00
hodlbod
bff2e9a28a Merge pull request #1239 from AsaiToshiya/AsaiToshiya-patch-9
NIP-24: clarify meaning of "event" for title
2024-05-17 08:00:20 -07:00
Asai Toshiya
7c3fd43736 Merge pull request #1240 from tyiu/tyiu/missing-comma-nip-59
Add missing comma in the example gift wrap JSON for NIP-59
2024-05-17 21:19:33 +09:00
Terry Yiu
1da44a5b71 Add missing comma in the example gift wrap JSON for NIP-59 2024-05-17 08:13:02 -04:00
Asai Toshiya
caee48316f NIP-24: clarify meaning of "event" for title 2024-05-17 19:45:27 +09:00
Jon Staab
734f379a2a Add ontolo to nip 32 2024-05-16 14:46:21 -03:00
Sam Samskies
b1f771302a fix NWC connection string example 2024-05-16 14:45:56 -03:00
kieran
dda408f487 update readme 2024-05-16 15:29:09 +01:00
kieran
f59df9c24f update tag keys 2024-05-16 15:28:08 +01:00
kieran
33d173b1c9 Add comments / make infohash indexed like NIP94 2024-05-16 15:28:07 +01:00
kieran
021a8f5bc7 remove weird char 2024-05-16 15:28:07 +01:00
kieran
824d0b7eac torrents 2024-05-16 15:28:06 +01:00
Asai Toshiya
38ee6511dc BREAKING.md: fix date 2024-05-14 01:17:46 +09:00
hodlbod
a02c3621a9 Merge pull request #1235 from AsaiToshiya/AsaiToshiya-patch-8
BREAKING.md: add NIP-34 change
2024-05-13 05:55:51 -07:00
Asai Toshiya
9f13e76f02 BREAKING.md: add NIP-34 change 2024-05-13 21:11:30 +09:00
hodlbod
0acdf57ab1 Merge pull request #1231 from adamdecaf/nip-90-link-fixes
nip90: fix links
2024-05-11 11:36:22 -07:00
Adam Shannon
c2d9b40d5b nip90: fix links 2024-05-11 12:41:23 -05:00
Vitor Pamplona
69e14f1dca Merge pull request #1230 from adamdecaf/misc-spelling-fixes
all: minor spelling fixes
2024-05-11 13:19:29 -04:00
Adam Shannon
cb9bddb8df all: minor spelling fixes 2024-05-11 11:52:32 -05:00
greenart7c3
ff24a56355 ; -> & 2024-04-29 09:25:04 -03:00
greenart7c3
6ee0648f00 Merge branch 'master' of https://github.com/greenart7c3/nips 2024-04-29 08:56:19 -03:00
greenart7c3
b21e996a89 Change web app methods do use nostrsigner: instead of intent: 2024-04-29 08:55:55 -03:00
greenart7c3
a2aaa3c00b add example of rememberLauncherForActivityResult 2024-03-18 15:10:25 -03:00
greenart7c3
6b26ebe6c5 Update 100.md 2024-03-18 15:01:03 -03:00
greenart7c3
4842f8612f Apply suggestions from code review
Co-authored-by: dluvian <133484344+dluvian@users.noreply.github.com>
2024-03-18 15:00:30 -03:00
greenart7c3
07074d8ba2 Apply suggestions from code review
Co-authored-by: dluvian <133484344+dluvian@users.noreply.github.com>
2024-03-08 09:20:19 -03:00
greenart7c3
bf7294b223 Removed author 2024-03-08 07:59:54 -03:00
greenart7c3
ded4c1659c fix typo 2024-02-14 14:37:42 -03:00
zmeyer44
cc6ac4f0b6 making the format a bit nicer 2024-02-01 11:14:59 +00:00
zmeyer44
49c9f37229 updated read me 2024-02-01 11:12:47 +00:00
greenart7c3
c55678b307 change androidmanifest.xml, add rejected collumn if user chose to always reject some event kind 2024-01-22 11:25:25 -03:00
zmeyer44
54328d8979 Removing "summary" tag
Content in the summary tag is duplicated in the .content field
2023-12-29 17:25:13 -06:00
zmeyer44
f316b219f4 Update 71.md
Co-authored-by: Pablo Fernandez <pfer@me.com>
2023-12-29 14:15:42 -06:00
zmeyer44
8136be6eab Update 71.md
Changed view start and end time to seconds
2023-12-27 08:26:15 -06:00
zmeyer44
2bd3c74002 Update 71.md
Adding segments
2023-12-12 14:01:51 -05:00
zmeyer44
d53f6fba15 Update 71.md
After discussing with Pablo, we decided to move away from relying on kind 1063 events and instead use the majority of the same tags for video events. The main motivations behind this are to allow for parameterized replaceable events for video events, prevent excessive `REQ` requests, not stringify event JSON in the `.content` section, ease of filtering by kind number, as well as some others. Happy to discuss this further.
2023-12-12 13:56:28 -05:00
zmeyer44
c84d40f4a6 Update 71.md
Co-authored-by: Pablo Fernandez <pfer@me.com>
2023-12-12 11:19:57 -05:00
zmeyer44
7afd1049d9 Update and rename 44.md to 71.md
Changing to NIP-71
2023-12-09 17:46:53 -05:00
zmeyer44
cec99e7b13 Update 44.md
Updating to reference NIP-94 file metadata event
2023-12-09 12:55:25 -05:00
zmeyer44
a2914eed6d Update 44.md
Adding some of Vitor's suggestions, differentiating between horizontal and vertical video kinds, changing how views are kept track of, and changing some tag names.
2023-12-08 09:06:14 -05:00
zmeyer44
01035dadf4 Update 44.md
fixing spelling error
2023-12-08 07:22:32 -05:00
zmeyer44
7646386956 Create NIP 44 for Video Events
Nip for video events to enable dedicated video clients (e.g. Netflix, YouTube) to be built on nostr.
2023-12-07 20:09:08 -05:00
greenart7c3
e050386b84 signer can return the application package name when sign in 2023-11-29 11:23:14 -03:00
greenart7c3
70a722b5d6 add permissions 2023-11-29 11:22:26 -03:00
greenart7c3
86e44b75eb Android Signer Application nip 2023-11-08 10:22:43 -03:00
33 changed files with 858 additions and 100 deletions

10
01.md
View File

@@ -77,9 +77,9 @@ This NIP defines 3 standard tags that can be used across all event kinds with th
- The `e` tag, used to refer to an event: `["e", <32-bytes lowercase hex of the id of another event>, <recommended relay URL, optional>]`
- The `p` tag, used to refer to another user: `["p", <32-bytes lowercase hex of a pubkey>, <recommended relay URL, optional>]`
- The `a` tag, used to refer to a (maybe tagged) replaceable event
- for a tagged-replaceable event: `["a", <kind integer>:<32-bytes lowercase hex of a pubkey>:<d tag value>, <recommended relay URL, optional>]`
- for a non-tagged-replaceable event: `["a", <kind integer>:<32-bytes lowercase hex of a pubkey>:, <recommended relay URL, optional>]`
- The `a` tag, used to refer to a (maybe parameterized) replaceable event
- for a parameterized replaceable event: `["a", <kind integer>:<32-bytes lowercase hex of a pubkey>:<d tag value>, <recommended relay URL, optional>]`
- for a non-parameterized replaceable event: `["a", <kind integer>:<32-bytes lowercase hex of a pubkey>:, <recommended relay URL, optional>]`
As a convention, all single-letter (only english alphabet letters: a-z, A-Z) key tags are expected to be indexed by relays, such that it is possible, for example, to query or subscribe to events that reference the event `"5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36"` by using the `{"#e": ["5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36"]}` filter.
@@ -87,7 +87,7 @@ As a convention, all single-letter (only english alphabet letters: a-z, A-Z) key
Kinds specify how clients should interpret the meaning of each event and the other fields of each event (e.g. an `"r"` tag may have a meaning in an event of kind 1 and an entirely different meaning in an event of kind 10002). Each NIP may define the meaning of a set of kinds that weren't defined elsewhere. This NIP defines two basic kinds:
- `0`: **metadata**: the `content` is set to a stringified JSON object `{name: <username>, about: <string>, picture: <url, string>}` describing the user who created the event. A relay may delete older events once it gets a new one for the same pubkey.
- `0`: **metadata**: the `content` is set to a stringified JSON object `{name: <username>, about: <string>, picture: <url, string>}` describing the user who created the event. [Extra metadata fields](24.md#kind-0) may be set. A relay may delete older events once it gets a new one for the same pubkey.
- `1`: **text note**: the `content` is set to the **plaintext** content of a note (anything the user wants to say). Content that must be parsed, such as Markdown and HTML, should not be used. Clients should also not parse content as those.
And also a convention for kind ranges that allow for easier experimentation and flexibility of relay implementation:
@@ -95,7 +95,7 @@ And also a convention for kind ranges that allow for easier experimentation and
- for kind `n` such that `1000 <= n < 10000`, events are **regular**, which means they're all expected to be stored by relays.
- for kind `n` such that `10000 <= n < 20000 || n == 0 || n == 3`, events are **replaceable**, which means that, for each combination of `pubkey` and `kind`, only the latest event MUST be stored by relays, older versions MAY be discarded.
- for kind `n` such that `20000 <= n < 30000`, events are **ephemeral**, which means they are not expected to be stored by relays.
- for kind `n` such that `30000 <= n < 40000`, events are **tagged-replaceable**, which means that, for each combination of `pubkey`, `kind` and the `d` tag's first value, only the latest event MUST be stored by relays, older versions MAY be discarded.
- for kind `n` such that `30000 <= n < 40000`, events are **parameterized replaceable**, which means that, for each combination of `pubkey`, `kind` and the `d` tag's first value, only the latest event MUST be stored by relays, older versions MAY be discarded.
In case of replaceable events with the same timestamp, the event with the lowest id (first in lexical order) should be retained, and the other discarded.

4
02.md
View File

@@ -8,7 +8,9 @@ Follow List
A special event with kind `3`, meaning "follow list" is defined as having a list of `p` tags, one for each of the followed/known profiles one is following.
Each tag entry should contain the key for the profile, a relay URL where events from that key can be found (can be set to an empty string if not needed), and a local name (or "petname") for that profile (can also be set to an empty string or not provided), i.e., `["p", <32-bytes hex key>, <main relay URL>, <petname>]`. The `content` can be anything and should be ignored.
Each tag entry should contain the key for the profile, a relay URL where events from that key can be found (can be set to an empty string if not needed), and a local name (or "petname") for that profile (can also be set to an empty string or not provided), i.e., `["p", <32-bytes hex key>, <main relay URL>, <petname>]`.
The `.content` is not used.
For example:

4
10.md
View File

@@ -38,13 +38,14 @@ They are citing from this event. `root-id` and `reply-id` are as above.
>This scheme is deprecated because it creates ambiguities that are difficult, or impossible to resolve when an event references another but is not a reply.
## Marked "e" tags (PREFERRED)
`["e", <event-id>, <relay-url>, <marker>]`
`["e", <event-id>, <relay-url>, <marker>, <pubkey>]`
Where:
* `<event-id>` is the id of the event being referenced.
* `<relay-url>` is the URL of a recommended relay associated with the reference. Clients SHOULD add a valid `<relay-URL>` field, but may instead leave it as `""`.
* `<marker>` is optional and if present is one of `"reply"`, `"root"`, or `"mention"`.
* `<pubkey>` is optional, SHOULD be the pubkey of the author of the referenced event
Those marked with `"reply"` denote the id of the reply event being responded to. Those marked with `"root"` denote the root id of the reply thread being responded to. For top level replies (those replying directly to the root event), only the `"root"` marker should be used. Those marked with `"mention"` denote a quoted or reposted event id.
@@ -52,6 +53,7 @@ A direct reply to the root of a thread should have a single marked "e" tag of ty
>This scheme is preferred because it allows events to mention others without confusing them with `<reply-id>` or `<root-id>`.
`<pubkey>` SHOULD be the pubkey of the author of the `e` tagged event, this is used in the outbox model to search for that event from the authors write relays where relay hints did not resolve the event.
## The "p" tag
Used in a text event contains a list of pubkeys used to record who is involved in a reply thread.

538
100.md Normal file
View File

@@ -0,0 +1,538 @@
# NIP-100
## Android Signer Application
`draft` `optional`
This NIP describes a method for 2-way communication between an Android signer and any Nostr client on Android. The Android signer is an Android Application and the client can be a web client or an Android application.
# Usage for Android applications
The Android signer uses Intents and Content Resolvers to communicate between applications.
To be able to use the Android signer in your application you should add this to your AndroidManifest.xml:
```xml
<queries>
<intent>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="nostrsigner" />
</intent>
</queries>
```
Then you can use this function to check if there's a signer application installed:
```kotlin
fun isExternalSignerInstalled(context: Context): Boolean {
val intent =
Intent().apply {
action = Intent.ACTION_VIEW
data = Uri.parse("nostrsigner:")
}
val infos = context.packageManager.queryIntentActivities(intent, 0)
return infos.size > 0
}
```
## Using Intents
To get the result back from the Signer Application you should use `registerForActivityResult` or `rememberLauncherForActivityResult` in Kotlin. If you are using another framework check the documentation of your framework or a third party library to get the result.
```kotlin
val launcher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartActivityForResult(),
onResult = { result ->
if (result.resultCode != Activity.RESULT_OK) {
Toast.makeText(
context,
"Sign request rejected",
Toast.LENGTH_SHORT
).show()
} else {
val signature = activityResult.data?.getStringExtra("signature")
// Do something with signature ...
}
}
)
```
Create the Intent using the **nostrsigner** scheme:
```kotlin
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("nostrsigner:$content"))
```
Set the Signer package name:
```kotlin
intent.`package` = "com.example.signer"
```
Send the Intent:
```kotlin
launcher.launch(intent)
```
### Methods
- **get_public_key**
- params:
```kotlin
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("nostrsigner:"))
intent.`package` = "com.example.signer"
intent.putExtra("type", "get_public_key")
// You can send some default permissions for the user to authorize for ever
val permissions = listOf(
Permission(
type = "sign_event",
kind = 22242
),
Permission(
type = "nip44_decrypt"
)
)
intent.putExtra("permissions", permissions.toJson())
context.startActivity(intent)
```
- result:
- If the user approved intent it will return the **npub** in the signature field
```kotlin
val npub = intent.data?.getStringExtra("signature")
// The package name of the signer application
val packageName = intent.data?.getStringExtra("package")
```
- **sign_event**
- params:
```kotlin
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("nostrsigner:$eventJson"))
intent.`package` = "com.example.signer"
intent.putExtra("type", "sign_event")
// To handle results when not waiting between intents
intent.putExtra("id", event.id)
// Send the current logged in user npub
intent.putExtra("current_user", npub)
context.startActivity(intent)
```
- result:
- If the user approved intent it will return the **signature**, **id** and **event** fields
```kotlin
val signature = intent.data?.getStringExtra("signature")
// The id you sent
val id = intent.data?.getStringExtra("id")
val signedEventJson = intent.data?.getStringExtra("event")
```
- **nip04_encrypt**
- params:
```kotlin
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("nostrsigner:$plaintext"))
intent.`package` = "com.example.signer"
intent.putExtra("type", "nip04_encrypt")
// to control the result in your application in case you are not waiting the result before sending another intent
intent.putExtra("id", "some_id")
// Send the current logged in user npub
intent.putExtra("current_user", account.keyPair.pubKey.toNpub())
// Send the hex pubKey that will be used for encrypting the data
intent.putExtra("pubKey", pubKey)
context.startActivity(intent)
```
- result:
- If the user approved intent it will return the **signature** and **id** fields
```kotlin
val encryptedText = intent.data?.getStringExtra("signature")
// the id you sent
val id = intent.data?.getStringExtra("id")
```
- **nip44_encrypt**
- params:
```kotlin
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("nostrsigner:$plaintext"))
intent.`package` = "com.example.signer"
intent.putExtra("type", "nip44_encrypt")
// to control the result in your application in case you are not waiting the result before sending another intent
intent.putExtra("id", "some_id")
// Send the current logged in user npub
intent.putExtra("current_user", account.keyPair.pubKey.toNpub())
// Send the hex pubKey that will be used for encrypting the data
intent.putExtra("pubKey", pubKey)
context.startActivity(intent)
```
- result:
- If the user approved intent it will return the **signature** and **id** fields
```kotlin
val encryptedText = intent.data?.getStringExtra("signature")
// the id you sent
val id = intent.data?.getStringExtra("id")
```
- **nip04_decrypt**
- params:
```kotlin
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("nostrsigner:$encryptedText"))
intent.`package` = "com.example.signer"
intent.putExtra("type", "nip04_decrypt")
// to control the result in your application in case you are not waiting the result before sending another intent
intent.putExtra("id", "some_id")
// Send the current logged in user npub
intent.putExtra("current_user", account.keyPair.pubKey.toNpub())
// Send the hex pubKey that will be used for decrypting the data
intent.putExtra("pubKey", pubKey)
context.startActivity(intent)
```
- result:
- If the user approved intent it will return the **signature** and **id** fields
```kotlin
val plainText = intent.data?.getStringExtra("signature")
// the id you sent
val id = intent.data?.getStringExtra("id")
```
- **nip44_decrypt**
- params:
```kotlin
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("nostrsigner:$encryptedText"))
intent.`package` = "com.example.signer"
intent.putExtra("type", "nip04_decrypt")
// to control the result in your application in case you are not waiting the result before sending another intent
intent.putExtra("id", "some_id")
// Send the current logged in user npub
intent.putExtra("current_user", account.keyPair.pubKey.toNpub())
// Send the hex pubKey that will be used for decrypting the data
intent.putExtra("pubKey", pubKey)
context.startActivity(intent)
```
- result:
- If the user approved intent it will return the **signature** and **id** fields
```kotlin
val plainText = intent.data?.getStringExtra("signature")
// the id you sent
val id = intent.data?.getStringExtra("id")
```
- **decrypt_zap_event**
- params:
```kotlin
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("nostrsigner:$eventJson"))
intent.`package` = "com.example.signer"
intent.putExtra("type", "decrypt_zap_event")
// to control the result in your application in case you are not waiting the result before sending another intent
intent.putExtra("id", "some_id")
// Send the current logged in user npub
intent.putExtra("current_user", account.keyPair.pubKey.toNpub())
context.startActivity(intent)
```
- result:
- If the user approved intent it will return the **signature** and **id** fields
```kotlin
val eventJson = intent.data?.getStringExtra("signature")
// the id you sent
val id = intent.data?.getStringExtra("id")
```
## Using Content Resolver
To get the result back from Signer Application you should use contentResolver.query in Kotlin. If you are using another framework check the documentation of your framework or a third party library to get the result.
If the user did not check the "remember my choice" option, the npub is not in Signer Application or the signer type is not recognized the `contentResolver` will return null
For the SIGN_EVENT type Signer Application returns two columns "signature" and "event". The column event is the signed event json
For the other types Signer Application returns the column "signature"
If the user chose to always reject the event, signer application will return the column "rejected" and you should not open signer application
### Methods
- **get_public_key**
- params:
```kotlin
val result = context.contentResolver.query(
Uri.parse("content://com.example.signer.GET_PUBLIC_KEY"),
listOf("login"),
null,
null,
null
)
```
- result:
- Will return the **npub** in the signature column
```kotlin
if (result == null) return
if (result.moveToFirst()) {
val index = it.getColumnIndex("signature")
if (index < 0) return
val npub = it.getString(index)
}
```
- **sign_event**
- params:
```kotlin
val result = context.contentResolver.query(
Uri.parse("content://com.example.signer.SIGN_EVENT"),
listOf("$eventJson", "", "${logged_in_user_npub}"),
null,
null,
null
)
```
- result:
- Will return the **signature** and the **event** columns
```kotlin
if (result == null) return
if (result.moveToFirst()) {
val index = it.getColumnIndex("signature")
val indexJson = it.getColumnIndex("event")
val signature = it.getString(index)
val eventJson = it.getString(indexJson)
}
```
- **nip04_encrypt**
- params:
```kotlin
val result = context.contentResolver.query(
Uri.parse("content://com.example.signer.NIP04_ENCRYPT"),
listOf("$plainText", "${hex_pub_key}", "${logged_in_user_npub}"),
null,
null,
null
)
```
- result:
- Will return the **signature** column
```kotlin
if (result == null) return
if (result.moveToFirst()) {
val index = it.getColumnIndex("signature")
val encryptedText = it.getString(index)
}
```
- **nip44_encrypt**
- params:
```kotlin
val result = context.contentResolver.query(
Uri.parse("content://com.example.signer.NIP44_ENCRYPT"),
listOf("$plainText", "${hex_pub_key}", "${logged_in_user_npub}"),
null,
null,
null
)
```
- result:
- Will return the **signature** column
```kotlin
if (result == null) return
if (result.moveToFirst()) {
val index = it.getColumnIndex("signature")
val encryptedText = it.getString(index)
}
```
- **nip04_decrypt**
- params:
```kotlin
val result = context.contentResolver.query(
Uri.parse("content://com.example.signer.NIP04_DECRYPT"),
listOf("$encryptedText", "${hex_pub_key}", "${logged_in_user_npub}"),
null,
null,
null
)
```
- result:
- Will return the **signature** column
```kotlin
if (result == null) return
if (result.moveToFirst()) {
val index = it.getColumnIndex("signature")
val encryptedText = it.getString(index)
}
```
- **nip44_decrypt**
- params:
```kotlin
val result = context.contentResolver.query(
Uri.parse("content://com.example.signer.NIP44_DECRYPT"),
listOf("$encryptedText", "${hex_pub_key}", "${logged_in_user_npub}"),
null,
null,
null
)
```
- result:
- Will return the **signature** column
```kotlin
if (result == null) return
if (result.moveToFirst()) {
val index = it.getColumnIndex("signature")
val encryptedText = it.getString(index)
}
```
- **decrypt_zap_event**
- params:
```kotlin
val result = context.contentResolver.query(
Uri.parse("content://com.example.signer.DECRYPT_ZAP_EVENT"),
listOf("$eventJson", "", "${logged_in_user_npub}"),
null,
null,
null
)
```
- result:
- Will return the **signature** column
```kotlin
if (result == null) return
if (result.moveToFirst()) {
val index = it.getColumnIndex("signature")
val eventJson = it.getString(index)
}
```
# Usage for Web Applications
Since web applications can't receive a result from the intent, you should add a modal to paste the signature or the event json or create a callback url.
If you send the callback url parameter, Signer Application will send the result to the url.
If you don't send a callback url, Signer Application will copy the result to the clipboard.
You can configure the `returnType` to be **signature** or **event**.
Android intents and browser urls have limitations, so if you are using the `returnType` of **event** consider using the parameter **compressionType=gzip** that will return "Signer1" + Base64 gzip encoded event json
## Methods
- **get_public_key**
- params:
```js
window.href = `nostrsigner:?compressionType=none&returnType=signature&type=get_public_key&callbackUrl=https://example.com/?event=`;
```
- **sign_event**
- params:
```js
window.href = `nostrsigner:${eventJson}?compressionType=none&returnType=signature&type=sign_event&callbackUrl=https://example.com/?event=`;
```
- **nip04_encrypt**
- params:
```js
window.href = `nostrsigner:${plainText}?pubKey=${hex_pub_key}&compressionType=none&returnType=signature&type=nip04_encrypt&callbackUrl=https://example.com/?event=`;
```
- **nip44_encrypt**
- params:
```js
window.href = `nostrsigner:${plainText}?pubKey=${hex_pub_key}&compressionType=none&returnType=signature&type=nip44_encrypt&callbackUrl=https://example.com/?event=`;
```
- **nip04_decrypt**
- params:
```js
window.href = `nostrsigner:${encryptedText}?pubKey=${hex_pub_key}&compressionType=none&returnType=signature&type=nip04_decrypt&callbackUrl=https://example.com/?event=`;
```
- **nip44_decrypt**
- params:
```js
window.href = `nostrsigner:${encryptedText}?pubKey=${hex_pub_key}&compressionType=none&returnType=signature&type=nip44_decrypt&callbackUrl=https://example.com/?event=`;
```
- **decrypt_zap_event**
- params:
```js
window.href = `nostrsigner:${eventJson}?compressionType=none&returnType=signature&type=decrypt_zap_event&callbackUrl=https://example.com/?event=`;
```
## Example
```js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>Test</h1>
<script>
window.onload = function() {
var url = new URL(window.location.href);
var params = url.searchParams;
if (params) {
var param1 = params.get("event");
if (param1) alert(param1)
}
let json = {
kind: 1,
content: "test"
}
let encodedJson = encodeURIComponent(JSON.stringify(json))
var newAnchor = document.createElement("a");
newAnchor.href = `nostrsigner:${encodedJson}?compressionType=none&returnType=signature&type=sign_event&callbackUrl=https://example.com/?event=`;
newAnchor.textContent = "Open External Signer";
document.body.appendChild(newAnchor)
}
</script>
</body>
</html>
```

2
13.md
View File

@@ -35,7 +35,7 @@ Example mined note
"created_at": 1651794653,
"kind": 1,
"tags": [
["nonce", "776797", "21"]
["nonce", "776797", "20"]
],
"content": "It's just me mining my own business",
"sig": "284622fc0a3f4f1303455d5175f7ba962a3300d136085b9566801bc2e0699de0c7e31e44c81fb40ad9049173742e904713c3594a1da0fc5d2382a25c11aba977"

2
15.md
View File

@@ -300,7 +300,7 @@ This event leverages naddr to enable comprehensive customization and sharing of
Bids are simply events of kind `1021` with a `content` field specifying the amount, in the currency of the auction. Bids must reference an auction.
> [!NOTE]
> Auctions can be edited as many times as desired (they are "tagged-replaceable events") by the author - even after the start_date, but they cannot be edited after they have received the first bid! This is enforced by the fact that bids reference the event ID of the auction (rather than the product UUID), which changes with every new version of the auctioned product. So a bid is always attached to one "version". Editing the auction after a bid would result in the new product losing the bid!
> Auctions can be edited as many times as desired (they are "parameterized replaceable events") by the author - even after the start_date, but they cannot be edited after they have received the first bid! This is enforced by the fact that bids reference the event ID of the auction (rather than the product UUID), which changes with every new version of the auctioned product. So a bid is always attached to one "version". Editing the auction after a bid would result in the new product losing the bid!
### Event `1022`: Bid confirmation

2
19.md
View File

@@ -44,7 +44,7 @@ These possible standardized `TLV` types are indicated here:
- for `nprofile` it will be the 32 bytes of the profile public key
- for `nevent` it will be the 32 bytes of the event id
- for `nrelay`, this is the relay URL
- for `naddr`, it is the identifier (the `"d"` tag) of the event being referenced. For non-tagged-replaceable events, use an empty string.
- for `naddr`, it is the identifier (the `"d"` tag) of the event being referenced. For non-parameterized replaceable events, use an empty string.
- `1`: `relay`
- for `nprofile`, `nevent` and `naddr`, _optionally_, a relay in which the entity (profile or event) is more likely to be found, encoded as ascii
- this may be included multiple times

4
23.md
View File

@@ -6,7 +6,7 @@ Long-form Content
`draft` `optional`
This NIP defines `kind:30023` (a _tagged-replaceable event_) for long-form text content, generally referred to as "articles" or "blog posts". `kind:30024` has the same structure as `kind:30023` and is used to save long form drafts.
This NIP defines `kind:30023` (a _parameterized replaceable event_) for long-form text content, generally referred to as "articles" or "blog posts". `kind:30024` has the same structure as `kind:30023` and is used to save long form drafts.
"Social" clients that deal primarily with `kind:1` notes should not be expected to implement this NIP.
@@ -31,7 +31,7 @@ Other metadata fields can be added as tags to the event as necessary. Here we st
### Editability
These articles are meant to be editable, so they should make use of the tagged replaceability feature and include a `d` tag with an identifier for the article. Clients should take care to only publish and read these events from relays that implement that. If they don't do that they should also take care to hide old versions of the same article they may receive.
These articles are meant to be editable, so they should make use of the parameterized replaceability feature and include a `d` tag with an identifier for the article. Clients should take care to only publish and read these events from relays that implement that. If they don't do that they should also take care to hide old versions of the same article they may receive.
### Linking

2
24.md
View File

@@ -40,4 +40,4 @@ tags
These tags may be present in multiple event kinds. Whenever a different meaning is not specified by some more specific NIP, they have the following meanings:
- `r`: a web URL the event is referring to in some way
- `title`: title of the event
- `title`: name of [NIP-51](51.md) sets, [NIP-52](52.md) calendar event, [NIP-53](53.md) live event or [NIP-99](99.md) listing

3
25.md
View File

@@ -67,8 +67,7 @@ content as an emoji if shortcode is specified.
"tags": [
["emoji", "soapbox", "https://gleasonator.com/emoji/Gleasonator/soapbox.png"]
],
"pubkey": "79c2cae114ea28a981e7559b4fe7854a473521a8d22a66bbab9fa248eb820ff6",
"created_at": 1682790000
...other fields
}
```

2
29.md
View File

@@ -16,7 +16,7 @@ Normally a group will originally belong to one specific relay, but the community
## Relay-generated events
Relays are supposed to generate the events that describe group metadata and group admins. These are tagged-replaceable events signed by the relay keypair directly, with the group _id_ as the `d` tag.
Relays are supposed to generate the events that describe group metadata and group admins. These are parameterized replaceable events signed by the relay keypair directly, with the group _id_ as the `d` tag.
## Group identifier

8
32.md
View File

@@ -151,3 +151,11 @@ A good heuristic for whether a use case fits this NIP is whether labels would ev
For example, many events might be labeled with a particular place, topic, or pubkey, but labels
with specific values like "John Doe" or "3.18743" are not labels, they are values, and should
be handled in some other way.
Appendix: Known Ontologies
-------------------------
Below is a non-exhaustive list of ontologies currently in widespread use.
- (social.ontolo.categories)[https://ontolo.social/]

4
33.md
View File

@@ -1,8 +1,8 @@
NIP-33
======
Tagged Replaceable Events
-------------------------
Parameterized Replaceable Events
--------------------------------
`final` `mandatory`

2
34.md
View File

@@ -125,7 +125,7 @@ Root Patches and Issues have a Status that defaults to 'Open' and can be set by
["p", "<root-event-author>"],
["p", "<revision-author>"],
// optional for improved subscription filter efficency
// optional for improved subscription filter efficiency
["a", "30617:<base-repo-owner-pubkey>:<base-repo-id>", "<relay-url>"],
["r", "<earliest-unique-commit-id-of-repo>"]

70
35.md Normal file
View File

@@ -0,0 +1,70 @@
NIP-35
======
Torrents
-----------
`draft` `optional`
This NIP defined a new `kind 2003` which is a Torrent.
`kind 2003` is a simple torrent index where there is enough information to search for content and construct the magnet link. No torrent files exist on nostr.
## Tags
- `x`: V1 BitTorrent Info Hash, as seen in the [magnet link](https://www.bittorrent.org/beps/bep_0053.html) `magnet:?xt=urn:btih:HASH`
- `file`: A file entry inside the torrent, including the full path ie. `info/example.txt`
- `tracker`: (Optional) A tracker to use for this torrent
In order to make torrents searchable by general category, you SHOULD include a few tags like `movie`, `tv`, `HD`, `UHD` etc.
## Tag prefixes
Tag prefixes are used to label the content with references, ie. `["i", "imdb:1234"]`
- `tcat`: A comma separated text category path, ie. `["i", "tcat:video,movie,4k"]`, this should also match the `newznab` category in a best effort approach.
- `newznab`: The category ID from [newznab](https://github.com/Prowlarr/Prowlarr/blob/develop/src/NzbDrone.Core/Indexers/NewznabStandardCategory.cs)
- `tmdb`: [The movie database](https://www.themoviedb.org/) id.
- `ttvdb`: [TV database](https://thetvdb.com/) id.
- `imdb`: [IMDB](https://www.imdb.com/) id.
- `mal`: [MyAnimeList](https://myanimelist.net/) id.
- `anilist`: [AniList](https://anilist.co/) id.
A second level prefix should be included where the database supports multiple media types.
- `tmdb:movie:693134` maps to `themoviedb.org/movie/693134`
- `ttvdb:movie:290272` maps to `thetvdb.com/movies/dune-part-two`
- `mal:anime:9253` maps to `myanimelist.net/anime/9253`
- `mal:manga:17517` maps to `myanimelist.net/manga/17517`
In some cases the url mapping isnt direct, mapping the url in general is out of scope for this NIP, the section above is only a guide so that implementers have enough information to succsesfully map the url if they wish.
```jsonc
{
"kind": 2003,
"content": "<long-description-pre-formatted>",
"tags": [
["title", "<torrent-title>"],
["x", "<bittorrent-info-hash>"],
["file", "<file-name>", "<file-size-in-bytes>"],
["file", "<file-name>", "<file-size-in-bytes>"],
["tracker", "udp://mytacker.com:1337"],
["tracker", "http://1337-tracker.net/announce"],
["i", "tcat:video,movie,4k"],
["i", "newznab:2045"],
["i", "imdb:tt15239678"],
["i", "tmdb:movie:693134"],
["i", "ttvdb:movie:290272"],
["t", "movie"],
["t", "4k"],
]
}
```
## Torrent Comments
A torrent comment is a `kind 2004` event which is used to reply to a torrent event.
This event works exactly like a `kind 1` and should follow `NIP-10` for tagging.
## Implementations
1. [dtan.xyz](https://git.v0l.io/Kieran/dtan)
2. [nostrudel.ninja](https://github.com/hzrd149/nostrudel/tree/next/src/views/torrents)

8
38.md
View File

@@ -13,7 +13,7 @@ This NIP enables a way for users to share live statuses such as what music they
## Live Statuses
A special event with `kind:30315` "User Status" is defined as an *optionally expiring* _tagged-replaceable event_, where the `d` tag represents the status type:
A special event with `kind:30315` "User Status" is defined as an *optionally expiring* _parameterized replaceable event_, where the `d` tag represents the status type:
For example:
@@ -44,7 +44,9 @@ Two common status types are defined: `general` and `music`. `general` represent
Any other status types can be used but they are not defined by this NIP.
The status MAY include an `r`, `p`, `e` or `a` tag linking to a URL, profile, note, or tagged-replaceable event.
The status MAY include an `r`, `p`, `e` or `a` tag linking to a URL, profile, note, or parameterized replaceable event.
The `content` MAY include emoji(s), or [NIP-30](30.md) custom emoji(s). If the `content` is an empty string then the client should clear the status.
# Client behavior
@@ -57,5 +59,3 @@ Clients MAY display this next to the username on posts or profiles to provide li
* Nostr music streaming services that update your music status when you're listening
* Podcasting apps that update your music status when you're listening to a podcast, with a link for others to listen as well
* Clients can use the system media player to update playing music status
The `content` MAY include emoji(s), or [NIP-30](30.md) custom emoji(s). If the `content` is an empty string then the client should clear the status.

2
46.md
View File

@@ -208,7 +208,7 @@ When the user types a NIP-05 the client:
#### Remote signer discovery via NIP-89
In this last case, most often used to fascilitate an OAuth-like signin flow, the client first looks for remote signers that have announced themselves via NIP-89 application handler events.
In this last case, most often used to facilitate an OAuth-like signin flow, the client first looks for remote signers that have announced themselves via NIP-89 application handler events.
First the client will query for `kind: 31990` events that have a `k` tag of `24133`.

6
47.md
View File

@@ -81,7 +81,7 @@ If the command was successful, the `error` field must be null.
## Nostr Wallet Connect URI
**client** discovers **wallet service** by scanning a QR code, handling a deeplink or pasting in a URI.
The **wallet service** generates this connection URI with protocol `nostr+walletconnect:` and base path it's hex-encoded `pubkey` with the following query string parameters:
The **wallet service** generates this connection URI with protocol `nostr+walletconnect://` and base path it's hex-encoded `pubkey` with the following query string parameters:
- `relay` Required. URL of the relay where the **wallet service** is connected and will be listening for events. May be more than one.
- `secret` Required. 32-byte randomly generated hex encoded string. The **client** MUST use this to sign events and encrypt payloads when communicating with the **wallet service**.
@@ -95,7 +95,7 @@ The **client** should then store this connection and use it when the user wants
### Example connection string
```sh
nostr+walletconnect:b889ff5b1513b641e2a139f661a661364979c5beee91842f8f0ef42ab558e9d4?relay=wss%3A%2F%2Frelay.damus.io&secret=71a8c14c1407c113601079c4302dab36460f0ccd0ad506f1f2dc73b5100e4f3c
nostr+walletconnect://b889ff5b1513b641e2a139f661a661364979c5beee91842f8f0ef42ab558e9d4?relay=wss%3A%2F%2Frelay.damus.io&secret=71a8c14c1407c113601079c4302dab36460f0ccd0ad506f1f2dc73b5100e4f3c
```
## Commands
@@ -402,7 +402,7 @@ Response:
## Example pay invoice flow
0. The user scans the QR code generated by the **wallet service** with their **client** application, they follow a `nostr+walletconnect:` deeplink or configure the connection details manually.
0. The user scans the QR code generated by the **wallet service** with their **client** application, they follow a `nostr+walletconnect://` deeplink or configure the connection details manually.
1. **client** sends an event to the **wallet service** with kind `23194`. The content is a `pay_invoice` request. The private key is the secret from the connection string above.
2. **wallet service** verifies that the author's key is authorized to perform the payment, decrypts the payload and sends the payment.
3. **wallet service** responds to the event by sending an event with kind `23195` and content being a response either containing an error message or a preimage.

2
51.md
View File

@@ -16,7 +16,7 @@ When new items are added to an existing list, clients SHOULD append them to the
## Standard lists
Standard lists use non-tagged-replaceable events, meaning users may only have a single list of each kind. They have special meaning and clients may rely on them to augment a user's profile or browsing experience.
Standard lists use non-parameterized replaceable events, meaning users may only have a single list of each kind. They have special meaning and clients may rely on them to augment a user's profile or browsing experience.
For example, _mute list_ can contain the public keys of spammers and bad actors users don't want to see in their feeds or receive annoying notifications from.

8
52.md
View File

@@ -6,7 +6,7 @@ Calendar Events
`draft` `optional`
This specification defines calendar events representing an occurrence at a specific moment or between moments. These calendar events are _tagged-replaceable_ and deletable per [NIP-09](09.md).
This specification defines calendar events representing an occurrence at a specific moment or between moments. These calendar events are _parameterized replaceable_ and deletable per [NIP-09](09.md).
Unlike the term `calendar event` specific to this NIP, the term `event` is used broadly in all the NIPs to describe any Nostr event. The distinction is being made here to discern between the two terms.
@@ -20,7 +20,7 @@ This kind of calendar event starts on a date and ends before a different date in
#### Format
The format uses a tagged-replaceable event kind `31922`.
The format uses a parameterized replaceable event kind `31922`.
The `.content` of these events should be a detailed description of the calendar event. It is required but can be an empty string.
@@ -79,7 +79,7 @@ This kind of calendar event spans between a start time and end time.
#### Format
The format uses a tagged-replaceable event kind `31923`.
The format uses a parameterized replaceable event kind `31923`.
The `.content` of these events should be a detailed description of the calendar event. It is required but can be an empty string.
@@ -180,7 +180,7 @@ This NIP is also intentionally not defining what happens if a calendar event cha
### Format
The format uses a tagged-replaceable event kind `31925`.
The format uses a parameterized replaceable event kind `31925`.
The `.content` of these events is optional and should be a free-form note that adds more context to this calendar event response.

4
53.md
View File

@@ -12,7 +12,7 @@ Service providers want to offer live activities to the Nostr network in such a w
### Live Event
A special event with `kind:30311` "Live Event" is defined as a _tagged-replaceable event_ of public `p` tags. Each `p` tag SHOULD have a **displayable** marker name for the current role (e.g. `Host`, `Speaker`, `Participant`) of the user in the event and the relay information MAY be empty. This event will be constantly updated as participants join and leave the activity.
A special event with `kind:30311` "Live Event" is defined as a _parameterized replaceable event_ of public `p` tags. Each `p` tag SHOULD have a **displayable** marker name for the current role (e.g. `Host`, `Speaker`, `Participant`) of the user in the event and the relay information MAY be empty. This event will be constantly updated as participants join and leave the activity.
For example:
@@ -77,7 +77,7 @@ Event `kind:1311` is live chat's channel message. Clients MUST include the `a` t
## Use Cases
Common use cases include meeting rooms/workshops, watch-together activities, or event spaces, such as [live.snort.social](https://live.snort.social) and [nostrnests.com](https://nostrnests.com).
Common use cases include meeting rooms/workshops, watch-together activities, or event spaces, such as [zap.stream](https://zap.stream).
## Example

9
54.md
View File

@@ -6,7 +6,7 @@ Wiki
`draft` `optional`
This NIP defines `kind:30818` (a _tagged-replaceable event_) for long-form text content similar to [NIP-23](23.md), but with one important difference: articles are meant to be descriptions, or encyclopedia entries, of particular subjects, and it's expected that multiple people will write articles about the exact same subjects, with either small variations or completely independent content.
This NIP defines `kind:30818` (a _parameterized replaceable event_) for long-form text content similar to [NIP-23](23.md), but with one important difference: articles are meant to be descriptions, or encyclopedia entries, of particular subjects, and it's expected that multiple people will write articles about the exact same subjects, with either small variations or completely independent content.
Articles are identified by lowercase, normalized ascii `d` tags.
@@ -36,6 +36,11 @@ The content should be Markdown, following the same rules as of [NIP-23](23.md),
One extra functionality is added: **wikilinks**. Unlike normal Markdown links `[]()` that link to webpages, wikilinks `[[]]` link to other articles in the wiki. In this case, the wiki is the entirety of Nostr. Clicking on a wikilink should cause the client to ask relays for events with `d` tags equal to the target of that wikilink.
Wikilinks can take these two forms:
1. `[[Target Page]]` -- in this case it will link to the page `target-page` (according to `d` tag normalization rules above) and be displayed as `Target Page`;
2. `[[target page|see this]]` -- in this case it will link to the page `target-page`, but will be displayed as `see this`.
### Merge Requests
Event `kind:818` represents a request to merge from a forked article into the source. It is directed to a pubkey and references the original article and the modified event.
@@ -79,7 +84,7 @@ Wiki-events can tag other wiki-events with a `defer` marker to indicate that it
This is a stronger signal of trust than a `+` reaction.
This marker is useful when a user edits someone else's entry; if the original author includes the editor's changes and the editor doesn't want to keep/maintain an indepedent version, the `link` tag could effectively be a considered a "deletion" of the editor's version and putting that pubkey's WoT weight behind the original author's version.
This marker is useful when a user edits someone else's entry; if the original author includes the editor's changes and the editor doesn't want to keep/maintain an independent version, the `link` tag could effectively be a considered a "deletion" of the editor's version and putting that pubkey's WoT weight behind the original author's version.
Why Markdown?
-------------

2
57.md
View File

@@ -36,7 +36,7 @@ A `zap request` is an event of kind `9734` that is _not_ published to relays, bu
In addition, the event MAY include the following tags:
- `e` is an optional hex-encoded event id. Clients MUST include this if zapping an event rather than a person.
- `a` is an optional event coordinate that allows tipping tagged-replaceable events such as NIP-23 long-form notes.
- `a` is an optional event coordinate that allows tipping parameterized replaceable events such as NIP-23 long-form notes.
Example:

4
58.md
View File

@@ -9,11 +9,11 @@ Badges
Three special events are used to define, award and display badges in
user profiles:
1. A "Badge Definition" event is defined as a tagged-replaceable event with kind `30009` having a `d` tag with a value that uniquely identifies the badge (e.g. `bravery`) published by the badge issuer. Badge definitions can be updated.
1. A "Badge Definition" event is defined as a parameterized replaceable event with kind `30009` having a `d` tag with a value that uniquely identifies the badge (e.g. `bravery`) published by the badge issuer. Badge definitions can be updated.
2. A "Badge Award" event is a kind `8` event with a single `a` tag referencing a "Badge Definition" event and one or more `p` tags, one for each pubkey the badge issuer wishes to award. Awarded badges are immutable and non-transferrable.
3. A "Profile Badges" event is defined as a tagged-replaceable event
3. A "Profile Badges" event is defined as a parameterized replaceable event
with kind `30008` with a `d` tag with the value `profile_badges`.
Profile badges contain an ordered list of pairs of `a` and `e` tags referencing a `Badge Definition` and a `Badge Award` for each badge to be displayed.

2
59.md
View File

@@ -155,7 +155,7 @@ Sign the `gift wrap` using the random key generated in the previous step.
"created_at": 1703021488,
"pubkey": "18b1a75918f1f2c90c23da616bce317d36e348bcf5f7ba55e75949319210c87c",
"id": "5c005f3ccf01950aa8d131203248544fb1e41a0d698e846bd419cec3890903ac",
"sig": "35fabdae4634eb630880a1896a886e40fd6ea8a60958e30b89b33a93e6235df750097b04f9e13053764251b8bc5dd7e8e0794a3426a90b6bcc7e5ff660f54259"
"sig": "35fabdae4634eb630880a1896a886e40fd6ea8a60958e30b89b33a93e6235df750097b04f9e13053764251b8bc5dd7e8e0794a3426a90b6bcc7e5ff660f54259",
"tags": [["p", "166bf3765ebd1fc55decfe395beff2ea3b2a4e0a8946e7eb578512b555737c99"]],
}
```

118
71.md Normal file
View File

@@ -0,0 +1,118 @@
NIP-71
======
Video Events
---------------
`draft` `optional`
This specification defines video events representing a dedicated post of externally hosted content. These video events are _parameterized replaceable_ and deletable per [NIP-09](09.md).
Unlike a `kind 1` event with a video attached, Video Events are meant to contain all additional metadata concerning the subject media and to be surfaced in video-specific clients rather than general micro-blogging clients. The thought is for events of this kind to be referenced in a Netflix, YouTube, or TikTok like nostr client where the video itself is at the center of the experience.
## Video Events
There are two types of video events represented by different kinds: horizontal and vertical video events. This is meant to allow clients to cater to each as the viewing experience for horizontal (landscape) videos is often different than that of vertical (portrait) videos (Stories, Reels, Shorts, etc).
#### Format
The format uses a parameterized replaceable event kind `34235` for horizontal videos and `34236` for vertical videos.
The `.content` of these events is a summary or description on the video content.
The list of tags are as follows:
* `d` (required) universally unique identifier (UUID). Generated by the client creating the video event.
* `url` (required) the url to the video file
* `m` a string indicating the data type of the file. The [MIME types](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types) format must be used, and they should be lowercase.
* `title` (required) title of the video
* `"published_at"`, for the timestamp in unix seconds (stringified) of the first time the video was published
* `x` containing the SHA-256 hexencoded string of the file.
* `size` (optional) size of file in bytes
* `dim` (optional) size of file in pixels in the form `<width>x<height>`
* `duration` (optional) video duration in seconds
* `magnet` (optional) URI to magnet file
* `i` (optional) torrent infohash
* `text-track` (optional, repeated) link to WebVTT file for video, type of supplementary information (captions/subtitles/chapters/metadata), optional language code
* `thumb` (optional) url of thumbnail with same aspect ratio
* `image` (optional) url of preview image with same dimensions
* `content-warning` (optional) warning about content of NSFW video
* `alt` (optional) description for accessibility
* `segment` (optional, repeated) start timestamp in format `HH:MM:SS.sss`, end timestamp in format `HH:MM:SS.sss`, chapter/segment title, chapter thumbnail-url
* `t` (optional, repeated) hashtag to categorize video
* `p` (optional, repeated) 32-bytes hex pubkey of a participant in the video, optional recommended relay URL
* `r` (optional, repeated) references / links to web pages
```json
{
"id": <32-bytes lowercase hex-encoded SHA-256 of the the serialized event data>,
"pubkey": <32-bytes lowercase hex-encoded public key of the event creator>,
"created_at": <Unix timestamp in seconds>,
"kind": 34235 | 34236,
"content": "<summary / description of video>",
"tags": [
["d", "<UUID>"],
["title", "<title of video>"],
["thumb", "<thumbnail image for video>"],
["published_at", "<unix timestamp>"],
["alt", <description>],
// Video Data
["url",<string with URI of file>],
["m", <MIME type>],
["x",<Hash SHA-256>],
["size", <size of file in bytes>],
["duration", <duration of video in seconds>],
["dim", <size of file in pixels>],
["magnet",<magnet URI> ],
["i",<torrent infohash>],
["text-track", "<encoded `kind 6000` event>", "<recommended relay urls>"],
["content-warning", "<reason>"],
["segment", <start>, <end>, "<title>", "<thumbnail URL>"],
// Participants
["p", "<32-bytes hex of a pubkey>", "<optional recommended relay URL>"],
["p", "<32-bytes hex of a pubkey>", "<optional recommended relay URL>"],
// Hashtags
["t", "<tag>"],
["t", "<tag>"],
// Reference links
["r", "<url>"],
["r", "<url>"]
]
}
```
## Video View
A video event view is a response to a video event to track a user's view or progress viewing the video.
### Format
The format uses a parameterized replaceable event kind `34237`.
The `.content` of these events is optional and could be a free-form note that acts like a bookmark for the user.
The list of tags are as follows:
* `a` (required) reference tag to kind `34235` or `34236` video event being viewed
* `d` (required) same as `a` reference tag value
* `viewed` (optional, repeated) timestamp of the user's start time in seconds, timestamp of the user's end time in seconds
```json
{
"id": <32-bytes lowercase hex-encoded SHA-256 of the the serialized event data>,
"pubkey": <32-bytes lowercase hex-encoded public key of the event creator>,
"created_at": <Unix timestamp in seconds>,
"kind": 34237,
"content": "<note>",
"tags": [
["a", "<34235 | 34236>:<video event author pubkey>:<d-identifier of video event>", "<optional relay url>"],
["e", "<event-id", "<relay-url>"]
["d", "<34235 | 34236>:<video event author pubkey>:<d-identifier of video event>"],
["viewed", <start>, <end>],
]
}
```

2
72.md
View File

@@ -76,7 +76,7 @@ The post-approval event MUST include `a` tags of the communities the moderator i
It's recommended that multiple moderators approve posts to avoid deleting them from the community when a moderator is removed from the owner's list. In case the full list of moderators must be rotated, the new moderator set must sign new approvals for posts in the past or the community will restart. The owner can also periodically copy and re-sign of each moderator's approval events to make sure posts don't disappear with moderators.
Post Approvals of replaceable events can be created in three ways: (i) by tagging the replaceable event as an `e` tag if moderators want to approve each individual change to the repleceable event; (ii) by tagging the replaceable event as an `a` tag if the moderator authorizes the replaceable event author to make changes without additional approvals and (iii) by tagging the replaceable event with both its `e` and `a` tag which empowers clients to display the original and updated versions of the event, with appropriate remarks in the UI. Since relays are instructed to delete old versions of a replaceable event, the `.content` of an `e`-approval MUST have the specific version of the event or Clients might not be able to find that version of the content anywhere.
Post Approvals of replaceable events can be created in three ways: (i) by tagging the replaceable event as an `e` tag if moderators want to approve each individual change to the replaceable event; (ii) by tagging the replaceable event as an `a` tag if the moderator authorizes the replaceable event author to make changes without additional approvals and (iii) by tagging the replaceable event with both its `e` and `a` tag which empowers clients to display the original and updated versions of the event, with appropriate remarks in the UI. Since relays are instructed to delete old versions of a replaceable event, the `.content` of an `e`-approval MUST have the specific version of the event or Clients might not be able to find that version of the content anywhere.
Clients SHOULD evaluate any non-`34550:*` `a` tag as posts to be included in all `34550:*` `a` tags.

6
75.md
View File

@@ -53,11 +53,11 @@ The following tags are OPTIONAL.
}
```
The goal MAY include an `r` or `a` tag linking to a URL or tagged-replaceable event.
The goal MAY include an `r` or `a` tag linking to a URL or parameterized replaceable event.
The goal MAY include multiple beneficiary pubkeys by specifying [`zap` tags](57.md#appendix-g-zap-tag-on-other-events).
Tagged-replaceable events can link to a goal by using a `goal` tag specifying the event id and an optional relay hint.
Parameterized replaceable events can link to a goal by using a `goal` tag specifying the event id and an optional relay hint.
```json
{
@@ -77,7 +77,7 @@ Clients MAY display funding goals on user profiles.
When zapping a goal event, clients MUST include the relays in the `relays` tag of the goal event in the zap request `relays` tag.
When zapping a tagged-replaceable event with a `goal` tag, clients SHOULD tag the goal event id in the `e` tag of the zap request.
When zapping a parameterized replaceable event with a `goal` tag, clients SHOULD tag the goal event id in the `e` tag of the zap request.
## Use cases

2
78.md
View File

@@ -12,7 +12,7 @@ Even though interoperability is great, some apps do not want or do not need inte
## Nostr event
This NIP specifies the use of event kind `30078` (tagged-replaceable event) with a `d` tag containing some reference to the app name and context -- or any other arbitrary string. `content` and other `tags` can be anything or in any format.
This NIP specifies the use of event kind `30078` (parameterized replaceable event) with a `d` tag containing some reference to the app name and context -- or any other arbitrary string. `content` and other `tags` can be anything or in any format.
## Some use cases

8
90.md
View File

@@ -162,8 +162,8 @@ Service providers can give feedback about a job back to the customer.
```
* `content`: Either empty or a job-result (e.g. for partial-result samples)
* `amount` tag: as defined in the [Job Result](#job-result) section.
* `status` tag: Service Providers SHOULD indicate what this feedback status refers to. [Appendix 1](#appendix-1-job-feedback-status) defines status. Extra human-readable information can be added as an extra argument.
* `amount` tag: as defined in the [Job Result](#job-result-kind6000-6999) section.
* `status` tag: Service Providers SHOULD indicate what this feedback status refers to. [Job Feedback Status](#job-feedback-status) defines status. Extra human-readable information can be added as an extra argument.
* NOTE: If the input params requires input to be encrypted, then `content` field will have encrypted payload with `p` tag as key.
@@ -177,7 +177,7 @@ Service providers can give feedback about a job back to the customer.
| `success` | Service Provider successfully processed the job. |
| `partial` | Service Provider partially processed the job. The `.content` might include a sample of the partial results. |
Any job feedback event MIGHT include results in the `.content` field, as described in the [Job Result](#job-result) section. This is useful for service providers to provide a sample of the results that have been processed so far.
Any job feedback event MIGHT include results in the `.content` field, as described in the [Job Result](#job-result-kind6000-6999) section. This is useful for service providers to provide a sample of the results that have been processed so far.
# Protocol Flow
@@ -199,7 +199,7 @@ Some service providers might choose to submit a `payment-required` as the first
It's not up to this NIP to define how individual vending machines should choose to run their business.
# Cancellation
A job request might be cancelled by publishing a `kind:5` delete request event tagging the job request event.
A job request might be canceled by publishing a `kind:5` delete request event tagging the job request event.
# Appendix 1: Job chaining
A Customer MAY request multiple jobs to be processed as a chain, where the output of a job is the input of another job. (e.g. podcast transcription -> summarization of the transcription). This is done by specifying as input an event id of a different job with the `job` type.

2
99.md
View File

@@ -6,7 +6,7 @@ Classified Listings
`draft` `optional`
This NIP defines `kind:30402`: a tagged-replaceable event to describe classified listings that list any arbitrary product, service, or other thing for sale or offer and includes enough structured metadata to make them useful.
This NIP defines `kind:30402`: a parameterized replaceable event to describe classified listings that list any arbitrary product, service, or other thing for sale or offer and includes enough structured metadata to make them useful.
The category of classifieds includes a very broad range of physical goods, services, work opportunities, rentals, free giveaways, personals, etc. and is distinct from the more strictly structured marketplaces defined in [NIP-15](https://github.com/nostr-protocol/nips/blob/master/15.md) that often sell many units of specific products through very specific channels.

View File

@@ -5,8 +5,10 @@ reverse chronological order.
| Date | Commit | NIP | Change |
| ----------- | --------- | -------- | ------ |
| 2024-05-25 | [5d1d1c17](https://github.com/nostr-protocol/nips/commit/5d1d1c17) | [NIP-71](71.md) | 'aes-256-gcm' tag was removed |
| 2024-04-30 | [bad88262](https://github.com/nostr-protocol/nips/commit/bad88262) | [NIP-34](34.md) | 'earliest-unique-commit' tag was removed (use 'r' tag instead) |
| 2024-02-25 | [4a171cb0](https://github.com/nostr-protocol/nips/commit/4a171cb0) | [NIP-18](18.md) | quote repost should use `q` tag |
| 2024-02-10 | [c6cd655c](https://github.com/nostr-protocol/nips/commit/c6cd655c) | [NIP-46](46.md) | Params were stringified |
| 2024-02-21 | [c6cd655c](https://github.com/nostr-protocol/nips/commit/c6cd655c) | [NIP-46](46.md) | Params were stringified |
| 2024-02-16 | [cbec02ab](https://github.com/nostr-protocol/nips/commit/cbec02ab) | [NIP-49](49.md) | Password first normalized to NFKC |
| 2024-02-15 | [afbb8dd0](https://github.com/nostr-protocol/nips/commit/afbb8dd0) | [NIP-39](39.md) | PGP identity was removed |
| 2024-02-07 | [d3dad114](https://github.com/nostr-protocol/nips/commit/d3dad114) | [NIP-46](46.md) | Connection token format was changed |

112
README.md
View File

@@ -51,6 +51,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
- [NIP-31: Dealing with Unknown Events](31.md)
- [NIP-32: Labeling](32.md)
- [NIP-34: `git` stuff](34.md)
- [NIP-35: Torrents](35.md)
- [NIP-36: Sensitive Content](36.md)
- [NIP-38: User Statuses](38.md)
- [NIP-39: External Identities in Profiles](39.md)
@@ -72,6 +73,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
- [NIP-58: Badges](58.md)
- [NIP-59: Gift Wrap](59.md)
- [NIP-65: Relay List Metadata](65.md)
- [NIP-71: Video Events](71.md)
- [NIP-72: Moderated Communities](72.md)
- [NIP-75: Zap Goals](75.md)
- [NIP-78: Application-specific data](78.md)
@@ -108,6 +110,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
| `42` | Channel Message | [28](28.md) |
| `43` | Channel Hide Message | [28](28.md) |
| `44` | Channel Mute User | [28](28.md) |
| `818` | Merge Requests | [54](54.md) |
| `1021` | Bid | [15](15.md) |
| `1022` | Bid confirmation | [15](15.md) |
| `1040` | OpenTimestamps | [03](03.md) |
@@ -121,6 +124,9 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
| `1971` | Problem Tracker | [nostrocket][nostrocket] |
| `1984` | Reporting | [56](56.md) |
| `1985` | Label | [32](32.md) |
| `2003` | Torrent | [35](35.md) |
| `2004` | Torrent Comment | [35](35.md) |
| `2022` | Coinjoin Pool | [joinstr][joinstr] |
| `4550` | Community Post Approval | [72](72.md) |
| `5000`-`5999` | Job Request | [90](90.md) |
| `6000`-`6999` | Job Result | [90](90.md) |
@@ -155,6 +161,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
| `30002` | Relay sets | [51](51.md) |
| `30003` | Bookmark sets | [51](51.md) |
| `30004` | Curation sets | [51](51.md) |
| `30005` | Video sets | [51](51.md) |
| `30008` | Profile Badges | [58](58.md) |
| `30009` | Badge Definition | [58](58.md) |
| `30015` | Interest sets | [51](51.md) |
@@ -173,17 +180,24 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
| `30403` | Draft Classified Listing | [99](99.md) |
| `30617` | Repository announcements | [34](34.md) |
| `30818` | Wiki article | [54](54.md) |
| `30819` | Redirects | [54](54.md) |
| `31890` | Feed | [NUD: Custom Feeds](https://wikifreedia.xyz/cip-01/97c70a44366a6535c1) |
| `31922` | Date-Based Calendar Event | [52](52.md) |
| `31923` | Time-Based Calendar Event | [52](52.md) |
| `31924` | Calendar | [52](52.md) |
| `31925` | Calendar Event RSVP | [52](52.md) |
| `31989` | Handler recommendation | [89](89.md) |
| `31990` | Handler information | [89](89.md) |
| `34235` | Video Event | [71](71.md) |
| `34236` | Short-form Portrait Video Event | [71](71.md) |
| `34237` | Video View Event | [71](71.md) |
| `34550` | Community Definition | [72](72.md) |
| `39000-9` | Group metadata events | [29](29.md) |
[NUD: Custom Feeds]: https://wikifreedia.xyz/cip-01/97c70a44366a6535c1
[nostrocket]: https://github.com/nostrocket/NIPS/blob/main/Problems.md
[lnpub]: https://github.com/shocknet/Lightning.Pub/blob/master/proto/autogenerated/client.md
[joinstr]: https://gitlab.com/1440000bytes/joinstr/-/blob/main/NIP.md
## Message types
@@ -213,58 +227,58 @@ Please update these lists when proposing NIPs introducing new event kinds.
## Standardized Tags
| name | value | other parameters | NIP |
| ----------------- | ------------------------------------ | -------------------- | ------------------------------------- |
| `e` | event id (hex) | relay URL, marker | [01](01.md), [10](10.md) |
| `p` | pubkey (hex) | relay URL, petname | [01](01.md), [02](02.md) |
| `a` | coordinates to an event | relay URL | [01](01.md) |
| `d` | identifier | -- | [01](01.md) |
| `g` | geohash | -- | [52](52.md) |
| `i` | identity | proof | [39](39.md) |
| `k` | kind number (string) | -- | [18](18.md), [25](25.md), [72](72.md) |
| `l` | label, label namespace | annotations | [32](32.md) |
| `L` | label namespace | -- | [32](32.md) |
| `m` | MIME type | -- | [94](94.md) |
| `q` | event id (hex) | relay URL | [18](18.md) |
| `r` | a reference (URL, etc) | petname | |
| `r` | relay url | marker | [65](65.md) |
| `t` | hashtag | -- | |
| `alt` | summary | -- | [31](31.md) |
| `amount` | millisatoshis, stringified | -- | [57](57.md) |
| `bolt11` | `bolt11` invoice | -- | [57](57.md) |
| `challenge` | challenge string | -- | [42](42.md) |
| `client` | name, address | relay URL | [89](89.md) |
| `clone` | git clone URL | -- | [34](34.md) |
| `content-warning` | reason | -- | [36](36.md) |
| `delegation` | pubkey, conditions, delegation token | -- | [26](26.md) |
| `description` | description | -- | [34](34.md), [57](57.md), [58](58.md) |
| `emoji` | shortcode, image URL | -- | [30](30.md) |
| `encrypted` | -- | -- | [90](90.md) |
| `expiration` | unix timestamp (string) | -- | [40](40.md) |
| `goal` | event id (hex) | relay URL | [75](75.md) |
| `image` | image URL | dimensions in pixels | [23](23.md), [58](58.md) |
| `imeta` | inline metadata | -- | [92](92.md) |
| `lnurl` | `bech32` encoded `lnurl` | -- | [57](57.md) |
| `location` | location string | -- | [52](52.md), [99](99.md) |
| `name` | name | -- | [34](34.md), [58](58.md) |
| `nonce` | random | -- | [13](13.md) |
| `preimage` | hash of `bolt11` invoice | -- | [57](57.md) |
| `price` | price | currency, frequency | [99](99.md) |
| `proxy` | external ID | protocol | [48](48.md) |
| `published_at` | unix timestamp (string) | -- | [23](23.md) |
| `relay` | relay url | -- | [42](42.md), [17](17.md) |
| `relays` | relay list | -- | [57](57.md) |
| `server` | file storage server url | -- | [96](96.md) |
| `subject` | subject | -- | [14](14.md), [17](17.md) |
| `summary` | article summary | -- | [23](23.md) |
| `thumb` | badge thumbnail | dimensions in pixels | [58](58.md) |
| `title` | article title | -- | [23](23.md) |
| `web` | webpage URL | -- | [34](34.md) |
| `zap` | pubkey (hex), relay URL | weight | [57](57.md) |
| name | value | other parameters | NIP |
| ----------------- | ------------------------------------ | ------------------------------- | ------------------------------------- |
| `e` | event id (hex) | relay URL, marker, pubkey (hex) | [01](01.md), [10](10.md) |
| `p` | pubkey (hex) | relay URL, petname | [01](01.md), [02](02.md) |
| `a` | coordinates to an event | relay URL | [01](01.md) |
| `d` | identifier | -- | [01](01.md) |
| `g` | geohash | -- | [52](52.md) |
| `i` | identity | proof | [39](39.md) |
| `k` | kind number (string) | -- | [18](18.md), [25](25.md), [72](72.md) |
| `l` | label, label namespace | annotations | [32](32.md) |
| `L` | label namespace | -- | [32](32.md) |
| `m` | MIME type | -- | [94](94.md) |
| `q` | event id (hex) | relay URL | [18](18.md) |
| `r` | a reference (URL, etc) | petname | [24](24.md) |
| `r` | relay url | marker | [65](65.md) |
| `t` | hashtag | -- | |
| `alt` | summary | -- | [31](31.md) |
| `amount` | millisatoshis, stringified | -- | [57](57.md) |
| `bolt11` | `bolt11` invoice | -- | [57](57.md) |
| `challenge` | challenge string | -- | [42](42.md) |
| `client` | name, address | relay URL | [89](89.md) |
| `clone` | git clone URL | -- | [34](34.md) |
| `content-warning` | reason | -- | [36](36.md) |
| `delegation` | pubkey, conditions, delegation token | -- | [26](26.md) |
| `description` | description | -- | [34](34.md), [57](57.md), [58](58.md) |
| `emoji` | shortcode, image URL | -- | [30](30.md) |
| `encrypted` | -- | -- | [90](90.md) |
| `expiration` | unix timestamp (string) | -- | [40](40.md) |
| `goal` | event id (hex) | relay URL | [75](75.md) |
| `image` | image URL | dimensions in pixels | [23](23.md), [58](58.md) |
| `imeta` | inline metadata | -- | [92](92.md) |
| `lnurl` | `bech32` encoded `lnurl` | -- | [57](57.md) |
| `location` | location string | -- | [52](52.md), [99](99.md) |
| `name` | name | -- | [34](34.md), [58](58.md) |
| `nonce` | random | difficulty | [13](13.md) |
| `preimage` | hash of `bolt11` invoice | -- | [57](57.md) |
| `price` | price | currency, frequency | [99](99.md) |
| `proxy` | external ID | protocol | [48](48.md) |
| `published_at` | unix timestamp (string) | -- | [23](23.md) |
| `relay` | relay url | -- | [42](42.md), [17](17.md) |
| `relays` | relay list | -- | [57](57.md) |
| `server` | file storage server url | -- | [96](96.md) |
| `subject` | subject | -- | [14](14.md), [17](17.md) |
| `summary` | article summary | -- | [23](23.md) |
| `thumb` | badge thumbnail | dimensions in pixels | [58](58.md) |
| `title` | article title | -- | [23](23.md) |
| `web` | webpage URL | -- | [34](34.md) |
| `zap` | pubkey (hex), relay URL | weight | [57](57.md) |
## Criteria for acceptance of NIPs
1. They should be implemented in at least two clients and one relay -- when applicable.
1. They should be fully implemented in at least two clients and one relay -- when applicable.
2. They should make sense.
3. They should be optional and backwards-compatible: care must be taken such that clients and relays that choose to not implement them do not stop working when interacting with the ones that choose to.
4. There should be no more than one way of doing the same thing.