npm package: @ixo/matrix
Description: ## Overview
Latest version: 1.2.3

# @ixo/matrix

## Overview

The `@ixo/matrix` package is a robust wrapper around the Matrix.org client SDK, specifically designed for the ixo-oracles ecosystem. It provides a secure, type-safe interface for managing Matrix communications with end-to-end encryption.

### Key Features

- 🔐 End-to-end encrypted room management
- 💬 Secure messaging with threading support
- 🔄 Type-safe state management
- 🔑 Cross-signing and cryptographic key management
- 🏗️ Oracle-specific room naming and access control
- 📦 Local storage for crypto and general data
- ⚡ Singleton pattern for efficient resource management

## Table of Contents

1. [Getting Started](#getting-started)
   - [Installation](#installation)
   - [Configuration](#configuration)
   - [Quick Start](#quick-start)
2. [Core Concepts](#core-concepts)
   - [Room Management](#room-management)
   - [Messaging](#messaging)
   - [State Management](#state-management)
   - [Client Operations and User Tokens](#client-operations-and-user-tokens)
3. [API Reference](#api-reference)
4. [Development](#development)

## Getting Started

### Installation

```bash
# Install using pnpm (recommended)
pnpm install @ixo/matrix

# Or using npm
npm install @ixo/matrix

# Or using yarn
yarn add @ixo/matrix
```

### Configuration

The package requires several environment variables for proper operation:

#### Matrix Server

```bash
MATRIX_BASE_URL=https://your-matrix-server.com    # Your Matrix homeserver URL
```

#### Oracle Admin Credentials

```bash
MATRIX_ORACLE_ADMIN_ACCESS_TOKEN=your_token       # Admin access token
MATRIX_ORACLE_ADMIN_USER_ID=@admin:your.server    # Admin user ID
MATRIX_ORACLE_ADMIN_PASSWORD=your_password        # Password for cross-signing
```

#### Security

```bash
MATRIX_RECOVERY_PHRASE=your_recovery_phrase       # For secret storage & key backup
```

#### Storage Paths (Optional)

All paths are created in the `matrix-local-storage` folder:

```bash
MATRIX_STORE_PATH=./matrix-store                           # General storage
MATRIX_SECRET_STORAGE_KEYS_PATH=./matrix-secret-storage    # Secret keys
```

### Environment Variables Explained

#### Cross-Signing and Security Variables

The package uses Matrix's cross-signing feature for enhanced security. This requires specific environment variables:

- `MATRIX_ORACLE_ADMIN_PASSWORD`: Required for authenticating cross-signing key uploads. When setting up cross-signing, the package needs to upload device signing keys to the server. This operation requires authentication using the admin password.

- `MATRIX_RECOVERY_PHRASE`: Used for:
  - Creating and managing secret storage
  - Generating recovery keys
  - Restoring key backups
  - Accessing encrypted data across devices

#### Prerequisites

- Access to a Matrix homeserver
- fs write permissions

### Quick Start

```typescript
import { MatrixManager } from '@ixo/matrix';

async function main() {
  // 1. Get the singleton instance
  const manager = MatrixManager.getInstance();

  // 2. Initialize the manager
  await manager.init();

  // 3. Create and join a room
  const roomId = await manager.createRoomAndJoin({
    did: 'did:ixo:123',
    oracleName: 'myOracle',
    userAccessToken: 'user_access_token',
  });

  // 4. Send a message
  await manager.sendMessage({
    roomId,
    message: 'Hello World',
  });
}
```

## Core Concepts

### Room Management

Rooms in the ixo-matrix ecosystem are secure, encrypted spaces for communication. Each room has:

- Unique DID-based identification
- Oracle-specific naming convention
- Controlled access permissions
- End-to-end encryption

#### Room Creation Process

1. **Room Naming**

```typescript
// Rooms are named using a deterministic hash of DID and oracle name
const roomName = MatrixManager.generateRoomNameFromDidAndOracle(
  'did:ixo:123',
  'myOracle',
); // Results in format: 'ixo-{md5hash}'

// Room aliases are generated by replacing spaces with underscores
const roomAlias = MatrixManager.generateRoomAliasFromName(roomName);
```

1. **Room Configuration**
   Each room is created with specific security settings:

- Private visibility (not publicly listed)
- End-to-end encryption enabled (using m.megolm.v1.aes-sha2)
- Guest access forbidden
- Shared history visibility
- Admin power levels for specific operations:
  - Kick: 9999
  - Ban: 9999
  - Invite: 9999
  - Redact: 9999

1. **Creating and Joining**

```typescript
// Create a room with all security features enabled
const roomId = await manager.createRoomAndJoin({
  did: 'did:ixo:123',
  oracleName: 'myOracle',
  userAccessToken: 'user_token',
});
```

1. **Access Control**

```typescript
// Check if a user has access to a room
const hasAccess = await manager.checkIsUserInRoom({
  roomId,
  userAccessToken: 'user_token',
});

// Get room by ID
const room = manager.getRoom(roomId);
```

1. **Room Lifecycle**

- Rooms are created with encryption enabled by default
- Admin user is automatically given highest power level
- Initial state includes encryption, guest access, and history visibility settings
- Room can be found using DID and oracle name:

```typescript
// Get room ID from DID and oracle name
const existingRoomId = await manager.getRoomId({
  did: 'did:ixo:123',
  oracleName: 'myOracle',
});
```

### Client Operations and User Tokens

The package uses two types of tokens for different operations:

#### 1. Admin Token (`MATRIX_ORACLE_ADMIN_ACCESS_TOKEN`)

Used for:

- Sending messages in rooms
- Managing room state
- Setting up encryption
- Cross-signing operations
- Getting room information
- Managing room power levels
- Creating rooms
- Inviting users to rooms

#### 2. User Token (Provided per operation)

Used only for:

- joining rooms
- Verifying room membership

Example usage:

```typescript
// Operations using Admin Token (automatically handled)
await manager.sendMessage({
  roomId,
  message: 'Hello World',
});

// Operations requiring User Token
// the user token is used only for joining the room -- the rest of the operations are handled by the admin token
await manager.createRoomAndJoin({
  did: 'did:ixo:123',
  oracleName: 'myOracle',
  userAccessToken: 'user_token', // User token required
});

// Check if the user is in the room using the user token
await manager.checkIsUserInRoom({
  roomId,
  userAccessToken: 'user_token', // User token required
});
```

Note: User tokens are temporary and automatically cleaned up after use. All other operations use the admin token internally.

### Messaging

The package supports various message types and threading:
All the messages will be sent from the Oracle Admin client.

```typescript
// Regular message
await manager.sendMessage({
  roomId,
  message: 'Hello World',
});

// Threaded reply
await manager.sendMessage({
  roomId,
  message: 'Reply',
  threadId: 'original_message_id',
});

// Oracle admin message
await manager.sendMessage({
  roomId,
  message: 'Admin notification',
  isOracleAdmin: true,
});
```

### State Management

Type-safe state management with validation:

```typescript
interface ProjectState {
  status: string;
  lastUpdate: number;
}

// Set state
await manager.stateManager.setState<ProjectState>({
  roomId,
  stateKey: 'oracle_project',
  data: {
    status: 'active',
    lastUpdate: Date.now(),
  },
});

// Get state
const state = await manager.stateManager.getState<ProjectState>(
  roomId,
  'oracle_project',
);

// Update state
await manager.stateManager.updateState<ProjectState>({
  roomId,
  stateKey: 'oracle_project',
  data: {
    status: 'completed',
  },
});
```

### LangChain Graph Checkpointing

The package provides a Matrix-based checkpointer implementation for LangChain graphs, allowing you to persist graph state in Matrix rooms:

```typescript
import { MatrixCheckpointSaver } from '@ixo/matrix';
import { StateGraph } from '@langchain/langgraph';

// Create your graph
const workflow = new StateGraph(graphState)
  .addNode('myNode', (state) => {
    // Your node logic
  })
  .addEdge(START, 'myNode')
  .addEdge('myNode', END);

// Compile the graph with Matrix checkpointing
const graph = workflow.compile({
  checkpointer: new MatrixCheckpointSaver('your-graph-name'),
});
```

## API Reference

### MatrixManager

The main interface for Matrix operations:

- `getInstance()`: Get singleton instance
- `init()`: Initialize the manager
- `createRoomAndJoin()`: Create and join a room
- `sendMessage()`: Send a message
- `stop()`: Cleanup resources

### MatrixStateManager

Handles state management:

- `setState<T>()`: Set typed state
- `getState<T>()`: Get typed state
- `updateState<T>()`: Update existing state
- `listStateEvents<T>()`: List all state events

## Development

### Testing

```bash
# Run unit tests
pnpm test

# Run integration tests
pnpm test:e2e

# Run with coverage
pnpm test:coverage
```

### Error Handling

```typescript
try {
  await manager.sendMessage({
    roomId,
    message: 'Hello',
  });
} catch (error) {
  if (error instanceof MatrixError) {
    // Handle Matrix-specific errors
    console.error('Matrix error:', error.errcode);
  } else {
    // Handle other errors
    console.error('General error:', error);
  }
}
```

## License

Internal package - All rights reserved.