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

@maximus-chain/multichain-lib

v4.0.1

Published

A multi-chain cryptocurrency primitives library. Built-in support for MaximusChain; register custom chains.

Readme

Multichain Library

A pure, multi-chain cryptocurrency primitives library for UTXO-based, secp256k1, ECDSA chains. Ships with built-in support for MaximusChain and Osmium, and lets you register any other compatible chain at runtime.

Every chain is fully isolated: create(name) returns a self-contained chain-lib (its own Networks, hash registry, and class closures), so two chain-libs — even for the same chain name — are safe to use concurrently, including across await boundaries.

import { create } from '@maximus-chain/multichain-lib';

const maximus = create('maximus');
const address = new maximus.PrivateKey('livenet').toAddress().toString();

Table of contents

Install

npm install @maximus-chain/multichain-lib

Quick start

// Node ESM (or any modern bundler)
import { create } from '@maximus-chain/multichain-lib';

const maximus = create('maximus');
const privateKey = new maximus.PrivateKey('livenet');
const address = privateKey.toAddress().toString();
const message = new maximus.Message('hello').sign(privateKey);
console.log(address, message.toString('hex'));

The create(name) call returns a chain-lib with the full set of chain-bound classes (Address, PrivateKey, PublicKey, HDPublicKey, HDPrivateKey, Script, Message, Transaction, ProRegTxPayload, Mnemonic, UnspentOutput, Unit, Opcode) plus the network (Networks) and helper namespaces (crypto, encoding, util, errors).

Loading the library

Node (CJS and ESM)

The package ships with both entry points:

// CJS — `main` in package.json
const { create } = require('@maximus-chain/multichain-lib');

// ESM — `module` in package.json
import { create } from '@maximus-chain/multichain-lib';

The default export is the full namespace (so import multichain from '...' keeps working too):

import multichain from '@maximus-chain/multichain-lib';
const maximus = multichain.create('maximus');

Browser (CDN / <script> tag)

The UMD bundle is published to npm and resolves via the unpkg field, which points at dist/multichain-lib.min.js. Include it directly:

<script src="https://unpkg.com/@maximus-chain/multichain-lib/dist/multichain-lib.min.js"></script>
<script>
  const maximus = window.multichain.create('maximus');
  const privateKey = new maximus.PrivateKey();
  const address = privateKey.toAddress().toString();
  console.log(address);
</script>

Browser (bundler)

If you use webpack / Rollup / Vite, prefer the ESM build (module field):

import { create } from '@maximus-chain/multichain-lib';

Named imports are first-class: create, chains, registerChain, createHashRegistry, version, and versionGuard are all exported.

Multi-chain usage

Built-in chains

import { create, chains } from '@maximus-chain/multichain-lib';

console.log(chains()); // ['maximus', 'osmium']
const maximus = create('maximus');
const osmium = create('osmium');

Each built-in chain brings its own address prefixes, network magic, message magic, and PoW hash algorithm.

Registering a custom chain

A chain is described by two pieces of data:

  1. A network config per environment (livenet and testnet) with version bytes, P2P magic, default port, and DNS seeds.
  2. A hash algorithm map (e.g. X11, SHA-256d, Scrypt) used by crypto.Hash.forNetwork.
import { create, registerChain } from '@maximus-chain/multichain-lib';

registerChain('mycoin', {
  name: 'mycoin',
  messageMagic: 'MyCoin Signed Message:\n',
  algorithms: {
    sha256d: (buf) => {
      // SHA-256 applied twice
      // ...
    },
  },
  livenet: {
    name: 'livenet',
    pubkeyhash: 0x00,
    privatekey: 0x80,
    scripthash: 0x05,
    xpubkey: 0x0488b21e,
    xprivkey: 0x0488ade4,
    networkMagic: 0xf9beb4d9,
    port: 8333,
    dnsSeeds: [],
    hashFunction: 'sha256d',
  },
  testnet: {
    name: 'testnet',
    pubkeyhash: 0x6f,
    privatekey: 0xef,
    scripthash: 0xc4,
    xpubkey: 0x043587cf,
    xprivkey: 0x04358394,
    networkMagic: 0x0b0b0b0b,
    port: 18333,
    dnsSeeds: [],
    hashFunction: 'sha256d',
  },
});

const mine = create('mycoin');
console.log(mine.crypto.Hash.list()); // ['sha256d']

See docs/INTEGRATE-CHAIN.md for the full list of config fields, where to find them in a chain's source code, and verification checklists.

