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

alg-bn

v0.4.2

Published

Baretto-Naehrig (BN) curve arithmetic, defaulting to the alt_bn128 (BN254) curve used by Ethereum precompiles. Built on top of [`alg-field`](https://www.npmjs.com/package/alg-field).

Readme

alg-bn

Baretto-Naehrig (BN) curve arithmetic, defaulting to the alt_bn128 (BN254) curve used by Ethereum precompiles. Built on top of alg-field.

  • Package: https://www.npmjs.com/package/alg-bn
  • Scoped mirror: https://www.npmjs.com/package/@wa1one/alg-bn

Install

npm install alg-bn

Usage

const { BN128Fp, BN128Fp2 } = require('alg-bn')

const G = BN128Fp.create(1n, 2n)
G.double().eq(G.add(G)) // true
G.isOnCurve() // true

API

BN128Fp

A point on the base curve y² = x³ + 3 over Fp, held in Jacobian coordinates (x, y, z).

  • new BN128Fp(x, y, z)x/y/z must be Field instances (from alg-field); otherwise the point is left uninitialized.
  • static n — the curve order (bigint).
  • static B — the curve coefficient, Field(3n).
  • static ZERO — the point at infinity, (0, 0, 0).
  • static create(x, y) — builds a point from raw bigint affine coordinates with z = 1. Returns BN128Fp.ZERO for (0, 0), null if the coordinates aren't on the curve, or the point otherwise.
  • .add(o) — Jacobian point addition.
  • .double() — Jacobian point doubling.
  • .multiply(s) — scalar multiplication by a bigint.
  • .neg() — the additive inverse (negates y).
  • .isZero()true if z is 0 (point at infinity).
  • .isOnCurve() — checks y² = x³ + b·z⁶.
  • .isValid()true if the coordinates are Field instances and the point is on the curve.
  • .toAffine() — normalizes z to 1 (or (0, 1, 0) for the point at infinity).
  • .toEthNotation() — like .toAffine(), but encodes the point at infinity as (0, 0, 0) instead of (0, 1, 0).
  • .eq(o) — compares x, y, z directly (not affine-normalized); two Jacobian representations of the same affine point can compare unequal unless you call .toAffine() first.
  • .toString()"x, y, z".

BN128Fp2

A point on the sextic twist curve over Fp2, mirroring BN128Fp but with Fp2 coordinates. Same Jacobian-coordinate caveats apply to .eq().

  • new BN128Fp2(x, y, z)x/y/z must be Fp2 instances.
  • static n — the curve order (bigint).
  • static ZERO — the point at infinity, (0, 0, 0).
  • static TWIST — the twist parameter, Fp2(9n, 1n).
  • static B_Fp2 — the twisted curve coefficient.
  • static create(a, b, c, d) — builds a point from raw bigint affine coordinates x = a + b·u, y = c + d·u, with z = 1. Returns BN128Fp2.ZERO for all-zero input, null if not on the curve, or the point otherwise.
  • .add(o) — Jacobian point addition.
  • .double() — Jacobian point doubling.
  • .multiply(s) — scalar multiplication; s is coerced to bigint if it isn't one already.
  • .isZero()true if z is 0.
  • .isOnCurve() — checks y² = x³ + B_Fp2·z⁶.
  • .isValid()true if the coordinates are Fp2 instances and the point is on the curve.
  • .toAffine() — normalizes z to 1 (or (0, 1, 0) for the point at infinity).
  • .toEthNotation() — like .toAffine(), but encodes the point at infinity as (0, 0, 0).
  • .mulByP() — applies the Frobenius twist (used when pairing with the base-field group).
  • .eq(o) — compares x, y, z directly; see the BN128Fp note above.
  • .toString()"[x, y, z]", where each coordinate is itself "a, b".

Curve, Curve2, Point, Point2, Point12

A second, affine-coordinate point representation, built on alg-field's tunable Fp2 tower rather than Field/Fp2 directly. Unlike BN128Fp/ BN128Fp2, .eq() here compares canonical affine coordinates directly, so points computed via different code paths (e.g. .multiply() vs. repeated .add()) compare equal without any extra normalization step. This is the family to use if you need a curve other than the BN254 default — nothing is hardcoded inside Curve/Curve2; every curve-specific constant (generator, b coefficient) comes from the params object you pass in.

const { Curve, Curve2, Bls12381Parameters } = require('alg-bn')

const curve = new Curve() // defaults to BN254 (Bn254Parameters)
curve.contains(curve.G) // true
curve.G.multiply(3n).eq(curve.G.add(curve.G.double())) // true

// Any curve with a matching params shape works, e.g. the bundled BLS12-381:
const blsCurve = new Curve(Bls12381Parameters)
const blsCurve2 = new Curve2(blsCurve)
blsCurve2.contains(blsCurve2.Gt) // true
  • Bn254Parameters, Bls12381Parameters — ready-made params objects for Curve/Curve2, each bundling { p, n, fp2Params, xiRe, twistType, b, Gx, Gy, G2b, G2x, G2y }: the field modulus and subgroup order, the derived Fp2 tower params every Fp2 value on that curve must share, the real part of the curve's Fp6 sextic non-residue and its twist type ('D' for BN254, 'M' for BLS12-381 — see the Point12 note below), and the base (G1) and twisted (G2) curve coefficients/generators. Named distinctly from alg-field's own Parameters/Bls12381Parameters (which are field-only, { p, n }) to avoid a collision when both packages are required together. To use a curve that isn't bundled, build an object with this same shape — fp2Params comes from alg-field's deriveFp2Params(p).
  • Curve — the base curve y² = x³ + b over Fp. new Curve(bn = Bn254Parameters) exposes .G (the generator, a Point), .infinity (the identity Point), and .contains(P).
  • Curve2 — the sextic twist curve (extends Curve). new Curve2(E = new Curve()) takes a base Curve instance and reads its twist coefficient and generator directly from E.bn.G2b/G2x/G2y — no curve-specific branching or derivation happens here. Exposes .Gt (the twist generator, a Point2) and .Fp12_1 (the Field12 multiplicative identity, used to build the Point12 identity).
  • Point — a point on Curve, in affine (x, y) Fp2 coordinates (base- curve points use im = 0). .add(), .double(), .multiply(n) (accepts a bigint or coercible value), .neg(), .twice(n), .eq(), .toString().
  • Point2 — a point on Curve2 (extends Point); the 3-argument constructor validates curve membership via Curve2.contains() and throws pointNotOnCurve otherwise.
  • Point12, .toF12() (on Point/Point2) — embeds a G1 or G2 point into the Fp12 pairing target group, in Field12 coordinates. Works for any curve whose params object supplies xiRe/twistType (both bundled parameters do) — alg-field's Field12 (>= 0.3.0) derives its degree-12 modulus polynomial from bn.p automatically, and Point2.toF12()'s untwist map branches on twistType to match whichever convention that curve's G2b was built with (G2b = b / xi for a D-twist, G2b = b * xi for an M-twist — these aren't a free choice, they're a real per-curve-family convention, so a curve you add yourself needs to get this right for its own G2b). alg-bn still has no complete Miller-loop pairing implementation for any curve — toF12()/Point12 are the embedding building block, not a full pairing.

JacobianPoint, JacobianPoint2

Same curve/params contract as Point/Point2 (built on the same Curve/ Curve2 instances, same tunable bn shape), but in Jacobian (x, y, z) coordinates instead of affine. Point/Point2 pay a full field inversion (.divide()) on every single .add()/.double(); Jacobian coordinates need none until you actually want the affine x/y back (.toAffine()), so .multiply() does its doublings/additions inversion-free and normalizes once at the end. Note: on alg-field's native-BigInt-backed fields, this is a smaller win than the classical "inversion costs 10-100x a multiplication" rule of thumb suggests — V8's BigInt modular inverse is close to multiplication cost at these prime sizes, so .multiply() here is roughly on par with Point.multiply() for BN254-sized primes and only modestly faster for larger ones (BLS12-381 in informal local benchmarks). Add it where you specifically want to avoid per-operation inversions (e.g. a much larger custom prime) rather than as a default performance upgrade.

const { Curve, JacobianPoint } = require('alg-bn')

const curve = new Curve()
const JG = JacobianPoint.fromAffine(curve, curve.G)
JG.multiply(12345n).toAffine().eq(curve.G.multiply(12345n)) // true
  • new JacobianPoint(E, x, y, z)x/y (both Fp2) with z omitted default to z = 1; all of x/y/z omitted builds the point at infinity. No on-curve validation (matching Point's 4-argument form) — use JacobianPoint.fromAffine or Curve.contains(P.toAffine()) if you need it.
  • JacobianPoint.fromAffine(E, P) — builds a JacobianPoint from an existing (already-validated) Point.
  • .toAffine() — normalizes to z = 1 and returns a Point.
  • .add(), .double(), .twice(n), .multiply(n), .neg(), .eq() (compares canonical Jacobian coordinates directly — like Point, not BN128Fp, no normalization needed first), .zero(), .toString(), .toF12() (both delegate to .toAffine()).
  • JacobianPoint2 — the Curve2 counterpart (extends JacobianPoint). new JacobianPoint2(E, x, y) (z omitted, i.e. a fresh affine-equivalent point) validates via Curve2.contains() and throws pointNotOnCurve, matching Point2; the 4-argument (E, x, y, z) form used internally by .add()/.twice() does not re-validate every intermediate value. JacobianPoint2.fromAffine(E, P) mirrors JacobianPoint.fromAffine.

Development

To run tests

npm test

To lint

npm run lint

To build

npm run build