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

@ensc/sdk

v0.1.2

Published

Official ENSC API client SDK — typed, server-side, with automatic Ed25519 request signing

Downloads

240

Readme

@ensc/sdk

Official client SDK for the ENSC API — typed end to end, server-side, with automatic Ed25519 request signing.

Install

npm install @ensc/sdk
# the web3 helper (optional) also needs viem:
npm install @ensc/sdk viem

Requires Node 18+ (or any modern runtime with fetch — Workers, Deno, Bun).

Server-side only

The SDK is built for backend use. Your API key and signing key are secrets — they must never reach a browser bundle. EnscClient refuses to construct in a browser context. Do not ship it to end users.

Authentication: two secrets and one identifier

The SDK needs three things, down from the old SDK's three secrets:

| Value | Secret? | Purpose | | --- | --- | --- | | apiKey | yes | Authorization: Bearer. Identifies the merchant, carries env + scopes. | | signingPrivateKey | yes | Ed25519 private key (base64url). Signs mutating requests. Reads don't need it. | | signingKeyId | no | The id of the registered public key. Sent as X-ENSC-Key-Id. |

Plus merchantId (mrc_…) — not a secret, but required because it's part of the canonical string every signed request is built from.

There is no payload encryption. Mutating requests are authenticated by an Ed25519 signature over a canonical representation of the request; nothing in the body is encrypted client-side.

Quick start

import { EnscClient } from '@ensc/sdk';

const ensc = new EnscClient({
  apiKey: process.env.ENSC_API_KEY!,
  merchantId: process.env.ENSC_MERCHANT_ID!,
  signingPrivateKey: process.env.ENSC_SIGNING_PRIVATE_KEY, // for writes
  signingKeyId: process.env.ENSC_SIGNING_KEY_ID,           // for writes
});

// Read — needs only apiKey + merchantId
const balance = await ensc.balance.get({
  account: '0x…',
  chain: 'lisk',
  asset: 'ENSC',
});

// Write — needs the signing key; signed automatically
const { unsignedTransaction, paymentIntentId } = await ensc.mint.create({
  recipient: '0x…',
  amount: '100',
  chain: 'lisk',
});

First-time setup: register a signing key

Generate the keypair locally — the private half never leaves your process:

import { EnscClient } from '@ensc/sdk';

const ensc = new EnscClient({ apiKey, merchantId }); // reads work without a signing key

const { registration, keypair } = await ensc.signingKeys.generate({
  env: 'live',
  name: 'production-server',
});

// Store keypair.privateKey as ENSC_SIGNING_PRIVATE_KEY
// Store registration.id  as ENSC_SIGNING_KEY_ID
// The API only ever saw keypair.publicKey.

The web3 flow: unsigned transactions

ENSC never holds a wallet key and never broadcasts. mint, redeem, transfer, and approve return an unsigned transaction for you to sign with your own wallet key and submit to the chain. The ENSC indexer reconciles the on-chain event afterward.

const { unsignedTransaction } = await ensc.mint.create({
  recipient: '0x…', amount: '100', chain: 'lisk',
});

// Option A — sign + broadcast with the optional helper (needs `viem`)
import { signAndBroadcast } from '@ensc/sdk/web3';
const txHash = await signAndBroadcast(unsignedTransaction, walletPrivateKey, {
  rpcUrl: 'https://rpc…',
});

// Option B — sign here, broadcast through your own infra
import { signTransaction } from '@ensc/sdk/web3';
const signed = await signTransaction(unsignedTransaction, walletPrivateKey);

walletPrivateKey is your on-chain EOA key — a separate secret from the ENSC API keys. It never touches the ENSC API and is never stored by the SDK; pass it per call. Do not put it in EnscClient config.

redeem returns an unsigned transaction plus settlement details; after broadcasting it, call ensc.withdraw.create({ pvRef, txHash }) to fire the fiat payout.

Verifying webhooks

ENSC signs every webhook delivery with Ed25519. Verify before trusting the payload — pass the exact raw body you received:

import { EnscClient } from '@ensc/sdk';

// In your webhook route:
const event = EnscClient.constructEvent({
  body: rawRequestBody,       // string or bytes, exactly as received
  headers: request.headers,   // Headers instance or a plain record
  publicKey: ENSC_WEBHOOK_PUBLIC_KEY,
});
// reaching here means the signature is valid

constructEvent throws EnscError('ENSC_INVALID_SIGNATURE') on failure. For non-throwing checks use EnscClient.verifyWebhookSignature(...), which returns { valid, reason? }.

Error handling

Every failure — including network errors — throws a single EnscError type, with the same code taxonomy the API uses.

import { EnscError, isEnscError, isEnscErrorCode } from '@ensc/sdk';

try {
  await ensc.mint.create({ … });
} catch (err) {
  if (isEnscErrorCode(err, 'ENSC_MINT_LIMIT_EXCEEDED')) {
    // handle the specific case
  } else if (isEnscError(err)) {
    console.error(err.code, err.status, err.message, err.details);
  }
}

Transient failures (network errors, 5xx) are retried automatically (maxRetries, default 2); 4xx is never retried. Mutating requests carry a stable idempotency key across retries, so a transparently retried POST cannot double-execute.

Chains

chain is a string at the API boundary. The SDK exports a ChainSlug union and KNOWN_CHAINS for autocomplete, but any string is accepted — an unknown or disabled chain comes back as ENSC_INVALID_CHAIN.

API surface

| Area | Resource | Methods | | --- | --- | --- | | Web3 | mint redeem transfer approve | create | | Web3 | withdraw virtualAccounts | create | | Reads | balance mintLimit | get | | Reads | verifyPayout | verify, verifyWithdraw | | Reads | events | list, get | | Management | apiKeys | create, list, rotate, revoke | | Management | signingKeys | register, generate, list, revoke | | Management | origins | create, list, remove | | Management | webhookEndpoints | create, list, get, update, remove, sendTest |

Verifying this package

@ensc/sdk is published only by GitHub Actions, from sdk-v* release tags, using npm trusted publishing (OIDC) — there is no long-lived npm token. Every published version is registry-signed; run npm audit signatures after installing to verify it. A legitimate release has exactly two runtime dependencies — @noble/curves and @noble/hashes — an optional viem peer, and no install scripts; anything else is a red flag. (A provenance attestation is planned — it requires publishing from a public repo.) For full consumer guidance — pinning, release cooldowns, --ignore-scripts — and to report a suspected compromise, contact [email protected].

License

MIT