Isolation guarantees

Two chain-libs — whether for the same chain name or different ones — never share state. There is no global, module-level "active chain" singleton anywhere in the library. This means:

  • Flipping libA.Networks.setActive('testnet') does not affect libB.
  • A hash algorithm registered on one chain's config does not leak into another.
  • It is safe to hold onto multiple chain-libs and use them concurrently from multiple await operations.
const a = create('maximus');
const b = create('maximus');
a.Networks.setActive('testnet');
console.log(b.Networks.getActive().name); // 'livenet' — unchanged

Subpath exports

Each built-in chain config is also reachable as a subpath export. This is useful when you want to import a chain config to pass to registerChain or just to keep a reference:

// Import the config object as a value
import { config as maximusConfig } from '@maximus-chain/multichain-lib/chains/maximus';
import { config as osmiumConfig } from '@maximus-chain/multichain-lib/chains/osmium';

// Or as default import — same content
import maximusConfig from '@maximus-chain/multichain-lib/chains/maximus';

The TypeScript types at these subpaths narrow create('<name>') to the chain-specific ChainLib (see below).

TypeScript

The package ships first-class types. The root API surface is:

import { create, chains, registerChain, createHashRegistry, version } from '@maximus-chain/multichain-lib';
import type { ChainLib, ChainConfig, HashRegistry } from '@maximus-chain/multichain-lib';

Per-chain types

create() is overloaded so that built-in chains return their chain-specific ChainLib:

import { create } from '@maximus-chain/multichain-lib';
import type { MaximusChainLib } from '@maximus-chain/multichain-lib/chains/maximus';
import type { OsmiumChainLib } from '@maximus-chain/multichain-lib/chains/osmium';

const m: MaximusChainLib = create('maximus');
const o: OsmiumChainLib = create('osmium');

const lib = create('anyOtherName'); // typed as the generic ChainLib

MaximusChainLib and OsmiumChainLib are aliases for ChainLib<MaximusConfig> / ChainLib<OsmiumConfig>, where the chain config type carries a literal name so that lib.chainName is narrowed to 'maximus' / 'osmium'.

Reusable code across chains

The ChainLib<C extends ChainConfig> interface is generic. Code that wants to be chain-agnostic takes <C extends ChainLib> (or ChainLib):

import { create } from '@maximus-chain/multichain-lib';
import type { ChainLib } from '@maximus-chain/multichain-lib';

// Same function works for any chain.
function deriveAddress<C extends ChainLib>(lib: C): string {
  return new lib.PrivateKey('livenet').toAddress().toString();
}

const a = deriveAddress(create('maximus'));
const b = deriveAddress(create('osmium'));

Each call to create() returns a fresh ChainLib with its own Networks, hash registry, and class closures, so passing the result into a generic function never mixes instances across chains.

Components

Every chain-lib returned by create(name) exposes the same shape. The examples below assume const lib = create('maximus'); (replace with any chain).

Address

const pk = new lib.PrivateKey('livenet');
const address = pk.toAddress();
address.toString(); // chain-specific base58 string
lib.Address.isValid(address.toString(), 'livenet'); // true

Unit

const sats = lib.Unit.fromBTC(1.3).toSatoshis();
const btc = lib.Unit.fromSatoshis(150000).toBTC();

Transaction

const privateKey = new lib.PrivateKey('testnet');
const utxo = {
  txId: '115e8f72f39fad874cfab0deed11a80f24f967a84079fb56ddf53ea02e308986',
  outputIndex: 0,
  address: privateKey.toAddress().toString(),
  script: lib.Script.buildPublicKeyHashOut(privateKey.toAddress()).toHex(),
  satoshis: 50000,
};

const transaction = new lib.Transaction()
  .from(utxo)
  .to('tb1q...', 15000)
  .feePerKb(1000)
  .change(privateKey.toAddress())
  .sign(privateKey);

console.log(transaction.serialize());

PrivateKey / PublicKey

const pk = new lib.PrivateKey('livenet');
const pub = pk.toPublicKey();
const wif = pk.toWIF();
const reimported = lib.PrivateKey.fromWIF(wif);

HDPublicKey / HDPrivateKey

const mnemonic = new lib.Mnemonic(
  'praise sewer someone ladder aunt simple grit similar garlic quality know own'
);
const hd = lib.HDPrivateKey.fromSeed(mnemonic.toSeed(), lib.Networks.testnet);
const derived = hd.deriveChild("m/44'/1'/0'/0/0");
console.log(derived.privateKey.toAddress().toString());

