@signalapp/mock-server
Version:
Mock Signal Server for writing tests
253 lines (252 loc) • 11.6 kB
TypeScript
import { KyberPreKeyRecord, PrivateKey, ProtocolAddress, PublicKey, SenderCertificate, SenderKeyRecord, SenderKeyStore as SenderKeyStoreBase, SessionRecord, SessionStore as SessionStoreBase, SignedPreKeyRecord, Uuid } from '@signalapp/libsignal-client';
import { ProfileKey, ProfileKeyCredentialRequest, ServerPublicParams } from '@signalapp/libsignal-client/zkgroup';
import { signalservice as Proto } from '../../protos/compiled';
import { AciString, DeviceId, PniString, ServiceIdKind, ServiceIdString } from '../types';
import { Contact } from '../data/contacts';
import { Group as GroupData } from '../data/group';
import { EnvelopeType, ModifyGroupOptions, ModifyGroupResult, StorageWriteResult } from '../server/base';
import { ServerGroup } from '../server/group';
import { ChangeNumberOptions, Device, DeviceKeys, SingleUseKey } from '../data/device';
import { Group } from './group';
import { StorageState } from './storage-state';
export type Config = Readonly<{
profileName: string;
contacts: Proto.AttachmentPointer.Params;
trustRoot: PublicKey;
serverPublicParams: ServerPublicParams;
generateNumber: () => Promise<string>;
generatePni: () => Promise<PniString>;
changeDeviceNumber: (device: Device, options: ChangeNumberOptions) => Promise<void>;
send: (device: Device, message: Buffer<ArrayBuffer>) => Promise<void>;
getSenderCertificate: () => Promise<SenderCertificate>;
getDeviceByServiceId: (serviceId: ServiceIdString, deviceId?: DeviceId) => Promise<Device | undefined>;
issueExpiringProfileKeyCredential: (device: Device, request: ProfileKeyCredentialRequest) => Promise<Buffer<ArrayBuffer> | undefined>;
getGroup: (publicParams: Uint8Array<ArrayBuffer>) => Promise<ServerGroup | undefined>;
createGroup: (group: Proto.Group.Params) => Promise<ServerGroup>;
modifyGroup: (options: ModifyGroupOptions) => Promise<ModifyGroupResult>;
waitForGroupUpdate: (group: GroupData) => Promise<void>;
getStorageManifest: () => Promise<Proto.StorageManifest.Params | undefined>;
getStorageItem: (key: Buffer<ArrayBuffer>) => Promise<Buffer<ArrayBuffer> | undefined>;
getAllStorageKeys: () => Promise<Array<Buffer<ArrayBuffer>>>;
waitForStorageManifest: (afterVersion?: bigint) => Promise<void>;
applyStorageWrite: (operation: Proto.WriteOperation.Params, shouldNotify?: boolean) => Promise<StorageWriteResult>;
}>;
export type EncryptOptions = Readonly<{
timestamp?: number;
sealed?: boolean;
serviceIdKind?: ServiceIdKind;
updatedPni?: PniString;
distributionId?: string;
group?: Group;
skipSkdmSend?: boolean;
}>;
export type EncryptTextOptions = EncryptOptions & Readonly<{
withProfileKey?: boolean;
withPniSignature?: boolean;
}>;
export type CreateGroupOptions = Readonly<{
title: string;
members: ReadonlyArray<PrimaryDevice>;
}>;
export type SendUpdateToList = ReadonlyArray<Readonly<{
device: Device;
options?: EncryptOptions;
}>>;
export type GroupActionsOptions = Readonly<{
timestamp?: number;
sendUpdateTo?: SendUpdateToList;
}>;
export type InviteToGroupOptions = Readonly<GroupActionsOptions & {
serviceIdKind?: ServiceIdKind;
}>;
export type AcceptPniInviteOptions = GroupActionsOptions;
export type SyncSentOptions = Readonly<{
timestamp: number;
destinationServiceId: ServiceIdString;
}>;
export type FetchStorageOptions = Readonly<{
timestamp: number;
}>;
export type SendStickerPackSyncOptions = Readonly<{
type: 'install' | 'remove';
packId: Buffer<ArrayBuffer>;
packKey: Buffer<ArrayBuffer>;
timestamp?: number;
}>;
export type SyncReadMessage = Readonly<{
senderAci: AciString;
timestamp: number;
}>;
export type SyncReadOptions = Readonly<{
timestamp?: number;
messages: ReadonlyArray<SyncReadMessage>;
}>;
export declare enum ReceiptType {
Delivery = "Delivery",
Read = "Read"
}
export type ReceiptOptions = Readonly<{
timestamp?: number;
type: ReceiptType;
messageTimestamps: ReadonlyArray<number>;
}>;
export type UnencryptedReceiptOptions = Readonly<{
timestamp?: number;
messageTimestamp: number;
}>;
export type ContentQueueEntry = Readonly<{
source: Device;
serviceIdKind: ServiceIdKind;
envelopeType: EnvelopeType;
content: Proto.Content;
}>;
export type DecryptionErrorQueueEntry = ContentQueueEntry & Readonly<{
timestamp: number;
ratchetKey: PublicKey | undefined;
senderDevice: number;
}>;
export type MessageQueueEntry = ContentQueueEntry & Readonly<{
body: string;
dataMessage: Proto.DataMessage;
}>;
export type ReceiptQueueEntry = ContentQueueEntry & Readonly<{
receiptMessage: Proto.ReceiptMessage;
}>;
export type StoryQueueEntry = ContentQueueEntry & Readonly<{
storyMessage: Proto.StoryMessage;
}>;
export type EditMessageQueueEntry = ContentQueueEntry & Readonly<{
editMessage: Proto.EditMessage;
}>;
export type SyncMessageQueueEntry = Readonly<{
source: Device;
syncMessage: Proto.SyncMessage;
}>;
export type PrepareChangeNumberEntry = Readonly<{
device: Device;
envelope: Buffer<ArrayBuffer>;
}>;
export type PrepareChangeNumberResult = ReadonlyArray<PrepareChangeNumberEntry>;
export declare const EMPTY_GROUP_ACTIONS: Proto.GroupChange.Actions.Params;
export declare const EMPTY_DATA_MESSAGE: Proto.DataMessage.Params;
export declare class SessionStore extends SessionStoreBase {
private readonly sessions;
saveSession(name: ProtocolAddress, record: SessionRecord): Promise<void>;
getSession(name: ProtocolAddress): Promise<SessionRecord | null>;
getExistingSessions(addresses: Array<ProtocolAddress>): Promise<Array<SessionRecord>>;
}
export declare class SenderKeyStore extends SenderKeyStoreBase {
private readonly keys;
saveSenderKey(sender: ProtocolAddress, distributionId: Uuid, record: SenderKeyRecord): Promise<void>;
getSenderKey(sender: ProtocolAddress, distributionId: Uuid): Promise<SenderKeyRecord | null>;
}
export declare class PrimaryDevice {
#private;
readonly device: Device;
private readonly config;
private isInitialized;
private lockPromise;
private readonly syncStates;
private readonly storageKey;
private readonly privateKey;
private pniPrivateKey;
private readonly contactsBlob;
private privSenderCertificate;
private readonly decryptionErrorQueue;
private readonly messageQueue;
private readonly receiptQueue;
private readonly storyQueue;
private readonly editMessageQueue;
private readonly syncMessageQueue;
private privPniPublicKey;
private readonly signedPreKeys;
private readonly preKeys;
private readonly kyberPreKeys;
private readonly sessions;
private readonly senderKeys;
private readonly identity;
readonly publicKey: PublicKey;
readonly profileKey: ProfileKey;
readonly profileName: string;
readonly secondaryDevices: Device[];
readonly accountEntropyPool: string;
readonly masterKey: Buffer<ArrayBuffer>;
readonly mediaRootBackupKey: NonSharedBuffer;
ephemeralBackupKey: Buffer<ArrayBuffer> | undefined;
storageRecordIkm: Buffer<ArrayBuffer> | undefined;
readonly userAgent = "OWI";
constructor(device: Device, config: Config);
init(): Promise<void>;
toContact(): Contact;
addSecondaryDevice(device: Device): void;
generateKeys(device: Device, serviceIdKind: ServiceIdKind): Promise<DeviceKeys & {
signedPreKeyRecord: SignedPreKeyRecord;
lastResortKeyRecord: KyberPreKeyRecord;
}>;
private getPreKeyIterator;
private generateKyberPreKey;
private getKyberPreKeyIterator;
getIdentityKey(serviceIdKind: ServiceIdKind): Promise<PrivateKey>;
getPublicKey(serviceIdKind: ServiceIdKind): PublicKey;
addSingleUseKey(target: Device, key: SingleUseKey, serviceIdKind?: ServiceIdKind): Promise<void>;
getAllGroups(storage: StorageState): Promise<ReadonlyArray<Group>>;
createGroup({ title, members: memberDevices, }: CreateGroupOptions): Promise<Group>;
waitForGroupUpdate(group: Group): Promise<Group>;
inviteToGroup(group: Group, invitee: Device, { timestamp, serviceIdKind, sendUpdateTo, }?: InviteToGroupOptions): Promise<Group>;
acceptPniInvite(group: Group, { timestamp, sendUpdateTo }?: AcceptPniInviteOptions): Promise<Group>;
modifyGroupDisappearingMessageTimer(group: Group, disappearingMessagesDuration: number, { timestamp, sendUpdateTo }?: GroupActionsOptions): Promise<Group>;
waitForStorageState({ after, }?: {
after?: StorageState;
}): Promise<StorageState>;
getStorageState(): Promise<StorageState | undefined>;
expectStorageState(reason: string): Promise<StorageState>;
setStorageState(state: StorageState, previousState?: StorageState): Promise<StorageState>;
getOrphanedStorageKeys(): Promise<Array<Buffer<ArrayBuffer>>>;
waitForSync(secondaryDevice: Device): Promise<void>;
resetSyncState(secondaryDevice: Device): void;
handleEnvelope(source: Device | undefined, serviceIdKind: ServiceIdKind, envelopeType: EnvelopeType, encrypted: Buffer<ArrayBuffer>): Promise<void>;
encryptText(target: Device, text: string, options?: EncryptTextOptions): Promise<Buffer<ArrayBuffer>>;
encryptSyncSent(target: Device, text: string, options: SyncSentOptions): Promise<Buffer<ArrayBuffer>>;
encryptSyncRead(target: Device, options: SyncReadOptions): Promise<Buffer<ArrayBuffer>>;
sendFetchStorage(options: FetchStorageOptions): Promise<void>;
sendStickerPackSync(options: SendStickerPackSyncOptions): Promise<void>;
encryptReceipt(target: Device, options: ReceiptOptions): Promise<Buffer<ArrayBuffer>>;
sendReceipt(target: Device, options: ReceiptOptions): Promise<void>;
sendUnencryptedReceipt(target: Device, { messageTimestamp, timestamp }: UnencryptedReceiptOptions): Promise<void>;
prepareChangeNumber(options?: EncryptOptions): Promise<PrepareChangeNumberResult>;
sendChangeNumber(result: PrepareChangeNumberResult): Promise<void>;
changeNumber(options?: EncryptOptions): Promise<void>;
sendText(target: Device, text: string, options?: EncryptTextOptions): Promise<void>;
sendRaw(target: Device, content: Proto.Content.Params, options?: EncryptOptions): Promise<void>;
sendSenderKey(target: Device, options?: EncryptOptions): Promise<string>;
unlink(device: Device): Promise<void>;
receive(source: Device, encrypted: Buffer<ArrayBuffer>): Promise<void>;
waitForMessage(): Promise<MessageQueueEntry>;
getMessageQueueSize(): number;
waitForDecryptionError(): Promise<DecryptionErrorQueueEntry>;
getDecryptionErrorQueueSize(): number;
waitForReceipt(): Promise<ReceiptQueueEntry>;
getReceiptQueueSize(): number;
waitForStory(): Promise<StoryQueueEntry>;
getStoryQueueSize(): number;
waitForEditMessage(): Promise<EditMessageQueueEntry>;
getEditQueueSize(): number;
waitForSyncMessage(predicate?: (entry: SyncMessageQueueEntry) => boolean): Promise<SyncMessageQueueEntry>;
private getProfileKeyPresentation;
private getPrivateKey;
private encryptContent;
private broadcast;
private getSyncState;
private handleSync;
private handleResendRequest;
private handleDataMessage;
private handleReceiptMessage;
private handleStoryMessage;
private handleEditMessage;
private encrypt;
private decrypt;
private lock;
private get senderCertificate();
private processSenderKeyDistribution;
private convertManifestToStorageState;
}