import { type VerifiedEvent } from "nostr-tools"; import { type GroupData } from "./GroupMeta"; import { type MessageOrigin } from "./MessageOrigin"; import { OneToManyChannel } from "./OneToManyChannel"; import type { SenderKeyDistribution } from "./SenderKey"; import { type StorageAdapter } from "./StorageAdapter"; import { type Rumor } from "./types"; export type PairwiseSend = (recipientOwnerPubkey: string, rumor: Rumor) => Promise; export type PublishOuter = (outer: VerifiedEvent, innerEventId?: string) => Promise; export interface GroupOptions { data: GroupData; /** Owner pubkey for *this* device (group membership is expressed in owner pubkeys). */ ourOwnerPubkey: string; /** Device identity pubkey for *this* device (used inside encrypted payloads). */ ourDevicePubkey: string; storage?: StorageAdapter; oneToMany?: OneToManyChannel; } export interface GroupDecryptedEvent { groupId: string; senderEventPubkey: string; senderDevicePubkey: string; senderOwnerPubkey?: string; origin: MessageOrigin; isSelf: boolean; isCrossDeviceSelf: boolean; outerEventId: string; outerCreatedAt: number; keyId: number; messageNumber: number; inner: Rumor; } /** * Signal-style efficient group messaging: * * - Each *device* has a per-group "sender event" pubkey (outer Nostr author). * - Each device uses a symmetric SenderKeyState chain for forward secrecy within that sender. * - Sender keys are distributed pairwise over 1:1 Double Ratchet sessions (forward secure). * - Group messages are published once using OneToManyChannel. * * This class is transport-agnostic: * - You provide `sendPairwise` for distributing keys over 1:1 sessions. * - You provide `publishOuter` for publishing the one-to-many outer events. * - You feed it incoming session rumors + outer events via the `handle…` methods. */ export declare class Group { data: GroupData; private readonly ourOwnerPubkey; private readonly ourDevicePubkey; private memberOwnerPubkeys; private readonly storage; private readonly oneToMany; private readonly storageVersion; private readonly versionPrefix; private initialized; private senderDeviceToEvent; private senderEventToDevice; private senderDeviceToOwner; private pendingOuter; constructor(opts: GroupOptions); groupId(): string; setData(data: GroupData): void; setMembers(memberOwnerPubkeys: string[]): void; listSenderEventPubkeys(): Promise; getSenderEventPubkeyForDevice(senderDevicePubkey: string): Promise; private init; private groupSenderPrefix; private senderEventSecretKeyKey; private senderEventPubkeyKey; private senderOwnerPubkeyKey; private latestKeyIdKey; private senderKeyStateKey; private setSenderEventMapping; private isMemberOwnerPubkey; private isSenderDeviceActive; private removeSenderDeviceState; private purgeInactiveSenders; private pendingKey; private queuePending; private drainPending; private ensureOurSenderEventKeys; private loadSenderKeyState; private saveSenderKeyState; private ensureOurSenderKeyState; private buildDistribution; private buildDistributionRumor; private buildGroupInnerRumor; private senderKeyRecipientOwnerPubkeys; /** * Rotate our sender key (new keyId + chain key) and distribute it to group members. */ rotateSenderKey(opts: { sendPairwise: PairwiseSend; nowMs?: number; }): Promise; /** * Send an inner group event over one-to-many transport. * - Ensures we have sender-event keys and a sender key state. * - Distributes sender key to group members if needed. * - Publishes exactly one outer event via OneToManyChannel. */ sendEvent(event: { kind: number; content: string; tags?: string[][]; }, opts: { sendPairwise: PairwiseSend; publishOuter: PublishOuter; nowMs?: number; }): Promise<{ outer: VerifiedEvent; inner: Rumor; }>; /** * Send a regular group chat message (kind 14). */ sendMessage(message: string, opts: { sendPairwise: PairwiseSend; publishOuter: PublishOuter; nowMs?: number; }): Promise<{ outer: VerifiedEvent; inner: Rumor; }>; /** * Handle an incoming 1:1 session rumor (decrypted Double Ratchet event). * * Currently this only consumes sender-key distribution rumors (kind 10446) for this group. * It may return decrypted outer group events that were pending until the distribution arrived. * * `fromSenderDevicePubkey` must come from authenticated session context (not `event.pubkey`). */ handleIncomingSessionEvent(event: Rumor, fromOwnerPubkey: string, fromSenderDevicePubkey?: string): Promise; /** * Handle an incoming one-to-many outer event (authored by a per-sender sender-event pubkey). * * Returns a decrypted inner rumor if possible, or null if we're missing mapping/state and queued it. */ handleOuterEvent(outer: VerifiedEvent): Promise; } //# sourceMappingURL=GroupChannel.d.ts.map