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

@recensus/sdk

v4.0.1

Published

Know Your Agent on Robinhood Chain: label your agent's transactions and x402 payments so they are counted and checkable on Recensus. viem wrappers, request signing and server middleware.

Readme

@recensus/sdk

KNOW YOUR AGENT. Recensus is KYA for Robinhood Chain: anyone can check what an agent has done on-chain, who stands behind it and what it has at stake (recensus.xyz/check). This package puts your agent's activity on that record. It labels your agent's transactions on Robinhood Chain (4663) — 24 bytes appended to calldata, or the EIP-3009 nonce of an x402 payment (RECENSUS-1) — so they are counted under your agent, checks that the label is safe to add, and verifies labelled agents on your own server. To check agents before you serve them, see @recensus/kya.

npm i @recensus/sdk viem

Label every transaction

import { createRecensus, deriveAgentId, robinhoodChain } from '@recensus/sdk';
import { createPublicClient, http, parseEther } from 'viem';

const recensus = createRecensus({
  agentId: deriveAgentId(operator, 'price-watcher'),
  flags: { autonomous: true },   // no human approves each send
  // flags: { test: true }       // in staging: excluded from public numbers
});

const chain = robinhoodChain();          // 4663, ETH for gas; robinhoodChain(rpcUrl) for your own node
const publicClient = createPublicClient({ chain, transport: http() });
const wallet = recensus.wrap(walletClient, publicClient);

await wallet.sendTransaction({ to: recipient, value: parseEther('0.01') });   // native ETH
await wallet.writeContract({ address, abi, functionName: 'transfer', args: [to, amount] });

Default-safe on Robinhood Chain: native ETH sends to an EOA, ERC-20 transfer, approve and transferFrom (USDG included), and Permit2. Each is proven labelled == unlabelled on a fork by the conformance suite.

wrap changes nothing else about the client. writeContract is passed to your wallet's own writeContract with the label as dataSuffix, so every field you set is kept.

When the label is not added

The label must never break a transaction. Before each send, the SDK:

  1. Checks the call. No label on a contract deployment, on calldata sent to an address with no code, on a contract marked tagSafe: false in the registry, on a wrapper such as handleOps, on anything in your denylist or denySelectors, or on calldata that already carries a label.
  2. Simulates both versions. The labelled and unlabelled calls run side by side. The label stays only if both succeed with the same return data. If the labelled call reverts, returns something different, or turns a revert into a success, the transaction goes unlabelled. It also goes unlabelled if the node cannot be reached.
  3. Makes room for it. If you set gas, it is raised by the label's measured cost, at least LABEL_GAS_ALLOWANCE (1,000). If the label does not fit, the call is sent unlabelled at your limit.

Every unlabelled send is reported through onUnlabelled, with a warning by default. A scoreboard row is a small thing to lose; a transaction is not.

A simulation cannot see a contract that reads its own calldata without reverting or returning anything different, such as one that hashes msg.data or an ERC-2771 forwarder target. If you call one, put it in denylist.

Label x402 payments

An x402 exact payment is sent by the seller or its facilitator, not by you, so there is no calldata of yours to label. The label goes in the EIP-3009 authorization's 32-byte nonce instead (RECENSUS-1 §3.4), and the token logs it in AuthorizationUsed with you as the authorizer.

import { x402Client } from '@x402/core/client';
import { x402ExactScheme, x402Networks } from '@recensus/sdk';

const client = new x402Client();
for (const network of x402Networks()) {           // eip155:4663, eip155:46630 (testnet)
  client.register(network, x402ExactScheme(recensus, account)); // a viem account
}

Payments are in USDG. For a stablecoin in the chain config the EIP-712 domain (Global Dollar / 1) comes from the config, not from the seller, and a seller naming another domain is refused before signing.

Or build the payload yourself:

const { x402Version, payload } = await createX402ExactPayment(recensus, account, paymentRequirements);

