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

feat: handle connection reject event #1020

Merged
merged 1 commit into from
Sep 18, 2024
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
2 changes: 1 addition & 1 deletion packages/sdk-communication-layer/src/KeyExchange.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { KeyExchange } from './KeyExchange';
import { SocketService } from './SocketService';

jest.mock('./ECIES');
jest.mock('./types/CommunicationLayer'); // Assuming CommunicationLayer is a class that can be mocked.
jest.mock('./SocketService'); // Assuming CommunicationLayer is a class that can be mocked.

describe('KeyExchange', () => {
let keyExchange: KeyExchange;
Expand Down
37 changes: 11 additions & 26 deletions packages/sdk-communication-layer/src/RemoteCommunication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import {
connectToChannel,
disconnect,
initCommunicationLayer,
initSocketService,
originatorSessionConnect,
resume,
} from './services/RemoteCommunication/ConnectionManager';
Expand All @@ -40,6 +40,7 @@
import { WalletInfo } from './types/WalletInfo';
import { logger } from './utils/logger';
import { Channel } from './types/Channel';
import { rejectChannel } from './services/RemoteCommunication/ConnectionManager/rejectChannel';

type MetaMaskMobile = 'metamask-mobile';

Expand Down Expand Up @@ -203,41 +204,18 @@
`[RemoteCommunication: constructor()] protocolVersion=${protocolVersion} relayPersistence=${relayPersistence} isOriginator=${this.state.isOriginator} communicationLayerPreference=${communicationLayerPreference} otherPublicKey=${otherPublicKey} reconnect=${reconnect}`,
);

this.initCommunicationLayer({
initSocketService({
communicationLayerPreference,
otherPublicKey,
reconnect,
ecies,
communicationServerUrl,
instance: this,
});

this.emitServiceStatusEvent({ context: 'constructor' });
}

private initCommunicationLayer({
communicationLayerPreference,
otherPublicKey,
reconnect,
ecies,
communicationServerUrl = DEFAULT_SERVER_URL,
}: Pick<
RemoteCommunicationProps,
| 'communicationLayerPreference'
| 'otherPublicKey'
| 'reconnect'
| 'ecies'
| 'communicationServerUrl'
>) {
return initCommunicationLayer({
communicationLayerPreference,
otherPublicKey,
reconnect,
ecies,
communicationServerUrl,
instance: this,
});
}

/**
* Initialize the connection from the dapp side.
*/
Expand Down Expand Up @@ -454,6 +432,13 @@
return this.state.communicationLayer?.getRPCMethodTracker();
}

reject({ channelId }: { channelId: string }) {
return rejectChannel({

Check warning on line 436 in packages/sdk-communication-layer/src/RemoteCommunication.ts

View check run for this annotation

Codecov / codecov/patch

packages/sdk-communication-layer/src/RemoteCommunication.ts#L435-L436

Added lines #L435 - L436 were not covered by tests
channelId,
state: this.state,
});
}

disconnect(options?: DisconnectOptions) {
return disconnect({
options,
Expand Down
7 changes: 1 addition & 6 deletions packages/sdk-communication-layer/src/SocketService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import {
} from './services/SocketService/ConnectionManager';
import { keyCheck, resetKeys } from './services/SocketService/KeysManager';
import { handleSendMessage } from './services/SocketService/MessageHandlers';
import { CommunicationLayer } from './types/CommunicationLayer';
import { CommunicationLayerMessage } from './types/CommunicationLayerMessage';
import { CommunicationLayerPreference } from './types/CommunicationLayerPreference';
import { ConnectToChannelOptions } from './types/ConnectToChannelOptions';
Expand Down Expand Up @@ -75,11 +74,7 @@ export interface RPCMethodCache {
[id: string]: RPCMethodResult;
}

export type SocketServiceInstanceType = SocketService &
EventEmitter2 &
CommunicationLayer;

export class SocketService extends EventEmitter2 implements CommunicationLayer {
export class SocketService extends EventEmitter2 {
public state: SocketServiceState = {
clientsConnected: false,
/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import { RemoteCommunicationState } from '../../../RemoteCommunication';
import { SocketService } from '../../../SocketService';
import { CommunicationLayer } from '../../../types/CommunicationLayer';
import { StorageManager } from '../../../types/StorageManager';
import { logger } from '../../../utils/logger';
import { generateChannelIdConnect } from './generateChannelIdConnect';
Expand All @@ -27,7 +26,7 @@ describe('generateChannelIdConnect', () => {
})),
isConnected: jest.fn(() => false),
getKeyInfo: jest.fn(() => ({ ecies: { public: 'mockPublicKey' } })),
} as unknown as CommunicationLayer,
} as unknown as SocketService,
ready: false,
channelId: undefined,
sessionDuration: 1000,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { RemoteCommunication } from '../../../RemoteCommunication';
import { SocketService } from '../../../SocketService';
import { CommunicationLayer } from '../../../types/CommunicationLayer';
import { ConnectionStatus } from '../../../types/ConnectionStatus';
import { MessageType } from '../../../types/MessageType';
import { StorageManager } from '../../../types/StorageManager';
Expand All @@ -22,7 +21,7 @@ describe('disconnect', () => {
getKeyInfo: jest.fn(() => ({ keysExchanged: false })),
sendMessage: jest.fn(),
disconnect: jest.fn(),
} as unknown as CommunicationLayer,
} as unknown as SocketService,
debug: false,
channelId: 'sampleChannelId',
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export * from './connectToChannel';
export * from './originatorSessionConnect';
export * from './resume';
export * from './initCommunicationLayer';
export * from './initSocketService';
export * from './disconnect';
export * from './handleAuthorization';
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import { CommunicationLayerPreference } from '../../../types/CommunicationLayerP
import { SocketService } from '../../../SocketService';
import { DEFAULT_SERVER_URL } from '../../../config';
import { ECIESProps } from '../../../ECIES';
import { initCommunicationLayer } from './initCommunicationLayer';
import { initSocketService } from './initSocketService';

jest.mock('../../../SocketService');

describe('initCommunicationLayer', () => {
describe('initSocketService', () => {
let instance: any;

const mockOn = jest.fn();
Expand Down Expand Up @@ -39,15 +39,15 @@ describe('initCommunicationLayer', () => {

it('should throw error for invalid communication protocol', () => {
expect(() => {
initCommunicationLayer({
initSocketService({
communicationLayerPreference: 'UNKNOWN' as CommunicationLayerPreference,
instance,
});
}).toThrow('Invalid communication protocol');
});

it('should initialize socket service for SOCKET communication preference', () => {
initCommunicationLayer({
initSocketService({
communicationLayerPreference: CommunicationLayerPreference.SOCKET,
instance,
});
Expand All @@ -61,7 +61,7 @@ describe('initCommunicationLayer', () => {
});

it('should populate originatorInfo using dappMetadata', () => {
initCommunicationLayer({
initSocketService({
communicationLayerPreference: CommunicationLayerPreference.SOCKET,
instance,
});
Expand All @@ -84,7 +84,7 @@ describe('initCommunicationLayer', () => {
writable: true,
});

initCommunicationLayer({
initSocketService({
communicationLayerPreference: CommunicationLayerPreference.SOCKET,
instance,
});
Expand All @@ -98,7 +98,7 @@ describe('initCommunicationLayer', () => {
});

it('should use DEFAULT_SERVER_URL if communicationServerUrl is not provided', () => {
initCommunicationLayer({
initSocketService({
communicationLayerPreference: CommunicationLayerPreference.SOCKET,
instance,
});
Expand All @@ -116,7 +116,7 @@ describe('initCommunicationLayer', () => {
privateKey: 'mockPrivateKey',
};

initCommunicationLayer({
initSocketService({
communicationLayerPreference: CommunicationLayerPreference.SOCKET,
instance,
ecies: eciesProps,
Expand All @@ -130,7 +130,7 @@ describe('initCommunicationLayer', () => {
});

it('should register event listeners for the communication layer', () => {
initCommunicationLayer({
initSocketService({
communicationLayerPreference: CommunicationLayerPreference.SOCKET,
instance,
});
Expand All @@ -141,7 +141,7 @@ describe('initCommunicationLayer', () => {
it('should pass otherPublicKey to SocketService if provided', () => {
const publicKey = 'samplePublicKey';

initCommunicationLayer({
initSocketService({
communicationLayerPreference: CommunicationLayerPreference.SOCKET,
otherPublicKey: publicKey,
instance,
Expand All @@ -155,7 +155,7 @@ describe('initCommunicationLayer', () => {
});

it('should enable reconnect in SocketService if reconnect is true', () => {
initCommunicationLayer({
initSocketService({
communicationLayerPreference: CommunicationLayerPreference.SOCKET,
reconnect: true,
instance,
Expand All @@ -171,7 +171,7 @@ describe('initCommunicationLayer', () => {
it('should pass logging option to SocketService', () => {
instance.state.logging = true;

initCommunicationLayer({
initSocketService({
communicationLayerPreference: CommunicationLayerPreference.SOCKET,
instance,
});
Expand All @@ -189,7 +189,7 @@ describe('initCommunicationLayer', () => {
throw new Error('Mock Event Listener Error');
});

initCommunicationLayer({
initSocketService({
communicationLayerPreference: CommunicationLayerPreference.SOCKET,
instance,
});
Expand All @@ -205,7 +205,7 @@ describe('initCommunicationLayer', () => {
it('should use provided communicationServerUrl', () => {
const customServerUrl = 'https://custom-server-url.com';

initCommunicationLayer({
initSocketService({
communicationLayerPreference: CommunicationLayerPreference.SOCKET,
communicationServerUrl: customServerUrl,
instance,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ type CommunicationLayerHandledEvents =
* @param instance The current instance of the RemoteCommunication class.
* @throws Error when an invalid communication protocol is specified.
*/
export function initCommunicationLayer({
export function initSocketService({
communicationLayerPreference,
otherPublicKey,
reconnect,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/connectToChannel.ts
import { validate } from 'uuid';
import { RemoteCommunicationState } from '../../../RemoteCommunication';
import { EventType } from '../../../types/EventType';
// import { logger } from '../../../utils/logger';

const logger = {
RemoteCommunication: (message: string, ...args: unknown[]) => {
console.log(message, ...args);

Check warning on line 9 in packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/rejectChannel.ts

View check run for this annotation

Codecov / codecov/patch

packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/rejectChannel.ts#L8-L9

Added lines #L8 - L9 were not covered by tests
},
};

/**
* Rejects a channel connection from the wallet.
*
* @param channelId Unique identifier for the channel.
* @param state Current state of the RemoteCommunication class instance.
* @returns void
*/
export async function rejectChannel({
channelId,
state,
}: {
channelId: string;
state: RemoteCommunicationState;
}): Promise<unknown> {
if (!validate(channelId)) {
logger.RemoteCommunication(

Check warning on line 28 in packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/rejectChannel.ts

View check run for this annotation

Codecov / codecov/patch

packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/rejectChannel.ts#L26-L28

Added lines #L26 - L28 were not covered by tests
`[RemoteCommunication: connectToChannel()] context=${state.context} invalid channel channelId=${channelId}`,
);
throw new Error(`Invalid channel ${channelId}`);

Check warning on line 31 in packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/rejectChannel.ts

View check run for this annotation

Codecov / codecov/patch

packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/rejectChannel.ts#L31

Added line #L31 was not covered by tests
}

if (state.isOriginator) {

Check warning on line 34 in packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/rejectChannel.ts

View check run for this annotation

Codecov / codecov/patch

packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/rejectChannel.ts#L34

Added line #L34 was not covered by tests
// only wallet can reject
logger.RemoteCommunication(

Check warning on line 36 in packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/rejectChannel.ts

View check run for this annotation

Codecov / codecov/patch

packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/rejectChannel.ts#L36

Added line #L36 was not covered by tests
`[RemoteCommunication: reject()] context=${state.context} isOriginator=${state.isOriginator} channelId=${channelId}`,
);
return;

Check warning on line 39 in packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/rejectChannel.ts

View check run for this annotation

Codecov / codecov/patch

packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/rejectChannel.ts#L39

Added line #L39 was not covered by tests
}

const { socket } = state.communicationLayer?.state ?? {};

Check warning on line 42 in packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/rejectChannel.ts

View check run for this annotation

Codecov / codecov/patch

packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/rejectChannel.ts#L42

Added line #L42 was not covered by tests

if (!socket?.connected) {
logger.RemoteCommunication(

Check warning on line 45 in packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/rejectChannel.ts

View check run for this annotation

Codecov / codecov/patch

packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/rejectChannel.ts#L44-L45

Added lines #L44 - L45 were not covered by tests
`[RemoteCommunication: reject()] context=${state.context} socket already connected`,
);
socket?.connect();

Check warning on line 48 in packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/rejectChannel.ts

View check run for this annotation

Codecov / codecov/patch

packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/rejectChannel.ts#L48

Added line #L48 was not covered by tests
}

logger.RemoteCommunication(

Check warning on line 51 in packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/rejectChannel.ts

View check run for this annotation

Codecov / codecov/patch

packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/rejectChannel.ts#L51

Added line #L51 was not covered by tests
`[RemoteCommunication: reject()] context=${state.context} channelId=${channelId} socket=${socket} emitting ${EventType.REJECTED}`,
);

// emit reject event
await new Promise<unknown>((resolve, reject) => {
socket?.emit(

Check warning on line 57 in packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/rejectChannel.ts

View check run for this annotation

Codecov / codecov/patch

packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/rejectChannel.ts#L56-L57

Added lines #L56 - L57 were not covered by tests
EventType.REJECTED,
{
channelId,
},
(error: unknown, response: unknown) => {
logger.RemoteCommunication(
`[RemoteCommunication: reject()] context=${state.context} socket=${socket?.id}`,

Check warning on line 64 in packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/rejectChannel.ts

View check run for this annotation

Codecov / codecov/patch

packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/rejectChannel.ts#L62-L64

Added lines #L62 - L64 were not covered by tests
{ error, response },
);

if (error) {
reject(error);
} else {
resolve(response);

Check warning on line 71 in packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/rejectChannel.ts

View check run for this annotation

Codecov / codecov/patch

packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/rejectChannel.ts#L68-L71

Added lines #L68 - L71 were not covered by tests
}
},
);
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import { v4 as uuidv4 } from 'uuid';
import { SocketService } from '../../../SocketService';
import { EventType } from '../../../types/EventType';
import { logger } from '../../../utils/logger';
import { handleJoinChannelResults } from '../ConnectionManager/handleJoinChannelResult';
import {
handleJoinChannelResults,
JoinChannelResult,
} from '../ConnectionManager/handleJoinChannelResult';
import { Channel } from '../../../types/Channel';
import { setupChannelListeners } from './setupChannelListeners';

Expand Down Expand Up @@ -47,14 +50,7 @@ export async function createChannel(instance: SocketService): Promise<Channel> {
context: `${instance.state.context}createChannel`,
clientType: 'dapp', // only dapp can create channel
},
async (
error: string | null,
result?: {
ready: boolean;
persistence?: boolean;
walletKey?: string;
},
) => {
async (error: string | null, result?: JoinChannelResult) => {
try {
await handleJoinChannelResults(instance, error, result);
resolve();
Expand Down
Loading
Loading