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

hushkit

v0.1.1

Published

Private on-chain communication for autonomous agents. ECIES-encrypted messaging on any EVM chain.

Readme

HushKit

Private on-chain communication for autonomous agents.

HushKit gives AI agents encrypted messaging channels on EVM blockchains. Messages are encrypted, stored on-chain as ciphertext, and only readable by the intended recipient. No relay servers, no trusted third parties — just math and smart contracts.

Built by PRXVT.

Why HushKit

  • On-chain — Messages live on the blockchain. No servers to run, no APIs to maintain.
  • Encrypted by default — Every message is end-to-end encrypted. The chain stores ciphertext only.
  • Agent-native — Typed message protocol, request-response patterns, and polling built in. No boilerplate.
  • Minimal — ~10KB. Just encrypted messaging, nothing else.

Install

npm install hushkit ethers

Quick Start

import {
  HushKit,
  deriveKeysFromSignature,
  KEY_DERIVATION_MESSAGE,
  bytesToHex,
} from "hushkit";

// 1. Create client
const hk = new HushKit({
  signer: wallet,
  contracts: { registry: "0x...", messenger: "0x..." },
});

// 2. Derive keys from wallet signature (deterministic)
const sig = await wallet.signMessage(KEY_DERIVATION_MESSAGE);
const keys = deriveKeysFromSignature(sig);
hk.setPrivateKey(bytesToHex(keys.privateKey, false));

// 3. Register public key on-chain (one-time)
await hk.register(bytesToHex(keys.publicKey));

// 4. Send encrypted message
await hk.send({ to: "0x...", message: "gm" });

// 5. Read inbox
const messages = await hk.getInbox();

Typed Message Protocol

Agents need structured communication, not raw strings. HushKit's typed protocol handles serialization, parsing, and filtering:

// Define your protocol
interface TaskRequest {
  type: "task_request";
  taskId: string;
  payload: any;
}
interface TaskResult {
  type: "task_result";
  taskId: string;
  result: any;
}

// Send typed messages (auto-serialized + encrypted)
await hk.sendTyped<TaskRequest>(workerAddress, {
  type: "task_request",
  taskId: "001",
  payload: { data: [1, 2, 3] },
});

// Listen for specific message types (auto-parsed + filtered)
hk.onMessage<TaskResult>("task_result", (payload, from) => {
  console.log(`Result from ${from}:`, payload.result);
});

// Request-response pattern with timeout
const { payload } = await hk.waitForMessage<TaskResult>(
  { type: "task_result", from: workerAddress },
  30_000
);

Polling

Not every agent runtime supports WebSockets. poll() works with any HTTP provider:

const sub = hk.poll(5000, async (messages) => {
  for (const msg of messages) {
    const parsed = JSON.parse(msg.content);
    // handle message...
  }
});

// Stop polling
sub.unsubscribe();

Multi-Agent Broadcast

Send the same message to multiple agents in a single transaction:

await hk.broadcast(
  [agent1Address, agent2Address, agent3Address],
  "new task available"
);

// Or with typed payloads
await hk.broadcastTyped(
  [agent1Address, agent2Address],
  { type: "task_available", taskId: "002" }
);

Gasless Registration

Agents can onboard without holding ETH. The agent signs an EIP-712 message, and a relayer submits it on-chain:

// Agent side — sign registration request (no gas needed)
const regData = await hk.signRegistration();

// Send regData to your relayer (API, coordinator, etc.)
// regData contains: { account, publicKey, deadline, signature }

// Relayer side — submit on-chain (relayer pays gas)
const txHash = await relayerHk.registerFor(regData);

Whitelist Mode

On cheap L2s, anyone can spam your inbox for fractions of a cent. Enable whitelist mode to drop messages from unknown senders before decryption — zero CPU wasted on spam.

// Only accept messages from known agents
hk.setWhitelist([coordinatorAddress, workerAddress]);

// Add more addresses later
hk.addToWhitelist(newAgentAddress);

// Remove an address
hk.removeFromWhitelist(oldAgentAddress);

// Disable whitelist (accept all messages again)
hk.clearWhitelist();

// Check current whitelist
const allowed = hk.getWhitelist(); // string[] | null

When enabled, getInbox(), subscribe(), poll(), onMessage(), and waitForMessage() all skip non-whitelisted senders before attempting decryption.

API Reference

Constructor

const hk = new HushKit({
  signer: Signer;          // ethers.js Signer (wallet)
  provider?: Provider;      // optional, defaults to signer.provider
  contracts: {
    registry: string;       // PublicKeyRegistry contract address
    messenger: string;      // Messenger contract address
  };
  debug?: boolean;          // enable debug logging (default: false)
});

Key Management

| Method | Description | |--------|-------------| | setPrivateKey(hex) | Set private key for decryption | | register(publicKeyHex?) | Register public key on-chain (one-time, immutable) | | signRegistration(deadline?) | Sign gasless registration request (EIP-712) | | registerFor(data) | Submit a gasless registration on behalf of another agent | | isRegistered(address) | Check if address has a registered key | | getPublicKey(address) | Get registered public key | | resolvePublicKey(address) | Resolve key from registry, falls back to tx signature recovery |

Messaging

| Method | Description | |--------|-------------| | send({ to, message }) | Send encrypted message | | broadcast(recipients, message) | Send to multiple recipients | | getInbox(options?) | Read and decrypt inbox | | getRawInbox(options?) | Get raw encrypted messages | | subscribe(callback) | Real-time message listener (WebSocket) | | getContractAddresses() | Get registry and messenger addresses |

Typed Protocol

| Method | Description | |--------|-------------| | sendTyped<T>(to, payload) | Send JSON payload (auto-serialized) | | broadcastTyped<T>(recipients, payload) | Broadcast JSON to multiple recipients | | onMessage<T>(type, handler) | Subscribe to messages by type | | waitForMessage<T>(filter, timeout) | Await a specific message type | | poll(interval, callback, options?) | Timer-based inbox polling (starts from current block) |

Whitelist

| Method | Description | |--------|-------------| | setWhitelist(addresses) | Enable whitelist with allowed addresses | | addToWhitelist(...addresses) | Add addresses (enables whitelist if disabled) | | removeFromWhitelist(...addresses) | Remove addresses from whitelist | | clearWhitelist() | Disable whitelist (accept all) | | getWhitelist() | Get allowed addresses, or null if disabled |

Crypto Utilities

import {
  encrypt,                    // ECIES encrypt
  decrypt,                    // ECIES decrypt
  generateKeyPair,            // Generate secp256k1 keypair
  deriveKeysFromSignature,    // Deterministic keys from wallet sig
  KEY_DERIVATION_MESSAGE,     // Standard message for key derivation
  bytesToHex,
  hexToBytes,
} from "hushkit";

How It Works

  1. Each agent derives a secp256k1 keypair from their wallet signature
  2. Public keys are registered on-chain via the PublicKeyRegistry contract
  3. To send a message, HushKit looks up the recipient's public key, encrypts with ECIES, and stores the ciphertext on-chain via the Messenger contract
  4. The recipient queries their inbox, fetches ciphertext from on-chain events, and decrypts locally

All encryption happens client-side. The contracts never see plaintext.

Supported Chains

Any EVM chain. Deploy the contracts and pass the addresses.

Deployed on Base:

| Contract | Address | |----------|---------| | HushkitRegistry | 0x6cd5534f2946f270C50C873f4E3f936735f128B4 | | HushkitMessenger | 0x98a95E13252394C45Efd5ccb39A13893b65Caf2c |

License

MIT