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

@witnium-tech/witniumchain

v0.10.0

Published

TypeScript SDK for WitniumChain — identity, billing, OAuth, witness writes (v5), key management, and chain-api read surfaces (contracts, witnesses, wallets, transactions, dashboards). Single canonical SDK; supersedes @witnium-tech/accounts-sdk and @witniu

Downloads

1,138

Readme

@witnium-tech/witniumchain

TypeScript SDK for WitniumChain — the canonical single client for both the accounts service (identity, billing, OAuth, delegated keys, witness writes) and the chain-api read surfaces (contract info, witness lookup, wallet balance, dashboards). The two-service backend is hidden behind one WitniumchainClient class; you give it one OAuth access token and it knows where each call belongs.

Status

v0.5 — adds OAuth 2.1 + PKCE login helpers on top of the v0.4 surface:

  • All 41 accounts routes (five auth modes: session / OAuth / org / admin / signed)
  • 9 chain-api read methods, routed to chainBaseUrl, reusing the same OAuth accessToken (accounts mints tokens with aud=https://api.witniumchain.com, so they're valid against both services unchanged)
  • Three layered clients on top: WitniumchainClient (end-user), WitniumchainOrgClient (org admin), WitniumchainAdminClient (sysadmin)
  • beginOAuthLogin / completeOAuthLogin / refreshAccessToken / signOut — browser-side Authorization-Code + PKCE login flow. Discovery-driven endpoint resolution (/.well-known/openid-configuration), PKCE verifier in sessionStorage, access token held in memory only, transparent 401-retry with single-flight refresh-token rotation. Refresh tokens are delivered as an HttpOnly wac_refresh cookie scoped to Path=/token — JavaScript never touches them. Non-browser callers (Node SSR, native apps without a cookie jar) fall back to in-band refresh-token delivery; the SDK handles both.
  • client.mfa.totp.enroll/confirm/disable + client.mfa.recoveryCodes.regenerate — TOTP MFA self-management. enroll returns the secret + otpauth URL (render as a QR code in your dashboard with any QR lib); confirm validates the first code and returns 10 single-use recovery codes (shown ONCE).

What's NOT exposed (by design): chain-api v5 writes — those are proxied by accounts' v5 surface which adds credit reservation + idempotency + scope checks. Calling chain-api writes directly would burn credits without billing them. See docs/PLAN-PHASE-SDK-UNIFIED.md for the routing rules.

Every type comes from the published OpenAPI specs of both services via openapi-typescript. npm run openapi:check regenerates and fails on diff; it runs ahead of every npm publish.

Install

npm install @witnium-tech/witniumchain

Auth model

The SDK accepts five distinct credentials. Configure whichever you need on the client; methods that require a credential you didn't supply throw at call time.

| Credential | Header / Cookie | Used by | |---|---|---| | sessionCookie | Cookie: wac_session=… | /v1/auth/logout, /v1/account/*, /v1/billing/*, /v1/keys/*, /v1/contracts/{pause,unpause}, /v1/oauth/sessions* | | accessToken | Authorization: Bearer <JWT> | /v1/users/me/delegated-keys/*, /v1/sign, all chain-api reads | | orgApiKey | Authorization: Bearer wcorg_live_… | /v1/orgs/me/* | | adminToken | Authorization: Bearer <ADMIN_TOKEN> | /v1/admin/* | | signedRequest | X-Witnium-Key/Timestamp/Signature | /v1/contracts/{addr}/witnesses/{propose,sign,finalize,revoke} |

Public routes need no credential (/v1/auth/{signup,verify,login,…}, /v1/contracts/provision, GET /v1/contracts/{addr}/witnesses/{id}, /health/*).

Two services, one client

Accounts and chain-api are separate services today (consolidation is a later phase). The SDK hides that:

const client = new WitniumchainClient({
  baseUrl: 'https://auth.witniumchain.com',      // accounts
  chainBaseUrl: 'https://api.witniumchain.com',  // chain-api (omit if you only need accounts)
  accessToken: oauthBearerJwt,
});

// Writes / billing / auth → accounts (baseUrl)
await client.proposeWitnessV5('0xabc', { ... });

// Reads of on-chain state → chain-api (chainBaseUrl)
const witness = await client.getWitnessV5('0xabc', witnessId);
const balance = await client.getWalletBalance('0xabc');

If you call a chain-api method without chainBaseUrl configured, the SDK throws a clear WitniumchainApiError at call time naming the missing config — no silent fallback to a wrong base URL.

Examples

End-user signup + login

import { WitniumchainClient } from '@witnium-tech/witniumchain';

const client = new WitniumchainClient({
  baseUrl: 'https://auth.witniumchain.com',
});

await client.signup({ email: '[email protected]', password: 'correct horse battery staple' });
// User clicks email link, lands on /verify?token=…
const { provisioningToken } = await client.verifyEmail('the-token-from-the-link');

// Then login (sets the wac_session cookie in a browser; in Node, capture
// from response headers and pass back via `sessionCookie`).
await client.login({ email: '[email protected]', password: '…' });

Org admin — create a user

const org = new WitniumchainClient({
  baseUrl: 'https://auth.witniumchain.com',
  orgApiKey: 'wcorg_live_…',
});

const { userId, provisioningToken } = await org.createOrgUser({
  email: '[email protected]',
});
// Forward `provisioningToken` to Bob — he calls /v1/contracts/provision
// with locally-generated owner + signing keypairs.

Sysadmin — create an organisation

const sys = new WitniumchainClient({
  baseUrl: 'https://auth.witniumchain.com',
  adminToken: process.env.ACCOUNTS_ADMIN_TOKEN!,
});

const { organization, apiKey } = await sys.createOrganization({
  name: 'Acme Inc.',
  email: '[email protected]',
  accountType: 'metered',
  signupGrantAmount: 100,
});
// `apiKey` is shown ONCE — store it now.

Sign in with Witnium (Authorization Code + PKCE)

For a browser SPA (e.g. a Lovable app) that wants to authenticate end-users against a Witnium org. No backend required.

const client = new WitniumchainClient({
  baseUrl: 'https://auth.witniumchain.com',
  oauthClientId: 'your-registered-client-id',
});

// 1. Kick off login. The SDK generates a PKCE pair, stashes the verifier in
//    sessionStorage, and returns the URL to send the user to.
const { authorizationUrl } = await client.beginOAuthLogin({
  redirectUri: 'https://your-app.example/callback',
});
window.location.assign(authorizationUrl);

// 2. On the callback page, complete the exchange. Returns the access token
//    (the SDK ALSO holds it in memory; subsequent BearerJWT calls Just Work).
const { accessToken, expiresAt } = await client.completeOAuthLogin(
  window.location.href,
);
window.history.replaceState({}, '', window.location.pathname); // strip ?code=…

// 3. Use the SDK normally. When the access token expires, the SDK refreshes
//    transparently on the next call. You only need to redirect to login if
//    refresh itself fails (refresh token revoked or expired).
const { keys } = await client.listDelegatedKeys();

// 4. Sign-out clears in-memory tokens.
client.signOut();

OAuth API — delegated-key + sign

const api = new WitniumchainClient({
  baseUrl: 'https://auth.witniumchain.com',
  accessToken: bearerJwt,
});

const prepared = await api.prepareDelegatedKey({ contractAddress: '0x…' });
// Sign prepared.messageToSign with your owner key locally:
const ownerSignature = await myOwnerSigner.sign(prepared.messageToSign);

const submitted = await api.submitDelegatedKey(prepared.id, { ownerSignature });
// submitted.confirmed === true once the addSigningKey tx mines (~10–15 s).

const { signature } = await api.sign(
  { delegatedKeyId: prepared.id, payload: 'deadbeef…' },
);

SDK signed-request (witness propose/sign/finalize)

const sdk = new WitniumchainClient({
  baseUrl: 'https://auth.witniumchain.com',
  signedRequest: {
    publicKeyHex: 'abcd…64-chars…',
    sign: async (canonicalMessage) => {
      // Sign with your Ed25519 key — e.g. via @noble/ed25519 or a KMS.
      // Return the 128-char hex signature.
      return await myEd25519Sign(canonicalMessage);
    },
  },
});

const intent = await sdk.proposeWitness('0x…', {
  dataId: '…64-hex…',
  requiredSigners: ['…signer-pubkey…'],
});

Errors

All non-2xx responses surface as WitniumchainApiError:

import { WitniumchainApiError } from '@witnium-tech/witniumchain';

try {
  await client.createOrgUser({ email: '[email protected]' });
} catch (err) {
  if (err instanceof WitniumchainApiError) {
    console.error(err.status, err.errorLabel, err.message);
    // err.body holds the raw parsed body for advanced inspection.
  }
}

License

MIT.