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

@ligate-labs/sdk

v0.2.0

Published

TypeScript SDK for Ligate Chain. Build-sign-submit transactions, query state, manage keys.

Readme

ligate-js

CI License: Apache-2.0 OR MIT Chain Docs Devnet

TypeScript SDK for Ligate Chain. Build, sign, submit transactions; query state; manage keys. Browser and Node compatible. Zero-dep on Buffer.

Quick start

Install

Not yet on npm. The @ligate-labs/sdk package has not been published to the registry yet (the rc dist-tag does not exist). Until the first npm publish, consume the SDK from git or as a local file:// dep:

# Pin to a git tag in your package.json:
pnpm add github:ligate-io/ligate-js#v0.1.1-devnet
# or pin to a commit SHA for byte-level reproducibility:
pnpm add github:ligate-io/ligate-js#<sha>

# Or, for local development against a checkout:
pnpm add file:../ligate-js

npm install and yarn add accept the same github: and file: syntaxes. This section will be replaced with pnpm add @ligate-labs/sdk (or @rc) once the first npm publish lands; tracked alongside the post-soak 0.1.0 (no suffix) cut.

Use

import { generateKeypair, LigateClient, submitTransfer } from '@ligate-labs/sdk'

// Generate or load a key.
const sender = generateKeypair()
console.log('address:', sender.address)

// Connect to a Ligate node. The `/v1` URL prefix is added automatically.
const rpcUrl = 'http://localhost:12346'
const client = new LigateClient({ rpcUrl })

// Pull chain identity + the sender's next nonce.
const info = await client.getRollupInfo()
const nonce = await client.getNonce(sender.publicKey)

// Build, sign, submit, wait for inclusion — one call.
const result = await submitTransfer({
  rpcUrl,
  privateKey: sender.privateKeyHex,
  publicKey: sender.publicKey,
  to: 'lig1xyz...',
  amountNano: 1_000_000_000n, // 1 LGT
  // tokenId accepts hex, Uint8Array, or `token_1...` bech32m form;
  // both signing and getBalance normalise internally.
  tokenId: 'token_1nyl0e0yweragfsatygt24zmd8jrr2vqtvdfptzjhxkguz2xxx3vs0y07u7',
  nonce,
  chainId: 4242n, // from chain `constants.toml` (`CHAIN_ID`)
  chainHash: info.chain_hash,
})

console.log('tx hash:', result.txHash)
console.log('included on chain:', result.included)

The /v1 prefix on the RPC URL is auto-appended idempotently, so http://host:port, http://host:port/, and http://host:port/v1 all work the same way. Mirrors the cli (GlobalArgs::rpc_with_v1) and ligate-api (Signer::new_with_chain_seed) so all three SDKs normalize the same way.

Lower-level API

When the bundled submitTransfer doesn't fit (custom polling, batch builds, signing offline) compose the primitives directly:

import {
  signTransfer,
  submitRawTx,
  waitForInclusion,
  LigateClient,
  keypairFromPrivateKey,
} from '@ligate-labs/sdk'

const client = new LigateClient({ rpcUrl: 'http://localhost:12346' })
const sender = keypairFromPrivateKey(process.env.LIGATE_KEY!)
const nonce = await client.getNonce(sender.publicKey)

// Step 1: build + sign offline. Returns borsh-encoded `Transaction::V0`
// bytes ready to send to `POST /v1/sequencer/txs`. Pure CPU, no network.
const bytes = signTransfer({
  privateKey: sender.privateKeyHex,
  publicKey: sender.publicKey,
  to: 'lig1xyz...',
  amountNano: 1_000_000_000n,
  tokenId: '<64-char hex>',
  nonce,
  chainId: 4242n,
  chainHash: '<64-char hex>',
})

// Step 2: submit. `waitForInclusion: false` returns the moment the
// sequencer accepts the bytes, no polling.
const { txHash } = await submitRawTx(client, bytes, { waitForInclusion: false })

// Step 3: poll for inclusion separately, with whatever cadence and
// timeout the consumer wants.
await waitForInclusion(client, txHash, { pollIntervalMs: 1000, timeoutMs: 60_000 })

API reference

Per-symbol reference (every exported function, type, and constant) is generated from the inline JSDoc via TypeDoc.

pnpm run docs   # writes static HTML to docs/

CI also builds it on every push and uploads the result as a typedoc-html workflow artifact (retention 14 days). Public hosting on docs.ligate.io/sdk is pending the subdomain routing decision; until that lands, grab the artifact from a recent CI run.

