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

dero-auth

v0.2.1

Published

Wallet-based authentication for DERO — Sign in with your DERO wallet. No email, no password, just cryptographic proof.

Readme

dero-auth

Sign in with your DERO wallet. No email. No password. Just cryptographic proof of wallet ownership.

dero-auth is a TypeScript library that provides wallet-based authentication for DERO — a privacy-focused cryptocurrency with encrypted transactions. It works like "Sign in with Ethereum" (SIWE/EIP-4361), but for DERO's privacy chain.

Privacy advantage: Unlike Ethereum auth, authenticating with DERO doesn't expose your transaction history. Your on-chain activity remains invisible to the service.

Features

  • Pure TypeScript signature verification (Schnorr on BN256) — no wallet needed server-side
  • React components — drop-in <SignInWithDero /> button and useDeroAuth() hook
  • Next.js integration — ready-made API route handlers and auth middleware
  • XSWD client — connects to DERO wallets (Engram, CLI) via WebSocket
  • SIWE-style message format — human-readable, domain-bound, replay-protected
  • JWT sessions — standard token-based session management
  • Zero personal data — just a cryptographic address

Quick Start

Install

npm install dero-auth

Set a JWT Secret (required)

Use a strong secret (at least 32 bytes):

export JWT_SECRET="$(openssl rand -base64 32)"

1. Server: Create API Routes (Next.js App Router)

// app/api/auth/challenge/route.ts
import { createAuthHandlers } from "dero-auth/next";

const { challengeHandler } = createAuthHandlers({
  domain: "myapp.com",
  uri: "https://myapp.com",
  jwtSecret: process.env.JWT_SECRET!,
});

export const POST = challengeHandler;
// app/api/auth/verify/route.ts
import { createAuthHandlers } from "dero-auth/next";

const { verifyHandler } = createAuthHandlers({
  domain: "myapp.com",
  uri: "https://myapp.com",
  jwtSecret: process.env.JWT_SECRET!,
});

export const POST = verifyHandler;

For production deployments, use a shared nonce store (Redis/DB) via the nonceStore option so replay protection works across multiple instances.

Production Nonce Store (Redis)

dero-auth includes a Redis-backed NonceStore adapter with atomic consume:

import { createClient } from "redis";
import { createAuthHandlers } from "dero-auth/next";
import { createRedisNonceStoreFromNodeRedis } from "dero-auth/server";

const redis = createClient({ url: process.env.REDIS_URL! });
await redis.connect();

const nonceStore = createRedisNonceStoreFromNodeRedis(redis, {
  keyPrefix: "myapp:auth:nonce:",
});

const { challengeHandler, verifyHandler } = createAuthHandlers({
  domain: "myapp.com",
  uri: "https://myapp.com",
  jwtSecret: process.env.JWT_SECRET!,
  nonceStore,
});

Install a Redis client of your choice in your app (redis or ioredis).

2. Client: Add the Provider and Button

// app/layout.tsx (or any parent component)
import { DeroAuthProvider } from "dero-auth/react";

export default function Layout({ children }) {
  return (
    <DeroAuthProvider appName="My App">
      {children}
    </DeroAuthProvider>
  );
}
// app/page.tsx (or any page)
import { SignInWithDero } from "dero-auth/react";

export default function LoginPage() {
  return <SignInWithDero />;
}

That's it. The button handles the full flow: wallet connection, challenge signing, and verification.

3. Custom Hook (Alternative)

If you don't want the provider pattern:

"use client";
import { useDeroAuth } from "dero-auth/react";

export default function LoginPage() {
  const { signIn, signOut, isAuthenticated, address, isLoading } = useDeroAuth();

  if (isAuthenticated) {
    return (
      <div>
        <p>Signed in as {address}</p>
        <button onClick={signOut}>Sign Out</button>
      </div>
    );
  }

  return (
    <button onClick={signIn} disabled={isLoading}>
      {isLoading ? "Connecting..." : "Sign In with DERO"}
    </button>
  );
}

How It Works

Authentication Flow

User                    Browser                   Server
 |                         |                         |
 | Click "Sign In"         |                         |
 |------------------------>|                         |
 |                         | POST /auth/challenge     |
 |                         |   { address }            |
 |                         |------------------------>|
 |                         |   { messageText, nonce } |
 |                         |<------------------------|
 |                         |                         |
 |  Wallet: "Sign this?"   | XSWD: SignData(message) |
 |  [Approve] [Deny]       |                         |
 |------------------------>|                         |
 |  PEM signature           |                         |
 |                         | POST /auth/verify        |
 |                         |   { signature, nonce }   |
 |                         |------------------------>|
 |                         |     Verify Schnorr sig   |
 |                         |     Check domain/nonce   |
 |                         |   { session (JWT) }      |
 |                         |<------------------------|
 |  Authenticated!          |                         |

