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

@xanaverse/contracts

v1.6.0

Published

The Bitcoin covenants behind zanaadu.com (trustless social media on BSV): lean hand-emitted covenants for posts, upvotes, downvotes, replies, sharded on-chain name and picture registries (SMT heads with a built-in marketplace), plus the sCrypt user-number

Readme

@xanaverse/contracts

The Bitcoin covenants behind zanaadu.com, trustless social media on BSV. Posts, upvotes, downvotes, replies, user numbers, names and profile pictures are all UTXOs whose payment, ownership and uniqueness rules are enforced by Bitcoin Script and validated by the network, not by a platform. This package ships every covenant the product has ever written, the exact bytes running on production today, the specs they were built from, and the interpreter harnesses that prove them, so anyone can verify the chain without trusting us.

What runs on production

zanaadu.com, mainnet, as of 2026-10-14. Every family below is recognised on chain by the sha256 of its static script suffix (the bytes after the state pushes). tools/verify-stamps.cjs recomputes these from the shipped code.

| Surface | Contract | Entry point | Written since | Suffix | sha256 of the suffix | |---|---|---|---|---|---| | Posts with a payout slot | PostAnchorV4 | /v3 | parsed by production's Workers since 2026-10-14; written from the frontend's two-key release | 1,099 B | 6205d253057ac07bfcae6a6235e30674443aaf0df27014098631bf2217cc7aa9 | | Posts | PostAnchorV3 | /v3 | 2026-07-16 | 1,082 B | f82ab0b117f36fd65afc5256bc8214fc088ef89d9b320cbab9f08fe0c55386cc | | Upvotes | UpvoteProofV3 | /v3 | 2026-07-16 | 1,805 B | 1856a697babeba7d3703c26aed7dc15856cfcd9096a2cf130e538a3e2918bc90 | | Downvotes | DownvoteProofV3 | /v3 | 2026-07-16 | 1,805 B | 4ef614df5f7f6025589fe544be6cf9e87750b5d8ef80f09fc6e55861ee6d8449 | | Replies | ReplyProofV3 | /v3 | 2026-07-16 | 1,826 B | 8378c40116038ec7052324b04965406678fee552d3645386944c6eb924b83aad | | Names | PfNameHeadV3 | /v3 | 2026-09-16 | 8,029 B | 4e1bd1ef10191ad54d1e6a15c136bc292daabbefa8875283294a10b23a2ad5c4 | | Profile pictures | PfPictureHeadV1 | /v3 | 2026-09-16 | 7,522 B | 4020fdb24166a9fb593fae4e0aacbbafe7c4358bcedb72e45c6a34bd01f82ce5 | | User numbers (@N) | UserRegistry + UserProof | main (sCrypt) | production launch, 2026-06 | compiled artifact | see dist/artifacts/ |

The two identity registries are sharded: 256 name heads under namespace eb6023d17b39d0dc4b3467452c2d029fcdbb061931ab5d6b38e806e55ad40a08 and 64 picture heads under 5e9779ee96d24707f10dc85fb6a280cf03d5a7a9a9abe3f2cc1408437335c457. The genesis outpoint of every head is in docs/HEAD-TABLE-name-production.json and docs/HEAD-TABLE-picture-production.json, the same tables the production indexer embeds and hash-verifies at boot. The user-number registry is a single sCrypt UTXO chain whose genesis is a9b16035cce2c62e1c86af85081beb658d65c2f5f53f052f7b70d72c38a549bb.

On chain, read only. These were written by earlier versions of the app and are still parsed, counted and reclaimable, but nothing new is written in them: PostAnchorV0, PostAnchor (v1), PostAnchorV2 (lockable posts) and the v1 sCrypt UpvoteProof, DownvoteProof, ReplyProof. Since 2026-07-16 every new post and engagement is a V3 lean covenant, including locked and hash-only posts (PostAnchorV3 is a superset of V2).

