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

@flashylabs/wdk-capability-audit

v0.1.0

Published

Scan a project's node_modules for installed @tetherto/wdk-* packages and report what chains each declares — mainnet, testnet, or unknown, against a small hand-maintained registry of chain identifiers this package is confident are real. Never guesses at a

Readme

@flashylabs/wdk-capability-audit

        ██
       ██
      ██████
        ██
       ██
      ██

A capability audit for wallets built on Tether's WDK. It scans a project's node_modules for every installed @tetherto/wdk-* package, reads what each one declares about the chains it supports, and classifies each chain as mainnet, testnet, or unknown — against a small, hand-maintained registry, never a guess.

tests license node

Built by Flashy Labs — part of the open-source toolkit we ship for teams building on Tether's WDK. Its siblings are @flashylabs/wdk-policy-guard and @flashylabs/wdk-staking-kit.

Why this exists

Before a team commits to a chain in production, somebody has to answer a boring but load-bearing question: which of the WDK modules we have installed actually point at mainnet, and which are still wired to a testnet we forgot to swap out? That question gets answered by hand today — open each @tetherto/wdk-* package, find its chain configuration, cross-reference the chain id against what you remember mainnet and testnet to be. It is exactly the kind of check that is easy to get right once and easy to get wrong silently the second time, six months later, after a dependency bump nobody re-reviewed.

This package turns that manual check into something that runs the same way every time and refuses rather than guesses when it isn't sure — see "Status" below for the one place that discipline currently bites: the assumption this tool makes about how a package declares its chains has not yet been confirmed against a real @tetherto/wdk-* release.

Install

npm install --save-dev @flashylabs/wdk-capability-audit

Quickstart

npx wdk-capability-audit                 # human-readable table, scans ./node_modules
npx wdk-capability-audit --dir ../app    # scan a different project
npx wdk-capability-audit --json          # the full wdk-capability-audit-report/1 report, on stdout

Or use it as a library:

import { auditDirectory, validateReport } from '@flashylabs/wdk-capability-audit'

const report = auditDirectory('/path/to/project')
console.log(report.summary)
// { packagesScanned: 3, packagesInspected: 0, packagesUnrecognizedShape: 3,
//   packagesUnreadable: 0, chainsTotal: 0,
//   chainsByClassification: { mainnet: 0, testnet: 0, unknown: 0 } }

console.log(validateReport(report)) // [] — this report conforms to schema/report.schema.json

What it produces

The primary product is the JSON report, not the table — --json emits a document conforming to schema/report.schema.json (JSON Schema, draft 2020-12), contract wdk-capability-audit-report/1:

{
  "contract": "wdk-capability-audit-report/1",
  "tool": { "name": "@flashylabs/wdk-capability-audit", "version": "0.1.0" },
  "generatedAt": "2026-09-22T12:00:00.000Z",
  "dir": "/path/to/project",
  "packages": [
    {
      "name": "@tetherto/wdk-wallet-evm",
      "version": "1.0.0-beta.19",
      "status": "unrecognized-shape",
      "chains": []
    }
  ],
  "summary": {
    "packagesScanned": 1,
    "packagesInspected": 0,
    "packagesUnrecognizedShape": 1,
    "packagesUnreadable": 0,
    "chainsTotal": 0,
    "chainsByClassification": { "mainnet": 0, "testnet": 0, "unknown": 0 }
  }
}

summary is computed from packages by buildReport() — there is no call shape through which a caller can pass in a summary that disagrees with the array beside it. validateReport(report) re-derives it independently and returns a list of problems (empty means valid) for any report that reaches your code some other way.

API

