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

@notrace/stealth-sdk

v1.0.0

Published

Real stealth addresses on Solana. ECDH-derived one-time addresses on ed25519, view-key recoverable, with a Memo-program footprint. Extracted from the production NoTrace wallet.

Readme

@notrace/stealth-sdk

Real stealth addresses on Solana. ECDH-derived, view-key recoverable, with a Memo-program footprint.

npm License ed25519


Extracted from the production NoTrace wallet. Zero relayers, zero mixers, zero on-chain program — just a fresh one-time address per payment, derived in the payer's browser. The recipient scans the Memo program with a view-key and finds their payments locally.

[!NOTE] This is the same code that ships in the NoTrace web wallet. Browser, Node 18+, Deno and Bun are all supported. No Buffer, no globals.

Install

npm install @notrace/stealth-sdk
# or
pnpm add @notrace/stealth-sdk
# or
yarn add @notrace/stealth-sdk

@solana/web3.js is an optional peer dep — only the scanner needs it (and even there, the scanner takes a small RpcLike interface, so you can wire in your own client).

Quick start

Recipient — generate identity, share a pay-link

import { generateMetaKey, makePayLink } from "@notrace/stealth-sdk";

const meta = generateMetaKey();
// Persist `meta.seed` somewhere encrypted — that's your whole identity.
const link = makePayLink(meta.pub);
// → "https://notracesol.xyz/pay#m=4mNp9q8K…"
// Share `link` anywhere. Nobody learns who the recipient is.

Payer — derive a one-time address and send

import { deriveStealthSender, encodeMemo, parsePayLink } from "@notrace/stealth-sdk";

const metaPub = parsePayLink(linkFromRecipient)!;
const { stealthPub, ephPub } = deriveStealthSender(metaPub);

// Build a Solana tx:
//   1. SystemProgram.transfer → stealthPub (base58)
//   2. Memo instruction with the body `encodeMemo(ephPub)` (e.g. "nt1:4mNp…")
// Sign + send with Phantom/web3.js. The recipient's scanner will find it.

Recipient — scan for incoming payments

import { Connection } from "@solana/web3.js";
import { scanForPayments, metaFromSeed } from "@notrace/stealth-sdk";

const meta = metaFromSeed(savedSeed);
const rpc = new Connection("https://solana-rpc.publicnode.com", "confirmed");

const payments = await scanForPayments(meta, rpc as any, { limit: 200 });
for (const p of payments) {
  console.log(p.lamports / 1e9, "SOL @", p.stealthPub, "from", p.source);
}

Recipient — sweep funds out of a stealth address

import { signWithScalar, verify } from "@notrace/stealth-sdk";

// `payment.stealthScalar` from the scanner is the secret you need.
const message = transferTx.serializeMessage();           // web3.js
const sig = signWithScalar(payment.stealthScalar, transferTx.feePayer!.toBytes(), message);
transferTx.addSignature(transferTx.feePayer!, Buffer.from(sig));
// Optionally double-check:
console.assert(verify(sig, message, transferTx.feePayer!.toBytes()));
await rpc.sendRawTransaction(transferTx.serialize());

How it works

NoTrace is an ERC-5564-style stealth-address scheme ported to ed25519:

SENDER                                     RECIPIENT
──────                                     ─────────
eph_scalar, eph_pub  ← fresh keypair       meta_scalar, meta_pub  ← persistent
shared = eph_scalar × meta_pub             shared = meta_scalar × eph_pub
tweak  = SHA512(ver ‖ shared ‖             tweak  = SHA512(ver ‖ shared ‖
                eph_pub ‖ meta_pub) mod L                  eph_pub ‖ meta_pub) mod L
stealth_pub = meta_pub + tweak × G         stealth_scalar = (meta_scalar + tweak) mod L
                                           stealth_pub    = stealth_scalar × G

The shared point is identical on both sides because eph_scalar × (meta_scalar × G) = meta_scalar × (eph_scalar × G). The sender knows stealth_pub (a valid Solana address) but not stealth_scalar — they can't spend the funds they just sent. Only the recipient, applying their meta_scalar to the sender-published eph_pub, recovers the spend scalar.

The protocol is self-contained: no Solana program needed. The wire format is a ~48-character Memo (nt1:<base58_eph_pub>) attached to a plain SystemProgram transfer.

API reference

| Export | Returns | Notes | | --- | --- | --- | | generateMetaKey() | MetaKey | Fresh meta-keypair. Persist .seed. | | metaFromSeed(seed) | MetaKey | Deterministic from a 32-byte seed. | | pubFromScalar(scalar) | Uint8Array(32) | scalar × G. | | deriveStealthSender(metaPub) | { stealthPub, ephPub } | Call once per payment. | | recoverStealth(metaScalar, metaPub, ephPub) | { stealthScalar, stealthPub } | Recipient-side. | | signWithScalar(scalar, pub, msg) | Uint8Array(64) | ed25519 sig from raw scalar. | | verify(sig, msg, pub) | boolean | Standard ed25519 verify. | | encodeMemo(ephPub) | string | nt1:<base58_eph_pub>. | | parseMemo(s) | Uint8Array(32) \| null | Returns null for non-NoTrace memos. | | makePayLink(metaPub, origin?) | string | https://…/pay#m=<base58>. | | parsePayLink(url) | Uint8Array(32) \| null | Accepts #m= or ?m= form. | | scanForPayments(meta, rpc, opts?) | StealthPayment[] | Polls the Memo program. | | checkSignature(sig, meta, rpc) | StealthPayment \| null | Single-tx variant. | | bs58encode / bs58decode | — | Zero-dep base58. |

Constants: MEMO_PREFIX ("nt1:"), MEMO_PROGRAM_ID, VERSION.

Security notes

  • The seed is the only secret. Lose meta.seed and you lose all incoming funds. Back it up encrypted, the same way you'd treat any private key.
  • The signing path uses a hedged Schnorr nonce (r = SHA512(random_prefix ‖ pub ‖ msg)), so bad randomness can't leak the scalar through a colliding r. Each stealth scalar typically signs just one sweep tx, but the hedge costs nothing.
  • The nt1: memo prefix is intentional — a future protocol revision can ship nt2: without breaking old wallets, which will simply skip those memos.
  • Stealth addresses are real ed25519 points; they're indistinguishable on-chain from any other Solana address.

License

MIT — see LICENSE.

Built by NoTrace. Issues, PRs, and audits welcome.