@leachain/vm-shim

@leachain/vm-shim is a reusable VM shim for Lea-chain WebAssembly modules, providing the necessary host environment for running smart contracts compatibly in both Node.js and browser environments.
Features
- Environment-Agnostic: Works seamlessly in both Node.js and modern web browsers.
- Secure by Default: Provides a sandboxed environment with no filesystem or network access unless explicitly passed in.
- Configurable: Allows custom handlers for events like
abort.
- Typed API: Includes TypeScript definitions for a better developer experience.
- Modern Tooling: Bundled with
esbuild for optimized, multi-format output (ESM, CJS, and IIFE).
Installation
npm install @leachain/vm-shim
Usage
The primary export is createShim, which generates the importObject for a WebAssembly instance.
ES Modules (ESM)
This is the recommended approach for modern Node.js and browser bundlers.
import { promises as fs } from 'fs';
import { createShim } from '@leachain/vm-shim';
async function runWasm() {
// 1. Create the shim instance
const { importObject, bindInstance } = createShim();
// 2. Read your Wasm module bytes
const wasmBytes = await fs.readFile('./path/to/your_contract.wasm');
// 3. Instantiate the module with the shim's import object
const { instance } = await WebAssembly.instantiate(wasmBytes, importObject);
// 4. IMPORTANT: Bind the created instance to the shim
// This allows host functions to access the Wasm module's memory.
bindInstance(instance);
// 5. Call an exported function from your Wasm module
const result = instance.exports.your_function(123);
console.log(`Wasm function returned: ${result}`);
}
runWasm().catch(console.error);
CommonJS (CJS)
For older Node.js environments, you can use require.
const { promises: fs } = require('fs');
const { createShim } = require('@leachain/vm-shim');
async function runWasm() {
// 1. Create the shim instance
const { importObject, bindInstance } = createShim();
// 2. Read your Wasm module bytes
const wasmBytes = await fs.readFile('./path/to/your_contract.wasm');
// 3. Instantiate the module with the shim's import object
const { instance } = await WebAssembly.instantiate(wasmBytes, importObject);
// 4. IMPORTANT: Bind the created instance to the shim
bindInstance(instance);
// 5. Call an exported function from your Wasm module
const result = instance.exports.your_function(123);
console.log(`Wasm function returned: ${result}`);
}
runWasm().catch(console.error);
API Reference
createShim(config?)
config <object> (Optional)
onAbort <(message: string) => void>: A custom handler to call when the Wasm module aborts. Defaults to process.exit(1) in Node.js and throws an Error in the browser.
- Returns
<object>
importObject <object>: The WebAssembly import object. Pass this to WebAssembly.instantiate.
bindInstance <(instance: WebAssembly.Instance) => void>: A function to bind the newly created Wasm instance to the shim. This must be called after instantiation.
print <object>: A colored logging utility with red, orange, green, and blue methods.
cstring(memory, ptr)
A utility function to read a null-terminated UTF-8 string from the Wasm instance's memory.
memory <WebAssembly.Memory>: The exported memory from your Wasm instance (instance.exports.memory).
ptr <number>: The pointer (memory address) of the string.
- Returns
<string>: The decoded string.
Contributing
Contributions are welcome! Please open an issue or submit a pull request for any bugs, features, or improvements.
License
This project is licensed under the ISC License.