| Export | What it does | |---|---| | discoverWdkPackages(dir?) | Reads <dir>/node_modules/@tetherto/wdk-* and returns {name, version, dir, readable} for each. Reads package.json only — never requires or imports a package's code. | | inspectModule(pkg) | Reads one discovered package's package.json for its declared chains (see "Status" for the assumed shape). Returns {status, chains}, status one of inspected / unrecognized-shape / unreadable. Never throws, never guesses. | | classifyChain(namespace, id) | Looks up {namespace, id} in the hand-maintained registry. Returns 'mainnet', 'testnet', or 'unknown''unknown' for anything not listed, always. | | listRegisteredChains() | Every chain this version's registry recognizes, as {namespace, id, classification}. | | buildReport({dir, packages, now?}) | Assembles a wdk-capability-audit-report/1 report, with summary always derived, never accepted as input. | | deriveSummary(packages) | The summary a given packages array implies — what validateReport() checks a report's own summary against. | | validateReport(report) | Validates a report against schema/report.schema.json plus the summary-derivation rule. Returns an array of problems; empty means valid. | | auditDirectory(dir?, now?) | The full pipeline: discover, inspect, classify, build. What the CLI calls. | | REPORT_CONTRACT, INSPECTION_STATUSES, CLASSIFICATIONS | The closed vocabularies every report's contract, status, and classification fields are drawn from. | | getFaucet(namespace, id) | Looks up the testnet faucet listed for a chain. Returns {name, url} or null — never a guess, and a fresh copy each call. | | listFaucets() | Every faucet this version lists, as {namespace, id, name, url}. | | listNoFaucetByDesign() | Testnet chains this package recognizes but deliberately lists no faucet for, with the reason — e.g. a deprecated network. Distinct from a chain simply not yet added. |

Full TypeScript declarations ship with the package, generated from the source's own JSDoc so the types can never drift from the implementation. test-types/consumer.ts is the type-level test that would fail if they ever did.

Faucets

Once you know a chain is testnet, the next question is where to get funds. wdk-capability-audit --faucets (or --faucets --json) prints a small, hand-maintained list — one faucet per testnet chain this package recognizes, source-checked on the date in FAUCET_REGISTRY_VERSION:

npx wdk-capability-audit --faucets

This package's own code never fetches or verifies these URLs. A listed faucet can go offline or change its terms at any time — see docs/wallet-style doctrine elsewhere in this org: "committed is not served." Treat the list as a checked-once pointer, not a live status.

bitcoin:testnet3 is deliberately listed with no faucet, not silently omitted: Bitcoin Core 30.0 (October 2025) removed testnet3 support entirely, and Core 28.0 had already added testnet4 (BIP 94) as its intended replacement. listNoFaucetByDesign() — and the CLI's own output — says so by name, rather than leaving a reader to wonder whether testnet3 was simply forgotten.

What this does not do

  • It does not modify any file or package it scans.
  • It does not execute or import untrusted code — it only reads package.json and the package's declared exports.
  • It does not guess at an unrecognized chain. It refuses.
  • It does not replace a human's judgment about whether a given chain is safe to point production at.

Design principles

  • This package reads; it never writes. Discovery and inspection read only package.json files as JSON — never a package's own JavaScript, and never anything executed or imported — so scanning an untrusted node_modules tree is safe by construction.
  • The registry only grows by verification, never by convenience. A chain id absent from src/registry.js classifies unknown, permanently, until someone adds it with a documented source — never inferred from a package's own claim about itself.
  • The summary is arithmetic, not an assertion. summary is computed from packages inside buildReport(), and validateReport() recomputes it independently — a report cannot claim a count its own array disagrees with.
  • An empty result is not a clean one. Zero installed @tetherto/wdk-* packages is a refusal (wdk-capability-audit: found no @tetherto/wdk-* packages, exit code 1), never a report with packages: [] that reads indistinguishably from real coverage.
  • An audit that cannot recognize what it is looking at must say so by name, because a shape mistaken for a fact is a fact nobody actually checked.

Status

Pre-1.0 (0.1.0). Read this section before trusting a report against anything that matters.

