Documentation Index
Fetch the complete documentation index at: https://mintlify.com/covenant-gov/pacto-app/llms.txt
Use this file to discover all available pages before exploring further.
Pacto’s frontend communicates with the Rust backend exclusively through Tauri commands and Tauri events. A command is an async RPC call: the TypeScript frontend calls invoke('command_name', { ...params }) and awaits a serialized result. Events flow in the opposite direction — the backend emits them and the frontend registers listeners with listen. All message-related functionality (direct messages, MLS group messages, files, voice memos, reactions, and history loading) flows through the commands and events documented on this page.
Import pattern
import { invoke } from '@tauri-apps/api/core';
import { listen } from '@tauri-apps/api/event';
Commands
message
Send a text direct message or MLS group message. This is the primary send entry point for all text content. The receiver field doubles as the routing key: an npub1… value routes to the NIP-59 Gift Wrap DM path; any other value (a hex group ID) routes to the MLS Kind 444 path.
| Parameter | Type | Description |
|---|
receiver | string | Recipient npub (DM) or group_id hex (MLS group) |
content | string | Message text |
repliedTo | string | Message ID being replied to, or empty string for no reply |
file | AttachmentFile | null | Optional file attachment (use file_message for path-based sends) |
virtualBucket | string | null | Optional virtual bucket label ("announcements" | "inbox" | "polls") for MLS groups |
Returns: boolean — true on success.
// Send a DM
await invoke('message', {
receiver: 'npub1abc...',
content: 'Hello!',
repliedTo: ''
});
// Send to an MLS group
await invoke('message', {
receiver: 'a1b2c3d4...', // hex group_id
content: 'Hey squad!',
repliedTo: ''
});
Receiver routing: if a chat already exists for the given receiver, Pacto uses the existing chat type. If no chat exists yet, receiver.startsWith('npub1') → DM path; any other value → MLS group path.
file_message
Send a file from a local filesystem path. Reads the file, extracts the extension, and generates blurhash metadata for supported image types before delegating to message with the file bytes as an AttachmentFile. On Android, cached bytes from a prior cache_android_file call are used if available.
| Parameter | Type | Description |
|---|
receiver | string | Recipient npub or group_id hex |
repliedTo | string | Message ID being replied to, or empty string |
filePath | string | Absolute path to the local file (or Android content URI) |
Returns: boolean — true on success.
await invoke('file_message', {
receiver: 'npub1abc...',
repliedTo: '',
filePath: '/home/user/documents/report.pdf'
});
voice_message
Send a voice memo as a WAV audio attachment. Accepts raw PCM/WAV bytes recorded by the frontend, wraps them as a .wav AttachmentFile, and routes through message.
| Parameter | Type | Description |
|---|
receiver | string | Recipient npub or group_id hex |
repliedTo | string | Message ID being replied to, or empty string |
bytes | number[] | Raw WAV audio bytes |
Returns: boolean — true on success.
// After recording audio into a Uint8Array:
await invoke('voice_message', {
receiver: 'npub1abc...',
repliedTo: '',
bytes: Array.from(audioBytes)
});
react_to_message
React to an existing message with an emoji. For DMs the reaction is Gift Wrapped and sent to both the recipient and back to the sender (for self-recovery). For MLS groups the reaction is sent as an MLS application message.
| Parameter | Type | Description |
|---|
referenceId | string | ID of the message being reacted to |
chatId | string | npub (DM) or group_id hex (MLS) — must match the chat that contains referenceId |
emoji | string | Emoji character to react with, e.g. "👍" |
Returns: boolean — true on success.
await invoke('react_to_message', {
referenceId: 'abc123def456...',
chatId: 'npub1abc...',
emoji: '🔥'
});
get_message_views
Load a paginated slice of message history for a chat from the local SQLite database. MLS group chats are provisioned on first load if no DB row exists yet. Results are also merged into the in-memory ChatState cache.
| Parameter | Type | Description |
|---|
chatId | string | npub (DM) or group_id hex (MLS) |
limit | number | Maximum number of messages to return |
offset | number | Pagination offset (0-based) |
virtualBucketFilter | string | null | Optionally filter by virtual bucket ("announcements", "inbox", "polls") |
Returns: Message[] — array of message objects.
const messages = await invoke('get_message_views', {
chatId: 'npub1abc...',
limit: 50,
offset: 0,
virtualBucketFilter: null
});
fetch_messages
Sync Gift Wrap events (Kind 1059) from Nostr relays for the currently authenticated account. When init: true, also hydrates the local database from disk before syncing and triggers init_finished once the initial load is complete. Automatically triggers sync_mls_groups_now after Gift Wrap sync to pick up any pending MLS group messages.
| Parameter | Type | Description |
|---|
init | boolean | true on first call after login (loads DB and emits init_finished) |
relayUrl | string | null | If set, sync only from this specific relay (single-relay reconnection mode) |
Returns: void
// Initial load on login
await invoke('fetch_messages', { init: true, relayUrl: null });
// Re-sync a specific relay
await invoke('fetch_messages', { init: false, relayUrl: 'wss://relay.example.com' });
create_account
Generate a new Nostr keypair derived from a freshly generated BIP39 12-word mnemonic. Returns the keypair for display/backup before the mnemonic is discarded.
Parameters: none
Returns: LoginKeyPair — { nsec: string, npub: string, mnemonic: string }
const keyPair = await invoke('create_account');
console.log('New npub:', keyPair.npub);
console.log('Save this mnemonic:', keyPair.mnemonic);
get_or_create_invite_code
Retrieve the current user’s invite code from local storage or the network. If no code exists locally, checks the account’s published application-specific data on Nostr relays before generating and publishing a new one.
Parameters: none
Returns: string — 8-character uppercase alphanumeric invite code.
const code = await invoke('get_or_create_invite_code');
// e.g. "XKBD29FQ"
Tauri events
Listen for these events using listen from @tauri-apps/api/event. Each listen call returns an unlisten function — always call it on component teardown to avoid memory leaks.
message_new
Emitted when a new DM rumor is processed after unwrapping a Gift Wrap. The chat_id is always the other user’s npub.
Payload: { message: Message, chat_id: string }
const unlisten = await listen('message_new', (event) => {
const { chat_id, message } = event.payload;
console.log(`New DM in ${chat_id}:`, message.content);
});
// Later, on component teardown:
unlisten();
init_finished
Emitted once after the initial account hydration completes during fetch_messages({ init: true }). Contains the full set of known profiles and chats to populate the UI state.
Payload: { profiles: Profile[], chats: Chat[] }
const unlisten = await listen('init_finished', (event) => {
const { profiles, chats } = event.payload;
console.log(`Loaded ${chats.length} chats and ${profiles.length} profiles`);
});
typing-update
Emitted when a typing indicator is received for a conversation. The conversation_id is the npub for DMs or the group_id hex for MLS groups.
Payload: { conversation_id: string }
const unlisten = await listen('typing-update', (event) => {
const { conversation_id } = event.payload;
// Show typing indicator for the relevant chat
});
Full DM send and receive example
import { invoke } from '@tauri-apps/api/core';
import { listen } from '@tauri-apps/api/event';
// 1. Listen for incoming DMs before sending
const unlisten = await listen('message_new', (event) => {
const { chat_id, message } = event.payload;
console.log(`New message in ${chat_id}:`, message.content);
});
// 2. Send a DM
await invoke('message', {
receiver: 'npub1abc...',
content: 'Hello!',
repliedTo: ''
});
// 3. Load history for this conversation
const history = await invoke('get_message_views', {
chatId: 'npub1abc...',
limit: 50,
offset: 0,
virtualBucketFilter: null
});
// 4. Teardown
unlisten();
For MLS group messages, substitute the hex group_id for the npub in receiver / chatId and listen to mls_message_new (with payload { group_id, message }) instead of message_new. See MLS Commands for the full group messaging reference.