[](https://github.com/xmtp/libxmtp/actions/workflows/lint.yml)
[](https://github.com/xmtp/libxmtp/actions/workflows/test.yml)

libXMTP
shared library encapsulating the core functionality of the XMTP messaging
protocol, such as cryptography, networking, and language bindings.
Documentation
·
Contributing
## Requirements
- [Rustup](https://rustup.rs/)
- [Docker](https://www.docker.com/get-started/)
- [Foundry](https://book.getfoundry.sh/getting-started/installation#using-foundryup)
- [just](https://github.com/casey/just) (optional for testing)
## Development
Adding Dependencies
- adding dependencies will require re-generating the `workspace-hack` crate,
which can be done with:
```bash
nix develop --command cargo hakari generate
```
to verify correctness you can optionally run
```bash
nix develop --command cargo hakari verify
```
Start Docker Desktop.
- To install other dependencies and start background services:
```bash
./dev/up
```
Specifically, this command creates and runs an XMTP node in Docker Desktop.
- This project uses [`just`](https://github.com/casey/just) as a command
runner. Run `just` to list all available recipes, including submodules for
Android, iOS, Node.js, and WASM:
```bash
just # List all recipes
just format # Format code
just lint # Run all linting
```
- To run tests:
```bash
RUST_LOG=off cargo test
```
Many team members also install and use `cargo nextest` for better test
isolation and log output behavior.
- run tests and open coverage in a browser:
```bash
./dev/test/coverage
```
- To run WebAssembly tests headless:
```bash
just wasm test
```
Note: If the tests fail with "bind() failed: Cannot assign requested address," Chrome is unable to bind to IPv6 and will fall back to IPv4. Although this should be a warning, Chromedriver currently logs this message as SEVERE, which halts the wasm-bindgen-test. You can optionally disable the Chromedriver logs output to prevent this.
```bash
CHROMEDRIVER_ARGS="--log-level=OFF" just wasm test
```
- To run WebAssembly tests interactively for a package, for example, `xmtp_mls`:
```bash
./dev/test/wasm-interactive xmtp_mls
```
- To run browser SDK tests:
```bash
./dev/test/browser-sdk
```
## Tips & Tricks
### Log Output Flags for Tests
- Output test logs in a async-aware context-specific tree format with the
environment variable `CONTEXTUAL`
```
CONTEXTUAL=1 cargo test
```
- Filter tests logs by Crate
```
RUST_LOG=xmtp_mls=debug,xmtp_api=off,xmtp_id=info cargo test
```
- Output test logs as in a structured JSON format for inspection with
third-party viewer
```
STRUCTURED=1 cargo test
```
- Two ways to replace InboxIds/InstallationIds/EthAddresses with a
human-readable string name in logs
_NOTE_: Only works when using `CONTEXTUAL=1` flag. So to get the replacement,
`CONTEXTUAL=1 cargo test`
1.)
Before the test runs, add an `TestLogReplace` declaration to the top
`replace.add` accepts two arguments: the string to replace in logs and the
string to replace it with. Note that on dropping the "TestLogReplace" object,
the replacements will no longer be made.
```rust
let mut replace = TestLogReplace::default();
replace.add(alix.installation_id(), "alix_installation_id");
```
2.) Build the `TesterBuilder` `with_name`
```rust
let tester = Tester::builder().with_name("alix").build().await;
```
This replaces all instances of alix's InboxIds, InstallationIds and Identifiers
with "alix", "alix_installation", "alix_identifier" respectively, in test output
logs.
## Quick Start (Dev Containers)
This project supports containerized development. From Visual Studio Code Dev
Containers extension specify the Dockerfile as the target:
`Reopen in Container`
or
Command line build using docker
```bash
docker build . -t libxmtp:1
```
## Quick Start (nix)
This project supports [Determinate Nix](https://docs.determinate.systems/) for
reproducible development environments. Nix provides pinned toolchains for Rust,
Android, iOS, WebAssembly, and Node.js builds.
```bash
./dev/nix-up # One-time setup: install Determinate Nix + direnv + binary caches
nix develop # Enter the default dev shell
```
To temporarily disable/enable direnv without uninstalling anything:
```bash
./dev/direnv-down # Disable direnv auto-activation
./dev/direnv-up # Re-enable direnv
```
See [docs/nix-setup.md](docs/nix-setup.md) for the full setup guide, including
binary cache configuration, available dev shells, and direnv usage.
## Structure
libxmtp/
├ apps/
│ ├ [`android`](./apps/android): Example Android app (in progress)
│ ├ [`cli`](./apps/cli): Example XMTP console client. Use the CLI to try out
sending double ratchet messages on the XMTP `dev` network.
│ └ [`mls_validation_service`](./apps/mls_validation_service): MLS validation
service
├ bindings/
│ ├ [`mobile`](./bindings/mobile): FFI bindings for Android and iOS
│ ├ [`node`](./bindings/node): Node.js bindings
│ └ [`wasm`](./bindings/wasm): WebAssembly bindings
├ crates/
│ ├ [`xmtp_api_grpc`](./crates/xmtp_api_grpc): API client for XMTP's gRPC API
│ ├ [`xmtp_cryptography`](./crates/xmtp_cryptography): Cryptographic operations
│ ├ [`xmtp_mls`](./crates/xmtp_mls): Version 3 of XMTP which implements
[Messaging Layer Security](https://messaginglayersecurity.rocks/)
│ └ [`xmtp_proto`](./crates/xmtp_proto): Generated code for handling XMTP
protocol buffers
├ sdks/
│ └ [`android`](./sdks/android): Android SDK (Kotlin)
### Run the benchmarks
**possible benchmarks include:**
- `group_limit`: benchmarks surrounding maximum members adding/removed from
group
- `crypto`: benchmarks surrounding cryptographic functions
**Example Commands**
- **Run a specific category of benchmark**
`cargo bench --features bench -p xmtp_mls --bench group_limit`
- **Run against dev grpc** DEV_GRPC=1 cargo bench --features bench -p xmtp_mls
--bench group_limit
- **Just run all benchmarks** ./dev/bench
- **Run one specific benchmark** ./dev/bench add_1_member_to_group
- **Generate flamegraph from one benchmark** ./dev/flamegraph
add_1_member_to_group
## Code Coverage
Code coverage is generated using `cargo llvm-cov` and is integrated into ci and
reported to [codecov](https://codecov.io).
To run the tests locally you can run the `dev/llvm-cov` script to run the same
workspace tests and generate both an lcov and html report.
If you have installed the `Coverage Gutters` extension in vscode (or a
derivative) you can get coverage information in your IDE.
## Contributing
See our [contribution guide](./CONTRIBUTING.md) to learn more about contributing
to this project.