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

@winbit32/wallet-kit

v0.2.0

Published

Embeddable Zcash + Monero wallet primitives extracted from Winbit32: scanner API clients and the WB32COSIGN FROST/Orchard cosign client with a headless initiator pipeline. Framework-agnostic, browser-first, Node >= 18.

Downloads

306

Readme

@winbit32/wallet-kit

Embeddable Zcash + Monero wallet primitives extracted from Winbit32. The goal: anyone who wants to add a Zcash/Monero wallet (scanning, shielded sends, FROST co-signing) to their site installs this package and calls functions — no Winbit32 UI required.

Status / roadmap

Extraction happens in slices (each slice moves source here and leaves a re-export shim at the old Winbit32 path, so the app keeps working):

| Slice | Contents | Status | | --- | --- | --- | | Scanner clients | Zcash Orchard scan-job/UTXO/broadcast client, Monero LWS scan-job client, base-URL resolution | Done | | Cosign client | WB32COSIGN relay transports, .wult share handling, FROST/Orchard ceremony, headless initiator pipeline | Done | | MCP payment tools | make_payment tools ship in winbit32MCP (the public payments-gateway home), which consumes this kit | Done (lives in winbit32MCP) | | MCP tool descriptors | Framework-free view-key tool descriptors (createWalletKitToolDescriptors): zec/xmr scan jobs, UTXOs, broadcast — mount on any MCP server | Done (v0.2.0) | | Shielded send/scan core | shielded-transaction-client (PCZT build/sign/broadcast via WebZjs), note cache; unblocks direct-phrase MCP sends | Planned |

What's in the box today

import {
	resolveWalletScannerBaseUrl,
	createWalletScannerClient,        // Zcash: Orchard scan jobs, UTXOs, tx broadcast
	createMoneroWalletScannerClient,  // Monero: LWS scan jobs
	mapScannerBalanceToSnapshot,      // wire → bigint balance snapshot
} from '@winbit32/wallet-kit';

const zec = createWalletScannerClient({ baseUrl: 'https://api.zcash.winbit32.com/api' });
const { data } = await zec.startOrchardScanJob({ ufvk, autoDetect: true });

const xmr = createMoneroWalletScannerClient();
const job = await xmr.startMoneroScanJob({ address, viewKey });
  • All clients take an optional baseUrl/apiKey; without them the public api.zcash.winbit32.com host is used (its nginx injects the upstream API key, so browsers need none).
  • resolveWalletScannerBaseUrl() honours REACT_APP_WALLET_SCANNER_URL and falls back to a same-origin /api proxy in development and the public host in production. Non-CRA embedders should pass baseUrl explicitly.
  • No runtime dependencies; browser-first (uses fetch); works in Node ≥ 18.

Co-signing (FROST/Orchard, 2-of-2)

The canonical WB32COSIGN client lives here (src/cosign/). It powers both browser initiators (Secresea-style "send from a .wult share" flows) and fully headless Node hosts such as the seneschal.space payments-gateway:

import {
	unwrapVaultShare, toOrchardBundle,        // .wult → key bundle
	deriveOrchardAddressFromBundle,           // bundle → UFVK + u1… address
	runHeadlessCosignSend,                    // scan → build → ceremony → broadcast
	resolveCosignConfig,
} from '@winbit32/wallet-kit';

const share = await unwrapVaultShare(wultBytes, password);
const bundle = toOrchardBundle(share);
const { txid } = await runHeadlessCosignSend({
	config: resolveCosignConfig({ relayBaseUrl, pcztApiBaseUrl, fetchImpl: fetch }),
	wasm, bundle, ufvk, unifiedAddress, scanner,
	toAddress: 'u1…', amountZat: 25_000, // zatoshis
	onQrReady: (qr) => showToHuman(qr),       // WB32COSIGN:1:… pairing payload
});
  • The host holds one share; the human's cosigner (winbit32.com #cosign) holds the other. Neither side ever has the full spending key.
  • Transports are pluggable (BroadcastChannel same-device, HTTPS relay cross-device); messages are AES-GCM encrypted with the QR session key.
  • The orchard-frost WASM is loaded by the host: browsers fetch it from public/orchard-frost/, Node hosts read the same artefacts from disk (see loadOrchardFrostWasmNode in the payments-gateway for the pattern).

MCP tool descriptors

Mount the kit's view-key capabilities on any MCP server without taking a dependency on any particular SDK:

import { createWalletKitToolDescriptors } from '@winbit32/wallet-kit';

const tools = createWalletKitToolDescriptors(); // public scanner defaults
for (const tool of tools) {
	// adapt `tool.params` (flat primitive spec) to your schema flavour
	server.registerTool(`myprefix_${tool.name}`, { /* … */ },
		async (input) => ({ content: [{ type: 'text', text: JSON.stringify(await tool.handler(input)) }] }));
}

Tools: zec_scan_start/status/cancel, zec_utxos, zec_broadcast, xmr_scan_start/status/cancel. All view-key-only — they can observe funds but never move them. Signing tools (e.g. make_payment) deliberately live with the host's payment state machine (see winbit32MCP), which uses the kit's headless cosign pipeline underneath.

Building

cd packages/wallet-kit
npm run build   # tsc → dist/ (CommonJS + .d.ts; ESM hosts use src/ via bundler)

The compiled dist/ is CommonJS so plain Node hosts (e.g. the payments-gateway via a file: dependency) can require/import it without a bundler. Browser consumers (Winbit32 itself) compile src/ directly through their own bundler via the alias seam described below.

Tests

Kit tests run under the host repo's jest (CRA 27) in a Node environment:

CI=true npx react-app-rewired test --watchAll=false --testPathPattern='packages/wallet-kit'

src/cosign/__tests__/ceremony.integration.test.ts runs a real FROST/Orchard ceremony against the staged WASM — initiator and an independently-implemented cosigner stand-in — plus the whole runHeadlessCosignSend pipeline against fake PCZT/scanner endpoints. It skips (not fails) if public/orchard-frost/ artefacts are missing.

How Winbit32 consumes it

The app imports @winbit32/wallet-kit directly from packages/wallet-kit/src via a webpack alias + jest moduleNameMapper + tsconfig paths (see config-overrides.js). npm workspaces are deliberately NOT used yet: the CRA + WASM webpack setup is sensitive to node_modules hoisting, so the alias seam gives us the package boundary without the install churn. When the kit is published, the alias is simply dropped and the app depends on the npm package like everyone else.

Old Winbit32 paths (src/components/toolbox/walletScannerBaseUrl.ts, .../zcash-extensions/api/walletScannerClient.ts, .../monero-extensions/api/moneroWalletScannerClient.ts) remain as re-export shims; new code should import from @winbit32/wallet-kit.