pub struct VectorCore;Expand description
The main entry point for Vector Core.
Provides a high-level API for all Vector operations. Internally uses global state (same pattern as the Tauri backend) for compatibility.
use vector_core::{VectorCore, CoreConfig};
use std::path::PathBuf;
let core = VectorCore::init(CoreConfig {
data_dir: PathBuf::from("/tmp/vector-data"),
event_emitter: None,
})?;
// Login with nsec
let result = core.login("nsec1...", None).await?;
println!("Logged in as {}", result.npub);Implementations§
Source§impl VectorCore
impl VectorCore
Sourcepub fn init(config: CoreConfig) -> Result<Self>
pub fn init(config: CoreConfig) -> Result<Self>
Initialize Vector Core with the given configuration.
Sourcepub async fn login(
&self,
key: &str,
password: Option<&str>,
) -> Result<LoginResult>
pub async fn login( &self, key: &str, password: Option<&str>, ) -> Result<LoginResult>
Login with an nsec key or mnemonic seed phrase.
Sourcepub fn generate_nsec(&self) -> Result<String>
pub fn generate_nsec(&self) -> Result<String>
Generate a fresh random account secret key (bech32 nsec). Lets a headless client spin up a
brand-new identity (add_account with no key) without depending on nostr-sdk directly.
Sourcepub async fn send_dm(&self, to_npub: &str, content: &str) -> Result<SendResult>
pub async fn send_dm(&self, to_npub: &str, content: &str) -> Result<SendResult>
Send a NIP-17 gift-wrapped text DM using the full pipeline. Retries a
transient publish miss (headless preset, 3 attempts) so an SDK/CLI bot rides
out a relay blip instead of silently dropping the message on the first miss;
self_send: false keeps it a plain send (no inbox self-copy).
Sourcepub async fn send_dm_reply(
&self,
to_npub: &str,
replied_to: &str,
content: &str,
) -> Result<SendResult>
pub async fn send_dm_reply( &self, to_npub: &str, replied_to: &str, content: &str, ) -> Result<SendResult>
Send a DM as a threaded reply to replied_to (an existing message’s event id).
Sourcepub async fn download_attachment(
&self,
attachment: &Attachment,
) -> Result<Vec<u8>>
pub async fn download_attachment( &self, attachment: &Attachment, ) -> Result<Vec<u8>>
Download a received attachment and decrypt it to plaintext bytes. Fetches the encrypted blob
from its Blossom URL (SSRF/Tor-aware client, size-capped) and AES-decrypts with the
attachment’s embedded key + nonce. Walks the primary URL then any BUD-04 fallback
mirrors (same ciphertext on other hosts) until one serves. Prefer
download_attachment_from when the message author is
known — it adds the BUD-03 hash-swap over the author’s advertised servers.
Sourcepub async fn download_attachment_from(
&self,
attachment: &Attachment,
author_npub: Option<&str>,
) -> Result<Vec<u8>>
pub async fn download_attachment_from( &self, attachment: &Attachment, author_npub: Option<&str>, ) -> Result<Vec<u8>>
download_attachment with the full source walk: primary URL →
embedded fallback mirrors → BUD-03 hash-swap (the same content-address on each of the
author’s kind-10063 servers). author_npub is the message author (your own npub for your
own messages); None skips the hash-swap stage.
Sourcepub async fn send_file(
&self,
to_npub: &str,
file_path: &str,
) -> Result<SendResult>
pub async fn send_file( &self, to_npub: &str, file_path: &str, ) -> Result<SendResult>
Send a NIP-17 gift-wrapped file attachment DM.
Sourcepub async fn send_reaction(
&self,
to_npub: &str,
reference_id: &str,
emoji: &str,
emoji_url: Option<&str>,
) -> Result<String>
pub async fn send_reaction( &self, to_npub: &str, reference_id: &str, emoji: &str, emoji_url: Option<&str>, ) -> Result<String>
Send a NIP-25 reaction to a DM message. emoji_url carries the NIP-30
image URL when reacting with a custom-pack emoji (content stays
:shortcode:). Returns the reaction’s rumor id. Local echo + persistence
are best-effort — the gift-wrap send is the source of truth.
Sourcepub async fn send_typing(&self, to_npub: &str) -> Result<()>
pub async fn send_typing(&self, to_npub: &str) -> Result<()>
Send an ephemeral typing indicator to a DM recipient. Fire-and-forget with a 30-second NIP-40 expiry so relays purge it quickly.
Sourcepub async fn edit_dm(
&self,
to_npub: &str,
message_id: &str,
new_content: &str,
) -> Result<String>
pub async fn edit_dm( &self, to_npub: &str, message_id: &str, new_content: &str, ) -> Result<String>
Edit a DM you previously sent (kind-16 edit) with an optimistic local echo. Returns the edit event id. Persistence is best-effort and only happens when the chat already exists locally.
Sourcepub async fn delete_dm(&self, message_id: &str) -> Result<DeleteOutcome>
pub async fn delete_dm(&self, message_id: &str) -> Result<DeleteOutcome>
Delete a DM you sent (NIP-09 over the retained gift-wrap keys).
Sourcepub async fn get_chats(&self) -> Vec<SerializableChat>
pub async fn get_chats(&self) -> Vec<SerializableChat>
Get chats from the in-memory state.
Sourcepub async fn get_messages(
&self,
chat_id: &str,
limit: usize,
offset: usize,
) -> Vec<Message>
pub async fn get_messages( &self, chat_id: &str, limit: usize, offset: usize, ) -> Vec<Message>
Get messages for a chat (paginated).
Sourcepub async fn get_messages_before(
&self,
chat_id: &str,
before: Option<(u64, &str)>,
limit: usize,
) -> Vec<Message>
pub async fn get_messages_before( &self, chat_id: &str, before: Option<(u64, &str)>, limit: usize, ) -> Vec<Message>
Cursor-paged local read: up to limit messages strictly before the
(at_ms, id) cursor, chronological. None returns the newest limit.
The cursor is compared BY VALUE, never resolved to a stored row, so it keeps working after its message is gone (NIP-09 delete, moderation hide, a self-destruct timer) — a persisted cursor must not wedge the walk. The id tiebreaks inside a same-millisecond burst, giving a total order that can’t skip or re-serve across pages. Local only: sync older history in from relays first.
Sourcepub async fn get_profile(&self, npub: &str) -> Option<SlimProfile>
pub async fn get_profile(&self, npub: &str) -> Option<SlimProfile>
Get a profile by npub.
Sourcepub async fn load_profile(&self, npub: &str) -> bool
pub async fn load_profile(&self, npub: &str) -> bool
Fetch a profile’s metadata and status from relays.
Sourcepub async fn update_profile(
&self,
name: &str,
avatar: &str,
banner: &str,
about: &str,
) -> bool
pub async fn update_profile( &self, name: &str, avatar: &str, banner: &str, about: &str, ) -> bool
Update the current user’s profile metadata and broadcast to relays.
Sourcepub async fn update_bot_profile(
&self,
name: &str,
avatar: &str,
banner: &str,
about: &str,
) -> bool
pub async fn update_bot_profile( &self, name: &str, avatar: &str, banner: &str, about: &str, ) -> bool
Like update_profile but marks the profile as a bot (bot: true in
the metadata). The SDK uses this for every bot; build human clients on update_profile.
Sourcepub async fn update_status(&self, status: &str) -> bool
pub async fn update_status(&self, status: &str) -> bool
Update the current user’s status and broadcast to relays.
Sourcepub async fn upload_public_image(&self, file_path: &str) -> Result<String>
pub async fn upload_public_image(&self, file_path: &str) -> Result<String>
Upload an image file to Blossom unencrypted and return its public URL — for avatars,
banners, and other images other clients must fetch directly. (The opposite of
send_file’s encrypted attachments.) Pass the URL to update_profile.
Sourcepub async fn block_user(&self, npub: &str) -> bool
pub async fn block_user(&self, npub: &str) -> bool
Block a user by npub.
Sourcepub async fn unblock_user(&self, npub: &str) -> bool
pub async fn unblock_user(&self, npub: &str) -> bool
Unblock a user by npub.
Sourcepub async fn set_nickname(&self, npub: &str, nickname: &str) -> bool
pub async fn set_nickname(&self, npub: &str, nickname: &str) -> bool
Set a nickname for a profile.
Sourcepub async fn get_blocked_users(&self) -> Vec<SlimProfile>
pub async fn get_blocked_users(&self) -> Vec<SlimProfile>
Get all blocked profiles.
Sourcepub fn queue_profile_sync(&self, npub: &str, priority: SyncPriority)
pub fn queue_profile_sync(&self, npub: &str, priority: SyncPriority)
Queue a profile for background sync.
Sourcepub async fn list_communities(&self) -> Vec<Value>
pub async fn list_communities(&self) -> Vec<Value>
List every Community held locally (owned or joined), each with its channels.
Sourcepub async fn create_community_v2(&self, name: &str) -> Result<Value>
pub async fn create_community_v2(&self, name: &str) -> Result<Value>
Create a fresh Concord v2 community owned by the local identity (the
SDK’s default; the GUI’s create_community stays v1 during the migration
window). Mints the self-certifying id + genesis, persists, publishes, and
registers each channel as a chat. Returns a version: 2 JSON summary.
Sourcepub async fn register_v2_chats(
&self,
community: &CommunityV2,
session: &SessionGuard,
)
pub async fn register_v2_chats( &self, community: &CommunityV2, session: &SessionGuard, )
Register each of a v2 community’s channels as a chat row (so it surfaces in
the chat list / communities()), mirroring the v1 create path. session
is captured by the caller BEFORE its network I/O, so this STATE write is
skipped if the account swapped mid-flight (else we’d write A’s community
into B’s in-memory chats).
Source§impl VectorCore
impl VectorCore
Sourcepub async fn join_community(&self, invite_url: &str) -> Result<Value>
pub async fn join_community(&self, invite_url: &str) -> Result<Value>
Join a Community from a public invite URL (vectorapp.io/invite#...). Fetches the
token-encrypted bundle, persists the member-view Community, and registers its channels
as chats. Returns a JSON summary.
Sourcepub fn list_pending_invites(&self) -> Result<Vec<Value>>
pub fn list_pending_invites(&self) -> Result<Vec<Value>>
List the parked private invites (giftwrapped) awaiting acceptance. Each entry is the community id, its name (from the stored bundle), and the inviter’s npub.
Sourcepub async fn accept_pending_invite(&self, community_id: &str) -> Result<Value>
pub async fn accept_pending_invite(&self, community_id: &str) -> Result<Value>
Accept a PARKED private invite by community id: rebuild the member-view Community from the stored bundle, finalize the join exactly like a public link, then drop the pending row. Mirrors the desktop’s consent-then-join for an invite delivered over a gift wrap.
Sourcepub async fn create_channel(
&self,
community_id: &str,
name: &str,
private: bool,
) -> Result<String>
pub async fn create_channel( &self, community_id: &str, name: &str, private: bool, ) -> Result<String>
Create a channel. A private one mints its own key plus the channel-scoped
access Role that is its access list (CORD-03/04); grant that role with
grant_channel_access to let someone read it.
Returns the new channel id (32-byte hex).
Sourcepub async fn rename_channel(
&self,
community_id: &str,
channel_id: &str,
name: &str,
) -> Result<()>
pub async fn rename_channel( &self, community_id: &str, channel_id: &str, name: &str, ) -> Result<()>
Rename a channel (a versioned edit of the same entity, so its history and id survive). Other folded fields are carried through untouched.
Sourcepub async fn delete_channel(
&self,
community_id: &str,
channel_id: &str,
) -> Result<()>
pub async fn delete_channel( &self, community_id: &str, channel_id: &str, ) -> Result<()>
Tombstone a channel. Deletion is terminal and the id is never reused; history stays readable to anyone who already holds its keys.
Sourcepub async fn grant_channel_access(
&self,
community_id: &str,
channel_id: &str,
npub: &str,
) -> Result<()>
pub async fn grant_channel_access( &self, community_id: &str, channel_id: &str, npub: &str, ) -> Result<()>
Grant npub read access to a private channel: adds the channel’s access
role and vends the key to them (CORD-03 “delivered on grant”).
Sourcepub async fn revoke_channel_access(
&self,
community_id: &str,
channel_id: &str,
npub: &str,
) -> Result<()>
pub async fn revoke_channel_access( &self, community_id: &str, channel_id: &str, npub: &str, ) -> Result<()>
Revoke npub’s read access: drops the access role and rekeys the channel
so the removal actually severs them (CORD-06). They keep whatever history
they already read — a rekey protects the future, never the past.
Sourcepub fn channel_access(
&self,
community_id: &str,
channel_id: &str,
) -> Result<Value>
pub fn channel_access( &self, community_id: &str, channel_id: &str, ) -> Result<Value>
Who may read a private channel: the channel-scoped Roles that are its access list (CORD-04 §2) and the members holding them.
Sync read off the folded roster. members is exactly the access-role
holders; owner is reported alongside because the owner is entitled
whether or not they hold one (a channel’s creator is granted the role, so
an owner-created channel lists them in both).
Sourcepub async fn create_public_invite(
&self,
community_id: &str,
expires_at_ms: Option<u64>,
label: Option<String>,
) -> Result<String>
pub async fn create_public_invite( &self, community_id: &str, expires_at_ms: Option<u64>, label: Option<String>, ) -> Result<String>
Mint a public invite link for a Community this identity owns. Returns the shareable URL.
expires_at_ms is an ABSOLUTE unix timestamp in MILLISECONDS (v2’s native unit and the
InviteEntry wire’s); the v1 path takes seconds, so it is converted here rather than at
each call site. label is the attribution bucket shown as “joined via
Sourcepub async fn invite_to_community(
&self,
community_id: &str,
invitee_npub: &str,
) -> Result<Value>
pub async fn invite_to_community( &self, community_id: &str, invitee_npub: &str, ) -> Result<Value>
Send a PRIVATE invite: gift-wrap this Community’s invite bundle directly to an npub over a NIP-17 DM (the same transport as a regular DM). The invitee parks it pending consent (accept_pending_invite). Requires CREATE_INVITE; a banned npub can’t be re-invited. Returns the wrap’s event id + relays.
Sourcepub fn list_public_invites(
&self,
community_id: &str,
) -> Result<Vec<PublicInviteRecord>>
pub fn list_public_invites( &self, community_id: &str, ) -> Result<Vec<PublicInviteRecord>>
The public invite links this account minted for a Community (to list + revoke). Each carries
the hex token (the link secret) needed by Self::revoke_public_invite. A local read for
both protocols — links minted on this device (a v2 mint also syncs the cross-device 13303
record; v2 join_count is not yet tracked and is always 0).
Sourcepub async fn revoke_public_invite(
&self,
community_id: &str,
token: &str,
) -> Result<()>
pub async fn revoke_public_invite( &self, community_id: &str, token: &str, ) -> Result<()>
Revoke a public invite link by its hex token. Retiring the LAST active link flips the Community to Private, which re-founds (rotates the base key + every channel key) to cut link-joined lurkers. Idempotent: a token this account doesn’t hold is a no-op. Needs a local key when the revoke triggers the privatize rekey (a bunker account can’t rotate).
Sourcepub async fn send_community_message(
&self,
channel_id: &str,
content: &str,
replied_to: Option<&str>,
) -> Result<String>
pub async fn send_community_message( &self, channel_id: &str, content: &str, replied_to: Option<&str>, ) -> Result<String>
Post a text message to a Community channel. Returns the message id (the inner id).
Sourcepub async fn send_community_file(
&self,
channel_id: &str,
file_path: &str,
) -> Result<String>
pub async fn send_community_file( &self, channel_id: &str, file_path: &str, ) -> Result<String>
Send a file to a Community channel as an encrypted attachment. Returns the message id.
Mirrors the DM file pipeline (encrypt → Blossom upload → NIP-92 imeta) but publishes
over the community transport.
Sourcepub async fn send_community_typing(&self, channel_id: &str) -> Result<()>
pub async fn send_community_typing(&self, channel_id: &str) -> Result<()>
Send an ephemeral typing indicator to a Community channel.
Sourcepub async fn send_community_reaction(
&self,
channel_id: &str,
message_id: &str,
emoji: &str,
emoji_url: Option<&str>,
) -> Result<()>
pub async fn send_community_reaction( &self, channel_id: &str, message_id: &str, emoji: &str, emoji_url: Option<&str>, ) -> Result<()>
React to a Community message. emoji_url carries the NIP-30 image URL for a custom
:shortcode: reaction (parity with DMs).
Sourcepub async fn edit_community_message(
&self,
channel_id: &str,
message_id: &str,
new_content: &str,
) -> Result<()>
pub async fn edit_community_message( &self, channel_id: &str, message_id: &str, new_content: &str, ) -> Result<()>
Edit one of your own Community messages.
Sourcepub async fn delete_community_message(&self, message_id: &str) -> Result<()>
pub async fn delete_community_message(&self, message_id: &str) -> Result<()>
Delete one of your own Community messages, resolving its channel from local
state (the GUI path). A headless v2 consumer holds no local history — use
Self::delete_community_message_in with the channel id instead.
Sourcepub async fn delete_community_message_in(
&self,
channel_id: &str,
message_id: &str,
) -> Result<()>
pub async fn delete_community_message_in( &self, channel_id: &str, message_id: &str, ) -> Result<()>
Delete one of your own Community messages in channel_id: a NIP-09 relay nuke when the
per-message key is held (v1) or the in-plane kind-5 (v2), plus a cooperative tombstone so
peers hide it, plus best-effort attachment cleanup.
Sourcepub async fn hide_community_message(
&self,
channel_id: &str,
message_id: &str,
) -> Result<()>
pub async fn hide_community_message( &self, channel_id: &str, message_id: &str, ) -> Result<()>
Moderation-hide someone ELSE’s community message under MANAGE_MESSAGES
(CORD-04 §3/§5). Protocol-agnostic: v2 seals the same kind-5 its authors
use, v1 publishes its 3305 tombstone; both re-derive the actor’s authority
from the signed inner against the folded Roster, so this is an authority
claim peers verify, never a local suppression.
Sourcepub async fn sync_community_channel(
&self,
channel_id: &str,
limit: usize,
) -> Result<(usize, Vec<String>)>
pub async fn sync_community_channel( &self, channel_id: &str, limit: usize, ) -> Result<(usize, Vec<String>)>
Catch a Community channel up from relays. v1: fetch + ingest the latest page of messages,
reactions, edits, and deletes, returning how many were brand-new. v2: consensus catch-up
only (rekeys + control refold) — chat history delivers over the live handler bridge, so the
count is always 0. Returns (new_message_count, warnings); warnings are NON-FATAL errors
hit during the sync (catch-up, control fold, read-cut resume) — surfaced rather than
swallowed so a headless caller is never blind to “the sync ran but a re-founding couldn’t
be resumed.”
Sourcepub async fn sync_channel_events(
&self,
channel_id: &str,
max_events: usize,
until_s: Option<u64>,
since_s: Option<u64>,
) -> Result<usize>
pub async fn sync_channel_events( &self, channel_id: &str, max_events: usize, until_s: Option<u64>, since_s: Option<u64>, ) -> Result<usize>
Cursor-paged relay sync: fetch ONE page of up to max_events events from
the channel’s relays (per relay — divergent relays can push the union
higher), ingest it, and return how many MESSAGES were new. A return of 0
means the page held nothing new, not that the channel is empty.
until_s / since_s are unix-seconds bounds (the back-paging cursor and
the time floor). Depth comes from looping, not from a bigger page:
max_events is clamped to 500 (relays clamp theirs anyway) and values
under 50 behave as 50 on v2 (the shared pager’s floor).
Consensus (root rotations, control folds, ban checks) is the FULL sync’s
job — sync_community_channel — so a
hundred-page walk doesn’t re-fold control a hundred times. Run one full
sync (or be listening) before deep walks.
Sourcepub async fn get_chat_commands(&self, chat_id: &str) -> ChatCommandsSnapshot
pub async fn get_chat_commands(&self, chat_id: &str) -> ChatCommandsSnapshot
The composer’s / picker snapshot for chat_id, answered INSTANTLY
from local state: the chat’s bot-flagged members (kind-0 bot: true —
the SDK sets it on every bot it builds) and their last-known manifests
from the persistent store. When the last refresh is older than a minute
(or the bot set changed), ONE background REQ re-fetches every bot’s
manifest together (5s unification window), persists newer editions, and
emits chat_commands_updated — the UI swaps the list in when it lands.
Works for BOTH community protocols (an invocation is plain content; only
the optional routing tag is v2-only) and DMs. The manifest REQ always
includes the discovery indexers beside the chat’s own relays, so an
unreachable or stranger-dropping community relay can’t blind the picker.
Sourcepub async fn get_community_members(&self, community_id: &str) -> Vec<Value>
pub async fn get_community_members(&self, community_id: &str) -> Vec<Value>
Observed members of a Community (best-effort: those who’ve posted or announced a join,
minus anyone who’s left or is banned). v1 entries are {npub, last_active}; a v2 entry
is {npub} (the Complete Memberlist carries no activity time). Best-effort throughout:
a transport failure yields an empty list, never an error.
Sourcepub fn community_capabilities(&self, community_id: &str) -> Result<Value>
pub fn community_capabilities(&self, community_id: &str) -> Result<Value>
My effective management capabilities in a community (role engine — owner is just position 0). Use to confirm a promotion/demotion landed. A local read: the roster is folded + persisted by the passive sync (v1) / control follow (v2), never fetched here.
Sourcepub async fn pin_community_message(
&self,
community_id: &str,
channel_id: &str,
message_id: &str,
) -> Result<()>
pub async fn pin_community_message( &self, community_id: &str, channel_id: &str, message_id: &str, ) -> Result<()>
Pin a message in a v2 community channel (CORD-04 §7). The proof is
rebuilt from the message’s recovered wrap; see service::pin_message.
Sourcepub async fn unpin_community_message(
&self,
community_id: &str,
channel_id: &str,
message_id: &str,
) -> Result<()>
pub async fn unpin_community_message( &self, community_id: &str, channel_id: &str, message_id: &str, ) -> Result<()>
Unpin a message: the next Pin List edition without the entry.
Sourcepub async fn fetch_pinned_attachment(
&self,
community_id: &str,
channel_id: &str,
rumor_id: &str,
) -> Result<Value>
pub async fn fetch_pinned_attachment( &self, community_id: &str, channel_id: &str, rumor_id: &str, ) -> Result<Value>
Fetch a pinned attachment FROM THE PIN ALONE (CORD-04 §7’s whole point:
the proof carries the rumor, whose imeta carries the blob URL and the
file’s decryption material — no chat history and no old epoch key
needed). Serves the already-downloaded copy when its content hash
verifies; otherwise runs the full download walk (mirrors + hash-swap),
decrypts, verifies, and caches at the same content-addressed path the
chat pipeline uses. Returns { path, mime, name }.
Sourcepub fn get_channel_pins(
&self,
community_id: &str,
channel_id: &str,
) -> Result<Value>
pub fn get_channel_pins( &self, community_id: &str, channel_id: &str, ) -> Result<Value>
A channel’s verified pins from the locally folded head — local-only read.
sealed: true means the list exists but is unreadable on this device;
render it as unavailable, never as empty.
Sourcepub fn community_roles(&self, community_id: &str) -> Result<Value>
pub fn community_roles(&self, community_id: &str) -> Result<Value>
The community’s owner npub + the admin npubs (role overview). A local read,
like Self::community_capabilities.
Sourcepub async fn grant_admin(&self, community_id: &str, npub: &str) -> Result<()>
pub async fn grant_admin(&self, community_id: &str, npub: &str) -> Result<()>
Grant a member the @admin role. Requires MANAGE_ROLES + outranking the role’s position.
Sourcepub async fn revoke_admin(&self, community_id: &str, npub: &str) -> Result<()>
pub async fn revoke_admin(&self, community_id: &str, npub: &str) -> Result<()>
Revoke a member’s @admin role.
Sourcepub async fn kick_member(&self, community_id: &str, npub: &str) -> Result<()>
pub async fn kick_member(&self, community_id: &str, npub: &str) -> Result<()>
Cooperatively kick a member — they self-remove but can rejoin. Requires KICK + outrank.
Sourcepub async fn set_member_banned(
&self,
community_id: &str,
npub: &str,
banned: bool,
) -> Result<()>
pub async fn set_member_banned( &self, community_id: &str, npub: &str, banned: bool, ) -> Result<()>
Ban (true) or unban (false) a member. Ban is terminal (no rejoin). The read cut:
a private community re-founds (full rotation); a public one rotates just the private
channels the member could read (CORD-05 §5 — no refound, the link refresh would
re-hand them the root). Requires BAN + outrank, checked against the folded roster
BEFORE any publish.
Sourcepub async fn dissolve_community(&self, community_id: &str) -> Result<()>
pub async fn dissolve_community(&self, community_id: &str) -> Result<()>
Owner dissolution / “Delete Community”: publish the terminal GroupDissolved tombstone (and
retire the owner’s own invite links, no rekey), sealing the community permanently. Owner-only
(re-verified cryptographically in service::dissolve_community); irreversible.
Sourcepub async fn edit_community_metadata(
&self,
community_id: &str,
name: Option<&str>,
description: Option<&str>,
) -> Result<()>
pub async fn edit_community_metadata( &self, community_id: &str, name: Option<&str>, description: Option<&str>, ) -> Result<()>
Edit community metadata (name / description) as an authorized member (MANAGE_METADATA). None leaves
a field unchanged; an empty description clears it.
Sourcepub async fn leave_community(&self, community_id: &str) -> Result<()>
pub async fn leave_community(&self, community_id: &str) -> Result<()>
Leave a Community: announce a best-effort “left” presence (before dropping keys), then drop the held keys + local channel chats. You need a fresh invite to rejoin.
Sourcepub async fn sync_dms(
&self,
since_days: Option<u64>,
handler: &dyn InboundEventHandler,
) -> Result<(u32, u32)>
pub async fn sync_dms( &self, since_days: Option<u64>, handler: &dyn InboundEventHandler, ) -> Result<(u32, u32)>
Sync DM history from relays using NIP-77 negentropy set reconciliation.
Reconciles local wrapper history with relay state, fetches missing events, and processes them through the standard prepare → commit pipeline.
Returns (total_events, new_messages).
let core = vector_core::VectorCore;
// Sync last 7 days of DMs
let (events, new) = core.sync_dms(Some(7), &vector_core::NoOpEventHandler).await?;
println!("Processed {} events, {} new messages", events, new);Sourcepub async fn subscribe_dms(&self) -> Result<SubscriptionId>
pub async fn subscribe_dms(&self) -> Result<SubscriptionId>
Subscribe to incoming DM events (NIP-17 GiftWraps).
Returns the subscription ID for use in a custom notification loop.
For a complete listen-and-process loop, use listen() instead.
Sourcepub async fn sync_communities(&self) -> Result<()>
pub async fn sync_communities(&self) -> Result<()>
Catch up every locally-held Community: fold control / re-foundings / rekeys / banlist and
fetch recent messages into local state for each channel. State-only (does not replay to an
InboundEventHandler). Called at listen() start and periodically for outage resilience;
also safe to call manually after a known disconnect.
Catch up every locally-held Community. v1 channels are synced inline; a v2
community is ENQUEUED for the follow worker (control/rekey re-fold + adopt),
non-blocking. State-only (no handler replay of history). Called at listen()
start and on reconnect; safe to call manually — the v2 enqueue is a no-op if
no listen() worker is running.
Sourcepub async fn listen(&self, handler: Arc<dyn InboundEventHandler>) -> Result<()>
pub async fn listen(&self, handler: Arc<dyn InboundEventHandler>) -> Result<()>
Start listening for incoming DMs.
Blocks until the client disconnects. Processes GiftWraps (DMs, files) → prepare_event → commit_prepared_event.
use vector_core::*;
use std::sync::Arc;
struct MyBot;
impl InboundEventHandler for MyBot {
fn on_dm_received(&self, chat_id: &str, msg: &Message, _is_new: bool) {
if msg.mine { return; }
let to = chat_id.to_string();
let reply = format!("Echo: {}", msg.content);
tokio::spawn(async move {
let _ = VectorCore.send_dm(&to, &reply).await;
});
}
}
let core = VectorCore::init(CoreConfig {
data_dir: "/tmp/bot-data".into(),
event_emitter: None,
})?;
core.login("nsec1...", None).await?;
core.listen(Arc::new(MyBot)).await?;Sourcepub async fn swap_session(&self)
pub async fn swap_session(&self)
Tear down the current session for an in-process account swap — the account-agnostic core of
the app’s reset_session(). Advances the session generation FIRST so any background task
holding a SessionGuard short-circuits before it can touch the next account’s storage; shuts
the client down (which ends any listen() notification loop bound to it, so the old account’s
events can’t land in the new account’s DB); closes the DB pool; and clears the key vaults plus
all in-memory per-account state. Follow with login() to bind the next account, then re-attach
listen(). (The app’s reset_session() additionally clears Tauri-only caches it owns.)
Trait Implementations§
Source§impl Clone for VectorCore
impl Clone for VectorCore
Source§fn clone(&self) -> VectorCore
fn clone(&self) -> VectorCore
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreimpl Copy for VectorCore
Auto Trait Implementations§
impl Freeze for VectorCore
impl RefUnwindSafe for VectorCore
impl Send for VectorCore
impl Sync for VectorCore
impl Unpin for VectorCore
impl UnsafeUnpin for VectorCore
impl UnwindSafe for VectorCore
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more