Skip to main content
The Node.js bindings provide native XMTP functionality for JavaScript and TypeScript applications using NAPI-RS. These bindings expose the core LibXMTP Rust library to Node.js with zero-copy data transfer and full async/await support.
These bindings are not intended to be used directly. Use the xmtp-js SDK instead, which provides a higher-level API built on top of these bindings.

Installation

The bindings are published to npm as @xmtp/node-bindings:

Requirements

  • Node.js >= 22
  • Platform-specific native binaries are automatically downloaded during installation

Architecture

The Node.js bindings use NAPI-RS to create high-performance native Node.js addons from Rust code.

Key Technologies

  • NAPI-RS: Rust framework for building Node.js addons
  • Native Modules: Platform-specific .node files containing compiled Rust code
  • Type Definitions: Auto-generated TypeScript .d.ts files
  • Tokio Integration: Async Rust code integrates with Node.js event loop

Code Organization

The Rust source code follows a modular structure organized by domain:

Error Handling

Rust errors are converted to JavaScript errors using the ErrorWrapper utility:

NAPI Attributes

The bindings use NAPI-RS procedural macros to expose Rust to JavaScript:
  • #[napi] on struct/impl - exports to JavaScript as a class
  • #[napi(object)] - exports as a plain JavaScript object
  • #[napi(getter)] - exports as a property getter
  • #[napi] on method - exports as a class method

Basic Usage

Here’s a basic example of creating a client and sending a message:

Development

Prerequisites

For development, you need:
  • Rust toolchain (managed via Nix or rustup)
  • Node.js >= 22
  • Yarn package manager

Setup

From the repository root:

Build Commands

Linting and Formatting

Testing

Running Tests

Tests are written in TypeScript using Vitest:

Test Structure

Tests are located in the test/ directory:
  • Client.test.ts - Client creation and management
  • Conversations.test.ts - Listing and creating conversations
  • Conversation.test.ts - Sending messages, managing members
  • EnrichedMessage.test.ts - Message content types
  • RemoteAttachmentEncryption.test.ts - Attachment handling

Example Test

Package Information

From package.json:

Key Dependencies

  • napi / napi-derive - Node.js FFI bindings
  • xmtp_mls - Core MLS implementation
  • xmtp_db - Database layer with encrypted SQLite
  • xmtp_proto - Protocol buffer definitions
  • xmtp_api_grpc - gRPC API client

Advanced Patterns

BigInt for Timestamps

Nanosecond timestamps use JavaScript BigInt to avoid precision loss:

Stream Handling

Streams return async iterables:

Content Types

The bindings support various content types:

Performance Considerations

Zero-Copy Data Transfer

NAPI-RS enables zero-copy transfer for:
  • Buffer/Uint8Array data
  • Large strings
  • Binary protocol messages

Async Performance

Rust async operations integrate with Node.js event loop:
  • No blocking of JavaScript thread
  • Efficient multi-threaded execution in Rust
  • Automatic backpressure handling for streams

Database Performance

The bindings use encrypted SQLite with:
  • Connection pooling
  • Prepared statement caching
  • Write-ahead logging (WAL) mode

Troubleshooting

Module Not Found

If you see “Cannot find module” errors:

Platform-Specific Issues

Native binaries are platform-specific. Ensure you’re using the correct binary for your OS:
  • bindings_node.darwin-arm64.node - macOS Apple Silicon
  • bindings_node.darwin-x64.node - macOS Intel
  • bindings_node.linux-x64-gnu.node - Linux x64
  • bindings_node.win32-x64-msvc.node - Windows x64

Database Errors

If you encounter database errors:

Resources

NAPI-RS Documentation

Learn about the NAPI-RS framework

Source Code

View the bindings source code

XMTP-JS SDK

Use the high-level JavaScript SDK

Example Tests

See real usage examples