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

@varnir/chain-client

v0.6.0

Published

The Varnir SDK - VarnirClient (onboard an identity, get a wallet, read balances, send, raise invoices) plus the low-level signing/transport primitives it is built from.

Readme

@varnir/chain-client

The Varnir SDK: onboard an identity, get a wallet, read balances, send funds, and raise invoices against a Varnir ledger network, plus the low-level signing and transport primitives it's built from.

This is what docs.varnir.site's SDK reference documents, and the same client this monorepo's own wallet and scanner applications are built on — not a thin wrapper kept separate from the "real" implementation.

Custody model

Every transaction this SDK sends is signed with a private key that stays in the calling process. VarnirClient takes your privateKeyHex (or an already-onboarded identity's key) as a constructor argument and signs locally, using either @activeledger/sdk-node (real Node.js) or pure-JS @noble/curves (browsers, React Native) depending on which transport you import — see Four entry points below. The key is never sent to a Varnir-hosted server, and no method on this client transmits it anywhere; the ledger only ever receives an already-signed transaction. This is custody, not a hosted signing service: whoever holds the private key controls the funds, and this SDK is how that holder signs without handing the key to anyone else.

An already-onboarded caller supplies both halves — the private key and the identity it's paired with. The SDK does not re-derive the identity from the key for you (it could — computeIdentity does exactly that), because treating a locally computed id as authoritative is how a caller ends up holding an identity that exists nowhere on the ledger.

Install

npm install @varnir/chain-client

Quick start

import {VarnirClient} from '@varnir/chain-client';
import {generateRecoveryPhrase, derivePrivateKeyFromPhrase} from '@varnir/chain-client/keys';

const {privateKeyHex} = derivePrivateKeyFromPhrase(generateRecoveryPhrase());

const client = await VarnirClient.onboard({network: 'testnet', privateKeyHex});
const wallet = await client.getWallet('niles');
const invoice = await client.createInvoice({wallets: [wallet], name: 'Invoice', amount: '10'});

'testnet' is the entire network configuration — node URLs, gateway URLs, deployed contract stream ids, each chain's ledger-side network spelling, and native decimals are all resolved internally. A caller never needs to know a hostname or a hex contract id.

The full method reference — onboard / new VarnirClient({privateKeyHex, identity}), identityExists, getIdentityStream, listWallets, getWallet, createWallet, getBalances, send, getTransfer, waitForTransfer, createInvoice, and the statics generateKey / computeIdentity — lives at docs.varnir.site.

Four entry points, one package

// The SDK, plus every low-level primitive it is built from.
import {VarnirClient, signPayloadBase64, sendToAnyNode, gatewayGet} from '@varnir/chain-client';

// Recovery phrases and BIP32/BIP44 derivation, re-exported from
// @varnir/signing. A subpath because it pulls in bip39 and its wordlist,
// which callers of the main entry point have no use for.
import {generateRecoveryPhrase, derivePrivateKeyFromPhrase} from '@varnir/chain-client/keys';

// Direct-to-node, real Node.js only — @activeledger/sdk-node, signs via
// node:crypto.
import {NodeTransport, importEllipticCurveKey} from '@varnir/chain-client/node';

// Direct-to-node, browsers and React Native — @activeledger/sdk-web,
// signs via @noble/curves (pure JS, no native/WebCrypto dependency).
import {WebTransport, importEllipticCurveKey} from '@varnir/chain-client/web';

Pick the transport by where your code runs, not by habit:

  • @varnir/chain-client (default import) — VarnirClient, the network/chain registry, a typed gateway HTTP client, and the manual-sign helpers. No dependency on either ledger SDK, so it's safe to import from anywhere, including a React Native bundler.
  • @varnir/chain-client/node — NodeTransport: generic direct-to-node ledger operations (key generation, onboarding, signing, sending) via @activeledger/sdk-node. Real Node.js only.
  • @varnir/chain-client/web — WebTransport: the same method shape as NodeTransport, via @activeledger/sdk-web. Safe in browsers and React Native — no Node core-module dependency, so it needs no polyfills.

Each transport lives behind its own subpath (via package.json's exports map) so a bundler never needs to tree-shake the other ledger SDK out — it's simply never imported unless you ask for it.

Importing an externally-derived key

If you already derive a secp256k1 key pair yourself (your own BIP32/BIP44 path, a hardware wallet, anything that isn't this package's own key generation), importEllipticCurveKey (from /node or /web) wraps an already-derived compressed secp256k1 key pair into the shape NodeTransport/WebTransport's signTransaction/onboardKey expect, without going through this package's own key generation:

import {importEllipticCurveKey, WebTransport} from '@varnir/chain-client/web';

const key = importEllipticCurveKey({privateKeyHex, publicKeyHex}); // your own key pair
const transport = new WebTransport();
await transport.onboardKey(key);

publicKeyHex must be the compressed form (33 bytes) — the uncompressed form is not supported.

Examples

examples/wallet-and-invoice-flow.ts is a complete external-automation walkthrough — onboard an identity, get a testnet wallet, and raise an invoice against it, entirely client-signed. Run it with npx tsx examples/wallet-and-invoice-flow.ts from this package's directory.

Known limitations

  • listTransactions's return shape has only been confirmed against a freshly-reset network with no indexed activity yet (it returned {"unknown": 1} instead of an array in that case). Treat the result as TransactionSummary[] | {unknown: number} and narrow with Array.isArray(...) before treating it as a list.
  • The React Native / native-mobile path (WebTransport on Hermes) has been verified on the web target; direct on-device iOS/Android signing behavior has not been separately confirmed.

License

MIT