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

@ergots/ergoscript

v0.5.0

Published

Pure-TS ErgoScript / ErgoTree parser + interpreter (phase 2 of ergots)

Downloads

57

Readme

@ergots/ergoscript

Pure-TypeScript ErgoTree parser, serializer, partial evaluator, and sigma-protocol verifier. Part of ergots. Browser-compatible. The wire layer (parse/serialize) and the v5 eval/cost surface are validated byte-for-byte against ergotree-ir + ergotree-interpreter (sigma-rust); the v6 (ErgoTree V3) eval/cost surface and adversarial faithfulness are validated against JVM-blessed conformance vectors (sigma-state, the canonical reference) — see the conformance run below.

Install

npm install @ergots/ergoscript

Usage

import {
  parseTree,
  serializeTree,
  isP2PK,
  p2pkPublicKey,
  addressFromErgoTree,
  ergoTreeFromAddress
} from '@ergots/ergoscript';

// Parse a serialized ErgoTree:
const treeBytes: Uint8Array = /* on-wire ErgoTree bytes (e.g. from a box.ergoTree field) */;
const tree = parseTree(treeBytes);
console.log(tree.header.version, tree.constants.length, tree.body.tag);

// Re-serialize — byte-identical to the input:
const roundTripped = serializeTree(tree);
// roundTripped equals treeBytes

// Recognize a P2PK guarding script and extract its public key:
if (isP2PK(tree)) {
  const pk = p2pkPublicKey(tree); // 33-byte compressed secp256k1 point
}

// Derive a base58 Ergo address from a tree:
const address = addressFromErgoTree(tree, 'mainnet');

// And back:
const reconstructed = ergoTreeFromAddress(address);

Evaluator

import { evaluate, evaluateWith, makeContext } from '@ergots/ergoscript';

// Evaluate a tree with default context (no box, no block, no transaction):
const result = evaluate(tree);

// Or supply context explicitly:
const ctx = makeContext({ /* EvalOpts */ });
const result2 = evaluateWith(tree, ctx);

