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

@waaskey/client-wasm

v0.2.0

Published

Browser/WASM MPC device-party core for Waaskey embedded wallets: client-side threshold ECDSA keygen & signing (cggmp24) over the relay, so the device holds its own key share.

Readme

client-wasm — browser MPC device party (+ client prime pool)

The browser (WASM) counterpart of the server-side party-runner: it drives the same cggmp24 ceremonies (aux-info-then-keygen, threshold sign) over the same WebSocket relay, so the device runs its own party share in the browser. The @waaskey/sdk package loads this module and calls its exports.

Curve-generic like the runner — one set of entry points serves secp256k1, secp256r1 and stark, dispatched on a curve string at the WASM boundary.

Exports (each takes one JSON string, resolves a JSON object)

| Export | Input | Resolves | |---|---|---| | keygen | { curve, relay_url, session_id, role, peer_role, party_index, peer_party_index, parties, threshold, pregenerated_primes_json? } | { aux_info_json, keyshare_json, shared_public_key_json } | | sign | { curve, relay…, share, participants, signer_position, digest } | { signature_json } | | keygenMember | { curve, relay_url, session_id, roles, party_index, threshold, relay_token?, pregenerated_primes_json? } | { aux_info_json, keyshare_json, shared_public_key_json } | | signMember | { curve, relay_url, session_id, roles, party_index, share, participants, digest, relay_token?, sign_nonce?, tweak? } | { signature_json } | | pregeneratePrimes | { curve } | { primes_json } |

keygen/sign are the fixed 2-party (device + server) ceremonies. keygenMember/signMember are their n-party (member-bound wallet, #353) counterparts: every member device + the platform join one relay session addressed by the full ordered roles roster (this device is roles[party_index]), so a t-of-n wallet can keygen/sign — routing each recipient-specific p2p message the 2-party path cannot. share on the sign wire is the KeyShare object (the exports deserialize it with serde_json::from_value), not a JSON string.

The device key share returned by keygen is sealed and stored on the device; it is never sent to the server. Secret material (shares, scalars, primes) is never logged — the console diagnostics are protocol phase markers only.

Client-side prime pool (waas-sdk #1, #2)

Paillier safe-prime generation is the slow part of a device keygen (minutes in single-threaded browser WASM). Primes are generated client-side and never served by the API — a server-held prime pool would let the server reconstruct the device's key share, collapsing the 2-of-3 design to custodial.

So generation stays on the client but moves off the keygen hot path:

  1. Ahead of time (a Web Worker during onboarding / idle) the SDK calls pregenerate_primes({ curve }), which generates a PregeneratedPrimes and returns it serialized under primes_json. The SDK caches it in its PrimePool.
  2. At keygen time the SDK passes that cached string back as keygen({ …, pregenerated_primes_json }). When present, keygen deserializes it and feeds it straight to aux_info_gen instead of generating; when absent, keygen generates inline exactly as before (the unchanged default / slow fallback, so keygen never fails on a cold pool).

primes_json and pregenerated_primes_json carry the same string — the exact PregeneratedPrimes serialization, round-tripped losslessly (a unit test pins this, and a gated real-MPC test proves a pool-primed keygen yields the same wallet public key as the inline path).

Primes are curve-agnostic. Safe-prime size is fixed by the security level (SecurityLevel128), not the curve, so one pregenerated set works for any of our curves. pregenerate_primes still takes (and validates) curve for a stable SDK call shape and forward-compatibility.

Building the wasm module

The SDK imports the wasm-pack output. Build it with wasm-pack (install once: cargo install wasm-pack):

# from the workspace root
just build-wasm            # → client-wasm/pkg/  (target: web)
just build-wasm bundler    # ESM for tsup/webpack (wasm-pack default)
just build-wasm nodejs     # CommonJS, for host smoke tests

# or directly (`-- --features reshare` exposes the device-side reshare exports the SDK needs):
wasm-pack build client-wasm --release --target web --scope waaskey --out-dir pkg -- --features reshare
  • Package name: --scope waaskey makes pkg/package.json name @waaskey/client-wasm — the optional peer dependency the SDK's loadClientWasm dynamically imports (waas-sdk #1). Release it via the Publish @waaskey/client-wasm workflow (.github/workflows/client-wasm-publish.yml): push a client-wasm-v* tag (or run it manually) and it builds the --target web package, prints the SHA-384 SRI to the job summary, and — with the NPM_TOKEN secret set — runs npm publish --access public (skipping safely if the version is already on the registry; bump client-wasm/Cargo.toml version to release a new one).
  • Output dir: client-wasm/pkg/ (git-ignored — a generated artifact, never committed; the SDK / CI builds it on demand and dynamically import()s it).
  • Target: web matches the existing front/vite-project consumer (import init, { … } from "../pkg/client_wasm.js"; await init();). Use bundler for tsup/webpack pipelines that handle the init themselves.
  • Export naming: the module exposes keygen, sign, keygenMember, signMember, and pregeneratePrimes (plus the reshare-gated reshareAssemble / completeReshare) — camelCase names are set via #[wasm_bindgen(js_name = …)] so the JS surface matches the SDK's ClientWasmModule directly, no loader-side rename needed.

Tests

cargo test -p client-wasm                       # fast serde/contract tests
cargo test -p client-wasm -- --ignored          # + the real-MPC prime-pool test (minutes)

The fast tests pin the wire contract (params shapes, prime round-trip). The gated prime_pool_keygen_matches_inline_shared_public_key runs a real 3-party aux_info_gen + keygen through the in-memory simulation and proves the pool path produces the same, usable wallet key as the inline path.