A TypeScript/JavaScript SDK for interacting with the Zenon Network of Momentum (NoM).
- 🚀 Modern ESM-first architecture – Optimized for tree-shaking and modern JavaScript
- 🔌 Dual protocol support – HTTP and WebSocket connections
- 💼 Wallet management – Create, import, and manage wallets with BIP39 mnemonic support
- 🔐 Transaction signing – Sign and send transactions with automatic PoW generation
- ⌨️ CLI Included – CLI for wallet management and sending transactions
- 📡 Real-time subscriptions – Subscribe to momentums and account blocks via WebSocket
- 🌐 Universal – Works in Node.js and browsers (ESM & UMD)
- 📝 TypeScript native – Full type definitions included
npm install znn-typescript-sdkimport { Zenon } from 'znn-typescript-sdk';
const zenon = Zenon.getInstance();
await zenon.initialize('wss://node.zenonhub.io:35998');npm create vite@latest my-zenon-app -- --template vanilla
cd my-zenon-app
npm install znn-typescript-sdk
npm run devimport { Zenon } from 'znn-typescript-sdk';
const zenon = Zenon.getInstance();
await zenon.initialize('wss://node.zenonhub.io:35998');The SDK ships two browser bundles:
- ESM (
dist/browser/bundle.browser.mjs): Modern module build for Vite/Rollup/Webpack. Import fromznn-typescript-sdkor the.mjsbundle. - UMD (
dist/browser/bundle.browser.js): Legacy global build that exposeswindow.ZnnSDKfor script-tag usage.
Use ESM when possible. Use UMD only if you must load the SDK via a <script> tag without a bundler.
The Proof of Work (PoW) module requires two external files in browser environments: pow.js and pow.wasm. These files must be accessible at runtime.
Setup:
- The PoW files are located in
node_modules/znn-typescript-sdk/dist/browser - Set the base path before any operations that require PoW:
import { Zenon } from 'znn-typescript-sdk';
// Point to where pow.js and pow.wasm are located
Zenon.setPowBasePath('node_modules/znn-typescript-sdk/dist/browser');
// Now you can send transactions (which use PoW)
const zenon = Zenon.getInstance();
await zenon.initialize('wss://node.zenonhub.io:35998');
const tx = await zenon.send(blockTemplate, keyPair);For UMD:
window.ZnnSDK.Zenon.setPowBasePath('node_modules/znn-typescript-sdk/dist/browser');Alternative – Copy to Public Folder:
For production apps, copy the PoW files to your public/static folder:
cp node_modules/znn-typescript-sdk/dist/browser/pow.* public/Then set the path:
Zenon.setPowBasePath('/'); // or 'assets' for relative pathsNote: Node.js environments don't need this configuration – PoW files are loaded automatically from the installation directory.
- HTTP:
https://node.zenonhub.io:35997- For simple API calls - WebSocket:
wss://node.zenonhub.io:35998- For real-time subscriptions and transactions
The main entry point is the Zenon singleton.
import { Zenon } from 'znn-typescript-sdk';
const zenon = Zenon.getInstance();These methods configure SDK-level settings and should be called before initializing the Zenon instance.
Set the network ID for transaction signing. Default is 1.
Zenon.setNetworkID(3); // Set to testnetGet the current network ID.
const networkId = Zenon.getNetworkID();Set the chain ID for transaction signing. Default is 1.
Zenon.setChainID(100); // Set to custom chainGet the current chain ID.
const chainId = Zenon.getChainIdentifier();Set the base path for loading PoW files in browser environments. Only needed for browser usage. The path is automatically normalized to meet browser module specifier requirements (adding ./ prefix and / suffix as needed).
// Before initialization in browser
// These are all valid and will be normalized automatically:
Zenon.setPowBasePath('node_modules/znn-typescript-sdk/dist/browser');
Zenon.setPowBasePath('/assets');
Zenon.setPowBasePath('./public');Get the current PoW base path.
const path = Zenon.getPowBasePath();By default, PoW runs synchronously on the main thread. In the browser this blocks the event loop for the full duration of generation, which freezes the UI and starves the WebSocket heartbeat/reconnect timers — long PoW can cause the node to drop the connection before the transaction is published. Moving PoW to a Web Worker fixes both problems. There are two ways to do this:
Zenon.usePowWorker()— the SDK's built-in, managed worker (simplest).Zenon.setPowProvider()— supply your own provider (full control).
Register the SDK's built-in Web Worker as the PoW provider. PoW then runs off the main thread automatically — no worker file or app-side code required. Browser-only.
The worker locates pow.js / pow.wasm using the current PoW base path, so call setPowBasePath first if needed. The worker is created lazily on the first transaction that requires PoW.
import { Zenon } from 'znn-typescript-sdk';
Zenon.setPowBasePath('/'); // where pow.js / pow.wasm are served
Zenon.usePowWorker(); // PoW now runs in a Web Worker
// send() runs PoW off the main thread; the WebSocket stays connected
const tx = await zenon.send(blockTemplate, keyPair);CSP note: the built-in worker is spawned from a
BlobURL, so a strict Content-Security-Policy must allowworker-src blob:(and the dynamic import ofpow.js). If your CSP forbids this, supply your own provider withsetPowProviderinstead.
Call Zenon.stopPowWorker() to terminate the worker and clear the provider. clearPowProvider() also stops it.
Register a custom Proof of Work provider. When set, it is used instead of the built-in WASM module during send and prepareBlock. Use this when usePowWorker doesn't fit (e.g. strict CSP, a shared worker, a native module, or a remote PoW service).
The provider receives the PoW data as a 64-character hex string and the required difficulty, and resolves to the 8-byte nonce as a hex string:
import { Zenon, type PowProvider } from 'znn-typescript-sdk';
// Example: a provider backed by your own Web Worker
const worker = new Worker(new URL('./pow.worker.js', import.meta.url), { type: 'module' });
const provider: PowProvider = (hashHex, difficulty) =>
new Promise((resolve, reject) => {
const id = crypto.randomUUID();
const onMessage = (e: MessageEvent) => {
if (e.data.id !== id) return;
worker.removeEventListener('message', onMessage);
e.data.error ? reject(new Error(e.data.error)) : resolve(e.data.nonce);
};
worker.addEventListener('message', onMessage);
worker.postMessage({ id, hashHex, difficulty });
});
Zenon.setPowProvider(provider);
// send() now runs PoW in the worker; the WebSocket stays connected
const tx = await zenon.send(blockTemplate, keyPair);Get the currently registered PoW provider, or undefined if none is set (the built-in WASM module is used).
Remove a previously registered PoW provider, restoring the built-in WASM-based generator.
Connect to a Zenon node via HTTP or WebSocket.
// WebSocket (for subscriptions and transactions)
await zenon.initialize('wss://node.zenonhub.io:35998');
// HTTP (for simple requests)
await zenon.initialize('https://node.zenonhub.io:35997');Note: WebSocket connections automatically reconnect if dropped, and the default settings are suitable for most use cases. However, reconnect (like all timers) cannot run while the main thread is blocked. The built-in PoW generator is synchronous, so long PoW can starve the heartbeat/reconnect machinery and the node may close the connection before the transaction publishes. To avoid this, run PoW off the main thread with
Zenon.usePowWorker(or a customsetPowProvider).
Disconnect and clean up resources.
zenon.clearConnection();Sign and send a transaction. Automatically generates PoW if needed.
const tx = await zenon.send(blockTemplate, keyPair);
console.log('Hash:', tx.hash.toString());Prepare a block for publishing — autofill fields, run PoW (if required), and set the hash and signature — without publishing it. This is the publish-free portion of send, and lets you control the connection lifecycle around PoW. For example, you can verify or restart the WebSocket connection after PoW completes but before publishing:
const prepared = await zenon.prepareBlock(blockTemplate, keyPair);
// Ensure the connection is healthy after PoW, then publish yourself
await zenon.ledger.publishRawTransaction(prepared);Tip: Combine
prepareBlockwithZenon.setPowProvider(a Web Worker provider) to keep the connection alive during PoW as well as control publishing afterward.
- Examples – Complete working examples
- API Overview – All API methods and embedded contract calls
- Embedded Contracts – Detailed documentation for embedded contracts
- Utilities – Utilities and constants for common tasks
- CLI Tool – Command-line interface
- Wallet Management – Creating and managing wallets
- Building WASM – Rebuilding the PoW module from source
git clone https://github.com/digitalSloth/znn-typescript-sdk.git
cd znn-typescript-sdk
npm install
npm run build
npm test- Node.js 20+ (ESM support)
- Modern browser with WebAssembly support
- Bundler for browser production apps (Vite, Webpack, etc.)
BSD-3-Clause
Contributions are welcome! Please feel free to submit a Pull Request.