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

@msgboard/cosign

v0.0.32

Published

Generic signature-share SDK over MsgBoard, bucketed under rotating day-granular category keys

Readme

@msgboard/cosign

Generic signature-share SDK over MsgBoard: post, read, and aggregate co-signature artifacts — (digest, signer, signature, scheme, meta) records — bucketed under rotating, day-granular UTC category keys so the working set stays small and self-pruning.

App-agnostic. A pluggable adapter encodes a specific multisig's verify/order/owner-read rules. cosign is a coordination/aggregation layer for existing off-chain-signature-aggregation multisig tools — it does not build its own multisig. The generic core plus the CosignAdapter interface land first; concrete adapters ship in this same package's src/adapters/ (the Gnosis Safe adapter first; full roadmap + non-fits in the cosign SDK spec). Pure board + crypto: no chain writes.

Canonical encodings (law — downstream tooling mirrors these)

  • Category key: keccak256(toBytes(${namespace}:${scope}:${isoDate})), where isoDate is UTC YYYY-MM-DD. Field separator is :; order is namespace:scope:isoDate.
  • SignatureRecord ABI tuple (order is law): (bytes32 digest, address signer, bytes signature, uint8 scheme, bytes meta).
  • Schemes: SCHEME = { ECDSA: 0, EIP1271: 1, EIP712: 2 }.

Quick start

import { MsgBoardClient } from '@msgboard/sdk'
import {
  type BoardClient,
  type CosignAdapter,
  SCHEME,
  postSignature,
  readSignatures,
  groupByDigest,
  aggregate,
} from '@msgboard/cosign'

// Wrap the real, lower-level MsgBoardClient into cosign's BoardClient seam.
// Posting is a two-step on the real client: doPoW (find a nonce) then addMessage.
function boardFrom(client: MsgBoardClient): BoardClient {
  return {
    async addMessage({ category, data }) {
      const { message } = await client.doPoW(category, data)
      return client.addMessage(message)
    },
    content({ category }) {
      return client.content({ category })
    },
  }
}

const board = boardFrom(new MsgBoardClient(provider))

// Post a signature under today's rotating category.
await postSignature(board, {
  namespace: 'cosign',
  scope: 'acme-team',
  record: { digest, signer, signature, scheme: SCHEME.ECDSA, meta: '0x' },
})

// Read the rolling 7-day window, group by digest, and aggregate via your adapter.
const records = await readSignatures(board, { namespace: 'cosign', scope: 'acme-team', days: 7 })
const forDigest = groupByDigest(records).get(digest) ?? []
const ordered = await aggregate(forDigest, myAdapter) // myAdapter satisfies CosignAdapter
// `ordered` is `{ signer, signature }[]` — hand to your existing execute path (out of scope here).

The core + CosignAdapter interface land first — supply a concrete adapter to aggregate. Concrete adapters ship in this same package's src/adapters/ (the Gnosis Safe adapter first — its own spec/plan; full roadmap + non-fits in the cosign SDK spec §9).

API

  • keys: isoDay, categoryKey, currentKey, keysForWindow (all accept an explicit now?: Date).
  • record: SignatureRecord, SCHEME, RECORD_ABI, encodeRecord, decodeRecord (decode throws on junk).
  • client: BoardClient, postSignature, readSignatures (skips undecodable junk, dedupes by data), groupByDigest, aggregate (filters by adapter.verify, applies adapter.order; verify errors propagate).
  • adapters: CosignAdapter (the seam — interface lands first; concrete adapters ship in src/adapters/ via follow-up plans, Safe first).