Skip to content

Commit

Permalink
feat: refactor Connection
Browse files Browse the repository at this point in the history
  • Loading branch information
abretonc7s committed Nov 23, 2023
1 parent af2c10d commit 8f89cd9
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 101 deletions.
15 changes: 1 addition & 14 deletions app/core/SDKConnect/Connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -299,12 +299,10 @@ export class Connection extends EventEmitter2 {
updateOriginatorInfos,
approveHost,
disapprove,
rpcQueueManager: this.rpcQueueManager,
batchRpcManager: this.batchRPCManager,
connection: this,
});
} catch (error) {
Logger.error(error as Error, 'Connection not initialized');
DevLogger.log(`Connection::CLIENTS_READY error`, error);
throw error;
}
},
Expand All @@ -313,21 +311,10 @@ export class Connection extends EventEmitter2 {
this.remote.on(
EventType.MESSAGE,
async (message: CommunicationLayerMessage) => {
if (
!this.backgroundBridge ||
!this.rpcQueueManager ||
!this.batchRPCManager
) {
throw new Error('Connection not initialized');
}

try {
await handleConnectionMessage({
message,
Engine,
backgroundBridge: this.backgroundBridge,
rpcQueueManager: this.rpcQueueManager,
batchRpcManager: this.batchRPCManager,
connection: this,
});
} catch (error) {
Expand Down
24 changes: 5 additions & 19 deletions app/core/SDKConnect/handlers/handleBatchRpcResponse.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,15 @@
import BackgroundBridge from 'app/core/BackgroundBridge/BackgroundBridge';
import BatchRPCManager, { BatchRPCState } from '../BatchRPCManager';
import { BatchRPCState } from '../BatchRPCManager';
import { Connection } from '../Connection';
import DevLogger from '../utils/DevLogger';
import { wait } from '../utils/wait.util';
import handleSendMessage from './handleSendMessage';
import RPCQueueManager from '../RPCQueueManager';

export const handleBatchRpcResponse = async ({
chainRpcs,
msg,
rpcQueueManager,
backgroundBridge,
batchRpcManager,
connection,
}: {
chainRpcs: BatchRPCState;
rpcQueueManager: RPCQueueManager;
backgroundBridge?: BackgroundBridge;
batchRpcManager: BatchRPCManager;
connection: Connection;
msg: any;
}): Promise<void> => {
Expand Down Expand Up @@ -49,12 +41,9 @@ export const handleBatchRpcResponse = async ({
await handleSendMessage({
msg: response,
connection,
backgroundBridge,
batchRpcManager,
rpcQueueManager,
});
// Delete the chain from the chainRPCManager
batchRpcManager.remove(chainRpcs.baseId);
connection.batchRPCManager.remove(chainRpcs.baseId);
} else if (isLastRpc) {
// Respond to the original rpc call with the list of responses append the current response
DevLogger.log(
Expand All @@ -73,15 +62,12 @@ export const handleBatchRpcResponse = async ({
await handleSendMessage({
msg: response,
connection,
backgroundBridge,
batchRpcManager,
rpcQueueManager,
});
// Delete the chain from the chainRPCManager
batchRpcManager.remove(chainRpcs.baseId);
connection.batchRPCManager.remove(chainRpcs.baseId);
} else {
// Save response and send the next rpc method
batchRpcManager.addResponse({
connection.batchRPCManager.addResponse({
id: chainRpcs.baseId,
index: chainRpcs.index,
response: msg?.data?.result,
Expand All @@ -99,7 +85,7 @@ export const handleBatchRpcResponse = async ({
nextRpc.params,
);

backgroundBridge?.onMessage({
connection.backgroundBridge?.onMessage({
name: 'metamask-provider',
data: nextRpc,
origin: 'sdk',
Expand Down
63 changes: 26 additions & 37 deletions app/core/SDKConnect/handlers/handleConnectionMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@ import {
} from '@metamask/sdk-communication-layer';
import { Platform } from 'react-native';
import Logger from '../../../util/Logger';
import BackgroundBridge from '../../BackgroundBridge/BackgroundBridge';
import BatchRPCManager from '../BatchRPCManager';
import { Connection, RPC_METHODS } from '../Connection';
import RPCQueueManager from '../RPCQueueManager';
import { METHODS_TO_REDIRECT } from '../SDKConnect';
import DevLogger from '../utils/DevLogger';
import {
Expand All @@ -23,16 +20,10 @@ import handleSendMessage from './handleSendMessage';
export const handleConnectionMessage = async ({
message,
Engine,
backgroundBridge,
rpcQueueManager,
batchRpcManager,
connection,
}: {
message: CommunicationLayerMessage;
Engine: any;
rpcQueueManager: RPCQueueManager;
backgroundBridge: BackgroundBridge;
batchRpcManager: BatchRPCManager;
connection: Connection;
}) => {
// TODO should probably handle this in a separate EventType.TERMINATE event.
Expand All @@ -48,6 +39,7 @@ export const handleConnectionMessage = async ({

// ignore anything other than RPC methods
if (!message.method || !message.id) {
DevLogger.log(`Connection::onMessage invalid message`, message);
return;
}

Expand Down Expand Up @@ -88,6 +80,7 @@ export const handleConnectionMessage = async ({
).PreferencesController;
const selectedAddress = preferencesController.state.selectedAddress;

DevLogger.log(`Connection::onMessage`, message);
// Wait for bridge to be ready before handling messages.
// It will wait until user accept/reject the connection request.
try {
Expand All @@ -112,10 +105,7 @@ export const handleConnectionMessage = async ({
};
handleSendMessage({
msg,
backgroundBridge,
batchRpcManager,
connection,
rpcQueueManager,
}).catch(() => {
Logger.log(error, `Connection approval failed`);
});
Expand All @@ -125,28 +115,27 @@ export const handleConnectionMessage = async ({

// Special case for metamask_connectSign
if (lcMethod === RPC_METHODS.METAMASK_CONNECTWITH.toLowerCase()) {
// format of the message:
// { method: 'metamask_connectWith', params: [ { method: 'personalSign' | 'eth_sendTransaction', params: any[] ] } ] } }
if (
!(
message?.params &&
Array.isArray(message.params) &&
message.params.length > 0
)
) {
throw new Error('Invalid message format');
}

// Extract the rpc method from the params
const rpc = message.params[0];
message.message = rpc.method;
message.params = rpc.params;
// Replace message.params with the selected address

if (Platform.OS === 'ios') {
// TODO: why does ios (older devices) requires a delay after request is initially approved?
await wait(1000);
}
// TODO activate once refactor is vetted.
// // format of the message:
// // { method: 'metamask_connectWith', params: [ { method: 'personalSign' | 'eth_sendTransaction', params: any[] ] } ] } }
// if (
// !(
// message?.params &&
// Array.isArray(message.params) &&
// message.params.length > 0
// )
// ) {
// throw new Error('Invalid message format');
// }
// // Extract the rpc method from the params
// const rpc = message.params[0];
// message.message = rpc.method;
// message.params = rpc.params;
// // Replace message.params with the selected address
// if (Platform.OS === 'ios') {
// // TODO: why does ios (older devices) requires a delay after request is initially approved?
// await wait(1000);
// }
} else if (lcMethod === RPC_METHODS.METAMASK_CONNECTSIGN.toLowerCase()) {
// Replace with personal_sign
message.method = RPC_METHODS.PERSONAL_SIGN;
Expand Down Expand Up @@ -184,7 +173,7 @@ export const handleConnectionMessage = async ({
}
const rpcs = message.params;
// Add rpcs to the batch manager
batchRpcManager.add({ id: message.id, rpcs });
connection.batchRPCManager.add({ id: message.id, rpcs });

// Send the first rpc method to the background bridge
const rpc = rpcs[0];
Expand All @@ -204,12 +193,12 @@ export const handleConnectionMessage = async ({
return;
}

rpcQueueManager.add({
connection.rpcQueueManager.add({
id: (message.id as string) ?? 'unknown',
method: message.method,
});

backgroundBridge.onMessage({
connection.backgroundBridge?.onMessage({
name: 'metamask-provider',
data: message,
origin: 'sdk',
Expand Down
16 changes: 7 additions & 9 deletions app/core/SDKConnect/handlers/handleConnectionReady.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ import { ApprovalController } from '@metamask/approval-controller';
import { MessageType, OriginatorInfo } from '@metamask/sdk-communication-layer';
import AppConstants from '../../../../app/core/AppConstants';
import Logger from '../../../util/Logger';
import BatchRPCManager from '../BatchRPCManager';
import { Connection } from '../Connection';
import RPCQueueManager from '../RPCQueueManager';
import DevLogger from '../utils/DevLogger';
import checkPermissions from './checkPermissions';
import handleSendMessage from './handleSendMessage';
Expand All @@ -17,17 +15,13 @@ import { setupBridge } from './setupBridge';
export const handleConnectionReady = async ({
originatorInfo,
Engine,
rpcQueueManager,
batchRpcManager,
connection,
approveHost,
disapprove,
updateOriginatorInfos,
}: {
originatorInfo: OriginatorInfo;
Engine: any;
rpcQueueManager: RPCQueueManager;
batchRpcManager: BatchRPCManager;
connection: Connection;
approveHost: ({ host, hostname }: approveHostProps) => void;
disapprove: (channelId: string) => void;
Expand Down Expand Up @@ -58,7 +52,7 @@ export const handleConnectionReady = async ({
}

DevLogger.log(
`SDKConnect::CLIENTS_READY id=${connection.channelId} apiVersion=${apiVersion}`,
`SDKConnect::CLIENTS_READY id=${connection.channelId} apiVersion=${apiVersion} origin=${connection.origin} trigger=${connection.trigger}`,
);
if (!originatorInfo) {
return;
Expand All @@ -69,6 +63,10 @@ export const handleConnectionReady = async ({
channelId: connection.channelId,
originatorInfo,
});
DevLogger.log(
`SDKConnect::CLIENTS_READY originatorInfo updated`,
originatorInfo,
);

if (connection.isReady) {
DevLogger.log(`SDKConnect::CLIENTS_READY already ready`);
Expand Down Expand Up @@ -119,6 +117,7 @@ export const handleConnectionReady = async ({
connection.sendAuthorized(true);
} else {
if (approvalController.get(connection.channelId)) {
DevLogger.log(`SDKConnect::CLIENTS_READY reject previous approval`);
// cleaning previous pending approval
approvalController.reject(
connection.channelId,
Expand All @@ -138,8 +137,6 @@ export const handleConnectionReady = async ({
handleSendMessage({
msg,
connection,
batchRpcManager,
rpcQueueManager,
}).catch((err) => {
Logger.log(err, `SDKConnect:: Connection failed to send otp`);
});
Expand Down Expand Up @@ -181,6 +178,7 @@ export const handleConnectionReady = async ({
connection.sendAuthorized(true);
}

DevLogger.log(`SDKConnect::CLIENTS_READY setup bridge`);
connection.backgroundBridge = setupBridge({
originatorInfo,
connection,
Expand Down
22 changes: 5 additions & 17 deletions app/core/SDKConnect/handlers/handleSendMessage.ts
Original file line number Diff line number Diff line change
@@ -1,52 +1,40 @@
import { Platform } from 'react-native';
import Routes from '../../../../app/constants/navigation/Routes';
import AppConstants from '../../../../app/core/AppConstants';
import BackgroundBridge from '../../BackgroundBridge/BackgroundBridge';
import { Platform } from 'react-native';
import Logger from '../../../util/Logger';
import Device from '../../../util/device';
import { Minimizer } from '../../NativeModules';
import BatchRPCManager from '../BatchRPCManager';
import { Connection } from '../Connection';
import RPCQueueManager from '../RPCQueueManager';
import { METHODS_TO_DELAY } from '../SDKConnect';
import DevLogger from '../utils/DevLogger';
import { wait } from '../utils/wait.util';
import handleBatchRpcResponse from './handleBatchRpcResponse';

export const handleSendMessage = async ({
msg,
rpcQueueManager,
backgroundBridge,
batchRpcManager,
connection,
}: {
msg: any;
rpcQueueManager: RPCQueueManager;
backgroundBridge?: BackgroundBridge;
batchRpcManager: BatchRPCManager;
connection: Connection;
}) => {
const msgId = msg?.data?.id + '';
const needsRedirect = connection.requestsToRedirect[msgId] !== undefined;
const method = rpcQueueManager.getId(msgId);
const method = connection.rpcQueueManager.getId(msgId);

DevLogger.log(`Connection::sendMessage`, msg);
// handle multichain rpc call responses separately
const chainRPCs = batchRpcManager.getById(msgId);
const chainRPCs = connection.batchRPCManager.getById(msgId);
if (chainRPCs) {
await handleBatchRpcResponse({
chainRpcs: chainRPCs,
msg,
connection,
batchRpcManager,
rpcQueueManager,
backgroundBridge,
});
return;
}

if (msgId && method) {
rpcQueueManager.remove(msgId);
connection.rpcQueueManager.remove(msgId);
}

connection.remote.sendMessage(msg).catch((err) => {
Expand All @@ -68,7 +56,7 @@ export const handleSendMessage = async ({

if (connection.origin === AppConstants.DEEPLINKS.ORIGIN_QR_CODE) return;

if (!rpcQueueManager.isEmpty()) {
if (!connection.rpcQueueManager.isEmpty()) {
DevLogger.log(`Connection::sendMessage NOT empty --- skip goBack()`);
return;
}
Expand Down
8 changes: 3 additions & 5 deletions app/core/SDKConnect/handlers/setupBridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import getRpcMethodMiddleware, {

import { OriginatorInfo } from '@metamask/sdk-communication-layer';
import { PROTOCOLS } from '../../../constants/deeplinks';
import DevLogger from '../utils/DevLogger';
import Logger from '../../../util/Logger';
import { Connection } from '../Connection';
import DevLogger from '../utils/DevLogger';
import handleSendMessage from './handleSendMessage';
import Logger from '../../../util/Logger';

export const setupBridge = ({
originatorInfo,
Expand All @@ -30,12 +30,10 @@ export const setupBridge = ({
url: PROTOCOLS.METAMASK + '://' + AppConstants.MM_SDK.SDK_REMOTE_ORIGIN,
isRemoteConn: true,
sendMessage: (msg: any) => {
DevLogger.log(`setupBride::sendMessage`, msg);
handleSendMessage({
msg,
connection,
batchRpcManager: connection.batchRPCManager,
rpcQueueManager: connection.rpcQueueManager,
backgroundBridge: connection.backgroundBridge,
}).catch((err) => {
Logger.error(err, 'Connection::sendMessage failed to send');
});
Expand Down

0 comments on commit 8f89cd9

Please sign in to comment.