Skip to content

Commit

Permalink
feat: revert socket server changes (#985)
Browse files Browse the repository at this point in the history
* feat: revert socket changes

* feat: environmentalize correctly

* feat: restore channel cleanup

* feat: restore initial values
  • Loading branch information
abretonc7s authored Aug 20, 2024
1 parent 9b52a5b commit e96b349
Show file tree
Hide file tree
Showing 73 changed files with 1,350 additions and 595 deletions.
2 changes: 1 addition & 1 deletion packages/devnext/.env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ NEXT_PUBLIC_COMM_SERVER_URL=http://192.168.50.114:4000/
NEXT_PUBLIC_SIMPLE_CONTRACT_ADDRESS='0x13A0A1998B968CFbb780500c83A74F0137193703'
# Replace with your Ganache RPC URL if different
NEXT_PUBLIC_PROVIDER_RPCURL='http://localhost:8545'
# NEXT_PUBLIC_INFURA_API_KEY='' # add your own api key
# NEXT_PUBLIC_INFURA_API_KEY=
8 changes: 8 additions & 0 deletions packages/devnext/src/pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const WithSDKConfig = ({ children }: { children: React.ReactNode }) => {
socketServer,
infuraAPIKey,
useDeeplink,
_experimentalDeeplinkProtocol,
checkInstallationImmediately,
} = useSDKConfig();

Expand All @@ -36,6 +37,7 @@ const WithSDKConfig = ({ children }: { children: React.ReactNode }) => {
'0x539': process.env.NEXT_PUBLIC_PROVIDER_RPCURL ?? '',
},
extensionOnly: false,
_experimentalDeeplinkProtocol,
logging: {
developerMode: true,
remoteLayer: true,
Expand All @@ -51,6 +53,11 @@ const WithSDKConfig = ({ children }: { children: React.ReactNode }) => {
dappMetadata: {
name: 'DevNext',
url: window.location.protocol + '//' + window.location.host,
iconUrl:
window.location.protocol +
'//' +
window.location.host +
'/favicon.ico',
},
i18nOptions: {
enabled: true,
Expand All @@ -68,6 +75,7 @@ export default function App({ Component, pageProps }: AppProps) {
<SDKConfigProvider
initialSocketServer={process.env.NEXT_PUBLIC_COMM_SERVER_URL}
initialInfuraKey={process.env.NEXT_PUBLIC_INFURA_API_KEY}
_initialExperimentalDeeplinkProtocol={false}
debug={true}
>
<WithSDKConfig>
Expand Down
10 changes: 8 additions & 2 deletions packages/devreactnative/src/StorageManagerRN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,11 @@ export class StorageManagerRN implements StorageManager {
console.debug('StorageManagerRN::peristChannelConfig() temp find', temp);
}

public async getPersistedChannelConfig(): Promise<ChannelConfig | undefined> {
public async getPersistedChannelConfig(options?: {
context?: string;
}): Promise<ChannelConfig | undefined> {
let payload;
const {context} = options || {};

if (this.debug) {
console.debug(
Expand All @@ -54,7 +57,10 @@ export class StorageManagerRN implements StorageManager {
}

if (this.debug) {
console.debug('StorageManagerRN::getPersistedChannelConfig()', payload);
console.debug(
`StorageManagerRN::getPersistedChannelConfig() context=${context}`,
payload,
);
}

if (!payload) {
Expand Down
297 changes: 297 additions & 0 deletions packages/sdk-communication-layer/e2e/sdk-comm.e2e.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,297 @@
import { describe, expect, it } from '@jest/globals';
import { v4 as uuidv4 } from 'uuid';
import {
CommunicationLayerPreference,
RemoteCommunicationProps,
EventType,
MessageType,
RemoteCommunication
} from '../src';

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const waitForEvent = (
remoteConn: RemoteCommunication,
event: string,
): Promise<unknown> => {
return new Promise((resolve) => {
remoteConn.on(event, (message: unknown) => {
console.log(`Received event ${event}`, message);
return resolve(message);
});
});
};


const sleep = (ms: number) => {
return new Promise((resolve) => {
const ref = setTimeout(resolve, ms);
return () => {
clearTimeout(ref);
};
});
};

export const waitForCondition = async ({
fn,
context,
waitTime = 1000,
}: {
fn: () => boolean;
waitTime?: number;
context?: string;
}) => {
let i = 0;
while (!fn()) {
i += 1;
if (i > 5 && i % 10 === 0) {
console.log(`Waiting for fn context=${context} to return true`);
}
await sleep(waitTime);
}
};

export const getClient = ({ type, options }: { type: 'dApp' | 'wallet', options: Partial<RemoteCommunicationProps> }) => {
const client = new RemoteCommunication({
context: `${type}-jest`,
communicationLayerPreference: CommunicationLayerPreference.SOCKET,
platformType: 'metamask-mobile',
protocolVersion: 2,
reconnect: false,
relayPersistence: true,
analytics: true,
logging: {
eciesLayer: true,
keyExchangeLayer: true,
remoteLayer: true,
serviceLayer: true,
plaintext: true,
},
...options, // overwrite default options
});
return client
}

describe('SDK Communication Layer', () => {
let clientsReady = false;
const communicationServerUrl = 'https://metamask-sdk.api.cx.metamask.io/';

describe('Protocol V1', () => {
it('should establish client/mobile connection through comm server with remote key exchange', async () => {
const communicationLayerPreference = CommunicationLayerPreference.SOCKET;

const remote = new RemoteCommunication({
communicationLayerPreference,
platformType: 'metamask-mobile',
communicationServerUrl,
dappMetadata: {
name: 'jest dapp',
url: 'http://somehwere.com',
},
context: 'initiator',
analytics: true,
logging: {
eciesLayer: true,
keyExchangeLayer: true,
remoteLayer: true,
serviceLayer: true,
plaintext: true,
},
});

// Generate new channel id and connect to it
const { channelId, pubKey } = await remote.generateChannelIdConnect();

remote.on(EventType.CLIENTS_READY, () => {
clientsReady = true;
});

const mmRemote = new RemoteCommunication({
communicationLayerPreference,
platformType: 'metamask-mobile',
otherPublicKey: pubKey,
communicationServerUrl,
analytics: true,
dappMetadata: {
name: 'SDK-COMM_TEST',
url: 'http://somewhere.com',
},
logging: {
eciesLayer: true,
keyExchangeLayer: true,
remoteLayer: true,
serviceLayer: true,
plaintext: true,
},
context: 'mm',
});

mmRemote.connectToChannel({ channelId });

await waitForCondition({ fn: () => clientsReady, context: 'clientsReady', waitTime: 1000 });

mmRemote.disconnect();
remote.disconnect();

expect(clientsReady).toBe(true);
});
})

describe('Protocol V2', () => {
it('should establish key/exchange with mobile connected first', async () => {
const channelId = uuidv4();

const dAppClient = getClient({
type: 'wallet', options: {
communicationServerUrl
}
})
const clientPublicKey = dAppClient.getKeyInfo()?.ecies.public ?? '';

const walletClient = getClient({ type: 'dApp', options: { communicationServerUrl, otherPublicKey: clientPublicKey } });

await dAppClient.connectToChannel({ channelId });
await walletClient.connectToChannel({ channelId, authorized: true });

// Send message from sdk to wallet
await dAppClient.sendMessage({
params: ['world'],
method: 'hello',
})

// wait for receicing message from dApp
await waitForEvent(walletClient, 'message');
// sleep(5000); // need times for ack the message

walletClient.disconnect();
dAppClient.disconnect();

expect(true).toBe(true);
});

it('should establish key/exchange with dApp connected first', async () => {
const channelId = uuidv4();

const dAppClient = getClient({
type: 'wallet', options: {
communicationServerUrl
}
})
await dAppClient.connectToChannel({ channelId });
const clientPublicKey = dAppClient.getKeyInfo()?.ecies.public ?? '';

const walletClient = getClient({ type: 'dApp', options: { communicationServerUrl, otherPublicKey: clientPublicKey } });
await walletClient.connectToChannel({ channelId, authorized: true });

await waitForCondition({
fn: () => {
return dAppClient.isAuthorized()
},
context: 'wait_auth',
waitTime: 1000,
})

// Send message from sdk to wallet
await dAppClient.sendMessage({
params: ['world'],
method: 'hello',
})

// wait for receicing message from dApp
await waitForEvent(walletClient, 'message');

walletClient.disconnect();
dAppClient.disconnect();

expect(true).toBe(true);
});

it('should establish key/exchange with 1side connected at anytime', async () => {
const channelId = uuidv4();

const dAppClient = getClient({
type: 'wallet', options: {
communicationServerUrl
}
})
await dAppClient.connectToChannel({ channelId });
const clientPublicKey = dAppClient.getKeyInfo()?.ecies.public ?? '';

const walletClient = getClient({ type: 'dApp', options: { communicationServerUrl, otherPublicKey: clientPublicKey } });

await walletClient.connectToChannel({ channelId, authorized: true });
await walletClient.sendMessage({
type: MessageType.WALLET_INIT,
data: {
chainId: '0x1',
accounts: ['0x123'],
}
})
walletClient.disconnect();

await dAppClient.connectToChannel({ channelId });
// Send message from sdk to wallet
await dAppClient.sendMessage({
params: ['world'],
method: 'hello',
})
dAppClient.disconnect();

// Reconnect and see if it receives the message
await walletClient.connectToChannel({ channelId, authorized: true });
// wait for receicing message from dApp
await waitForEvent(walletClient, 'message');

walletClient.disconnect();
dAppClient.disconnect();

expect(true).toBe(true);
});

it('should reconnect to an existing channel with persistence', async () => {
const channelId = uuidv4();

const dAppClient = getClient({
type: 'wallet', options: {
communicationServerUrl
}
})
await dAppClient.connectToChannel({ channelId });
const clientPublicKey = dAppClient.getKeyInfo()?.ecies.public ?? '';

const walletClient = getClient({ type: 'dApp', options: { communicationServerUrl, otherPublicKey: clientPublicKey } });

await walletClient.connectToChannel({ channelId, authorized: true });

dAppClient.disconnect();

await walletClient.sendMessage({
type: MessageType.WALLET_INIT,
data: {
chainId: '0x1',
accounts: ['0x123'],
}
})

// dApp reconnect
await dAppClient.connectToChannel({ channelId });

// wait for receicing message from wakket
await waitForEvent(dAppClient, 'message');

// Send message from sdk to wallet and disconnect, wallet should receive message anyway
await dAppClient.sendMessage({
params: ['world'],
method: 'hello',
})
// wait for receicing message from dApp
await waitForEvent(walletClient, 'message');

await sleep(1000);
walletClient.disconnect();
dAppClient.disconnect();

expect(true).toBe(true);
});
})
});

Loading

0 comments on commit e96b349

Please sign in to comment.