Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: added join function in SpaceV2 #703

Merged
merged 2 commits into from
Sep 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 71 additions & 45 deletions packages/restapi/src/lib/spaceV2/SpaceV2.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,33 @@
import Constants, { ENV } from "../constants";
import { VIDEO_CALL_TYPE } from "../payloads/constants";
import { SignerType, VideoCallData, VideoCallStatus } from "../types";
import { produce } from "immer";

export const initVideoCallData: VideoCallData = {
meta: {
chatId: '',
initiator: {
address: '',
signal: null,
},
broadcast: {
livepeerInfo: null,
hostAddress: '',
coHostAddress: '',
},
},
import { join } from "./join";

import Constants, { ENV } from "../constants";
import { EnvOptionsType, SignerType, SpaceDTO, SpaceV2Data, VideoCallStatus } from "../types";
import { pCAIP10ToWallet } from "../helpers";

export const initSpaceInfo: SpaceDTO = {
members: [],
pendingMembers: [],
contractAddressERC20: null,
numberOfERC20: -1,
contractAddressNFT: null,
numberOfNFTTokens: -1,
verificationProof: '',
spaceImage: null,
spaceName: '',
isPublic: false,
spaceDescription: '',
spaceCreator: '',
spaceId: '',
scheduleAt: null,
scheduleEnd: null,
status: null,
inviteeDetails: {}
};

export const initSpaceV2Data: SpaceV2Data = {
spaceInfo: initSpaceInfo,
local: {
stream: null,
audio: null,
Expand All @@ -33,50 +46,67 @@ export const initVideoCallData: VideoCallData = {
],
};

export interface SpaceV2ConstructorType extends EnvOptionsType {
signer: SignerType;
pgpPrivateKey: string;
chainId: number;
address: string;
setSpaceV2Data: (fn: (data: SpaceV2Data) => SpaceV2Data) => void;
}

export class SpaceV2 {
// user, call related info
protected signer: SignerType;
protected chainId: number;
protected pgpPrivateKey: string;
protected env: ENV;
protected callType: VIDEO_CALL_TYPE;

private peerConnections: Map<string, RTCPeerConnection> = new Map();

protected data!: VideoCallData;
setData: (fn: (data: VideoCallData) => VideoCallData) => void;

constructor({
signer,
chainId,
pgpPrivateKey,
env = Constants.ENV.PROD,
callType = VIDEO_CALL_TYPE.PUSH_VIDEO,
setData,
}: {
signer: SignerType;
chainId: number;
pgpPrivateKey: string;
env?: ENV;
callType?: VIDEO_CALL_TYPE;
setData: (fn: (data: VideoCallData) => VideoCallData) => void;
}) {
protected data!: SpaceV2Data;

setSpaceV2Data: (fn: (data: SpaceV2Data) => SpaceV2Data) => void;

constructor(options: SpaceV2ConstructorType) {
const {
signer,
pgpPrivateKey,
address,
chainId,
env = Constants.ENV.PROD,
setSpaceV2Data, // to update the 'spaceData' state maintained by the developer
} = options || {};

this.signer = signer;
this.chainId = chainId;
this.pgpPrivateKey = pgpPrivateKey;
this.env = env;
this.callType = callType;

setData(() => initVideoCallData);
setSpaceV2Data(() => initSpaceV2Data);

// set the state updating function
this.setData = function (fn) {
this.setSpaceV2Data = function (fn) {
// update the react state
setData(fn);
setSpaceV2Data(fn);

// update the class variable
this.data = fn(this.data);
};


// initializing state
// set the local address inside video call 'data'
this.setSpaceV2Data((oldSpaceV2Data) => {
return produce(oldSpaceV2Data, (draft) => {
draft.local.address = pCAIP10ToWallet(address);
});
});

// init the state maintained by the developer
setSpaceV2Data(() => initSpaceV2Data);

// init the spaceSpecificData class variable
this.data = initSpaceV2Data;
}

// Add a connected peer to the space
Expand Down Expand Up @@ -125,15 +155,11 @@ export class SpaceV2 {
*/
}

async join(options: any) {
/**
* will contain logic to handle joining of speakers and listeners based on role
*/
}

async invite(options: any) {
/**
* will contain logic to handle invites made by host to listener
*/
}

public join = join;
}
59 changes: 59 additions & 0 deletions packages/restapi/src/lib/spaceV2/approve.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import {
isValidETHAddress,
} from '../helpers';
import Constants from '../constants';
import {
EnvOptionsType,
SignerType
} from '../types';
import {
approve as approveRequest
} from '../chat/approveRequest';
0xNilesh marked this conversation as resolved.
Show resolved Hide resolved

interface ApproveRequestOptionsType extends EnvOptionsType {
senderAddress: string;
pgpPrivateKey ? : string | null;
status ? : 'Approved';
account ? : string | null;
signer ? : SignerType | null;
}

export const approve = async (
options: ApproveRequestOptionsType
): Promise < string > => {
const {
status = 'Approved',
account = null,
signer = null,
senderAddress, // space id
env = Constants.ENV.PROD,
pgpPrivateKey = null,
} = options || {};

try {

if (account == null && signer == null) {
throw new Error(`At least one from account or signer is necessary!`);
}

if (!isValidETHAddress(senderAddress) && !senderAddress.startsWith("spaces:")) {
throw new Error("Not a valid spaceId or ETH address");
}
return await approveRequest({
status: status,
account: account,
signer: signer,
senderAddress: senderAddress,
env: env,
pgpPrivateKey: pgpPrivateKey
})
} catch (err) {
console.error(
`[Push SDK] - API - Error - API ${approve.name} -: `,
err
);
throw Error(
`[Push SDK] - API - Error - API ${approve.name} -: ${err}`
);
}
};
39 changes: 39 additions & 0 deletions packages/restapi/src/lib/spaceV2/get.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import Constants, {
ENV
} from '../constants';
import {
SpaceDTO
} from '../types';
import {
groupDtoToSpaceDto
} from './../chat/helpers';
import {
getGroup
} from '../chat/getGroup';

export interface GetSpaceType {
spaceId: string,
env ? : ENV
}

export const get = async (
options: GetSpaceType
): Promise < SpaceDTO > => {
const {
spaceId,
env = Constants.ENV.PROD
} = options || {};
try {
if (spaceId == null || spaceId.length == 0) {
throw new Error(`spaceId cannot be null or empty`);
}
const group = await getGroup({
chatId: spaceId,
env
})
return groupDtoToSpaceDto(group);
} catch (err) {
console.error(`[Push SDK] - API - Error - API ${get.name} -: `, err);
throw Error(`[Push SDK] - API - Error - API ${get.name} -: ${err}`);
}
};
5 changes: 5 additions & 0 deletions packages/restapi/src/lib/spaceV2/helpers/getPlainAddress.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const getPlainAddress = (prefixedAddress: string) => {
return prefixedAddress.replace('eip155:', '');
};

export default getPlainAddress;
87 changes: 87 additions & 0 deletions packages/restapi/src/lib/spaceV2/join.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { ChatStatus } from '../types';
import { approve } from './approve';
import { get } from './get';
import getPlainAddress from './helpers/getPlainAddress';
import { SpaceV2 } from './SpaceV2';

export async function join(this: SpaceV2) {
try {
const space = await get({
spaceId: this.data.spaceInfo.spaceId,
env: this.env,
});

if (space.status !== ChatStatus.ACTIVE)
throw new Error('Space not active yet');

// checking what is the current role of caller address

let isSpeaker = false;
let isListener = false;
const localAddress = getPlainAddress(this.data.local.address);
space.members.forEach((member) => {
if (getPlainAddress(member.wallet) === localAddress) {
if (member.isSpeaker) {
isSpeaker = true;
return;
} else {
isListener = true;
return;
}
}
});
let isSpeakerPending = false;
space.pendingMembers.forEach((pendingMember) => {
if (
getPlainAddress(pendingMember.wallet) === localAddress &&
pendingMember.isSpeaker
) {
isSpeakerPending = true;
return;
}
});

console.log(
'ISSPEAKER',
isSpeaker,
'isListener',
isListener,
'isSpeakerPending',
isSpeakerPending
);

// acc to the found role (speaker or listner), executing req logic

// if speaker is pending then approve first or if listner is pending/not found then approve first
if (!isSpeaker && !isListener) {
console.log('CALLING APPROVE');
await approve({
signer: this.signer,
pgpPrivateKey: this.pgpPrivateKey,
senderAddress: this.data.spaceInfo.spaceId,
env: this.env,
});
}

if (isSpeaker || isSpeakerPending) {
// Call joinSpeaker
} else {
// Call joinListener
}

const updatedSpaceInfo = await get({
spaceId: this.data.spaceInfo.spaceId,
env: this.env,
});

console.log('UPDATED SPACE', updatedSpaceInfo);
// update space specific data
this.setSpaceV2Data(() => ({
...this.data,
spaceInfo: updatedSpaceInfo
}));
} catch (err) {
console.error(`[Push SDK] - API - Error - API ${join.name} -: `, err);
throw Error(`[Push SDK] - API - Error - API ${join.name} -: ${err}`);
}
}
11 changes: 11 additions & 0 deletions packages/restapi/src/lib/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,17 @@ export type VideoCallData = {
incoming: PeerData[];
};

export type SpaceV2Data = {
spaceInfo: SpaceDTO;
local: {
stream: IMediaStream;
audio: boolean | null;
video: boolean | null;
address: string;
};
incoming: PeerData[];
}

export type VideoCreateInputOptions = {
video?: boolean;
audio?: boolean;
Expand Down