mirror of
https://github.com/nostr-protocol/nips.git
synced 2024-12-12 18:36:24 +00:00
Compare commits
34 Commits
5887eb22ce
...
f55e545ba8
Author | SHA1 | Date | |
---|---|---|---|
|
f55e545ba8 | ||
|
a1ca7a194b | ||
|
e942427f8f | ||
|
624b989f9f | ||
|
b35dd7d294 | ||
|
b94ad00ac7 | ||
|
d71887a8e2 | ||
|
33cad5108e | ||
|
b04922586e | ||
|
d857cfb1b8 | ||
|
a2be191ecd | ||
|
936616b3c0 | ||
|
a92d2e2edd | ||
|
6d16019e9e | ||
|
2ac43aa3f1 | ||
|
2776a2aa14 | ||
|
5ec59fd70c | ||
|
33efff81a6 | ||
|
c7a943da2d | ||
|
e17cbbe7d3 | ||
|
3c57cd5cd7 | ||
|
225d5b0207 | ||
|
a343d17681 | ||
|
f4d9db5505 | ||
|
16f134c0a2 | ||
|
ad4f6d8d62 | ||
|
4b5ca2ebc7 | ||
|
cbcc8de803 | ||
|
afa93ffb26 | ||
|
b2a2711af1 | ||
|
299c8b992e | ||
|
7d80aecff5 | ||
|
901135a0ee | ||
|
93f96f060b |
242
111.md
Normal file
242
111.md
Normal file
@ -0,0 +1,242 @@
|
||||
# NIP-111
|
||||
|
||||
Nostr-Specific Private Key Generation from Deterministic Wallet Signatures (Sign-In-With-X)
|
||||
--
|
||||
`draft` `optional` `author:0xc0de4c0ffee` `author:sshmatrix`
|
||||
|
||||
## Abstract
|
||||
|
||||
This specification provides an optional method for Nostr Clients, NIP-07 providers and Wallet providers to generate deterministic private keys from chain-agnostic CAIP-122 Signatures (`Sign-In-With-X` specification). The keypairs generated using this specification are Nostr-specific and do not expose the original signing keypair. The new private keys are derived using SHA-256 HMAC Key Derivation Function (HKDF) with NIP-02 or NIP-05 names, CAIP-02 Blockchain ID & CAIP-10 Account ID Specification identifiers, and deterministic signatures from connected wallets as inputs.
|
||||
|
||||
## Introduction
|
||||
|
||||
NIP-111 at its core is an account abstraction specification in which a cryptographic signature calculated by one signing algorithm and its native keypair (e.g. [Bitcoin-native Schnorr algorithm](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki)) can be used to derive a deterministic cryptographic keypair for another signing algorithm (e.g. [Ethereum-native ECDSA algorithm](https://eips.ethereum.org/EIPS/eip-191)) using an appropriate singular (non-invertible) key derivation function. This specification particularly describes the case where the former and latter algorithms are Schnorr and ECDSA respectively, and the one-way adaptor from ECDSA to Schnorr keypair is HMAC-based Key Derivation Function ([HKDF](https://datatracker.ietf.org/doc/html/rfc586)).
|
||||
|
||||
NIP-111 specification originated from the desire to allow Nostr to function with widely popular Ethereum wallets such as Metamask and leverage the strong network effects of Ethereum ecosystem. The problem however lay in the fact that Nostr Protocol uses Bitcoin-native Schnorr algorithm for signing messages/data while Ethereum (and its wallets such as Metamask etc) uses ECDSA algorithm. The difference in two signing algorithms and respective signing keypairs is the exact technical incompatibility that this specification originally succeeded in resolving by enabling [Sign-In With Ethereum](https://login.xyz) (SIWE) on Nostr. The underlying schema however is fully capable of functioning as a chain-agnostic workflow and this improved draft reflects that property by using [CAIP](https://github.com/ChainAgnostic/CAIPs) (Chain-Agnostic Improvement Proposals) implementations.
|
||||
|
||||
## Terminology
|
||||
|
||||
### a) Username
|
||||
`username` is either of the following:
|
||||
|
||||
- `petname` is a [NIP-02](https://github.com/nostr-protocol/nips/blob/master/02.md) compatible name,
|
||||
- `petname@example.com` is a [NIP-05](https://github.com/nostr-protocol/nips/blob/master/05.md) identifier,
|
||||
- `example.com` is NIP-05 identifier `_@example.com`,
|
||||
- `sub.example.com` is NIP-05 identifier `_@sub.example.com`,
|
||||
|
||||
such that
|
||||
|
||||
```js
|
||||
let username = 'petname' || 'petname@example.com' || 'example.com' || 'sub.example.com'
|
||||
```
|
||||
|
||||
### b) Password
|
||||
`password` is an optional `string` value used to salt the key derivation function (HKDF),
|
||||
```js
|
||||
let password = "horse staple battery"
|
||||
```
|
||||
|
||||
## c) Chain-agnostic Identifiers
|
||||
Chain-agnostic [CAIP-02: Blockchain ID Specification](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-2.md) and [CAIP-10: Account ID Specification](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-10.md) schemes are used to generate blockchain and address identifiers `caip02` and `caip10` respectively,
|
||||
```js
|
||||
let caip02 =
|
||||
`eip155:<evm_chain_id>` ||
|
||||
`cosmos:<hub_id_name>` ||
|
||||
`bip122:<16 bytes genesis/fork hash>`;
|
||||
|
||||
let caip10 = `${caip02}:<checksum_address>`;
|
||||
```
|
||||
|
||||
### d) Info
|
||||
`info` is CAIP-10 and NIP-02/NIP-05 identifier string formatted as:
|
||||
```js
|
||||
let info = `${caip10}:${username}`;
|
||||
```
|
||||
|
||||
### e) Message
|
||||
Deterministic `message` to be signed by the wallet provider,
|
||||
```js
|
||||
let message = `Log into Nostr client as '${username}'\n\nIMPORTANT: Please verify the integrity and authenticity of connected Nostr client before signing this message\n\nSIGNED BY: ${caip10}`
|
||||
```
|
||||
|
||||
### f) Signature
|
||||
[RFC-6979](https://datatracker.ietf.org/doc/html/rfc6979) compatible (ECDSA) deterministic `signature` calculated by the wallet provider using native keypair,
|
||||
```js
|
||||
let signature = wallet.signMessage(message);
|
||||
```
|
||||
|
||||
### g) Salt
|
||||
`salt` is SHA-256 hash of the `info`, optional password and last **32 bytes** of signature string formatted as:
|
||||
```js
|
||||
let salt = await sha256(`${info}:${password?password:""}:${signature.slice(68)}`);
|
||||
```
|
||||
where, `signature.slice(68)` are the last 32 bytes of the deterministic ECDSA-derived Ethereum signature.
|
||||
|
||||
### h) Key Derivation Function (KDF)
|
||||
HMAC-Based KDF `hkdf(sha256, inputKey, salt, info, dkLen = 42)` is used to derive the **42 bytes** long **hashkey** with inputs,
|
||||
|
||||
- `inputKey` is SHA-256 hash of signature bytes,
|
||||
```js
|
||||
let inputKey = await sha256(hexToBytes(signature.slice(2)));
|
||||
```
|
||||
|
||||
- `info` is same as defined before, i.e.
|
||||
```js
|
||||
let info = `${caip10}:${username}`;
|
||||
```
|
||||
|
||||
- `salt` is same as defined before, i.e.
|
||||
```js
|
||||
let salt = await sha256(`${info}:${password?password:""}:${signature.slice(68)}`);
|
||||
```
|
||||
|
||||
- `dkLen` (Derived Key Length) is set to `42`,
|
||||
```js
|
||||
let dkLen = 42;
|
||||
```
|
||||
[FIPS 186-4 B.4.1](https://csrc.nist.gov/publications/detail/fips/186/4/final) requires hashkey length to be `>= n + 8`, where `n = 32` is the **bytelength** of the final `secp256k1` private key, such that `42 >= 32 + 8`.
|
||||
|
||||
- `hashToPrivateKey()` function is FIPS 186-4 B.4.1 implementation to convert HKDF-derived hashkey to valid `secp256k1` keypair. This function is implemented in JavaScript library `@noble/secp256k1` as `hashToPrivateKey()`.
|
||||
|
||||
```js
|
||||
let hashKey = hkdf(sha256, inputKey, salt, info, dkLen = 42);
|
||||
let privKey = secp256k1.utils.hashToPrivateKey(hashKey);
|
||||
let pubKey = secp256k1.schnorr.getPublicKey(privKey);
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
The resulting architecture of NIP-111 can be visually interpreted as follows:
|
||||
|
||||
![](https://raw.githubusercontent.com/dostr-eth/resources/main/graphics/nip-111.png)
|
||||
|
||||
## Implementation Requirements
|
||||
|
||||
- Connected Ethereum wallet Signer **MUST** be EIP-191 and RFC-6979 compatible.
|
||||
- The `message` **MUST** be string formatted as
|
||||
```
|
||||
`Log into Nostr client as '${username}'\n\nIMPORTANT: Please verify the integrity and authenticity of connected Nostr client before signing this message\n\nSIGNED BY: ${caip10}`
|
||||
```
|
||||
- HKDF `inputKey` **MUST** be generated as the SHA-256 hash of 65 bytes long signature.
|
||||
- HKDF `salt` **MUST** be generated as SHA-256 hash of string
|
||||
```
|
||||
${info}:${password?password:""}:${signature.slice(68)}
|
||||
```
|
||||
- HKDF Derived Key Length (`dkLen`) **MUST** be 42.
|
||||
- HKDF `info` **MUST** be string formatted as
|
||||
```
|
||||
${caip10}:${username}
|
||||
```
|
||||
|
||||
## JS Example
|
||||
```js
|
||||
import * as secp256k1 from '@noble/secp256k1'
|
||||
import {hkdf} from '@noble/hashes/hkdf'
|
||||
import {sha256} from '@noble/hashes/sha256'
|
||||
import {queryProfile} from './nip05'
|
||||
import {getPublicKey} from './keys'
|
||||
import {ProfilePointer} from './nip19'
|
||||
|
||||
// const wallet = connected ethereum wallet with ethers.js
|
||||
let username = "me@example.com"
|
||||
let chainId = wallet.getChainId(); // get ChainID from connected wallet
|
||||
let address = wallet.getAddress(); // get Address from wallet
|
||||
let caip10 = `eip155:${chainId}:${address}`;
|
||||
let message = `Log into Nostr client as '${username}'\n\nIMPORTANT: Please verify the integrity and authenticity of connected Nostr client before signing this message\n\nSIGNED BY: ${caip10}`
|
||||
let signature = wallet.signMessage(message); // request Signature from wallet
|
||||
let password = "horse staple battery"
|
||||
|
||||
/**
|
||||
*
|
||||
* @param username NIP-02/NIP-05 identifier
|
||||
* @param caip10 CAIP identifier for the blockchain account
|
||||
* @param sig Deterministic signature from X-wallet provider
|
||||
* @param password Optional password
|
||||
* @returns Deterministic private key as hex string
|
||||
*/
|
||||
export async function privateKeyFromX(
|
||||
username: string,
|
||||
caip10: string,
|
||||
sig: string,
|
||||
password: string | undefined
|
||||
): Promise < string > {
|
||||
if (sig.length < 64)
|
||||
throw new Error("Signature too short");
|
||||
let inputKey = await sha256(secp256k1.utils.hexToBytes(sig.toLowerCase().startsWith("0x") ? sig.slice(2) : sig))
|
||||
let info = `${caip10}:${username}`
|
||||
let salt = await sha256(`${info}:${password?password:""}:${sig.slice(-64)}`)
|
||||
let hashKey = await hkdf(sha256, inputKey, salt, info, 42)
|
||||
return secp256k1.utils.bytesToHex(secp256k1.utils.hashToPrivateKey(hashKey))
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param username NIP-02/NIP-05 identifier
|
||||
* @param caip10 CAIP identifier for the blockchain account
|
||||
* @param sig Deterministic signature from X-wallet provider
|
||||
* @param password Optional password
|
||||
* @returns
|
||||
*/
|
||||
export async function signInWithX(
|
||||
username: string,
|
||||
caip10: string,
|
||||
sig: string,
|
||||
password: string | undefined
|
||||
): Promise < {
|
||||
petname: string,
|
||||
profile: ProfilePointer | null,
|
||||
privkey: string
|
||||
} > {
|
||||
let profile = null
|
||||
let petname = username
|
||||
if (username.includes(".")) {
|
||||
try {
|
||||
profile = await queryProfile(username)
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
throw new Error("Nostr Profile Not Found")
|
||||
}
|
||||
if(profile == null){
|
||||
throw new Error("Nostr Profile Not Found")
|
||||
}
|
||||
petname = (username.split("@").length == 2) ? username.split("@")[0] : username.split(".")[0]
|
||||
}
|
||||
let privkey = await privateKeyFromX(username, caip10, sig, password)
|
||||
let pubkey = getPublicKey(privkey)
|
||||
if (profile?.pubkey && pubkey !== profile.pubkey) {
|
||||
throw new Error("Invalid Signature/Password")
|
||||
}
|
||||
return {
|
||||
petname,
|
||||
profile,
|
||||
privkey
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Implementations
|
||||
1) Nostr Tools : [Sign-In-With-X](https://github.com/dostr-eth/nostr-tools/tree/siwx) ([Pull Request #132](https://github.com/nbd-wtf/nostr-tools/pull/132))
|
||||
2) Nostr Client: [Dostr](https://github.com/dostr-eth/dostr-client)
|
||||
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- Users **SHOULD** always verify the integrity and authenticity of the Nostr client before signing the message.
|
||||
- Users **SHOULD** ensure that they only input their Nostr `username` and `password` in trusted and secure clients.
|
||||
|
||||
## References:
|
||||
|
||||
- [RFC-6979: Deterministic Usage of the DSA and ECDSA](https://datatracker.ietf.org/doc/html/rfc6979)
|
||||
- [RFC-5869: HKDF (HMAC-based Extract-and-Expand Key Derivation Function)](https://datatracker.ietf.org/doc/html/rfc5869)
|
||||
- [CAIP-02: Blockchain ID Specification](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-2.md)
|
||||
- [CAIP-10: Account ID Specification](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-10.md)
|
||||
- [CAIP-122: Sign-in-With-X)](https://github.com/ChainAgnostic/CAIPs/pull/122)
|
||||
- [Digital Signature Standard (DSS), FIPS 186-4 B.4.1](https://csrc.nist.gov/publications/detail/fips/186/4/final)
|
||||
- [BIP-340: Schnorr Signature Standard](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki)
|
||||
- [ERC-191: Signed Data Standard](https://eips.ethereum.org/EIPS/eip-191)
|
||||
- [EIP-155: Simple Replay Attack Protection](https://eips.ethereum.org/EIPS/eip-155)
|
||||
- [NIP-02: Contact List and Petnames](https://github.com/nostr-protocol/nips/blob/master/02.md)
|
||||
- [NIP-05: Mapping Nostr Keys to DNS-based Internet Identifiers](https://github.com/nostr-protocol/nips/blob/master/05.md)
|
||||
- [ECDSA Signature Standard](https://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.38.8014)
|
||||
- [@noble/hashes](https://github.com/paulmillr/noble-hashes)
|
||||
- [@noble/secp256k1](https://github.com/paulmillr/noble-secp256k1)
|
2
17.md
2
17.md
@ -133,7 +133,7 @@ When sending a message to anyone, clients must then connect to the relays in the
|
||||
|
||||
This example sends the message `Hola, que tal?` from `nsec1w8udu59ydjvedgs3yv5qccshcj8k05fh3l60k9x57asjrqdpa00qkmr89m` to `nsec12ywtkplvyq5t6twdqwwygavp5lm4fhuang89c943nf2z92eez43szvn4dt`.
|
||||
|
||||
The two final GiftWraps, one to the receiver and the other to the sender, are:
|
||||
The two final GiftWraps, one to the receiver and the other to the sender, respectively, are:
|
||||
|
||||
```json
|
||||
{
|
||||
|
4
29.md
4
29.md
@ -30,8 +30,6 @@ When encountering just the `<host>` without the `'<group-id>`, clients MAY infer
|
||||
|
||||
Events sent by users to groups (chat messages, text notes, moderation events etc) MUST have an `h` tag with the value set to the group _id_.
|
||||
|
||||
`h` tags MAY include the group's name as the second argument. This allows `unmanaged` groups to be assigned human-readable names without relay support.
|
||||
|
||||
## Timeline references
|
||||
|
||||
In order to not be used out of context, events sent to these groups may contain references to previous events seen from the same relay in the `previous` tag. The choice of which previous events to pick belongs to the clients. The references are to be made using the first 8 characters (4 bytes) of any event in the last 50 events seen by the user in the relay, excluding events by themselves. There can be any number of references (including zero), but it's recommended that clients include at least 3 and that relays enforce this.
|
||||
@ -242,3 +240,5 @@ A definition for `kind:10009` was included in [NIP-51](51.md) that allows client
|
||||
### Using `unmanaged` relays
|
||||
|
||||
To prevent event leakage, when using `unmanaged` relays, clients should include the [NIP-70](70.md) `-` tag, as just the `previous` tag won't be checked by other `unmanaged` relays.
|
||||
|
||||
Groups MAY be named without relay support by adding a `name` to the corresponding tag in a user's `kind 10009` group list.
|
||||
|
8
44.md
8
44.md
@ -63,7 +63,7 @@ NIP-44 version 2 has the following design characteristics:
|
||||
- SHA256 is used instead of SHA3 or BLAKE because it is already used in nostr. Also BLAKE's speed advantage
|
||||
is smaller in non-parallel environments.
|
||||
- A custom padding scheme is used instead of padmé because it provides better leakage reduction for small messages.
|
||||
- Base64 encoding is used instead of another compression algorithm because it is widely available, and is already used in nostr.
|
||||
- Base64 encoding is used instead of another encoding algorithm because it is widely available, and is already used in nostr.
|
||||
|
||||
### Encryption
|
||||
|
||||
@ -86,7 +86,7 @@ NIP-44 version 2 has the following design characteristics:
|
||||
- Content must be encoded from UTF-8 into byte array
|
||||
- Validate plaintext length. Minimum is 1 byte, maximum is 65535 bytes
|
||||
- Padding format is: `[plaintext_length: u16][plaintext][zero_bytes]`
|
||||
- Padding algorithm is related to powers-of-two, with min padded msg size of 32
|
||||
- Padding algorithm is related to powers-of-two, with min padded msg size of 32bytes
|
||||
- Plaintext length is encoded in big-endian as first 2 bytes of the padded blob
|
||||
5. Encrypt padded content
|
||||
- Use ChaCha20, with key and nonce from step 3
|
||||
@ -148,8 +148,8 @@ validation rules, refer to BIP-340.
|
||||
- `x[i:j]`, where `x` is a byte array and `i, j <= 0` returns a `(j - i)`-byte array with a copy of the
|
||||
`i`-th byte (inclusive) to the `j`-th byte (exclusive) of `x`.
|
||||
- Constants `c`:
|
||||
- `min_plaintext_size` is 1. 1b msg is padded to 32b.
|
||||
- `max_plaintext_size` is 65535 (64kb - 1). It is padded to 65536.
|
||||
- `min_plaintext_size` is 1. 1bytes msg is padded to 32bytes.
|
||||
- `max_plaintext_size` is 65535 (64kB - 1). It is padded to 65536bytes.
|
||||
- Functions
|
||||
- `base64_encode(string)` and `base64_decode(bytes)` are Base64 ([RFC 4648](https://datatracker.ietf.org/doc/html/rfc4648), with padding)
|
||||
- `concat` refers to byte array concatenation
|
||||
|
16
46.md
16
46.md
@ -72,12 +72,12 @@ _user_ passes this token to _remote-signer_, which then sends `connect` *respons
|
||||
{
|
||||
"kind": 24133,
|
||||
"pubkey": <local_keypair_pubkey>,
|
||||
"content": <nip04(<request>)>,
|
||||
"content": <nip44(<request>)>,
|
||||
"tags": [["p", <remote-signer-pubkey>]],
|
||||
}
|
||||
```
|
||||
|
||||
The `content` field is a JSON-RPC-like message that is [NIP-04](04.md) encrypted and has the following structure:
|
||||
The `content` field is a JSON-RPC-like message that is [NIP-44](44.md) encrypted and has the following structure:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
@ -109,7 +109,7 @@ Each of the following are methods that the _client_ sends to the _remote-signer_
|
||||
|
||||
### Requested permissions
|
||||
|
||||
The `connect` method may be provided with `optional_requested_permissions` for user convenience. The permissions are a comma-separated list of `method[:params]`, i.e. `nip04_encrypt,sign_event:4` meaning permissions to call `nip04_encrypt` and to call `sign_event` with `kind:4`. Optional parameter for `sign_event` is the kind number, parameters for other methods are to be defined later. Same permission format may be used for `perms` field of `metadata` in `nostrconnect://` string.
|
||||
The `connect` method may be provided with `optional_requested_permissions` for user convenience. The permissions are a comma-separated list of `method[:params]`, i.e. `nip44_encrypt,sign_event:4` meaning permissions to call `nip44_encrypt` and to call `sign_event` with `kind:4`. Optional parameter for `sign_event` is the kind number, parameters for other methods are to be defined later. Same permission format may be used for `perms` field of `metadata` in `nostrconnect://` string.
|
||||
|
||||
## Response Events `kind:24133`
|
||||
|
||||
@ -118,13 +118,13 @@ The `connect` method may be provided with `optional_requested_permissions` for u
|
||||
"id": <id>,
|
||||
"kind": 24133,
|
||||
"pubkey": <remote-signer-pubkey>,
|
||||
"content": <nip04(<response>)>,
|
||||
"content": <nip44(<response>)>,
|
||||
"tags": [["p", <client-pubkey>]],
|
||||
"created_at": <unix timestamp in seconds>
|
||||
}
|
||||
```
|
||||
|
||||
The `content` field is a JSON-RPC-like message that is [NIP-04](04.md) encrypted and has the following structure:
|
||||
The `content` field is a JSON-RPC-like message that is [NIP-44](44.md) encrypted and has the following structure:
|
||||
|
||||
```json
|
||||
{
|
||||
@ -150,7 +150,7 @@ The `content` field is a JSON-RPC-like message that is [NIP-04](04.md) encrypted
|
||||
{
|
||||
"kind": 24133,
|
||||
"pubkey": "eff37350d839ce3707332348af4549a96051bd695d3223af4aabce4993531d86",
|
||||
"content": nip04({
|
||||
"content": nip44({
|
||||
"id": <random_string>,
|
||||
"method": "sign_event",
|
||||
"params": [json_stringified(<{
|
||||
@ -170,7 +170,7 @@ The `content` field is a JSON-RPC-like message that is [NIP-04](04.md) encrypted
|
||||
{
|
||||
"kind": 24133,
|
||||
"pubkey": "fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52",
|
||||
"content": nip04({
|
||||
"content": nip44({
|
||||
"id": <random_string>,
|
||||
"result": json_stringified(<signed-event>)
|
||||
}),
|
||||
@ -224,4 +224,4 @@ The `<remote-signer-app-pubkey>` MAY be used to verify the domain from _remote-s
|
||||
|
||||
_remote-signer_ MAY publish a NIP-89 `kind: 31990` event with `k` tag of `24133`, which MAY also include one or more `relay` tags and MAY include `nostrconnect_url` tag. The semantics of `relay` and `nostrconnect_url` tags are the same as in the section above.
|
||||
|
||||
_client_ MAY improve UX by discovering _remote-signers_ using their `kind: 31990` events. _client_ MAY then pre-generate `nostrconnect://` strings for the _remote-signers_, and SHOULD in that case verify that `kind: 31990` event's author is mentioned in signer's `nostr.json?name=_` file as `<remote-signer-app-pubkey>`.
|
||||
_client_ MAY improve UX by discovering _remote-signers_ using their `kind: 31990` events. _client_ MAY then pre-generate `nostrconnect://` strings for the _remote-signers_, and SHOULD in that case verify that `kind: 31990` event's author is mentioned in signer's `nostr.json?name=_` file as `<remote-signer-app-pubkey>`.
|
||||
|
8
51.md
8
51.md
@ -14,7 +14,7 @@ When new items are added to an existing list, clients SHOULD append them to the
|
||||
|
||||
## Types of lists
|
||||
|
||||
## Standard lists
|
||||
### Standard lists
|
||||
|
||||
Standard lists use normal 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.
|
||||
|
||||
@ -29,14 +29,14 @@ For example, _mute list_ can contain the public keys of spammers and bad actors
|
||||
| Public chats | 10005 | [NIP-28](28.md) chat channels the user is in | `"e"` (kind:40 channel definitions) |
|
||||
| Blocked relays | 10006 | relays clients should never connect to | `"relay"` (relay URLs) |
|
||||
| Search relays | 10007 | relays clients should use when performing search queries | `"relay"` (relay URLs) |
|
||||
| Simple groups | 10009 | [NIP-29](29.md) groups the user is in | `"group"` ([NIP-29](29.md) group id + relay URL), `"r"` for each relay in use |
|
||||
| Simple groups | 10009 | [NIP-29](29.md) groups the user is in | `"group"` ([NIP-29](29.md) group id + relay URL + optional group name), `"r"` for each relay in use |
|
||||
| Interests | 10015 | topics a user may be interested in and pointers | `"t"` (hashtags) and `"a"` (kind:30015 interest set) |
|
||||
| Emojis | 10030 | user preferred emojis and pointers to emoji sets | `"emoji"` (see [NIP-30](30.md)) and `"a"` (kind:30030 emoji set) |
|
||||
| DM relays | 10050 | Where to receive [NIP-17](17.md) direct messages | `"relay"` (see [NIP-17](17.md)) |
|
||||
| Good wiki authors | 10101 | [NIP-54](54.md) user recommended wiki authors | `"p"` (pubkeys) |
|
||||
| Good wiki relays | 10102 | [NIP-54](54.md) relays deemed to only host useful articles | `"relay"` (relay URLs) |
|
||||
|
||||
## Sets
|
||||
### Sets
|
||||
|
||||
Sets are lists with well-defined meaning that can enhance the functionality and the UI of clients that rely on them. Unlike standard lists, users are expected to have more than one set of each kind, therefore each of them must be assigned a different `"d"` identifier.
|
||||
|
||||
@ -56,7 +56,7 @@ Aside from their main identifier, the `"d"` tag, sets can optionally have a `"ti
|
||||
| Emoji sets | 30030 | categorized emoji groups | `"emoji"` (see [NIP-30](30.md)) |
|
||||
| Release artifact sets | 30063 | groups of files of a software release | `"e"` (kind:1063 [file metadata](94.md) events), `"i"` (application identifier, typically reverse domain notation), `"version"` |
|
||||
|
||||
## Deprecated standard lists
|
||||
### Deprecated standard lists
|
||||
|
||||
Some clients have used these lists in the past, but they should work on transitioning to the [standard formats](#standard-lists) above.
|
||||
|
||||
|
2
90.md
2
90.md
@ -185,7 +185,7 @@ Any job feedback event MIGHT include results in the `.content` field, as describ
|
||||
* Customer publishes a job request (e.g. `kind:5000` speech-to-text).
|
||||
* Service Providers MAY submit `kind:7000` job-feedback events (e.g. `payment-required`, `processing`, `error`, etc.).
|
||||
* Upon completion, the service provider publishes the result of the job with a `kind:6000` job-result event.
|
||||
* At any point, if there is an `amount` pending to be paid as instructed by the service provider, the user can pay the included `bolt11` or zap the job result event the service provider has sent to the user
|
||||
* At any point, if there is an `amount` pending to be paid as instructed by the service provider, the user can pay the included `bolt11` or zap the job result event the service provider has sent to the user.
|
||||
|
||||
Job feedback (`kind:7000`) and Job Results (`kind:6000-6999`) events MAY include an `amount` tag, this can be interpreted as a suggestion to pay. Service Providers MUST use the `payment-required` feedback event to signal that a payment is required and no further actions will be performed until the payment is sent.
|
||||
|
||||
|
@ -5,6 +5,7 @@ reverse chronological order.
|
||||
|
||||
| Date | Commit | NIP | Change |
|
||||
| ----------- | --------- | -------- | ------ |
|
||||
| 2024-12-05 | [6d16019e](https://github.com/nostr-protocol/nips/commit/6d16019e) | [46](46.md) | message encryption was changed to NIP-44 |
|
||||
| 2024-11-12 | [2838e3bd](https://github.com/nostr-protocol/nips/commit/2838e3bd) | [29](29.md) | `kind: 12` and `kind: 10` were removed (use `kind: 1111` instead) |
|
||||
| 2024-11-12 | [926a51e7](https://github.com/nostr-protocol/nips/commit/926a51e7) | [46](46.md) | NIP-05 login was removed |
|
||||
| 2024-11-12 | [926a51e7](https://github.com/nostr-protocol/nips/commit/926a51e7) | [46](46.md) | `create_account` method was removed |
|
||||
@ -30,8 +31,7 @@ reverse chronological order.
|
||||
| 2024-02-07 | [d3dad114](https://github.com/nostr-protocol/nips/commit/d3dad114) | [46](46.md) | Connection token format was changed |
|
||||
| 2024-01-30 | [1a2b21b6](https://github.com/nostr-protocol/nips/commit/1a2b21b6) | [59](59.md) | 'p' tag became optional |
|
||||
| 2023-01-27 | [c2f34817](https://github.com/nostr-protocol/nips/commit/c2f34817) | [47](47.md) | optional expiration tag should be honored |
|
||||
| 2024-01-10 | [3d8652ea](https://github.com/nostr-protocol/nips/commit/3d8652ea) | [02](02.md) | list entries should be chronological |
|
||||
| 2024-01-10 | [3d8652ea](https://github.com/nostr-protocol/nips/commit/3d8652ea) | [51](51.md) | list entries should be chronological |
|
||||
| 2024-01-10 | [3d8652ea](https://github.com/nostr-protocol/nips/commit/3d8652ea) | [02](02.md), [51](51.md) | list entries should be chronological |
|
||||
| 2023-12-30 | [29869821](https://github.com/nostr-protocol/nips/commit/29869821) | [52](52.md) | 'name' tag was removed (use 'title' tag instead) |
|
||||
| 2023-12-27 | [17c67ef5](https://github.com/nostr-protocol/nips/commit/17c67ef5) | [94](94.md) | 'aes-256-gcm' tag was removed |
|
||||
| 2023-12-03 | [0ba45895](https://github.com/nostr-protocol/nips/commit/0ba45895) | [01](01.md) | WebSocket status code `4000` was replaced by 'CLOSED' message |
|
||||
@ -46,10 +46,7 @@ reverse chronological order.
|
||||
| 2023-08-21 | [89915e02](https://github.com/nostr-protocol/nips/commit/89915e02) | [11](11.md) | 'min_prefix' was removed |
|
||||
| 2023-08-20 | [37c4375e](https://github.com/nostr-protocol/nips/commit/37c4375e) | [01](01.md) | replaceable events with same timestamp should be retained event with lowest id |
|
||||
| 2023-08-15 | [88ee873c](https://github.com/nostr-protocol/nips/commit/88ee873c) | [15](15.md) | 'countries' tag was renamed to 'regions' |
|
||||
| 2023-08-14 | [72bb8a12](https://github.com/nostr-protocol/nips/commit/72bb8a12) | [12](12.md) | NIP-12, 16, 20 and 33 were merged into NIP-01 |
|
||||
| 2023-08-14 | [72bb8a12](https://github.com/nostr-protocol/nips/commit/72bb8a12) | [16](16.md) | NIP-12, 16, 20 and 33 were merged into NIP-01 |
|
||||
| 2023-08-14 | [72bb8a12](https://github.com/nostr-protocol/nips/commit/72bb8a12) | [20](20.md) | NIP-12, 16, 20 and 33 were merged into NIP-01 |
|
||||
| 2023-08-14 | [72bb8a12](https://github.com/nostr-protocol/nips/commit/72bb8a12) | [33](33.md) | NIP-12, 16, 20 and 33 were merged into NIP-01 |
|
||||
| 2023-08-14 | [72bb8a12](https://github.com/nostr-protocol/nips/commit/72bb8a12) | [12](12.md), [16](16.md), [20](20.md), [33](33.md) | NIP-12, 16, 20 and 33 were merged into NIP-01 |
|
||||
| 2023-08-11 | [d87f8617](https://github.com/nostr-protocol/nips/commit/d87f8617) | [25](25.md) | empty `content` should be considered as "+" |
|
||||
| 2023-08-01 | [5d63b157](https://github.com/nostr-protocol/nips/commit/5d63b157) | [57](57.md) | 'zap' tag was changed |
|
||||
| 2023-07-15 | [d1814405](https://github.com/nostr-protocol/nips/commit/d1814405) | [01](01.md) | `since` and `until` filters should be `since <= created_at <= until` |
|
||||
|
@ -119,6 +119,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
|
||||
| `14` | Direct Message | [17](17.md) |
|
||||
| `16` | Generic Repost | [18](18.md) |
|
||||
| `17` | Reaction to a website | [25](25.md) |
|
||||
| `20` | Picture | [68](68.md) |
|
||||
| `40` | Channel Creation | [28](28.md) |
|
||||
| `41` | Channel Metadata | [28](28.md) |
|
||||
| `42` | Channel Message | [28](28.md) |
|
||||
@ -282,6 +283,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
|
||||
| `L` | label namespace | -- | [32](32.md) |
|
||||
| `m` | MIME type | -- | [94](94.md) |
|
||||
| `p` | pubkey (hex) | relay URL, petname | [01](01.md), [02](02.md) |
|
||||
| `P` | pubkey (hex) | -- | [57](57.md) |
|
||||
| `q` | event id (hex) | relay URL, pubkey (hex) | [18](18.md) |
|
||||
| `r` | a reference (URL, etc) | -- | [24](24.md), [25](25.md) |
|
||||
| `r` | relay url | marker | [65](65.md) |
|
||||
|
Loading…
Reference in New Issue
Block a user