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

@dotk/wasm

v2.1.0

Published

The dotk protocol engine and Kaspa node client as WebAssembly: derive, verify and build .k name transactions in the browser

Readme

@dotk/wasm

The protocol engine behind dotk.name, compiled to WebAssembly. It derives addresses, encodes and decodes registry state, replays the card reader rules, builds and assembles transactions, and speaks wRPC to a Kaspa node, so a page can check what it is shown against the chain instead of trusting whoever served it.

import { DotkProtocol } from '@dotk/wasm'
import genesis from './generated/genesis'

const protocol = new DotkProtocol(genesis, 'mainnet')

The bundler target means a bundler resolves the .wasm and fetches it: no init() to call and no URL to configure. Vite, webpack and Rollup all treat it as an ordinary asset.

DotkProtocol

The engine. Everything below is a method on it, most useful first.

Names and prices. normalizeName folds what a person typed into the on-chain form and validateName says whether it can be one. keyOf is blake3(name), the key the registry is indexed by, and registrationFee is what a name of that length costs.

Addresses. deedAddressOf(name, ownerAddress) is where a name's deed lives, which is the one address a reader can probe a node for. ownerOf turns an address into the (ownerType, owner) pair a deed stores and ownerAddress turns it back. gapAddress and devfundAddress do the same for the other two things the registry pays to.

Building a transaction. buildSplit, buildActivate, buildTransfer and buildRelease produce an intent: the protocol seats, with no funding yet. assemble adds coins, the fee and the change; assembleWithCards does it for a transfer carrying records, and assembleSweep reclaims cards on their own. newborn names the deed a split will create, so a reveal can be built on a commit that has not been sent. applySignatures folds a wallet's answer back in.

Cards, the records object a name carries. cardPlan decides what a transfer should mint and sweep, verifyCard replays the reader rules against a deed and a UTXO, cardRecords decodes a blob, and cardAddress and cardValue say where a card lives and what it holds.

Subnames, a label a name's owner points at an address. bob.alice.k is the label bob on the card of alice.k. subnames lists every sub:<label> record a card carries, each with the payee it names or, under fault, the tag that refused it. subnameOf answers one label's payee, and throws that tag where the rules refuse the stored value. subnameValue builds such a record from an address and subnameKey from a label. subnameValue refuses an address for another network, and it refuses a payee nobody can spend: a zero payload, or a key that is no point on the curve. splitSubname divides a typed bob.alice.k into its label and its parent, and validateSubname answers why an input divides into neither. A payee is the parent owner's claim, and the chain proves none of it.

How a refusal reads. A method here refuses by throwing, and what it throws is a string. A refusal that the subname rules name opens that string with the fault tag, for example bad-label: the label part "Bob" breaks the label rule. The tag is the contract. Match on it, and show the words to a person.

The keyspace. keyspaceOf(keys) derives the whole partition from a set of deed keys and answers a DotkKeyspace, whose gapCount, gapBounds and gapAddresses enumerate the gaps between them without asking anyone.

The build itself. templateHashes reports the covenant bytecode this engine compiled against, and genesisVersion the one manifest shape it reads.

DotkRpc

A Kaspa node client over wRPC. connect and disconnect bracket a session and isConnected and url describe it; getInfo, feerate and virtualDaaScore ask the node about itself; fundingUtxos, covenantUtxos and covenantUtxosByAddresses list what an address holds, split by whether it carries a covenant id; and submitTransaction sends one.

readyMass answers the node's ready mempool mass, or undefined where the node does not report it. Pass it to an assembler beside feerate. While it fits in one block, the fee is the relay floor. Past one block, the fee ranks by storage mass too. Without it, the fee is the feerate on the fee mass.

It carries no deployment

new DotkProtocol(manifest, network) takes the manifest as an argument, and refuses published bytecode that does not reproduce the template hashes that manifest states. So one build serves every deployment, and a version of this package says which engine you have rather than which registry it is for. What you supply is your own manifest, built into your bundle rather than fetched, so that an indexer cannot hand a page the identity it judges that same indexer by.

The compatibility that does matter is the manifest schema. genesisVersion() says which shape this build writes; a manifest declaring a newer one carries fields this build does not read, which is advisory rather than fatal, and construction refuses a manifest on its contents alone: bytecode that does not reproduce the pinned template hashes, or a genesis binding that does not reproduce the registry covenant id.

License

MIT.