It signs locally, valid from a minute ago for min(maxTimeoutSeconds, 600) seconds, and refuses anything but scheme exact over EIP-3009 on an eip155:<chainId> network (X402RefusedError, before signing). A Permit2 payment is refused rather than paid unlabelled. recensus.nonce() gives a fresh labelled nonce for any other EIP-3009 authorization; parseNonceLabel(nonce) reads one back.

Verify labelled agents on your server

Hono:

import { requireRecensus } from '@recensus/sdk/middleware';

app.use('/api/*', requireRecensus({
  apiUrl: 'https://recensus.xyz/_api',
  origin: 'https://shop.example',   // this server's own origin: required
  minTier: 'claimed',
}));

Express: capture the raw body first, so the signature is checked over the bytes that were sent.

import express from 'express';
import { requireRecensusExpress, captureRawBody } from '@recensus/sdk/middleware';

app.use(express.json({ verify: captureRawBody }));
app.use('/api', requireRecensusExpress({
  apiUrl: 'https://recensus.xyz/_api',
  origin: 'https://shop.example',
  minTier: 'claimed',
}));

The identity is on c.get('recensus') in Hono and req.recensus in Express. Without captureRawBody, Express refuses any request that carries a body with BAD_SIGNATURE: a re-serialised req.body is not what the agent signed. Both are also exported from the package root.

The agent signs each request with the key it sends from. The middleware checks, in order: the clock skew, the signature, a /v1/verify lookup, that the key is a declared sender of that agent, that the agent is not suspended, that its tier is high enough, and last the nonce. The nonce is recorded only after every other check passes, so a failing request takes no slot, and a replay still fails. The identity's agentId and key are lowercase. The signed URL is built from origin, never from the request's Host, so a request signed for another server does not verify on yours.

minTier must be claimed or staked:<digits>. Anything else throws when the lane is built, rather than letting every claimed agent in. Stakes are compared as BigInt.

The default nonce store is in memory for one process, one per lane. Behind more than one instance, pass a shared nonceStore. It keeps a nonce until its timestamp leaves the skew window, and caps any one key at 1,000 live nonces (memoryNonceStore(maxEntries, maxPerKey)), so one agent can't fill it for the rest.

Each lane has its own lookup cache (30 s) and budgets. Lookups are budgeted per signing key (lookupsPerKeyPerMinute, default 10), so a key that invents agent IDs spends only its own budget. The lane's ceiling (lookupsPerMinute, default 60) serves cached answers instead of refreshes once it's spent, and never refuses an agent whose key is within budget. Concurrent lookups for one agent share one request, and a failed lookup is remembered for 5 s. Pass budgetKey(input) to budget by the socket address as well (input.request is the Hono context or the Express request). Put your own per-agent rate limit in front of the lane too.

Rejections are 403 with a code: MISSING_HEADERS, STALE_TIMESTAMP, REPLAY, BAD_SIGNATURE, KEY_NOT_BOUND, TIER_TOO_LOW, SUSPENDED. VERIFY_UNAVAILABLE means Recensus could not be reached, gave an answer of the wrong shape, or this key has spent its lookup budget with nothing cached, so you can decide whether to fail open. LANE_BUSY means this key holds its share of live nonces, or the store is full of them; it never forgets one to make room.

Agents sign with recensus.signRequest({ method, url, body }, account).

4.0

  • Robinhood Chain (4663) replaces Arc: robinhoodChain(rpcUrl?) and robinhoodTestnetChain(rpcUrl?) replace arcChain, and x402 payments are in USDG on eip155:4663. Arc support is removed; the last Arc versions are 3.0.0–3.1.0. See CHANGELOG.md.

2.0

  • requireRecensus requires origin. 1.x rebuilt the signed URL from the Host header, so one merchant could replay a request at another.
  • wrap needs something to simulate with: a public client, or a wallet client viem can extend. 1.x sent everything unlabelled when it had nothing to simulate with. 2.0 refuses to wrap instead.
  • A caller-set gas is raised for the label rather than left too low.
  • The simulation compares return data, not only reverts.

Docs: https://recensus.xyz/docs/get-counted · Agent lane: https://recensus.xyz/docs/agent-lane · License: MIT