Nostr WoT

Documentação

Tudo que você precisa para integrar Web of Trust em seu aplicativo.

Referência do SDK

Crie aplicações Nostr com funções de dados, ferramentas de relays, interface de login e consultas opcionais de distância no grafo de seguimentos.

Pacotes publicados

Versões verificadas no npm em 20 de setembro de 2026. O metapacote exporta WoT na raiz e outros módulos por subcaminhos. Também é possível instalar diretamente pacotes com escopo; @nostr-wot/pq é um pacote separado.

Instalação

terminal
$npm install [email protected]

Configuração do provedor

NostrSdkProvider combina configuração de dados, estado da sessão e contexto WoT opcional. Forneça myPubkey explicitamente para consultas ao Oracle; o login não define automaticamente a raiz das consultas WoT.

tsx
"use client";
import type { ReactNode } from "react";
import { NostrSdkProvider } from "nostr-wot-sdk/react";

export function Providers({ children }: { children: ReactNode }) {
  return (
    <NostrSdkProvider
      relays={["wss://relay.damus.io", "wss://nos.lol"]}
      profileAggregators={["wss://purplepag.es"]}
    >
      {children}
    </NostrSdkProvider>
  );
}

Compatibilidade com Oracle

A versão publicada @nostr-wot/wot 1.0.0 usa o contrato antigo /api/distance/FROM/TO?maxHops= e espera o campo distance. Oracle 0.3.0 usa /distance?from=&to=&max_hops= e retorna hops. Alterar apenas a URL base não os torna compatíveis. Use fetch diretamente com Oracle 0.3.0 ou a fonte do grafo local abaixo.

typescript
async function oracleDistance(from: string, to: string) {
  const query = new URLSearchParams({ from, to, max_hops: "2" });
  const response = await fetch(
    "https://wot-oracle.mappingbitcoin.com/distance?" + query,
  );
  if (!response.ok) throw new Error("Oracle HTTP " + response.status);
  const result = await response.json();
  return result.hops as number | null;
}

Referência da API Oracle

Camada de dados

Funções independentes buscam perfis, notas, conversas, seguimentos e interações. Os hooks React adicionam um cache que retorna dados armazenados enquanto os revalida. As funções de dados compartilham seu próprio pool de conexões.

terminal
$npm install @nostr-wot/[email protected]
typescript
import {
  fetchProfile, fetchNotesByAuthor, fetchEngagement, setDefaultRelays,
} from "@nostr-wot/data";

setDefaultRelays(["wss://relay.damus.io", "wss://nos.lol"]);

async function loadAuthor(pubkey: string) {
  const profile = await fetchProfile(pubkey);
  const notes = await fetchNotesByAuthor(pubkey, { limit: 50 });
  const engagement = await fetchEngagement(notes.map(note => note.id));
  return { profile, notes, engagement };
}
tsx
"use client";
import { useProfile } from "@nostr-wot/data/react";

function ProfileCard({ pubkey }: { pubkey: string }) {
  const profile = useProfile(pubkey);
  if (!profile) return null;
  return <h1>{profile.displayName ?? profile.name ?? pubkey}</h1>;
}

Gestão de relays

RelayPool envolve um transporte PoolLike compatível fornecido pela aplicação. Configure urls, use subscribe com onEvent/onEose e feche as assinaturas ao terminar. Um wrapper de relay criado separadamente não se conecta automaticamente ao provedor de dados.

terminal
$npm install @nostr-wot/[email protected]
typescript
import { RelayPool, type PoolLike, type NostrEvent } from "@nostr-wot/relay";

function watchNotes(transport: PoolLike, onEvent: (event: NostrEvent) => void) {
  const pool = new RelayPool({
    urls: ["wss://relay.damus.io", "wss://nos.lol"],
    pool: transport,
  });
  const sub = pool.subscribe({ kinds: [1], limit: 50 }, { onEvent });
  return () => {
    sub.close();
    pool.destroy();
  };
}

Interface de login

LoginButton e useSession compartilham a sessão de NostrSdkProvider. Os métodos incluem NIP-07, NIP-46, geração e importação de chaves. Instale o pacote UI diretamente para importar seus componentes e estilos.

terminal
$npm install @nostr-wot/[email protected]
tsx
"use client";
import { LoginButton, useSession } from "@nostr-wot/ui";
import { NostrSdkProvider } from "nostr-wot-sdk/react";
import "@nostr-wot/ui/styles.css";

function Account() {
  const { pubkey } = useSession();
  return <><LoginButton /><output>{pubkey}</output></>;
}

function App() {
  return <NostrSdkProvider><Account /></NostrSdkProvider>;
}

Distâncias da rede de confiança

WoT consulta o Oracle por padrão. getDistance retorna um número ou null; isInMyWoT retorna um booleano. getDetails fornece saltos, uma contagem numérica de caminhos e informações opcionais sobre conexões intermediárias e seguimentos mútuos. Use chaves públicas hexadecimais válidas de 64 caracteres.

Migração para @nostr-wot/wot 1.0.0

A versão 1.0.0 removeu a detecção de extensão, os métodos de pontuação de confiança e useTrustScore. Use useWoT ou useIsInWoT e leia seus objetos de resultado. Para consultas locais, forneça uma WoTLocalSource, como WotGraph.asWoTSource() de @nostr-wot/graph. Apenas getDistance, isInMyWoT e filterByWoT usam essa fonte; os demais métodos continuam consultando o Oracle.

Exemplo de grafo local

Carregue e rastreie um grafo local antes de passar sua fonte ao WoT. O exemplo React recebe esse grafo preparado e usa useIsInWoT; useWoT também solicita getDetails ao Oracle. @nostr-wot/graph tem sua própria API getScore, separada da API de pontuação removida do WoT.

terminal
$npm install @nostr-wot/[email protected] @nostr-wot/[email protected]
typescript
import { WotGraph } from "@nostr-wot/graph";
import { WoT } from "@nostr-wot/wot";

async function prepareGraph(myPubkey: string, targetPubkey: string) {
  const graph = new WotGraph({
    namespace: "my-app",
    relays: ["wss://relay.damus.io", "wss://nos.lol"],
  });
  await graph.load();
  await graph.crawl(myPubkey, { maxDepth: 2 });
  const wot = new WoT({ source: graph.asWoTSource(), maxHops: 2 });
  const distance = await wot.getDistance(targetPubkey);
  const inWoT = await wot.isInMyWoT(targetPubkey);
  return { graph, distance, inWoT };
}
tsx
"use client";
import type { WotGraph } from "@nostr-wot/graph";
import { NostrSdkProvider, useIsInWoT } from "nostr-wot-sdk/react";

function FollowBadge({ pubkey }: { pubkey: string }) {
  const { inWoT, loading, error } = useIsInWoT(pubkey, { maxHops: 2 });
  if (loading || error || !inWoT) return null;
  return <span>{pubkey}</span>;
}

function LocalTrust({ graph, pubkey }: { graph: WotGraph; pubkey: string }) {
  return (
    <NostrSdkProvider wot={{ enabled: true, options: { source: graph.asWoTSource() } }}>
      <FollowBadge pubkey={pubkey} />
    </NostrSdkProvider>
  );
}