Wire-format gotchas (so you don't hit them)

The SDK takes care of these, but they're worth knowing if you're debugging or extending it:

  • Don't pre-wrap. signTransfer returns borsh(Transaction::V0(Version0)). The chain's POST /v1/sequencer/txs handler wraps in AuthenticatorInput::Standard(...) server-side. Pre-wrapping double-wraps and the chain rejects with Cannot decompress Edwards point. (See ligate-chain#245.)
  • Address derivation is pubkey[..28]. First 28 bytes of the 32-byte Ed25519 pubkey, bech32m-encoded with the lig HRP. NOT SHA-256(pubkey)[..28] — that's how genesis-stub addresses are derived from string labels (and using it for keypair-derived addresses produces CannotReserveGas("Insufficient balance") on submit).
  • Confirmation is HTTP polling, not WebSocket. waitForInclusion polls GET /v1/ledger/txs/{hash} every 500ms. The Sovereign SDK's wait_for_tx_processing uses a WebSocket subscription that hits a URL-parsing bug (invalid port value) on non-standard ports. (See ligate-cli#8.)
  • Signature is over borsh(UnsignedTransaction) ++ chain_hash. The 32-byte chain hash binds signatures to the runtime version; it comes from GET /v1/rollup/info. Without the hash, a signature for ligate-localnet-1 would also work on ligate-devnet-1, which the chain explicitly prevents.

Compatibility

  • Node: 20+ (uses global fetch, crypto.getRandomValues, native BigInt).
  • Browsers: any with fetch and crypto.getRandomValues (all modern). The SDK avoids Buffer so it bundles cleanly without polyfills.
  • Edge runtimes: Cloudflare Workers, Vercel Edge, Deno — all fine, same constraints as browsers.

Development

pnpm install                # install dependencies
pnpm typecheck              # tsc --noEmit
pnpm test                   # vitest run (unit suite only, ~400ms)
pnpm test:watch             # vitest watch mode
pnpm test:e2e               # vitest e2e (REQUIRES a running localnet — see below)
pnpm fmt                    # prettier --write
pnpm fmt:check              # prettier --check (CI gate)
pnpm build                  # compile to dist/ for publish
pnpm size                   # size-limit bundle budget check
pnpm run docs               # generate TypeDoc HTML in docs/

Pre-commit hooks

.pre-commit-config.yaml runs prettier --check on every commit so formatting drift is caught locally instead of in CI. One-time setup per clone:

brew install pre-commit         # or: pip install pre-commit
pre-commit install              # writes .git/hooks/pre-commit

Skip the hook for an emergency commit with git commit --no-verify; the same check still re-runs in CI.

Examples

Three runnable scripts in examples/ demonstrate the public surface:

# Generate a fresh keypair and (optionally) write to a JSON file.
pnpm tsx examples/generate-keypair.ts
pnpm tsx examples/generate-keypair.ts --out my-key.json

# Build + sign + submit a 1 LGT transfer to a recipient. Uses the
# localnet dev key by default; pass --from to use a generated keypair.
# Requires a running localnet (see end-to-end section below).
pnpm tsx examples/transfer.ts \
    --to lig1u8z2rxh6ymjwkqsasme64f5kfphtfm2kf4kkn0clusfpr34amezsp5j7yp \
    --amount 1

# Poll an address's balance every N seconds (Ctrl-C to stop).
pnpm tsx examples/watch-balance.ts \
    lig1u8z2rxh6ymjwkqsasme64f5kfphtfm2kf4kkn0clusfpr34amezsp5j7yp \
    --interval 5

Each example reads LIGATE_RPC, LIGATE_CHAIN_ID, and LIGATE_TOKEN_ID env vars; defaults match the localnet bring-up in ligate-chain/devnet/. Run any example with --help for the full flag list.

Browser test matrix

CI runs Playwright against Chromium, Firefox, and WebKit to prove the SDK actually works in a real browser engine (not just that the bundle emits — that's bundle:browser-check). Tests live in tests/browser/; the smoke spec navigates to a static HTML page that loads the bundled SDK via <script type="module"> and exercises key generation, address derivation, and transaction signing.

# Local run (downloads browsers on first run):
pnpm exec playwright install
pnpm test:browser

The Playwright globalSetup (tests/browser/global-setup.ts) bundles the SDK with esbuild before any spec runs, so the bundle is always fresh.

End-to-end test against a running localnet

e2e/ is the canary for wire-format drift between the TS SDK and the Rust chain. Stubbed-fetch unit tests pin URL shapes + discriminants, but only running against a real chain catches a borsh field-order mismatch.

# Boot a localnet from the chain repo (separate terminal):
cd ~/Desktop/ligate-chain
cargo run --bin ligate-node

# Then in this repo:
pnpm test:e2e

The suite reads chain config from env (LIGATE_E2E_RPC, LIGATE_E2E_CHAIN_ID, LIGATE_E2E_TOKEN_ID); defaults match the chain's localnet config out-of-the-box. If the RPC isn't reachable, every e2e test SKIPS with a clear "boot a localnet first" message rather than failing.

CI runs the unit suite (pnpm test) on every PR but does NOT run e2e — opt-in via pnpm test:e2e locally before tagging a release.

The chain-side test vector is the localnet dev key (devnet/local-dev-key.json, ligate-chain#247) — private key 0x01...01, address lig132yw8ht5p8cetl2jmvknewjawt9xwzdlrk2pyxlnwjyqz3m499u. Pinned in test/keys.test.ts. If chain regenerates the dev key, those tests need the new vectors.

Status

Devnet. ligate-devnet-1 is live.

Latest devnet-aligned release: v0.1.1-devnet, cut alongside ligate-chain v0.1.1-devnet. Not yet published to npm; install via github:ligate-io/ligate-js#v0.1.1-devnet (see Install) until the first npm publish lands.

Versioning

Going forward, releases drop the -devnet suffix per the convention adopted in ligate-chain#374. Plain semver tags (v0.1.x, v0.2.x, ...) for the package, with network identity carried in chain_id rather than the package version. Past -devnet tags stay as archaeology. The next SDK cut (v0.1.2 or higher) is the first to land on the new scheme alongside ligate-chain v0.1.3.

Anything tagged 0.1.x-devnet may still break wire format between releases as the chain settles. Pin exact versions if you depend on byte-level stability. Post-soak 0.1.0 (no suffix) is the first version where minor-version SemVer applies; patch bumps are guaranteed wire-compatible inside 0.1.x.

Related repos

  • ligate-chain — Sovereign SDK rollup, the chain itself
  • ligate-cli — Rust operator and builder cli (sister tool to this SDK)
  • faucet — public devnet drip service
  • explorer — block / tx browser

License

Dual-licensed under Apache 2.0 or MIT at your option.