evaluate returns an SValue (discriminated union keyed on .kind). 68 of 68 implementable Expr arms are wired (F5 batch 4 added the 68th, LastBlockUtxoRootHash; 21 wire opcodes are reserved in sigma-rust and parse-reject via 'opcode-reserved', mirroring the JVM's CheckValidOpCode path — FunDef (0xd7) was once in this group but is now parsed+evaluated as a ValDef from v6 P6, while FlatMap/TrivialPropFalse/TrivialPropTrue joined it (the bare opcodes have no Expr-layer serializer; flatMap dispatches as a method and the TrivialProp pair also has a separate SigmaBoolean-leaf form)). The 128-entry method-handler registry covers the full v5 surface plus the V3-gated v6 P0–P7a methods (numeric V3 bitwise/shifts/toBits/toBytes, SUnsignedBigInt methods/casts/arith/modular, Coll V3 reverse/startsWith/endsWith/get, Global.some/none/serialize/deserializeTo/fromBigEndianBytes/encodeNbits/decodeNbits/powHit, Box.getReg 99:19, Context.getVarFromInput 101:12, GroupElement.expUnsigned 7:6, the full SHeader/SPreHeader/SContext accessor surface). First-class functions (lambdas in tuples/colls/applied via Apply/ByIndex/SelectField; lexical closures capturing their definition-site env; FunDef 0xd7 parsed and evaluated as a ValDef; new EvalError 'apply-unresolved-type-var' for type-var-arg lambda apply). 84 EvalError codes. Cost values are JVM-accurate per arm.

Adversarial consensus faithfulness (conformance run F1–F5, validated against JVM-blessed SANTA vectors): ergots accepts exactly what the JVM sigma-state reference accepts and rejects exactly what it rejects, for hand-crafted as well as compiler-produced trees. Closed over the run: SHeader.stateRootAvlTree and powOnetimePk→generator (ergots leads sigma-rust toward the JVM), the independent SContext.lastBlockUtxoRootHash context field, and a family of adversarial over-accept gates the JVM rejects — non-pair-STuple/non-unary-SFunc value types ('unsupported-value-type'), SelectField on a non-pair ('select-field-non-pair'), rule-1012 header size-bit ('header-version-requires-size', all three ErgoTree ingresses), and rule-1019 v6-typed box registers ('register-v6-type').

Sigma-protocol verifier

import { verifySignature } from '@ergots/ergoscript';

// sigmaBoolean comes from an SValue.SigmaProp (from evaluate, or via parseSigmaBoolean)
const ok: boolean = verifySignature(sigmaBoolean, message, signature);

Verifies a Schnorr-style sigma-protocol proof against the full SigmaBoolean 6-variant surface (TrivialProp, ProveDlog, ProveDhTuple, Cand, Cor, Cthreshold including GF(2^192) polynomial threshold). Throws VerifyError on malformed signature bytes or off-curve points.

See API.md for the full reference (every export, its signature, error codes, and type definitions).

Public surface

The package exports a small consumer-facing API:

  • Wire format: parseTree, serializeTree, MAX_TREE_SIZE
  • Addresses: isP2PK, p2pkPublicKey, addressFromErgoTree, ergoTreeFromAddress, base58Encode, base58Decode
  • Evaluator: evaluate, evaluateWith, makeContext
  • Sigma-protocol verifier: verifySignature
  • Types: ErgoTree, TreeHeader, SType, SValue, Expr, SigmaBoolean, Network, AddressType, EvalContext, EvalOpts
  • Errors: ErgoTreeParseError, ErgoTreeSerializeError, AddressDecodeError, EvalError, VerifyError

The boundary contract — what other packages may rely on, with preconditions, postconditions, invariants, and the full error taxonomy — is documented in facts/ergoscript.md at the repo root.

Browser compatibility

Runs unchanged in evergreen browsers and Node >= 20. No Buffer, no node:crypto, no dynamic Node built-ins, no WASM. ESM-only. The bundle is scanned in CI for forbidden references (Buffer/process/node:* and Scala.js identifier patterns) before any release.

The package is stateless and pure: bytes in, structured result out. No I/O, no clock, no PRNG, no globalThis reads.

What this package does NOT do

  • v6 method surface — complete. All v6 phases shipped: P0–P6 + P7a as dedicated phases; P7b closed (its nominal behavior-changes — substConstants v6, AvlTree.insert/insertOrUpdate v6 — were already landed in the 2h-era port; the gap it surfaced, AvlTree Tier-2 cost, shipped as conformance-run F4); P8 (validation) delivered as the F1–F5 conformance run (JVM-blessed SANTA vectors, eval tier 100% green). (allZK/anyZK are source-level sugar over the shipped SigmaAnd/SigmaOr — no opcode, nothing to build.) Calling a method outside the registry throws EvalError 'method-not-implemented' (e.g. the mainnet-unreachable Box accessor method-forms 99:2..6 — a documented adversarial-only residual, tracked for a follow-up). Reserved/deprecated opcodes (ModQ family, OpTrue/OpFalse, UnitConstant, Select1-5, CollShift/CollRotate, SomeValue, NoneValue, FlatMap, TrivialPropFalse, TrivialPropTrue) parse-reject via 'opcode-reserved' and are never dispatched at the Expr layer (mirrors the JVM CheckValidOpCode reject and sigma-rust behavior; flatMap still dispatches as a method, and TrivialProp true/false still parse as a SigmaBoolean leaf inside a SigmaProp constant). FunDef (0xd7) is now parsed+evaluated (v6 P6).
  • No sigma-protocol prover. verifySignature is the verifier side of the sigma protocol — it checks proofs produced by sigma-rust's prover or any conformant prover. Proof generation is out of scope.
  • No .es source compiler. This is a binary AST parser — .es source compilation (sigma-rust's ergoscript-compiler) is out of scope.
  • No transaction building, no key derivation, no mnemonic/BIP32. Those belong to the future wallet / transaction-broadcaster package.

Validation strategy

Every parse + serialize primitive is validated byte-for-byte against fixtures generated by a Rust crate (fixture-gen/) that calls directly into sigma-rust's ergotree-ir at branch integration/ergots. The corpus covers:

  • Synthetic edge cases — VLQ boundary values, every SType variant, every SValue kind, every MIR Expr variant individually.
  • Real-world contracts — 45 legacy + 14 ecosystem + 15 significant-15 contracts pulled from sigma-rust's PR 862 ergoscript-compiler-v2 corpus.
  • Mainnet box scripts — guarding scripts from real Ergo mainnet outputs.

Six fixtures in the upstream sigma-rust corpus are flagged known_unstable because sigma-rust itself does not round-trip them; those are excluded from byte-equality but still parse-tested. Mutation testing single-byte-flips each fixture and asserts every flip either throws a typed error class or is byte-equal (a flip landing in a tolerated padding region) — total taxonomy coverage on every documented error code.

Evaluator validation adds two further layers:

  • Layer C1 — per-arm fixtures (one or more eval/<arm>.json files per arm, each entry covering both the evaluated SValue and the jit cost) validated byte-for-byte against ergotree-interpreter via try_eval_out / try_eval_out_with_version.
  • Layer C2 — corpus eval-filter: real mainnet box scripts are run through the evaluator and the subset that the current arm set can fully reduce is compared against sigma-rust's output value-for-value.
  • Layer C3.a — operator-driven mutation testing on the higher-order Coll arms and the AVL+ method handlers, targeting ≥ 90% kill rate per arm.

License

MIT