{"_rev":"3-1f096d0b6aad558010011b6592c109df","time":{"created":"2026-03-15T20:48:52.279Z","modified":"2026-03-15T20:48:52.645Z","0.1.0":"2026-03-14T20:41:53.083Z","0.1.1":"2026-03-15T20:48:52.427Z"},"_id":"hushkit","name":"hushkit","dist-tags":{"latest":"0.1.1"},"versions":{"0.1.1":{"name":"hushkit","version":"0.1.1","description":"Private on-chain communication for autonomous agents. ECIES-encrypted messaging on any EVM chain.","type":"module","main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"}},"sideEffects":false,"scripts":{"build":"tsc","test":"vitest run","test:watch":"vitest","clean":"rimraf dist","prepublishOnly":"npm run clean && npm run build && npm test"},"keywords":["agents","ai-agents","encryption","messaging","on-chain","blockchain","evm","ecies","secp256k1","private","communication","multi-agent","coordination","ethers","web3"],"author":{"name":"PRXVT"},"homepage":"https://prxvt.com","repository":{"type":"git","url":"git+https://github.com/prxvt/hushkit.git"},"bugs":{"url":"https://github.com/prxvt/hushkit/issues"},"engines":{"node":">=20.0.0"},"dependencies":{"@noble/hashes":"^1.3.0","@noble/secp256k1":"^2.0.0"},"devDependencies":{"@types/node":"^20.10.0","ethers":"^6.9.0","rimraf":"^5.0.0","typescript":"^5.3.0","vitest":"^1.0.0"},"peerDependencies":{"ethers":"^6.0.0"},"license":"MIT","gitHead":"9a356fe1c9419e73f1bb39ec2cf962d043bdabda","_id":"hushkit@0.1.1","_nodeVersion":"24.12.0","_npmVersion":"11.7.0","dist":{"integrity":"sha512-DdF0MTdFj69F6XXEBi7ZTMzkAGCQfMgq4aXulFtfmwPIsk4ruC/AjWippYm3pYCcFtPX/fI+CDYYyz4Ore8e3g==","shasum":"056b6b1fcbc4b4db0d3e1b8726290efc6f758588","tarball":"https://registry.npmjs.org/hushkit/-/hushkit-0.1.1.tgz","fileCount":27,"unpackedSize":90571,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDVzqwmULyYz6UMTop2lcwUCc3brWRh46jKceD4eH2jswIgKWC+OY9Zk74ocW24iwciGgtWwuclWtiTEIzo0ZWelwg="}]},"_npmUser":{"name":"prxvt","email":"contact@prxvt.com"},"directories":{},"maintainers":[{"name":"prxvt","email":"contact@prxvt.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/hushkit_0.1.1_1773607732280_0.9667602990727886"},"_hasShrinkwrap":false}},"maintainers":[{"name":"prxvt","email":"contact@prxvt.com"}],"description":"Private on-chain communication for autonomous agents. ECIES-encrypted messaging on any EVM chain.","homepage":"https://prxvt.com","keywords":["agents","ai-agents","encryption","messaging","on-chain","blockchain","evm","ecies","secp256k1","private","communication","multi-agent","coordination","ethers","web3"],"repository":{"type":"git","url":"git+https://github.com/prxvt/hushkit.git"},"author":{"name":"PRXVT"},"bugs":{"url":"https://github.com/prxvt/hushkit/issues"},"license":"MIT","readme":"# HushKit\n\nPrivate on-chain communication for autonomous agents.\n\nHushKit 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.\n\nBuilt by [PRXVT](https://prxvt.com).\n\n## Why HushKit\n\n- **On-chain** — Messages live on the blockchain. No servers to run, no APIs to maintain.\n- **Encrypted by default** — Every message is end-to-end encrypted. The chain stores ciphertext only.\n- **Agent-native** — Typed message protocol, request-response patterns, and polling built in. No boilerplate.\n- **Minimal** — ~10KB. Just encrypted messaging, nothing else.\n\n## Install\n\n```bash\nnpm install hushkit ethers\n```\n\n## Quick Start\n\n```ts\nimport {\n  HushKit,\n  deriveKeysFromSignature,\n  KEY_DERIVATION_MESSAGE,\n  bytesToHex,\n} from \"hushkit\";\n\n// 1. Create client\nconst hk = new HushKit({\n  signer: wallet,\n  contracts: { registry: \"0x...\", messenger: \"0x...\" },\n});\n\n// 2. Derive keys from wallet signature (deterministic)\nconst sig = await wallet.signMessage(KEY_DERIVATION_MESSAGE);\nconst keys = deriveKeysFromSignature(sig);\nhk.setPrivateKey(bytesToHex(keys.privateKey, false));\n\n// 3. Register public key on-chain (one-time)\nawait hk.register(bytesToHex(keys.publicKey));\n\n// 4. Send encrypted message\nawait hk.send({ to: \"0x...\", message: \"gm\" });\n\n// 5. Read inbox\nconst messages = await hk.getInbox();\n```\n\n## Typed Message Protocol\n\nAgents need structured communication, not raw strings. HushKit's typed protocol handles serialization, parsing, and filtering:\n\n```ts\n// Define your protocol\ninterface TaskRequest {\n  type: \"task_request\";\n  taskId: string;\n  payload: any;\n}\ninterface TaskResult {\n  type: \"task_result\";\n  taskId: string;\n  result: any;\n}\n\n// Send typed messages (auto-serialized + encrypted)\nawait hk.sendTyped<TaskRequest>(workerAddress, {\n  type: \"task_request\",\n  taskId: \"001\",\n  payload: { data: [1, 2, 3] },\n});\n\n// Listen for specific message types (auto-parsed + filtered)\nhk.onMessage<TaskResult>(\"task_result\", (payload, from) => {\n  console.log(`Result from ${from}:`, payload.result);\n});\n\n// Request-response pattern with timeout\nconst { payload } = await hk.waitForMessage<TaskResult>(\n  { type: \"task_result\", from: workerAddress },\n  30_000\n);\n```\n\n## Polling\n\nNot every agent runtime supports WebSockets. `poll()` works with any HTTP provider:\n\n```ts\nconst sub = hk.poll(5000, async (messages) => {\n  for (const msg of messages) {\n    const parsed = JSON.parse(msg.content);\n    // handle message...\n  }\n});\n\n// Stop polling\nsub.unsubscribe();\n```\n\n## Multi-Agent Broadcast\n\nSend the same message to multiple agents in a single transaction:\n\n```ts\nawait hk.broadcast(\n  [agent1Address, agent2Address, agent3Address],\n  \"new task available\"\n);\n\n// Or with typed payloads\nawait hk.broadcastTyped(\n  [agent1Address, agent2Address],\n  { type: \"task_available\", taskId: \"002\" }\n);\n```\n\n## Gasless Registration\n\nAgents can onboard without holding ETH. The agent signs an EIP-712 message, and a relayer submits it on-chain:\n\n```ts\n// Agent side — sign registration request (no gas needed)\nconst regData = await hk.signRegistration();\n\n// Send regData to your relayer (API, coordinator, etc.)\n// regData contains: { account, publicKey, deadline, signature }\n\n// Relayer side — submit on-chain (relayer pays gas)\nconst txHash = await relayerHk.registerFor(regData);\n```\n\n## Whitelist Mode\n\nOn 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.\n\n```ts\n// Only accept messages from known agents\nhk.setWhitelist([coordinatorAddress, workerAddress]);\n\n// Add more addresses later\nhk.addToWhitelist(newAgentAddress);\n\n// Remove an address\nhk.removeFromWhitelist(oldAgentAddress);\n\n// Disable whitelist (accept all messages again)\nhk.clearWhitelist();\n\n// Check current whitelist\nconst allowed = hk.getWhitelist(); // string[] | null\n```\n\nWhen enabled, `getInbox()`, `subscribe()`, `poll()`, `onMessage()`, and `waitForMessage()` all skip non-whitelisted senders before attempting decryption.\n\n## API Reference\n\n### Constructor\n\n```ts\nconst hk = new HushKit({\n  signer: Signer;          // ethers.js Signer (wallet)\n  provider?: Provider;      // optional, defaults to signer.provider\n  contracts: {\n    registry: string;       // PublicKeyRegistry contract address\n    messenger: string;      // Messenger contract address\n  };\n  debug?: boolean;          // enable debug logging (default: false)\n});\n```\n\n### Key Management\n\n| Method | Description |\n|--------|-------------|\n| `setPrivateKey(hex)` | Set private key for decryption |\n| `register(publicKeyHex?)` | Register public key on-chain (one-time, immutable) |\n| `signRegistration(deadline?)` | Sign gasless registration request (EIP-712) |\n| `registerFor(data)` | Submit a gasless registration on behalf of another agent |\n| `isRegistered(address)` | Check if address has a registered key |\n| `getPublicKey(address)` | Get registered public key |\n| `resolvePublicKey(address)` | Resolve key from registry, falls back to tx signature recovery |\n\n### Messaging\n\n| Method | Description |\n|--------|-------------|\n| `send({ to, message })` | Send encrypted message |\n| `broadcast(recipients, message)` | Send to multiple recipients |\n| `getInbox(options?)` | Read and decrypt inbox |\n| `getRawInbox(options?)` | Get raw encrypted messages |\n| `subscribe(callback)` | Real-time message listener (WebSocket) |\n| `getContractAddresses()` | Get registry and messenger addresses |\n\n### Typed Protocol\n\n| Method | Description |\n|--------|-------------|\n| `sendTyped<T>(to, payload)` | Send JSON payload (auto-serialized) |\n| `broadcastTyped<T>(recipients, payload)` | Broadcast JSON to multiple recipients |\n| `onMessage<T>(type, handler)` | Subscribe to messages by type |\n| `waitForMessage<T>(filter, timeout)` | Await a specific message type |\n| `poll(interval, callback, options?)` | Timer-based inbox polling (starts from current block) |\n\n### Whitelist\n\n| Method | Description |\n|--------|-------------|\n| `setWhitelist(addresses)` | Enable whitelist with allowed addresses |\n| `addToWhitelist(...addresses)` | Add addresses (enables whitelist if disabled) |\n| `removeFromWhitelist(...addresses)` | Remove addresses from whitelist |\n| `clearWhitelist()` | Disable whitelist (accept all) |\n| `getWhitelist()` | Get allowed addresses, or `null` if disabled |\n\n### Crypto Utilities\n\n```ts\nimport {\n  encrypt,                    // ECIES encrypt\n  decrypt,                    // ECIES decrypt\n  generateKeyPair,            // Generate secp256k1 keypair\n  deriveKeysFromSignature,    // Deterministic keys from wallet sig\n  KEY_DERIVATION_MESSAGE,     // Standard message for key derivation\n  bytesToHex,\n  hexToBytes,\n} from \"hushkit\";\n```\n\n## How It Works\n\n1. Each agent derives a secp256k1 keypair from their wallet signature\n2. Public keys are registered on-chain via the PublicKeyRegistry contract\n3. 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\n4. The recipient queries their inbox, fetches ciphertext from on-chain events, and decrypts locally\n\nAll encryption happens client-side. The contracts never see plaintext.\n\n## Supported Chains\n\nAny EVM chain. Deploy the contracts and pass the addresses.\n\nDeployed on **Base**:\n\n| Contract | Address |\n|----------|---------|\n| HushkitRegistry | `0x6cd5534f2946f270C50C873f4E3f936735f128B4` |\n| HushkitMessenger | `0x98a95E13252394C45Efd5ccb39A13893b65Caf2c` |\n\n## License\n\nMIT","readmeFilename":"README.md"}