fix: hide v3 closed group protobuf messages for now

pull/2620/head
Audric Ackermann 2 years ago
parent 456d52ab1a
commit fddfc8c501

@ -73,41 +73,41 @@ message DataExtractionNotification {
optional uint64 timestamp = 2; optional uint64 timestamp = 2;
} }
message GroupInviteMessage { // message GroupInviteMessage {
required string name = 1; // required string name = 1;
required bytes memberPrivateKey = 2; // required bytes memberPrivateKey = 2;
} // }
// this will replace our closedGroupControlMessage but we will need to keep both for some time // this will replace our closedGroupControlMessage but we will need to keep both for some time
message GroupMessage { // message GroupMessage {
optional GroupAdminMessage adminMessage = 31; // optional GroupAdminMessage adminMessage = 31;
optional GroupMemberLeftMessage memberLeftMessage = 32; // optional GroupMemberLeftMessage memberLeftMessage = 32;
optional GroupInviteMessage inviteMessage = 33; // optional GroupInviteMessage inviteMessage = 33;
optional GroupPromoteMessage promoteMessage = 34; // optional GroupPromoteMessage promoteMessage = 34;
} // }
message GroupPromoteMessage { // message GroupPromoteMessage {
required bytes privateKey = 1; // this is the group admins key // required bytes privateKey = 1; // this is the group admins key
} // }
message GroupAdminMessage { // message GroupAdminMessage {
enum Type { // enum Type {
DELETE_GROUP = 1; // members, groupSignature // DELETE_GROUP = 1; // members, groupSignature
DELETE_GROUP_ALL_MEMBERS = 2; // groupSignature // DELETE_GROUP_ALL_MEMBERS = 2; // groupSignature
DELETE_MESSAGES_ALL_MEMBERS = 3; // groupSignature // DELETE_MESSAGES_ALL_MEMBERS = 3; // groupSignature
DELETE_ATTACHMENTS_ALL_MEMBERS = 4; // groupSignature // DELETE_ATTACHMENTS_ALL_MEMBERS = 4; // groupSignature
} // }
//
// @required // // @required
required Type type = 1; // required Type type = 1;
repeated bytes members = 2; // repeated bytes members = 2;
// @required // @required
required bytes groupSignature = 3; // used by every members to make sure incoming admin action can be trusted // required bytes groupSignature = 3; // used by every members to make sure incoming admin action can be trusted
} // }
message GroupMemberLeftMessage { // message GroupMemberLeftMessage {
// the pubkey of the member who left is already in the senderIdentity // the pubkey of the member who left is already in the senderIdentity
} // }
message DataMessage { message DataMessage {
@ -212,7 +212,7 @@ message DataMessage {
optional OpenGroupInvitation openGroupInvitation = 102; optional OpenGroupInvitation openGroupInvitation = 102;
optional ClosedGroupControlMessage closedGroupControlMessage = 104; optional ClosedGroupControlMessage closedGroupControlMessage = 104;
optional string syncTarget = 105; optional string syncTarget = 105;
optional GroupMessage groupMessage = 120; // optional GroupMessage groupMessage = 120;
} }
message CallMessage { message CallMessage {

@ -6,7 +6,7 @@ type RetrieveAlwaysNeeded = {
pubkey: string; pubkey: string;
namespace: number; namespace: number;
last_hash: string; last_hash: string;
timestamp: number; timestamp?: number;
}; };
export type RetrievePubkeySubRequestType = { export type RetrievePubkeySubRequestType = {

@ -1,55 +1,55 @@
import { SignalService } from '../../../../../../protobuf'; // import { SignalService } from '../../../../../../protobuf';
import { isArray } from 'lodash'; // import { isArray } from 'lodash';
import { GroupMessage, GroupMessageParams } from './GroupMessage'; // import { GroupMessage, GroupMessageParams } from './GroupMessage';
// import { PubKey } from '../../../../../types'; // // import { PubKey } from '../../../../../types';
// import { from_hex } from 'libsodium-wrappers-sumo'; // // import { from_hex } from 'libsodium-wrappers-sumo';
interface GroupAdminMessageParams extends GroupMessageParams { // interface GroupAdminMessageParams extends GroupMessageParams {
/* // /*
* A proof that we are an admin (a proof that we have access to the private key of the closed group). // * A proof that we are an admin (a proof that we have access to the private key of the closed group).
* this field is needed for all types of admin messages so that every member can make // * this field is needed for all types of admin messages so that every member can make
*/ // */
groupSignature: Uint8Array; // groupSignature: Uint8Array;
} // }
interface GroupAdminMessageParams extends GroupMessageParams { // interface GroupAdminMessageParams extends GroupMessageParams {
/** // /**
* hex string of the members to delete the group from. // * hex string of the members to delete the group from.
* a single '*' is allowed too and means 'every members' // * a single '*' is allowed too and means 'every members'
* // *
*/ // */
members: Array<string>; // members: Array<string>;
} // }
export class GroupAdminGroupMessage extends GroupMessage { // export class GroupAdminGroupMessage extends GroupMessage {
// private readonly members: Array<string>; // // private readonly members: Array<string>;
constructor(params: GroupAdminMessageParams) { // constructor(params: GroupAdminMessageParams) {
super(params); // super(params);
if (!params.members || !isArray(params.members) || !params.members.length) { // if (!params.members || !isArray(params.members) || !params.members.length) {
throw new Error('members parameter must be set'); // throw new Error('members parameter must be set');
} // }
// if (params.members.length === 1 && params.members[0] === '*') { // // if (params.members.length === 1 && params.members[0] === '*') {
// this.members = params.members; // // this.members = params.members;
// } else { // // } else {
// const allAreValid = params.members.every(PubKey.isValidGroupPubkey); // // const allAreValid = params.members.every(PubKey.isValidGroupPubkey);
// if (!allAreValid) { // // if (!allAreValid) {
// throw new Error('One of the members is not a `isValidGroupPubkey`'); // // throw new Error('One of the members is not a `isValidGroupPubkey`');
// } // // }
// this.members = params.members; // // this.members = params.members;
// } // // }
throw new Error('TODO and add tests'); // throw new Error('TODO and add tests');
} // }
public dataProto(): SignalService.DataMessage { // public dataProto(): SignalService.DataMessage {
const dataMessage = new SignalService.DataMessage(); // const dataMessage = new SignalService.DataMessage();
dataMessage.groupMessage = super.groupMessage(); // dataMessage.groupMessage = super.groupMessage();
dataMessage.groupMessage.adminMessage = new SignalService.GroupAdminMessage(); // dataMessage.groupMessage.adminMessage = new SignalService.GroupAdminMessage();
// dataMessage.groupMessage.members = this.members.map(from_hex); // // dataMessage.groupMessage.members = this.members.map(from_hex);
return dataMessage; // return dataMessage;
} // }
} // }

@ -1,48 +1,48 @@
import { SignalService } from '../../../../../../protobuf'; // import { SignalService } from '../../../../../../protobuf';
import { isEmpty, isString } from 'lodash'; // import { isEmpty, isString } from 'lodash';
import { GroupMessage, GroupMessageParams } from './GroupMessage'; // import { GroupMessage, GroupMessageParams } from './GroupMessage';
import { PubKey } from '../../../../../types'; // import { PubKey } from '../../../../../types';
import { from_hex } from 'libsodium-wrappers-sumo'; // import { from_hex } from 'libsodium-wrappers-sumo';
export interface GroupInviteMessageParams extends GroupMessageParams { // export interface GroupInviteMessageParams extends GroupMessageParams {
name: string; // name: string;
/** // /**
* hex string of that member private key // * hex string of that member private key
*/ // */
memberPrivateKey: string; // memberPrivateKey: string;
} // }
export class GroupInviteMessage extends GroupMessage { // export class GroupInviteMessage extends GroupMessage {
private readonly name: string; // private readonly name: string;
private readonly memberPrivateKey: string; // private readonly memberPrivateKey: string;
constructor(params: GroupInviteMessageParams) { // constructor(params: GroupInviteMessageParams) {
super(params); // super(params);
if (!params.name || isEmpty(params.name) || !isString(params.name)) { // if (!params.name || isEmpty(params.name) || !isString(params.name)) {
throw new Error('name parameter must be valid'); // throw new Error('name parameter must be valid');
} // }
if ( // if (
!params.memberPrivateKey || // !params.memberPrivateKey ||
isEmpty(params.memberPrivateKey) || // isEmpty(params.memberPrivateKey) ||
!isString(params.memberPrivateKey) || // !isString(params.memberPrivateKey) ||
!PubKey.isHexOnly(params.memberPrivateKey) // !PubKey.isHexOnly(params.memberPrivateKey)
) { // ) {
throw new Error('memberPrivateKey parameter must be valid'); // throw new Error('memberPrivateKey parameter must be valid');
} // }
this.name = params.name; // this.name = params.name;
this.memberPrivateKey = params.memberPrivateKey; // this.memberPrivateKey = params.memberPrivateKey;
} // }
public dataProto(): SignalService.DataMessage { // public dataProto(): SignalService.DataMessage {
const dataMessage = new SignalService.DataMessage(); // const dataMessage = new SignalService.DataMessage();
dataMessage.groupMessage = super.groupMessage(); // dataMessage.groupMessage = super.groupMessage();
dataMessage.groupMessage.inviteMessage = new SignalService.GroupInviteMessage(); // dataMessage.groupMessage.inviteMessage = new SignalService.GroupInviteMessage();
dataMessage.groupMessage.inviteMessage.name = this.name; // dataMessage.groupMessage.inviteMessage.name = this.name;
dataMessage.groupMessage.inviteMessage.memberPrivateKey = from_hex(this.memberPrivateKey); // dataMessage.groupMessage.inviteMessage.memberPrivateKey = from_hex(this.memberPrivateKey);
return dataMessage; // return dataMessage;
} // }
} // }

@ -1,18 +1,18 @@
import { SignalService } from '../../../../../../protobuf'; // import { SignalService } from '../../../../../../protobuf';
import { GroupMessage, GroupMessageParams } from './GroupMessage'; // import { GroupMessage, GroupMessageParams } from './GroupMessage';
interface GroupMemberLeftMessageParams extends GroupMessageParams {} // interface GroupMemberLeftMessageParams extends GroupMessageParams {}
export class GroupMemberLeftMessage extends GroupMessage { // export class GroupMemberLeftMessage extends GroupMessage {
constructor(params: GroupMemberLeftMessageParams) { // constructor(params: GroupMemberLeftMessageParams) {
super(params); // super(params);
} // }
public dataProto(): SignalService.DataMessage { // public dataProto(): SignalService.DataMessage {
const dataMessage = new SignalService.DataMessage(); // const dataMessage = new SignalService.DataMessage();
dataMessage.groupMessage = super.groupMessage(); // dataMessage.groupMessage = super.groupMessage();
dataMessage.groupMessage.memberLeftMessage = new SignalService.GroupMemberLeftMessage(); // dataMessage.groupMessage.memberLeftMessage = new SignalService.GroupMemberLeftMessage();
return dataMessage; // return dataMessage;
} // }
} // }

@ -1,18 +1,18 @@
import { SignalService } from '../../../../../../protobuf'; // import { SignalService } from '../../../../../../protobuf';
import { DataMessage } from '../../../DataMessage'; // import { DataMessage } from '../../../DataMessage';
import { MessageParams } from '../../../Message'; // import { MessageParams } from '../../../Message';
export interface GroupMessageParams extends MessageParams {} // export interface GroupMessageParams extends MessageParams {}
export abstract class GroupMessage extends DataMessage { // export abstract class GroupMessage extends DataMessage {
constructor(params: GroupMessageParams) { // constructor(params: GroupMessageParams) {
super({ // super({
timestamp: params.timestamp, // timestamp: params.timestamp,
identifier: params.identifier, // identifier: params.identifier,
}); // });
} // }
protected groupMessage() { // protected groupMessage() {
return new SignalService.GroupMessage(); // return new SignalService.GroupMessage();
} // }
} // }

@ -1,34 +1,34 @@
import { SignalService } from '../../../../../../protobuf'; // import { SignalService } from '../../../../../../protobuf';
import { isEmpty } from 'lodash'; // import { isEmpty } from 'lodash';
import { GroupMessage, GroupMessageParams } from './GroupMessage'; // import { GroupMessage, GroupMessageParams } from './GroupMessage';
import { from_hex } from 'libsodium-wrappers-sumo'; // import { from_hex } from 'libsodium-wrappers-sumo';
export interface GroupPromoteMessageParams extends GroupMessageParams { // export interface GroupPromoteMessageParams extends GroupMessageParams {
/** // /**
* hex string of the group private key // * hex string of the group private key
*/ // */
privateKey: string; // privateKey: string;
} // }
export class GroupPromoteMessage extends GroupMessage { // export class GroupPromoteMessage extends GroupMessage {
private readonly privateKey: string; // private readonly privateKey: string;
constructor(params: GroupPromoteMessageParams) { // constructor(params: GroupPromoteMessageParams) {
super(params); // super(params);
if (!params.privateKey || isEmpty(params.privateKey)) { // if (!params.privateKey || isEmpty(params.privateKey)) {
throw new Error('privateKey parameter must be set'); // throw new Error('privateKey parameter must be set');
} // }
this.privateKey = params.privateKey; // this.privateKey = params.privateKey;
} // }
public dataProto(): SignalService.DataMessage { // public dataProto(): SignalService.DataMessage {
const dataMessage = new SignalService.DataMessage(); // const dataMessage = new SignalService.DataMessage();
dataMessage.groupMessage = super.groupMessage(); // dataMessage.groupMessage = super.groupMessage();
dataMessage.groupMessage.promoteMessage = new SignalService.GroupPromoteMessage(); // dataMessage.groupMessage.promoteMessage = new SignalService.GroupPromoteMessage();
dataMessage.groupMessage.promoteMessage.privateKey = from_hex(this.privateKey); // dataMessage.groupMessage.promoteMessage.privateKey = from_hex(this.privateKey);
return dataMessage; // return dataMessage;
} // }
} // }

@ -1,87 +1,89 @@
import { expect } from 'chai'; // import { expect } from 'chai';
import { SignalService } from '../../../../../../protobuf'; // import { SignalService } from '../../../../../../protobuf';
import { GroupInviteMessage } from '../../../../../../session/messages/outgoing/controlMessage/group/v3/GroupInviteMessage'; // import { GroupInviteMessage } from '../../../../../../session/messages/outgoing/controlMessage/group/v3/GroupInviteMessage';
import { v4 } from 'uuid'; // import { v4 } from 'uuid';
import { Constants } from '../../../../../../session'; // import { Constants } from '../../../../../../session';
import { from_hex } from 'libsodium-wrappers-sumo'; // import { from_hex } from 'libsodium-wrappers-sumo';
describe('GroupInviteMessage', () => { // describe('GroupInviteMessage', () => {
it('can create valid message', () => { // beforeEach(async () => {});
const message = new GroupInviteMessage({
timestamp: 12345,
memberPrivateKey: '654321',
name: 'groupName',
identifier: v4(),
});
const plainText = message.plainTextBuffer(); // it('can create valid message', async () => {
const decoded = SignalService.Content.decode(plainText); // const message = new GroupInviteMessage({
expect(decoded.dataMessage) // timestamp: 12345,
.to.have.property('groupMessage') // memberPrivateKey: '654321',
.to.have.property('inviteMessage') // name: 'groupName',
.to.have.deep.property('name', 'groupName'); // identifier: v4(),
expect(decoded.dataMessage) // });
.to.have.property('groupMessage')
.to.have.property('inviteMessage')
.to.have.deep.property('memberPrivateKey', from_hex('654321'));
expect(message) // const plainText = message.plainTextBuffer();
.to.have.property('timestamp') // const decoded = SignalService.Content.decode(plainText);
.to.be.equal(12345); // expect(decoded.dataMessage)
}); // .to.have.property('groupMessage')
// .to.have.property('inviteMessage')
// .to.have.deep.property('name', 'groupName');
// expect(decoded.dataMessage)
// .to.have.property('groupMessage')
// .to.have.property('inviteMessage')
// .to.have.deep.property('memberPrivateKey', from_hex('654321'));
it('correct ttl', () => { // expect(message)
const message = new GroupInviteMessage({ // .to.have.property('timestamp')
timestamp: 12345, // .to.be.equal(12345);
memberPrivateKey: '654321', // });
name: 'groupName',
identifier: v4(),
});
expect(message.ttl()).to.equal(Constants.TTL_DEFAULT.TTL_MAX); // it('correct ttl', () => {
}); // const message = new GroupInviteMessage({
// timestamp: 12345,
// memberPrivateKey: '654321',
// name: 'groupName',
// identifier: v4(),
// });
it('has an identifier even if none are provided', () => { // expect(message.ttl()).to.equal(Constants.TTL_DEFAULT.TTL_MAX);
const message = new GroupInviteMessage({ // });
timestamp: 12345,
memberPrivateKey: '654321',
name: 'groupName',
});
expect(message.identifier).to.not.equal(null, 'identifier cannot be null'); // it('has an identifier even if none are provided', () => {
expect(message.identifier).to.not.equal(undefined, 'identifier cannot be undefined'); // const message = new GroupInviteMessage({
}); // timestamp: 12345,
// memberPrivateKey: '654321',
// name: 'groupName',
// });
describe('constructor throws on invalid ', () => { // expect(message.identifier).to.not.equal(null, 'identifier cannot be null');
it('memberPk is empty', () => { // expect(message.identifier).to.not.equal(undefined, 'identifier cannot be undefined');
expect(() => { // });
new GroupInviteMessage({
timestamp: 12345,
memberPrivateKey: undefined as any,
name: 'groupName',
});
}).throws();
});
it('memberPk is not a string', () => { // describe('constructor throws on invalid ', () => {
expect(() => { // it('memberPk is empty', () => {
new GroupInviteMessage({ // expect(() => {
timestamp: 12345, // new GroupInviteMessage({
memberPrivateKey: 1234 as any, // timestamp: 12345,
name: 'groupName', // memberPrivateKey: undefined as any,
}); // name: 'groupName',
}).throws(); // });
}); // }).throws();
// });
it('memberPk is not a hex string', () => { // it('memberPk is not a string', () => {
expect(() => { // expect(() => {
new GroupInviteMessage({ // new GroupInviteMessage({
timestamp: 12345, // timestamp: 12345,
memberPrivateKey: '03ghklmnopqrstuvxyz' as any, // memberPrivateKey: 1234 as any,
name: 'groupName', // name: 'groupName',
}); // });
}).throws(); // }).throws();
}); // });
});
}); // it('memberPk is not a hex string', () => {
// expect(() => {
// new GroupInviteMessage({
// timestamp: 12345,
// memberPrivateKey: '03ghklmnopqrstuvxyz' as any,
// name: 'groupName',
// });
// }).throws();
// });
// });
// });

@ -1,49 +1,52 @@
import { expect } from 'chai'; // import { expect } from 'chai';
import { SignalService } from '../../../../../../protobuf'; // import { SignalService } from '../../../../../../protobuf';
import { v4 } from 'uuid'; // import { v4 } from 'uuid';
import { Constants } from '../../../../../../session'; // import { Constants } from '../../../../../../session';
import { GroupMemberLeftMessage } from '../../../../../../session/messages/outgoing/controlMessage/group/v3/GroupMemberLeftMessage'; // import { GroupMemberLeftMessage } from '../../../../../../session/messages/outgoing/controlMessage/group/v3/GroupMemberLeftMessage';
describe('GroupMemberLeftMessage', () => { // describe('GroupMemberLeftMessage', () => {
it('can create valid message', () => { // beforeEach(async () => {});
const message = new GroupMemberLeftMessage({
timestamp: 12345, // it('can create valid message', async () => {
identifier: v4(), // const message = new GroupMemberLeftMessage({
}); // timestamp: 12345,
// identifier: v4(),
const plainText = message.plainTextBuffer(); // });
const decoded = SignalService.Content.decode(plainText);
expect(decoded.dataMessage) // const plainText = message.plainTextBuffer();
.to.have.property('groupMessage') // const decoded = SignalService.Content.decode(plainText);
.to.have.property('memberLeftMessage').to.be.not.undefined; // expect(decoded.dataMessage)
expect(decoded.dataMessage) // .to.have.property('groupMessage')
.to.have.property('groupMessage') // .to.have.property('memberLeftMessage').to.be.not.undefined;
.to.have.property('memberLeftMessage').to.be.not.null; // expect(decoded.dataMessage)
// .to.have.property('groupMessage')
expect(decoded.dataMessage) // .to.have.property('memberLeftMessage').to.be.not.null;
.to.have.property('groupMessage')
.to.have.property('memberLeftMessage').to.be.empty; // expect(decoded.dataMessage)
expect(message) // .to.have.property('groupMessage')
.to.have.property('timestamp') // .to.have.property('memberLeftMessage').to.be.empty;
.to.be.equal(12345); // expect(message)
}); // .to.have.property('timestamp')
// .to.be.equal(12345);
it('correct ttl', () => { // });
const message = new GroupMemberLeftMessage({
timestamp: 12345, // it('correct ttl', () => {
identifier: v4(), // const message = new GroupMemberLeftMessage({
}); // timestamp: 12345,
// identifier: v4(),
expect(message.ttl()).to.equal(Constants.TTL_DEFAULT.TTL_MAX); // });
});
// expect(message.ttl()).to.equal(Constants.TTL_DEFAULT.TTL_MAX);
it('has an identifier even if none are provided', () => { // });
const message = new GroupMemberLeftMessage({
timestamp: 12345, // it('has an identifier even if none are provided', () => {
}); // const message = new GroupMemberLeftMessage({
// timestamp: 12345,
expect(message.identifier).to.not.equal(null, 'identifier cannot be null'); // });
expect(message.identifier).to.not.equal(undefined, 'identifier cannot be undefined');
}); // expect(message.identifier).to.not.equal(null, 'identifier cannot be null');
}); // expect(message.identifier).to.not.equal(undefined, 'identifier cannot be undefined');
// });
// });

@ -1,58 +1,60 @@
import { expect } from 'chai'; // import { expect } from 'chai';
import { SignalService } from '../../../../../../protobuf'; // import { SignalService } from '../../../../../../protobuf';
import { GroupPromoteMessage } from '../../../../../../session/messages/outgoing/controlMessage/group/v3/GroupPromoteMessage'; // import { GroupPromoteMessage } from '../../../../../../session/messages/outgoing/controlMessage/group/v3/GroupPromoteMessage';
import { v4 } from 'uuid'; // import { v4 } from 'uuid';
import { Constants } from '../../../../../../session'; // import { Constants } from '../../../../../../session';
import { from_hex } from 'libsodium-wrappers-sumo'; // import { from_hex } from 'libsodium-wrappers-sumo';
describe('GroupPromoteMessage', () => { // describe('GroupPromoteMessage', () => {
it('can create valid message', () => { // beforeEach(async () => {});
const message = new GroupPromoteMessage({
timestamp: 12345, // it('can create valid message', async () => {
identifier: v4(), // const message = new GroupPromoteMessage({
privateKey: '1234', // timestamp: 12345,
}); // identifier: v4(),
// privateKey: '1234',
const plainText = message.plainTextBuffer(); // });
const decoded = SignalService.Content.decode(plainText);
expect(decoded.dataMessage) // const plainText = message.plainTextBuffer();
.to.have.property('groupMessage') // const decoded = SignalService.Content.decode(plainText);
.to.have.property('promoteMessage') // expect(decoded.dataMessage)
.to.have.deep.property('privateKey', from_hex('1234')); // .to.have.property('groupMessage')
expect(message) // .to.have.property('promoteMessage')
.to.have.property('timestamp') // .to.have.deep.property('privateKey', from_hex('1234'));
.to.be.equal(12345); // expect(message)
}); // .to.have.property('timestamp')
// .to.be.equal(12345);
it('correct ttl', () => { // });
const message = new GroupPromoteMessage({
timestamp: 12345, // it('correct ttl', () => {
identifier: v4(), // const message = new GroupPromoteMessage({
privateKey: '1234', // timestamp: 12345,
}); // identifier: v4(),
// privateKey: '1234',
expect(message.ttl()).to.equal(Constants.TTL_DEFAULT.TTL_MAX); // });
});
// expect(message.ttl()).to.equal(Constants.TTL_DEFAULT.TTL_MAX);
it('has an identifier even if none are provided', () => { // });
const message = new GroupPromoteMessage({
timestamp: 12345, // it('has an identifier even if none are provided', () => {
privateKey: '1234', // const message = new GroupPromoteMessage({
}); // timestamp: 12345,
// privateKey: '1234',
expect(message.identifier).to.not.equal(null, 'identifier cannot be null'); // });
expect(message.identifier).to.not.equal(undefined, 'identifier cannot be undefined');
}); // expect(message.identifier).to.not.equal(null, 'identifier cannot be null');
// expect(message.identifier).to.not.equal(undefined, 'identifier cannot be undefined');
describe('constructor throws on invalid ', () => { // });
it('privateKey empty', () => {
expect(() => { // describe('constructor throws on invalid ', () => {
new GroupPromoteMessage({ // it('privateKey empty', () => {
timestamp: 12345, // expect(() => {
privateKey: null as any, // new GroupPromoteMessage({
}); // timestamp: 12345,
}).throws(); // privateKey: null as any,
}); // });
}); // }).throws();
}); // });
// });
// });

Loading…
Cancel
Save