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

usewinch

v0.1.2

Published

Pay-per-crawl middleware — turn any content route into an x402 paywall AI agents can actually pay (USDC on Arc via Circle Gateway). Auto-generates the free /preview and paid /content from your existing pages.

Readme

usewinch

Express middleware that turns any route into an x402-gated nanopayment wall on Arc testnet. Buyers pay fractions of a cent in USDC; settlement is instant via Circle Gateway batching; no payment-processor contract or custodial wallet required for the publisher.

Install

npm install usewinch
# Peer deps (required — the /server bundle hard-imports these at load time):
npm install @x402/core @x402/evm

usewinch ships @circle-fin/[email protected] as a direct dependency. No patching is required — 3.2.0 ships with the corrected maxTimeoutSeconds (604800 s / 7 days) that Circle's facilitator now requires.

Quick start — one line, both routes

createLeptonarcRouter mounts a free /preview/:id (teaser auto-derived from your content) and a paid, 402-gated /content/:id for you — no route boilerplate, no second handler.

import express from "express";
import { createLeptonarcRouter } from "usewinch";

const app = express();

app.use(createLeptonarcRouter({
  payTo: "0xYourWallet",
  price: "$0.001",                       // per crawl
  publisherKey: "pub_…",                 // from your leptonarc dashboard
  backendUrl: "https://your-leptonarc.app",
  content: {
    "1": { title: "The Lepton Standard", body: "…full article text…" },
  },
}));

app.listen(4030);
  • GET /preview/1{ id, title, abstract, price, payTo }free. abstract is auto-excerpted from body (or pass your own).
  • GET /content/1HTTP 402 until the agent pays; then your full body, settlement reported to your dashboard.

content may also be an async lookup, so it works with a DB / CMS / filesystem:

createLeptonarcRouter({ payTo, price: "$0.002",
  content: async (id) => db.articles.findById(id) }); // → { title, body, abstract? } | null

Scaffold a ready-to-run server with:

npx usewinch init

No install-time magic. This package never rewrites your server code on npm install — auto-injecting middleware via a postinstall script is a supply-chain anti-pattern. You get an explicit app.use(...) and an opt-in npx usewinch init instead.

Point it at your live site — fromUrl

Don't want to hand it text at all? Give it your page URLs and it scrapes them for you. Per id (cached): it fetches the page, extracts the real article text (Mozilla Readability — strips nav/ads/boilerplate), and derives the free teaser.

import { createLeptonarcRouter, fromUrl } from "usewinch";

app.use(createLeptonarcRouter({
  payTo: "0xYourWallet",
  price: "$0.001",
  publisherKey: "pub_…",
  content: fromUrl((id) => `https://mysite.com/articles/${id}`, {
    summarize: "groq",                        // LLM teaser (optional)
    groqApiKey: process.env.GROQ_API_KEY,
    // model: "llama-3.1-8b-instant",
    // ttlMs: 1000 * 60 * 60,                 // re-scrape hourly
  }),
}));
  • The paid content is the real scraped page text — it is never LLM-generated.
  • The LLM (Groq, OpenAI-compatible) only writes the free abstract, and only from facts in the extracted text. Omit summarize (or drop the key) and the abstract falls back to plain truncation — the paywall keeps working either way.
  • Results are cached per id, so the fetch + extract + summarize happens once, not on every crawl.

Lower-level — gate routes you already have

import "dotenv/config";
import express from "express";
import { leptonarcProxy } from "usewinch";

const app = express();
const proxy = leptonarcProxy({
  payTo: process.env.SELLER_ADDRESS,   // your Arc wallet address
  price: "$0.001",                      // 1000 micro-USDC per request
  backendUrl: process.env.LEPTONARC_BACKEND_URL, // optional; logs to console if absent
});

// Free preview — title + abstract + price hint.
app.get("/preview/:id", (req, res) => {
  res.json({ price: proxy.config.price, /* ...your metadata */ });
});

