npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@lastrum/auth

v0.2.1

Published

Sign-In with Liquid via Lastrum (SIWL) — server-side verify + client helpers + React component.

Readme

@lastrum/auth

Sign-In with Liquid via Lastrum (SIWL) — login federado para apps web, estilo Sign-In with Ethereum (EIP-4361) adaptado para Liquid Network.

  • Sem custódia, sem senha, sem OAuth.
  • Identidade pseudonima por-origem (mesma carteira gera pubkeys diferentes em apps diferentes — privacy by design).
  • Verificação offline no servidor (sem chamadas pra Lastrum).
  • Zero dependências exceto @noble/secp256k1 + @noble/hashes.

Install

npm install @lastrum/auth
# ou
bun add @lastrum/auth

Quickstart

Servidor (Node.js)

import express from "express";
import { InMemoryNonceStore, verifyMessage } from "@lastrum/auth/server";

const app = express();
app.use(express.json());

const nonceStore = new InMemoryNonceStore();

app.post("/auth/nonce", async (req, res) => {
  const nonce = await nonceStore.issue({ ttlSeconds: 600 });
  res.json({ nonce, expirationMinutes: 10 });
});

app.post("/auth/verify", async (req, res) => {
  const { message, pubkey, address, signature } = req.body;
  const result = await verifyMessage(message, {
    expectedDomain: req.hostname, // ou seu domain fixo
    pubkey,
    address,
    signature,
    nonceStore,
  });
  if (!result.ok) return res.status(401).json({ error: "auth_failed" });
  // result.pubkey é a identidade da sessão (estável por usuário pra este app)
  const session = createSession(result.pubkey);
  res.cookie("session", session, { httpOnly: true, secure: true, sameSite: "lax" });
  res.json({ ok: true, pubkey: result.pubkey });
});

app.listen(3000);

Cliente (browser)

import { SignInWithLastrumClient } from "@lastrum/auth";

const client = new SignInWithLastrumClient({
  nonceEndpoint: "/auth/nonce",
});

document.getElementById("login").addEventListener("click", async () => {
  const result = await client.signIn({
    domain: location.host,
    uri: location.origin + "/login",
    statement: "Login para gerenciar seus pedidos.",
  });
  // POST pro servidor verificar
  const res = await fetch("/auth/verify", {
    method: "POST",
    credentials: "include",
    headers: { "content-type": "application/json" },
    body: JSON.stringify(result),
  });
  if (res.ok) window.location.href = "/dashboard";
});

React (opcional)

O componente aceita 3 modos de configuração — escolha conforme sua arquitetura:

1. Produção com backend (recomendado)

import { SignInWithLastrum } from "@lastrum/auth/react";

<SignInWithLastrum
  nonceEndpoint="/auth/nonce"
  verifyEndpoint="/auth/verify"
  onLogin={({ pubkey }) => console.log("Logado:", pubkey)}
/>

Servidor controla emissão e single-use do nonce (Redis), e emite a sessão (cookie/JWT) após verify. Padrão pra SaaS, exchanges, qualquer dapp com API própria. Use isto em produção.

2. SPA sem backend / Edge functions

import { SignInWithLastrum } from "@lastrum/auth/react";
import { verifyMessage, InMemoryNonceStore } from "@lastrum/auth";

const nonces = new InMemoryNonceStore();

<SignInWithLastrum
  nonceFn={async () => nonces.issue({ ttlSeconds: 600 })}
  verifyFn={async ({ message, signature, pubkey, address }) => {
    const r = await verifyMessage(message, {
      expectedDomain: location.host, pubkey, address, signature, nonceStore: nonces,
    });
    if (!r.ok) throw new Error(r.reason);
    return r;
  }}
  onLogin={(result) => /* persiste em localStorage / Zustand / etc */}
/>

Sem servidor — nonceFn produz o nonce, verifyFn valida assinatura client-side. Anti-replay vive em memória do tab (suficiente pra dapps puramente client-side onde a sessão também é client-side).

3. Demo mode (sem verify)

<SignInWithLastrum
  nonceFn={() => crypto.randomUUID()}
  onLogin={(result) => console.log("Signed!", result.signature)}
/>

Sem verifyEndpoint/verifyFn → o componente pula verify e dispara onLogin com o SignInResult cru ({ message, signature, address, pubkey }). Útil pra páginas de showcase, playgrounds, prototipagem.

⚠️ Quando escolher cada um: se você tem backend e quer sessão real, 1. Se é SPA puro / Edge / Cloudflare Worker, 2. Se é só demo / preview UI, 3.

API

verifyMessage(message, opts) → VerifyResult

Server-side. Verifica:

  • Parse OK
  • domain bate com expectedDomain
  • pubkey e address batem com os reportados
  • Janela temporal: Issued At ≤ now + 60s skew, now ≤ Expiration Time, janela ≤ 10 min
  • Nonce single-use (consome via nonceStore)
  • Assinatura ECDSA secp256k1 sobre sha256(message) válida

Retorna { ok: true, pubkey, address, issuedAt, message } ou { ok: false, reason: "..." } com reason opaca pra log.

SignInWithLastrumClient.signIn(params) → SignInResult

Cliente. Encadeia: fetch nonce → liquid_requestAccountsbuildMessageliquid_signMessage. Retorna shape pronto pra POST no /verify.

NonceStore

Interface mínima. Implementações:

  • InMemoryNonceStore — pra dev/teste
  • Em produção, wrap Redis (ver doc docs/integrations/login-with-redbird.md)

buildMessage(params) / parseMessage(text)

Helpers puros se você quer montar/parsear mensagens fora do client. Formato em ADR-0025.

Versionamento

Pacote segue semver próprio começando em 0.1.0. Independente da extensão Lastrum (que usa cohort version 3.x). Compatível com Lastrum v3.5+ (Spec 010 — Lastrum Provider).

License

MIT