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

@kaleidorg/swap-sdk

v0.3.0

Published

KaleidoSwap swap SDK — Boltz-protocol atomic swaps (submarine/reverse/chain) for the browser over WebAssembly

Readme

@kaleidorg/swap-sdk

TypeScript and WebAssembly bindings for KaleidoSwap: Boltz-protocol atomic swaps (submarine, reverse, and chain) between Bitcoin, Lightning, and Liquid.

Install

npm install @kaleidorg/swap-sdk

Usage

await init() takes no argument and behaves the same in both runtimes: browsers resolve the packaged WebAssembly binary relative to the module, and Node reads it from disk via the "node" export condition. Await it once before constructing any client.

import { BoltzClient, init } from "@kaleidorg/swap-sdk";

await init();
const boltz = BoltzClient.forNetwork("signet");
const pairs = await boltz.submarinePairs();

"signet" reaches the live KaleidoSwap maker, so the snippet above runs as written. "regtest" resolves to http://localhost:9001/v2 and needs this repository's local harness.

Bundlers must emit the packaged vendor/bindings_wasm_bg.wasm asset referenced by the generated module.

BoltzClient.forNetwork resolves the default KaleidoSwap maker, which today serves "signet" and "regtest" only. "mainnet" and "testnet" are rejected rather than silently falling back to a third-party maker — reach one of those by passing an explicit base URL to new BoltzClient(baseUrl, timeoutSecs?). Signet settles on Mutinynet, so pair it with Mutinynet chain access (https://esplora.signet.kaleidoswap.com), never a testnet3 endpoint: the two encode addresses identically, so a mismatch raises no error and simply creates swaps on one chain while funding or watching another.

Supplying the binary yourself

To serve the WebAssembly binary from your own CDN, or as a bundler asset URL, pass any WasmSource (a BufferSource, URL, Request, Response, or URL string):

await init(new URL("/assets/bindings_wasm_bg.wasm", location.origin));

wasmUrl points at the packaged binary if you need to copy or re-host it. Under Node you can also pass it straight to init — a file: source is read from disk, since Node's fetch rejects that scheme. For a pre-compiled WebAssembly.Module, use initWithModule — it is separate from init so that WasmSource stays type-safe (WebAssembly.Module is an empty interface in TypeScript's lib, so a union containing it accepts any value).

One case needs an explicit source: bundling the Node entry into a single file, as a CLI or a serverless artifact does, moves import.meta.url away from the packaged vendor/, so the default lookup has nothing to find. Copy bindings_wasm_bg.wasm next to your output and pass it — that failure surfaces at runtime rather than at build time, so reach for this before you ship a bundle.

SDK operations also require the web APIs used by the selected client, including fetch and WebSocket. Node 22 and newer provide both.

Swap keys

Swap keys and preimages derive client-side from a wallet mnemonic via BIP85 index 26589 — no key material leaves the caller:

import { SwapMasterKey } from "@kaleidorg/swap-sdk";

const master = SwapMasterKey.fromWalletMnemonic(walletMnemonic, "regtest");
const { publicKey, secretKey } = master.deriveSwapKey(0n);

Typed surface

  • BoltzClient — Boltz swap API (create submarine/reverse/chain swaps, pairs, fees, quotes, restore).
  • BoltzWsApi / BoltzWsUpdates — WebSocket swap-status stream.
  • SwapScript — reconstruct a swap from its creation response, then build claim/refund transactions (constructClaim, constructRefund) or caller-funded Liquid PSETs (prepareLiquidClaim, prepareLiquidRefund). Chain swaps claim through constructCooperativeClaim instead — the cheaper MuSig2 keyspend, partial-signed with the swap's refund key rather than its claim key. constructClaim cannot carry the lockup script that path signs against, so a chain swap taking the script path must pass cooperative: false.
  • SwapMasterKey — BIP85 swap key and preimage derivation.
  • isKaleidoSwapError — narrow a rejection to its stable code.

Boltz request and response payloads are Rust-defined and cross the boundary as plain objects typed any; the rest of the surface is hand-typed. The packaged dist/index.d.ts carries the full signatures and their documentation.

Every rejection produced after an argument reaches the Rust binding is an Error carrying a code. Input the binding rejects — a mistyped string argument, an unparseable key or preimage, or a request object missing a required field — uses InvalidArgument and names the argument or field. Failures from the swap engine carry their own code; binding-internal failures use Internal.

Values rejected earlier by wasm-bindgen's generated ABI glue remain native JavaScript errors. In particular, passing a number where a declared bigint is required throws TypeError before Rust can attach a code.

Lossless integer values

Amounts cross the WASM boundary as bigint. Use the exported toJson helper when serializing SDK responses:

import { toJson } from "@kaleidorg/swap-sdk";

console.log(toJson({ amount: 1000n }));

This applies to arguments as well as responses, and the declared type is the rule to follow — it differs by where the value crosses the boundary.

A parameter declared bigint is passed on the wasm-bindgen ABI, which accepts a BigInt and nothing else, so it needs the n suffix:

master.deriveSwapKey(0n); // ok
master.deriveSwapKey(0); // TypeError: Cannot convert 0 to a BigInt

tsc rejects the plain-number form ahead of that throw. The same applies to any other bigint argument, such as the BoltzClient constructor's timeoutSecs.

Fields inside request objects are declared number even where the Rust type behind them is 64-bit, because those objects are deserialized rather than passed on the ABI. Pass what the field declares and both cases are correct.

Arkade Intents venue (@kaleidorg/swap-sdk/arkade)

An optional subpath serving the Arkade Intents RFQ routes (arkade:BTC ↔ lightning:BTC) against any solver card. Opt-in by design: it peer-depends on @arkade-os/sdk and @arkade-os/swap, which a Boltz-only consumer never installs.

import {
  ArkadeIntentsVenue,
  InMemoryArkadeSwapStore,
} from "@kaleidorg/swap-sdk/arkade";

const venue = new ArkadeIntentsVenue({
  wallet,
  arkServerUrl,
  transport,
  store,
});
const { address, fundAmountSats } = await venue.prepareLightningSend({
  invoice,
});
// The recovery record is persisted BEFORE this returns. Funding is the
// quote acceptance:
const txid = await wallet.send({ address, amount: fundAmountSats });
await venue.notifyFunded(record.id, txid);

Drive venue.reconcile() from your own scheduler (MV3 chrome.alarms, a node interval) — one evidence-driven pass that claims funded receives, refunds matured sends, and resolves records from chain evidence. The venue owns no timers and trusts no relay status message.

Development checks

Build fresh WASM bindings from the repository root before running the package checks:

make wasm-pack-build
cd typescript-sdk
npm ci
npm run typecheck
npm run lint
npm run format:check
npm test
npm run smoke:package
npm run smoke:browser-package

smoke:browser-package loads the packaged browser entry in headless Firefox, so it needs firefox on PATH — point BROWSER_BIN at the binary if it lives elsewhere (on macOS, /Applications/Firefox.app/Contents/MacOS/firefox). Both smoke scripts pack a throwaway tarball when given no argument, or check a supplied one: npm run smoke:package -- path/to/package.tgz.