// Paid content — the gate + settlement reporter run before your handler.
app.get("/content/:id", ...proxy.content, (req, res) => {
  res.json({ body: "full content here" });
});

app.listen(4030);

API

leptonarcProxy(config, deps?)

Creates the proxy instance.

| Option | Type | Required | Description | |---|---|---|---| | payTo | string | yes | Seller's Arc wallet address (0x…). Settlement goes here. | | price | string | yes | Price string like "$0.001" (maps to 1000 micro-USDC on 6-dec USDC). | | publisherKey | string | no | Opaque publisher identifier included in event payloads. | | backendUrl | string | no | URL of your leptonarc backend (/api/events will be POSTed). Omit to log to console. |

Returns { config, preview, content }:

  • config — the resolved ProxyConfig (useful for reading price back out in preview routes).
  • preview — a single Express handler that returns { url, price, payTo } — a free teaser.
  • content — a two-handler array [gate, settled] spread directly into a route: app.get("/content/:id", ...proxy.content, yourHandler). The gate returns 402 to unpaid requests; settled fires a PaymentEvent to your backend (or console) before calling next.

req.payment (inside paid handlers)

After the gate passes, req.payment is set by the SDK:

{
  payer: string;       // buyer's wallet address
  amount: bigint;      // micro-USDC (e.g. 1000n for $0.001)
  transaction: string; // settlement UUID (Circle Gateway batch reference)
}

Env vars

| Var | Used by | Description | |---|---|---| | SELLER_ADDRESS | example/server.ts | The Arc wallet to receive payments. | | LEPTONARC_BACKEND_URL | leptonarcProxy | Optional backend URL for event reporting. | | BUYER_PRIVATE_KEY | example/buyer.ts | Buyer's private key for the example buyer script. |

Routes: /preview + /content pattern

  • GET /preview/:id — free. Returns metadata + price. No 402, no payment needed.
  • GET /content/:id — gated. Returns 402 Payment Required with a PAYMENT-REQUIRED base64 header (x402 v2 protocol) to unpaid callers. A buyer with a funded GatewayClient pays inline and receives the full response body.

How it settles on Arc

When a buyer calls gateway.pay(url, { method: "GET" }), the GatewayClient (from @circle-fin/x402-batching/client) fetches the 402, signs an EIP-3009 transferWithAuthorization over Circle's Gateway batch wallet, and replays the request with an X-PAYMENT header. The createGatewayMiddleware on the server verifies the signature against Circle's facilitator (https://gateway-api-testnet.circle.com), confirms settlement, and sets req.payment before calling next. Settlement is synchronous from the application's perspective — pay() returns after Circle accepts the signed authorization. On-chain batch settlement lands shortly after.

Full spike findings (chain id, USDC address, Gateway wallet, RPC, timing notes) are documented in docs/superpowers/spikes/2026-06-30-arc-payment-findings.md.

Live settlement proof

The example server (example/server.ts) and buyer (example/buyer.ts) were run against Arc testnet on 2026-07-01 using the spike's funded wallet:

buyer address: 0x1D1B13de8a4024577896Fdf4eE5B47ee3bC6C6eF
settlement UUID: ab138d4d-d241-4993-9a03-c3601f186153
amount paid: 0.001 USDC (1000 micro-USDC)
server log: [leptonarc] paid 1000 micro-USDC for /content/1 by 0x1d1b13de8a4024577896fdf4ee5b47ee3bc6c6ef (ab138d4d-d241-4993-9a03-c3601f186153)

No patch was applied to @circle-fin/x402-batching — version 3.2.0 settled cleanly with the default timeout.

Running the example

# From packages/proxy — set .env with SELLER_ADDRESS + BUYER_PRIVATE_KEY
npm run example          # starts publisher on :4030

# In a second terminal:
npx tsx example/buyer.ts # deposits 1 USDC, pays /content/1, prints settlement UUID