// From an xpub
const hdPub = new lib.HDPublicKey('tpubD...');
const child = hdPub.deriveChild('m/1/100', false);
console.log(child.publicKey.toAddress().toString());

Script

const pk1 = new lib.PublicKey('02...');
const pk2 = new lib.PublicKey('02...');
const pk3 = new lib.PublicKey('02...');
const redeem = lib.Script.buildMultisigOut([pk1, pk2, pk3], 2);
const scriptHashOut = redeem.toScriptHashOut();
const multisigAddress = lib.Address.payingTo(scriptHashOut, lib.Networks.livenet);

Message

const message = new lib.Message('Welcome to Multichain');
const signature = message.sign(privateKey);
console.log(message.verify(privateKey.toAddress(), signature)); // true

Mnemonic

const m = new lib.Mnemonic(
  'praise sewer someone ladder aunt simple grit similar garlic quality know own'
);
console.log(m.toSeed().toString('hex'));
const hd = m.toHDPrivateKey(null, lib.Networks.livenet);

Networks

Each chain-lib has its own Networks instance with livenet and testnet. By default the chain-lib starts on livenet.

lib.Networks.setActive('testnet');
console.log(lib.Networks.defaultNetwork.name); // 'testnet'
lib.Networks.enableRegtest(); // opt-in: switch port/magic to regtest values

ProRegTxPayload

const payload = new lib.ProRegTxPayload();
payload.version = 1;
payload.type = 1;
payload.mode = 0;
payload.collateralHash = '0'.repeat(64);
payload.collateralIndex = 0;
payload.service = '1.2.3.4:9999';
payload.keyIDOwner = '0'.repeat(40);
payload.pubKeyOperator = '0'.repeat(96);
payload.keyIDVoting = '0'.repeat(40);
payload.operatorReward = 0;
payload.scriptPayout = lib.Script.buildPublicKeyHashOut(
  new lib.Address(payoutAddress, lib.Networks.livenet)
).toHex();
payload.inputsHash = '0'.repeat(64);

const tx = new lib.Transaction()
  .from(utxos)
  .to(collateralAddress, 1000000000)
  .feePerKb(1000)
  .change(changeAddress)
  .setExtraPayload(payload);

tx.version = 3;
tx.type = 1;

Per-chain ProRegTxPayload defaults

The default version and the strictness of type validation come from the chain's ChainConfig:

multichain.create('maximus').ProRegTxPayload; // version defaults to 2
multichain.create('fewbit').ProRegTxPayload;  // version defaults to 1

Built-in chains that diverge from the Dash version = 2 declare payloadVersions.proRegTx in their chain config. Chains whose Core rejects any type !== 0 (MASTERNODE_TYPE_BASIC) can opt in to the strict check via enforceMasternodeTypeBasic: true (Fewbit enables this — CheckProRegTx in fewbit-network/Core-Wallet rejects ptx.nType != 0). Consumers can still override version and type per payload.

UnspentOutput

const utxo = new lib.UnspentOutput({
  txId: '...',
  outputIndex: 0,
  address: '...',
  script: '...',
  satoshis: 50000,
});

Encoding helpers

lib.encoding exposes Base58, Base58Check, BufferReader, BufferWriter, and Varint. lib.crypto exposes BN, ECDSA, Hash (the chain's isolated hash registry), Point, Signature, Signer, Random, BLS.

lib.encoding.Base58.encode(Buffer.from('hi'));
lib.crypto.Hash.list(); // chain-specific algorithm names

Adding a new chain

See docs/INTEGRATE-CHAIN.md for:

  • The full configuration shape (chain-level + per-network fields).
  • Where to find each value in a chain's source code (src/chainparams.cpp for most Bitcoin-derived chains).
  • A worked Litecoin example.
  • A verification checklist.

Documentation

Tests

git clone https://github.com/Maximus-Chain/multichain-lib
cd multichain-lib
npm install
npm test

This runs the full test pipeline: types (tsd), Node unit tests (vitest), and browser end-to-end tests (Playwright).

You can also run each suite independently:

npm run test:types     # tsd, type assertions
npm run test:node      # vitest, Node-side unit tests
npm run test:browser   # playwright, browser bundle tests
npm run coverage       # vitest with v8 coverage

License

Code released under the MIT license.

Copyright 2026 MaximusChain.