The chain-inspection convention is an explicit, unverified assumption. inspectModule() looks for a package's chains at wdk.chains inside its own package.json — a plain object keyed by a chain label, each entry shaped { "namespace": "evm", "id": 1 }. This convention has not been observed in a real, published @tetherto/wdk-* package. While building this tool, six real packages were inspected directly on the development machine — @tetherto/wdk (1.0.0-beta.18), wdk-wallet (1.0.0-beta.19), wdk-wallet-evm (1.0.0-beta.19), wdk-wallet-evm-erc-4337 (1.0.0-beta.20), wdk-wallet-tron (1.0.0-beta.13), and wdk-failover-provider (1.0.0-beta.2) — and none of them declares a wdk.chains field, or any static chain/network configuration, in package.json. Chain configuration in those packages is supplied by the integrating application at runtime — e.g. wdk.registerWallet('evm', WalletManagerEvm, { chainId: 84532, provider }) — not published by the package itself as static, statically-readable data.

Given that gap, inspectModule() is designed to do the honest thing rather than the convenient one: every one of those six real packages inspects as status: "unrecognized-shape" today, and that refusal is itself the behavior under test (test/inspect.test.mjs, test/audit.test.mjs). This is this tool telling the truth about a real gap between an assumed convention and what currently ships, not a bug to be papered over. If a future WDK release adopts this convention (or a different one this tool should learn), inspectModule() is the one place that needs to change — see CONTRIBUTING.md.

Discovery matches @tetherto/wdk-* exactly, as specified. The umbrella @tetherto/wdk package (name exactly wdk, no suffix) is therefore never scanned by this tool, by design — only @tetherto/wdk-<something> packages are.

The chain registry is intentionally short. src/registry.js lists only the chain identifiers this package's authors are confident are correct: Ethereum mainnet and its current public testnets, four EVM L2 mainnet/testnet pairs, Tron's mainnet/Nile/Shasta, and Bitcoin's mainnet, testnet3, testnet4, and signet. A production deployment on a chain not in that list will classify unknown — that is correct behavior, not a gap to silently work around by guessing.

The faucet list (src/faucets.js, --faucets) is checked by web search, not verified live. Every URL was confirmed against at least one official docs page or the faucet's own title, on the date in FAUCET_REGISTRY_VERSION — this package's own code never fetches them, so a faucet can go stale between that date and when you read this. bitcoin:testnet3 is a worked example of the discipline this whole package is built on: Bitcoin Core deprecated and then removed testnet3 support (found via the same search pass that built the rest of the list), so rather than listing a faucet for a network that's disappearing, listNoFaucetByDesign() says so by name and points at the replacement.

Testing

npm test          # node's built-in test runner, no external services, no network access
npm run check     # confirms the generated manifest is current

Tests are hermetic: test/fixtures/ contains a synthetic node_modules/@tetherto/... tree (some packages shaped to match the assumed convention, some shaped like the real packages above, one with invalid JSON, one with an empty chain list) — nothing depends on anything actually being installed on the machine running CI.

Security

This package never signs anything, holds a key, or makes a network call. Its entire job is reading local package.json files and classifying what it finds against a fixed, versioned table — see SECURITY.md for the full threat model and how to report a vulnerability.

Provenance

Built to turn a manual, ad-hoc review step — "what chains do our installed WDK modules actually point at?" — into something repeatable, open-sourced because the question belongs to every team building on WDK, not just to us. See CHANGELOG.md.

Contributing

See CONTRIBUTING.md.

⚡ The Strike

This README commits to a secret, the way classifyChain() commits to a verdict — fixed in the registry before you ask, checkable by anyone after:

sha256: c6d3f6a386b47dde5db720cd2fb3c7163488da27a5bf9f499ee2b88eeac1c7a8

The preimage is already on this page — one exact sentence from "Design principles," above. Recover it, hash it yourself (never trust, verify — that includes us), and open an issue titled ⚡ STRIKE containing the sentence. First verified striker per release gets their name in STRIKERS.md.

No prize, no token. An audit tool has enough unverifiable claims in the world already; this one isn't going to add one about itself.

License

Apache-2.0 © 2026 Flashy Labs


Built by Flashy Labs, the mesh platform for organisations' agents. If something here is broken, unclear, or just interesting, open an issue — we read them.