Frozen history, not in the product. Exported so old outputs stay verifiable and so the harnesses keep proving them byte for byte: PfNameHeadV2 (ec1ad66d…, the beta registries of 2026-08, superseded on 2026-09-08 by V3 which commits the name's casing), PfPictureProofV1 (abfc46d1…, a per-token picture asset, mainnet-proven 2026-08-26, replaced by the picture registry on 2026-08-28), PfNameProofV1 (its name twin, rehearsal only), PfNameHeadV1 (the register-only head of the first mainnet rehearsals) and PfMintQuotaHead (designed, never deployed).

Standalone. TimeLockedGift (sCrypt, since 1.4.0) is a one-shot time-locked payment covenant. It is complete and mainnet-tested but zanaadu.com does not use it.

Install

npm install @xanaverse/contracts

The main entry needs the peer dependency scrypt-ts ^1.4.0 (contract classes and artifacts). The /v3 entry has zero dependencies: plain functions that return hex.

Verify what you installed

# 1. The shipped bytes are the frozen production stamps (three sources compared,
#    sha256 recomputed with node:crypto). Exit 0 = all match.
node node_modules/@xanaverse/contracts/tools/verify-stamps.cjs

# 2. Execute every covenant through the BSV Script interpreter (needs scrypt-ts installed).
#    Positives and negatives per arm, mainnet relay flags, real signatures and preimages.
node node_modules/@xanaverse/contracts/poc-shrink/v3/harness.cjs                          # posts + engagement, 59 cases
node node_modules/@xanaverse/contracts/poc-shrink/v3/harness.cjs --v4                     # V4 posts + engagement witnessing the payout, 16 cases
node node_modules/@xanaverse/contracts/tools/post-v4-mutations.cjs                         # V4 covenant mutants, 3 of 3 killed
node node_modules/@xanaverse/contracts/poc-shrink/v3/harness-pf-name-v3.cjs --fuzz 200    # names, 156 cases + 400 fuzz
node node_modules/@xanaverse/contracts/poc-shrink/v3/harness-pf-picture-head.cjs --fuzz 200  # pictures, 129 cases + 400 fuzz

poc-shrink/v3/emit.ts is the emitter source of record and compile.sh is the exact tsc recipe that reproduces emit.compiled.cjs, the file the harnesses execute. The raw sCrypt sources are in src/contracts/; the artifacts in dist/artifacts/ are what npm run compile produces from them.

Entry points

// sCrypt contracts: user numbers, legacy posts and engagement, TimeLockedGift
import { UserRegistry, UserProof, UserRegistryArtifact, parsePostAnchor } from '@xanaverse/contracts'

// Lean covenant emitters: posts, engagement, names, pictures, SMT, PUSHTX machinery
import { emitPostAnchorV3Lock, emitPfNameV3Lock, SmtTree256 } from '@xanaverse/contracts/v3'

Both are shipped as CommonJS and ESM with type declarations.

The /v3 covenants

Every V3-family output is [state prefix][static suffix]: the state is a fixed sequence of data pushes and the suffix is a constant script that reads its own state back off the stack. Recognition is the end-anchored sha256 of the suffix (table above); the descriptors export those stamps:

import { V3_DESCRIPTORS, PF_NAME_V3_DESCRIPTORS, PF_PICTURE_HEAD_DESCRIPTORS } from '@xanaverse/contracts/v3'

for (const d of [...V3_DESCRIPTORS, ...PF_NAME_V3_DESCRIPTORS, ...PF_PICTURE_HEAD_DESCRIPTORS]) {
  console.log(d.contract, d.suffixLen, d.suffixSha256, d.stateFields)
}

Spending a covenant is PUSHTX: the unlock carries the BIP143 sighash preimage of the spending transaction, the script verifies it against a fixed key and then reads the outputs it needs to constrain straight out of the preimage. Engagement and posts use SIGHASH_SINGLE|ANYONECANPAY|FORKID (0xc3, one output bound); the registries use SIGHASH_ALL|ANYONECANPAY|FORKID (0xc1, the whole output set bound). Builders must produce MINIMALDATA pushes and low-S signatures; poc-shrink/ENGAGEMENT_V3_DESIGN.md §3 and docs/PF-SPEC.md §3.8 list the mainnet relay rules a builder follows.

Shared machinery exported for builders and verifiers: buildSighashPreimage, pushtxBlock, pushData, scriptNum, pushInt, p2pkhLock, sha256Hex, hash256Hex, the OP table and the Asm symbolic-stack builder every suffix is emitted with.

Posts: PostAnchorV3

State prefix, 11 pushes in order: creatorProtocolPubKey (33 B), slot2 (32 B commitment, becomes contentHash after publish), nonce (32 B), lockUntil (4 B LE), contentMode (4 B LE), committedSats (8 B LE), createdAt, parentHash, content, tags, creatorIdentityKey. The last five are empty in the template and set at publish.

| Selector | Arm | What the covenant enforces | |---|---|---| | OP_1 | publish | creator signature; reveals the body (mode 1) or its hash (modes 2/3) against the template commitment; rebuilds the anchor at committedSats with lockUntil, contentMode, committedSats copied verbatim | | OP_2 | addContent | mode 3 only; proves sha256(content) == contentHash and reveals the body | | OP_0 | reclaim | creator signature; the spending tx must carry nLockTime >= lockUntil with a non-final sequence, so the network refuses it early; pays committedSats back |

import {
  emitPostAnchorV3Lock, buildPostAnchorV3PublishedState,
  emitPostV3PublishUnlock, emitPostV3AddContentUnlock, emitPostV3ReclaimUnlock,
  type PostAnchorV3State,
} from '@xanaverse/contracts/v3'

Content modes: 1 body on chain at publish, 2 hash only (body off chain), 3 hash at publish and body revealed later with addContent. Design: poc-shrink/SINGLE_TX_POST_DESIGN.md and ENGAGEMENT_V3_DESIGN.md §3.9.

Engagement: UpvoteProofV3, DownvoteProofV3, ReplyProofV3

State prefix (votes, 7 pushes): voterProtocolPubKey, slot2 (commitment, then the post's contentHash), nonce, creatorProtocolPubKey, creatorIdentityKey, voterIdentityKey, paymentAmount. Replies add replyContent, parentContentHash, createdAt. The act arm proves the target post exists (the post transaction rides in the unlock and is walked in script), forces the payment output to the post creator's key at or above the baked-in minimum (100 sats for votes, 50 for replies) and rebuilds the proof with the revealed fields; reclaim is voter-signed. Payment amounts are read from the proof, never estimated: earnings are the sum of paymentAmount over proof UTXOs.

import {
  emitUpvoteProofV3Lock, emitDownvoteProofV3Lock, emitReplyProofV3Lock,
  emitVoteActUnlock, emitReplyActUnlock, emitEngagementReclaimUnlock,
  ENGAGEMENT_SUFFIXES, type EngagementV3State,
} from '@xanaverse/contracts/v3'

Names: PfNameHeadV3

A name is a leaf in a depth-256 sparse Merkle tree whose root lives in one of 256 shard heads (a UTXO chain per shard). Each head is 20 <namespaceId 32> <shardId> <shardMask> 20 <root 32> [SUFFIX 8,029 B], with namespaceId, shardId and shardMask immutable and copied forward by every arm.

  • Charset [A-Za-z0-9_], 1 to 20 bytes, checked in script.
  • Uniqueness is case-insensitive: leafKey = sha256(fold(name)) with the ASCII lowercase fold computed in script, so Alice and alice are one name and a second mint dies on the non-membership proof. The leaf commits the cased bytes the holder chose.
  • leaf = sha256(name ‖ ownerSigner33 ‖ ownerIdentity33 ‖ minterIdentity33 ‖ price8); home shard = leafKey[0] & shardMask.
  • Names are permanent, like user numbers: there is no expiry. Ownership, listing, sale to a buyer (seller paid by a script-forced P2PKH output) and release back to the pool are all arms of the head, all miner-enforced.
  • Every owner signature is SIGHASH_ALL|ANYONECANPAY|FORKID; the covenant binds the whole output set, so nothing can be smuggled into a spend.

| Selector | Arm | Signer | Leaf transition | |---|---|---|---| | 1 | mint | new owner | empty → leaf(name, S, I, M = I, 0) | | 2 | list | owner | price 0 → argA (1 ≤ p < 2^48) | | 3 | updatePrice | owner | listed → argA | | 4 | delist | owner | listed → price 0 | | 5 | transfer | owner | owner → (argA, argB), price 0 | | 6 | buy | buyer (argA) | listed → (argA, argB), price 0; extra output P2PKH(hash160(S)) at the listed price | | 7 | recase | owner | name → argA with the same fold; price kept | | 0 | release | current owner | leaf → empty |

Unlock pushes, bottom to top: 256 siblings (bottom-to-top proof order), preimage, sig, name, ownerSigner, ownerIdentity, minterIdentity, price8, argA, argB, tail (the spender's outputs after the head and the arm's extra output), sel.

import {
  emitPfNameV3Lock, emitPfNameV3Unlock, pfNameV3Next,
  pfNameFold, pfNameV3LeafKey, pfNameV3Leaf, pfNameV3ShardOf, pfNameV3KeySlotOk,
  PF_NAME_V3_SEL, type PfNameHeadState, type PfNameV3UnlockArgs,
} from '@xanaverse/contracts/v3'

Spec: docs/PF-SPEC.md §1 to §3 and §3c.

Profile pictures: PfPictureHeadV1

The same head shape and arms over 64 shards, with leafKey = imageHash = sha256(exact image bytes) witnessed directly (32-byte width check in script, no re-hash), so one image can be registered once across the whole network, and selector 7 is touch, an owner-signed no-op that re-emits the leaf. The image bytes never ride in a head spend; they are published in a separate content transaction (OP_FALSE OP_RETURN envelope, docs/PF-SPEC.md §4.5) by anyone, before or after the mint, and a reader only trusts bytes that hash to the committed imageHash.

import {
  emitPfPictureHeadLock, emitPfPictureHeadUnlock, pfPictureHeadNext,
  pfPictureLeafKey, pfPictureLeaf, pfPictureShardOf,
  PF_PICTURE_HEAD_SEL, type PfPictureHeadState, type PfPictureHeadUnlockArgs,
} from '@xanaverse/contracts/v3'

Spec: docs/PF-SPEC.md §3b.

Sparse Merkle tree reference

SmtTree256, smtComputeRoot, smtDirectionsForKey, SMT_EMPTY_ROOT_HEX: depth 256, single SHA-256, node = sha256(left ‖ right), empty leaf = 32 zero bytes, proofs emitted bottom to top. Bit-exact with the UserRegistry covenant (the empty root is asserted equal at module load) and with the production indexer.

The sCrypt contracts (main entry)

import { UserRegistry, UserRegistryArtifact, UserProof, UserProofArtifact } from '@xanaverse/contracts'

UserRegistry.loadArtifact(UserRegistryArtifact)
UserProof.loadArtifact(UserProofArtifact)

const registry = UserRegistry.fromLockingScript(lockingScriptHex)
console.log(`Users registered: ${registry.nextUserId - 1n}`)

Contract classes

| Contract | Status on production | |---|---| | UserRegistry | LIVE. Singleton assigning sequential user numbers, SMT duplicate prevention | | UserProof | LIVE. Tradeable user-number ownership NFT with a built-in marketplace | | PostAnchor (v1) | on chain, read only since 2026-07-16 | | PostAnchorV0 | on chain, read only (frozen legacy format) | | PostAnchorV2 | on chain, read only since 2026-07-16 (lockable posts; V3 carries the same fields) | | UpvoteProof, ReplyProof, DownvoteProof (v1) | on chain, read only since 2026-07-16 | | TimeLockedGift | standalone, not used by the product |

Artifacts are exported next to every class (PostAnchorArtifact, UserProofArtifact, …). Load an artifact before instantiating or parsing.

Protocol constants

import {
  PROTOCOL_ID, PROTOCOL_KEY_ID, PROTOCOL_COUNTERPARTY, PROTOCOL_BASKETS, PROTOCOL_SHARED_CONFIG
} from '@xanaverse/contracts'

PROTOCOL_ID           // [0, 'xanaverse']   BRC-42 key derivation
PROTOCOL_KEY_ID       // '1'
PROTOCOL_COUNTERPARTY // 'self'
PROTOCOL_BASKETS      // { posts, upvotes, replies, downvotes } BRC-100 basket names

Parsing legacy posts (version-aware)

parsePostAnchor detects v0, v1 and v2 from the script itself and returns a normalised shape; getPostAnchorInstance returns the raw contract for reclaim (a v2 post must reclaim through the v2 instance, whose reclaim() carries the CLTV gate and pays out committedSats). getUpvoteProofInstance, getDownvoteProofInstance, getReplyProofInstance do the same for v1 engagement proofs. V3 outputs are not sCrypt contracts: recognise them by suffix stamp and read the state pushes in the order given above.

import { parsePostAnchor, isPostAnchor, getPostAnchorInstance } from '@xanaverse/contracts'
import type { ParsedPostAnchor } from '@xanaverse/contracts'

if (isPostAnchor(lockingScript)) {
  const post: ParsedPostAnchor = parsePostAnchor(lockingScript)
  post.version      // 0 | 1 | 2
  post.content      // post text
  post.contentHash  // sha256
  post.tags         // v1+
  post.lockUntil    // v2 only; 0n = unlocked
  post.contentMode  // v2 only; 1n full | 2n hash-only | 3n hash+data
}

UserRegistry and UserProof

interface UserRegistryState {
  nextUserId: bigint               // next sequential number
  registeredKeysRoot: ByteString   // SMT root of registered identities (depth 256)
  treasuryAddress: PubKeyHash      // registration fee recipient
  platformAddress: PubKeyHash      // marketplace fee recipient
}
UserRegistry.REGISTRATION_FEE = 1000n
UserRegistry.SMT_DEPTH = 256

interface UserProofState {
  userId: bigint                   // immutable
  originalRegistrant: PubKey       // immutable provenance
  ownerPubKey: PubKey              // current owner's protocol key
  ownerIdentityKey: PubKey         // current owner's identity key
  isForSale: boolean
  salePrice: bigint
  platformAddress: PubKeyHash
}
UserProof.PLATFORM_FEE_BPS = 100n  // 1 % marketplace fee

Marketplace methods, all covenant-enforced with the owner signature first: list(sig, price), updatePrice(sig, newPrice), delist(sig), buy(sig, newOwner, newOwnerIdentityKey) (the covenant validates the seller payout), transfer(sig, newOwner, newOwnerIdentityKey), reclaim(sig).

PostAnchorV2 and TimeLockedGift (timelocks on BSV)

OP_CHECKLOCKTIMEVERIFY is a NOP on BSV post-Genesis. What Genesis kept is consensus enforcement of transaction finality: a transaction with a future nLockTime and a non-final input sequence is not mined until median-time-past passes the lock. Both covenants read the spending transaction's own nLockTime and nSequence out of the sighash preimage (timeLock()) and force the spender to build a transaction the network refuses to confirm early. PostAnchorV3 uses the same mechanism for reclaim.

import { TimeLockedGift, TimeLockedGiftArtifact } from '@xanaverse/contracts'
TimeLockedGift.loadArtifact(TimeLockedGiftArtifact)
const gift = new TimeLockedGift(PubKey(recipientPubKeyHex), BigInt(unlockUnixTime), BigInt(satoshis))
// unlock(sig): timelock elapsed, recipient signature, output pinned to P2PKH(recipient, amount)

What is in the tarball

| Path | What | |---|---| | dist/ | CommonJS + ESM builds, type declarations, compiled sCrypt artifacts | | src/contracts/ | raw sCrypt sources of the main-entry contracts | | src/v3/index.ts | the /v3 entry (re-exports the emitter) | | poc-shrink/v3/emit.ts | the emitter source of record, every clause annotated with its spec section | | poc-shrink/v3/emit.compiled.cjs, compile.sh | the compiled emitter the harnesses run, and the exact recipe that reproduces it | | poc-shrink/v3/harness*.cjs | interpreter harnesses: posts + engagement, name head V3 / V2 / V1, picture head, asset tokens, quota head | | poc-shrink/ENGAGEMENT_V3_DESIGN.md, SINGLE_TX_POST_DESIGN.md, v3/SIZES.md | the V3 designs and measured sizes | | docs/PF-SPEC.md | the name and picture registry spec (snapshot at this release) | | docs/HEAD-TABLE-*-production.json | the production genesis head tables (namespace, shards, outpoints, table hash) | | tools/verify-stamps.cjs | the stamp verifier |

Trust model

  • Counts are derived by querying proof UTXOs; an indexer can cache them but cannot invent them.
  • Every payment rule (engagement minimums, seller payouts, platform fees) is enforced by Bitcoin Script at the network level.
  • Identity is a Merkle proof: a name, a picture or a user number is verifiable against a head's committed root by anyone with the chain.
  • Timelocks are enforced by transaction-finality consensus, not application code.
  • The bytes are frozen and stamped; the harnesses and verify-stamps let you check both before you rely on either.

License

MIT