NIP-01
- Descrição básica do protocolo
- Eventos e assinaturas 🔑
- Tags 🏷️
- Kinds (tipos de eventos) 📂
- Comunicação cliente ↔ relay 🌐
Descrição básica do protocolo
rascunho · obrigatório
Este NIP define o protocolo básico do Nostr, que todos os clientes e relays devem implementar. Novos NIPs podem adicionar campos, mensagens e funcionalidades opcionais ou obrigatórias às estruturas e fluxos descritos aqui.
Analogia: imagine que o Nostr é uma cidade de cartas 📬, onde cada pessoa escreve cartas (eventos) e envia para caixas postais (relays). Para que todo mundo entenda, é preciso seguir as mesmas regras.
Eventos e assinaturas 🔑
Cada usuário possui um par de chaves criptográficas:
- Chave privada → segredo do autor da carta (assinatura).
- Chave pública → endereço público para receber mensagens.
No Nostr, o único tipo de objeto é o evento.
Estrutura de um evento 📝
{
"id": "<hash sha256 do evento>",
"pubkey": "<chave pública do autor>",
"created_at": 1700000000,
"kind": 1,
"tags": [],
"content": "Olá Nostr!",
"sig": "<assinatura criptográfica>"
}
Campos explicados:
- id: identidade única do evento, gerada pelo hash. 🔹 Exemplo: cada carta recebe um número de registro único.
- pubkey: chave pública do autor. 🔹 Como colocar o nome e endereço no envelope.
- created_at: timestamp Unix do evento. 🔹 Que horas a carta foi escrita.
- kind: tipo do evento. 🔹 Ex.: mensagem, foto, perfil.
- tags: metadados estruturados. 🔹 Etiquetas que ajudam a organizar cartas.
- content: conteúdo do evento. 🔹 A mensagem escrita.
- sig: assinatura digital do autor. 🔹 Prova de que foi realmente você que escreveu.
Como o id do evento é gerado 🧩
O id é o SHA-256 da serialização JSON UTF-8 do evento:
[
0,
"<pubkey>",
1700000000,
1,
[],
"Olá Nostr!"
]
Regras obrigatórias:
-
UTF-8 para codificação
-
Sem espaços ou quebras de linha
-
Caracteres especiais escapados:
\n→ quebra de linha\"→ aspas\\→ barra invertida\t,\r,\b,\f
Analogia: o id é como colocar a carta em uma máquina que transforma cada letra em números e letras únicos. Qualquer mudança, o número muda.
Tags 🏷️
As tags são arrays de strings que conectam ou descrevem eventos.
Exemplo
"tags": [
["e", "ID_DE_OUTRA_CARTA"],
["p", "CHAVE_PUBLICA_DE_OUTRO_USUARIO"],
["alt", "resposta"]
]
e→ conecta a outro evento (resposta ou thread)p→ menciona outro usuárioalt→ etiqueta personalizada
Analogia: como etiquetas coloridas em cartas que indicam relações.
Tags padronizadas
-
e → evento relacionado:
["e", "<id de outro evento>", "<relay opcional>", "<pubkey opcional>"] -
p → referência a outro usuário:
["p", "<pubkey>", "<relay opcional>"] -
a → eventos substituíveis ou endereçáveis:
["a", "<kind>:<pubkey>:<d>", "<relay opcional>"]
Analogia:
e→ “essa carta responde aquela carta”p→ “falo com João”a→ “essa carta pode ser atualizada ou acessada com código especial”
Kinds (tipos de eventos) 📂
O kind define como interpretar o evento.
Kind 0 → Metadados do usuário
{
"kind": 0,
"content": "{\"name\":\"Alice\",\"about\":\"Desenvolvedora\",\"picture\":\"https://exemplo.com/avatar.png\"}"
}
🔹 Analogia: kind 0 é como preencher um crachá: nome, sobre você e foto.
Faixas de kinds
| Faixa | Tipo | Analogia |
|---|---|---|
1, 2, 4–44, 1000–9999 |
Regulares | cartas normais guardadas para sempre |
0, 3, 10000–19999 |
Substituíveis | cartazes que podem ser atualizados |
20000–29999 |
Efêmeros | bilhetes que desaparecem |
30000–39999 |
Endereçáveis | mensagens secretas com código |
⚠️ Se dois eventos substituíveis tiverem o mesmo timestamp, vence o menor id.
Comunicação cliente ↔ relay 🌐
Relays são caixas postais que recebem e enviam eventos. O cliente abre uma conexão WebSocket por relay e envia/recebe eventos.
Mensagens do cliente para relay
- Enviar evento
["EVENT", { ...evento... }]
Analogia: Alice coloca a carta na caixa postal.
- Criar assinatura (REQ)
["REQ", "sub1", {
"kinds": [1],
"authors": ["<pubkey>"],
"limit": 10
}]
Analogia: Alice pede as últimas 10 cartas de Bob.
- Encerrar assinatura
["CLOSE", "sub1"]
Analogia: Alice diz “não quero mais receber cartas de Bob”.
Filtros 🔍
{
"ids": ["<event_id>"],
"authors": ["<pubkey>"],
"kinds": [1],
"#e": ["<event_id>"],
"since": 1700000000,
"until": 1700001000,
"limit": 50
}
- Dentro de um filtro → todas as regras devem ser verdadeiras (AND)
- Entre filtros → basta uma regra ser verdadeira (OR)
Analogia: escolher apenas cartas que atendem a certos critérios, como “somente cartas do João” e “somente as últimas 5 cartas”.
Mensagens do relay para o cliente
- Enviar evento
["EVENT", "sub1", { ...evento... }]
- Confirmação de envio (OK)
["OK", "<event_id>", true, ""]
Ou erro:
["OK", "<event_id>", false, "rate-limited: escrevendo rápido demais"]
- Fim dos eventos armazenados (EOSE)
["EOSE", "sub1"]
- Encerramento pelo relay (CLOSED)
["CLOSED", "sub1", "error: filtro não suportado"]
Prefixos padronizados de erro ⚠️
duplicate→ carta repetidapow→ carta difícil de enviarblocked→ carta bloqueadarate-limited→ escrevendo rápido demaisinvalid→ carta inválidarestricted→ não permitidomute→ carta ignoradaerror→ outro erro
Analogia: sinais da caixa postal explicando por que a carta não foi aceita.