Skip to main content

WASM bindings

The WASM bindings expose the Rust DKLS23 threshold-signature engine to JavaScript and TypeScript. The Rust crate is compiled to WebAssembly with wasm-bindgen, which generates a JS module and a .d.ts declaration file next to the .wasm binary. The result is published as the npm package @silencelaboratories/dkls-wasm.

There is no re-implementation of the protocol in JavaScript: the cryptography that runs is the same audited Rust code used by the native SDKs. JavaScript only creates the objects, feeds protocol messages in, and takes results out.

Features provided by bindings

  • Setup messagesKeygenSetupBuilder, SignSetupBuilder, QcSetupBuilder and FinishSetupBuilder build the signed setup message that bootstraps every protocol run, and KeygenSetup / SignSetup decode a received one so a party can validate it before joining. See Naming-Bootstrapping for what a setup message is.
  • Protocol sessionsKeygenSession, SignSession, QcSession and KeyExportSession wrap the Rust protocol state machines. You call output_message() / input_message() and route the bytes yourself, over whatever transport you already have.
  • Relay-driven entry pointsinit_dkg / join_dkg, init_dsg / join_dsg, init_pre / init_finish and init_qc connect to a message relay over a WebSocket and run a whole protocol to completion in a single await.
  • KeysharesKeyshare serializes to and from bytes (toBytes() / fromBytes()), exposes publicKey() and keyId(), and derives soft BIP32 child public keys with deriveChildPubkey().

Between them, these cover distributed key generation, key refresh, signing, pre-signing, quorum change (adding, removing or recovering parties) and key export. The threshold and the number of parties are yours to choose — the bindings are not restricted to Trio's 2-of-3.

Two levels of API

The same protocols are reachable at two levels, and the choice is only about who owns the transport:

SessionsRelay entry points
TypesKeygenSession, SignSession, …init_dkg, join_dkg, init_dsg, …
Transportyou manage routing of the MPC messagesthere is a message relay service to which the MPC nodes connects to
Use it whenmessages must travel over an existing channel, or you need to inspect every rounda relay is available and you want the protocol to just run

Where they can be used

Anywhere JavaScript runs with WebAssembly and the Web Crypto API available:

  • Browsers — web wallets, dApps, browser extensions, and any page where a keyshare must stay on the user's device. This is the primary target: the module is built for the web target, so await init() fetches and instantiates the .wasm over the network with no Node-specific loading. It also works inside a Web Worker, which keeps the protocol rounds off the UI thread.
  • Server-side runtimes — Node.js, Deno and Bun, for the parties that live in your backend. A single deployment can mix the two: one party in the browser, the others on servers, all speaking the same protocol.
  • Desktop and hybrid apps — anything running a browser engine, such as Electron or Tauri.

Two requirements are worth knowing before you start:

  • A secure context. The bindings draw randomness from crypto.getRandomValues, so pages must be served over HTTPS or from localhost.
  • await init() before anything else. That initializes the WebAssembly module; every other function throws until it has resolved.