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

@gosniffy/sdk

v0.3.0

Published

Typed TypeScript client for the Sniffy ASO API (x402-paywalled on Morph).

Readme

@gosniffy/sdk

Typed TypeScript client for the Sniffy ASO API — pay-per-sniff App Store keyword diagnosis, competitor analysis, and metadata recommendations. Paid endpoints settle over the x402 protocol on Morph Hoodi testnet (eip155:2910).

Install

npm i @gosniffy/sdk viem
# or pnpm add @gosniffy/sdk viem

viem is a peer dependency — bring your own wallet.

Usage

import { createSniffy, PaymentRequiredError } from "@gosniffy/sdk";

const sniffy = createSniffy({
  baseUrl: "https://api.sniffy.io",       // default
  signer,                                  // optional viem account; required for .diagnose()
});

const quote = await sniffy.quote({ store: "ios", app, country, keywords });
try {
  const report = await sniffy.diagnose({ sniffId: quote.sniffId });
} catch (err) {
  if (err instanceof PaymentRequiredError) {
    // intercept and surface payment details to user
  }
  throw err;
}

Three methods

| Method | Endpoint | Payment | Returns | |--------|----------|---------|---------| | sniffy.sample() | GET /api/v1/aso/sample | Free | Canned sample report (always works) | | sniffy.quote(input) | POST /api/v1/aso/quote | Free | Quote with shallowScan preview | | sniffy.diagnose(input) | POST /api/v1/aso/diagnose | x402 | Full paid report with receipt |

Diagnose options

By default, .diagnose() auto-pays when a signer is configured. Pass { autoPay: false } to intercept the 402 and drive the payment UX yourself:

try {
  await sniffy.diagnose(input, { autoPay: false });
} catch (err) {
  if (err instanceof PaymentRequiredError) {
    // err.response — full DiagnoseUnpaidResponse
    // err.payment  — x402 payment requirements (network, amount, asset, payTo, …)
    // err.sniffId  — request identifier
  }
}

Wallet setup (testnet)

The default network is Morph Hoodi testnet (eip155:2910). Use a throwaway key — never paste a mainnet private key into a CLI or env file.

import { privateKeyToAccount } from "viem/accounts";

const signer = privateKeyToAccount(process.env.SNIFFY_PRIVATE_KEY as `0x${string}`);
const sniffy = createSniffy({ signer });

Fund the wallet with HoodiTestToken (the demo asset at 0xEcF966Cc754BC411E1F1106fbb4e343b835E85E4) via the Morph faucet.

Provenance labels

Every report field carries a provenance label: live | cached | fixture | inferred. Surface them when reporting to the user — fixture results are best-effort, not real-time data.

License

MIT