Message Format

The message shown to the user in their wallet:

myapp.com wants you to sign in with your DERO wallet:
dero1qy...abc123

Sign in to My App

URI: https://myapp.com
Version: 1
Chain ID: dero-mainnet
Nonce: k8j2m4n6p8q0
Issued At: 2026-02-14T12:00:00.000Z
Expiration Time: 2026-02-14T12:05:00.000Z

Cryptography

  • Signature scheme: Schnorr signatures on BN256 (Barreto-Naehrig 254-bit curve)
  • Hash function: Keccak-256, reduced modulo the curve order
  • Address format: Bech32 with 33-byte compressed G1 public key
  • Verification: Pure TypeScript using @noble/curves (audited by Cure53)
  • No blockchain query needed: Signatures are verified mathematically, offline

Package Exports

| Import | Description | |-----------------------|--------------------------------------| | dero-auth | Core types and message format | | dero-auth/crypto | Pure crypto: Schnorr verify, BN256, address parsing | | dero-auth/server | Server SDK: challenges, verification, JWT sessions | | dero-auth/client | Browser SDK: XSWD wallet connection, signing flow | | dero-auth/react | React: Provider, button, hooks | | dero-auth/next | Next.js: API handlers, auth middleware |

API Reference

Core (dero-auth)

import {
  serializeMessage,   // DeroAuthMessage → string
  parseMessage,        // string → DeroAuthMessage
  validateMessage,     // Check domain, nonce, expiry
  generateNonce,       // Crypto-random nonce string
  type DeroAuthMessage,
  type DeroAuthConfig,
  type DeroAuthSession,
} from "dero-auth";

Crypto (dero-auth/crypto)

import {
  verifySignature,     // Verify PEM signature → { address, message }
  parsePEM,            // Parse DERO PEM format
  decodeAddress,       // DERO address → public key
  encodeAddress,       // Public key → DERO address
  isValidAddress,      // Validate address format
  reducedHash,         // Keccak256 mod curve order
  decompressG1,        // 33 bytes → G1 point
  compressG1,          // G1 point → 33 bytes
} from "dero-auth/crypto";

Server (dero-auth/server)

import {
  createChallengeServer,  // Challenge generation + nonce management
  verifyAuth,             // Full verification pipeline
  createSessionManager,   // JWT session creation/verification
} from "dero-auth/server";

Client (dero-auth/client)

import {
  XSWDClient,         // Low-level XSWD WebSocket client
  createAuthClient,   // High-level auth flow client
} from "dero-auth/client";

React (dero-auth/react)

import {
  DeroAuthProvider,    // Context provider
  SignInWithDero,      // Drop-in button
  useDeroAuth,         // Standalone hook
  useDeroAuthContext,  // Hook for use within provider
} from "dero-auth/react";

Next.js (dero-auth/next)

import {
  createAuthHandlers,        // API route handlers
  createDeroAuthMiddleware,  // Auth middleware
  getAuthAddress,            // Extract address from request
} from "dero-auth/next";

Protecting Routes (Next.js Middleware)

// middleware.ts
import { createDeroAuthMiddleware } from "dero-auth/next";

export const middleware = createDeroAuthMiddleware({
  jwtSecret: process.env.JWT_SECRET!,
  protectedPaths: ["/dashboard", "/api/protected"],
  loginPath: "/login",
});

export const config = {
  matcher: ["/dashboard/:path*", "/api/protected/:path*"],
};

Requirements

  • DERO wallet: Engram (desktop) or DERO CLI wallet with XSWD enabled
  • Node.js: >= 20.19.0
  • React: 18+ or 19+ (optional, for React components)
  • Next.js: 14+ (optional, for Next.js helpers)

Wallet Compatibility

| Wallet | Connection | Status | |----------------|-------------|-----------| | Engram (desktop) | XSWD (ws://localhost:44326) | Supported | | DERO CLI wallet | XSWD (ws://localhost:10103) | Supported |

Why Not Just Use Ethereum Auth?

| | Ethereum (SIWE) | DERO Auth | |---|---|---| | Transaction privacy | All transactions visible on-chain | Transactions encrypted, invisible to verifier | | Wallet extension | MetaMask required | Connects to local wallet via WebSocket | | Personal data | Address links to full history | Address reveals nothing about activity | | Verification | Pure JS (ecrecover) | Pure JS (Schnorr on BN256) |

Development

# Install dependencies
npm install

# Run tests
npm test

# Type check
npx tsc --noEmit

# Build
npm run build

# Run demo app
JWT_SECRET="$(openssl rand -base64 32)" cd demo && npm install && npm run dev

License

MIT — see LICENSE

DHEBP is not affiliated with or endorsed by the DERO Project or its core developers.