From c5f5b88f06688e7bacb77ced625f1859d89af5ca Mon Sep 17 00:00:00 2001 From: Omri Date: Wed, 13 Sep 2023 11:15:32 +0300 Subject: [PATCH 01/26] feat: extend the time we resume the session without showing OTP --- app/core/SDKConnect/SDKConnect.ts | 92 ++++++++++++++++++++++--------- 1 file changed, 66 insertions(+), 26 deletions(-) diff --git a/app/core/SDKConnect/SDKConnect.ts b/app/core/SDKConnect/SDKConnect.ts index b6aba28e2fb..63ac41d7130 100644 --- a/app/core/SDKConnect/SDKConnect.ts +++ b/app/core/SDKConnect/SDKConnect.ts @@ -84,6 +84,7 @@ export interface ConnectionProps { initialConnection?: boolean; originatorInfo?: OriginatorInfo; validUntil: number; + lastAuthorized: number; // timestamp of last received activity } export interface ConnectedSessions { [id: string]: Connection; @@ -152,6 +153,8 @@ export class Connection extends EventEmitter2 { isResumed = false; initialConnection: boolean; + lastAuthorized: number; + /** * Prevent double sending 'authorized' message. */ @@ -191,6 +194,7 @@ export class Connection extends EventEmitter2 { rpcQueueManager, originatorInfo, approveHost, + lastAuthorized, getApprovedHosts, disapprove, revalidate, @@ -213,6 +217,7 @@ export class Connection extends EventEmitter2 { super(); this.origin = origin; this.channelId = id; + this.lastAuthorized = lastAuthorized; this.reconnect = reconnect || false; this.isResumed = false; this.originatorInfo = originatorInfo; @@ -324,30 +329,49 @@ export class Connection extends EventEmitter2 { !this.initialConnection && this.origin === AppConstants.DEEPLINKS.ORIGIN_QR_CODE ) { - if (approvalController.get(this.channelId)) { - // cleaning previous pending approval - approvalController.reject( - this.channelId, - ethErrors.provider.userRejectedRequest(), - ); - } - this.approvalPromise = undefined; + const currentTime = Date.now(); + const channelWasActiveRecently = + !!this.lastAuthorized && + currentTime - this.lastAuthorized < HOUR_IN_MS; - if (!this.otps) { - this.otps = generateOTP(); - } - this.sendMessage({ - type: MessageType.OTP, - otpAnswer: this.otps?.[0], - }).catch((err) => { - Logger.log(err, `SDKConnect:: Connection failed to send otp`); - }); - // Prevent auto approval if metamask is killed and restarted - disapprove(this.channelId); + if (channelWasActiveRecently) { + this.approvalPromise = undefined; - // Always need to re-approve connection first. - await this.checkPermissions(); - this.sendAuthorized(true); + // Prevent auto approval if metamask is killed and restarted + disapprove(this.channelId); + + // Always need to re-approve connection first. + await this.checkPermissions({ + lastAuthorized: this.lastAuthorized, + }); + + this.sendAuthorized(true); + } else { + if (approvalController.get(this.channelId)) { + // cleaning previous pending approval + approvalController.reject( + this.channelId, + ethErrors.provider.userRejectedRequest(), + ); + } + this.approvalPromise = undefined; + + if (!this.otps) { + this.otps = generateOTP(); + } + this.sendMessage({ + type: MessageType.OTP, + otpAnswer: this.otps?.[0], + }).catch((err) => { + Logger.log(err, `SDKConnect:: Connection failed to send otp`); + }); + // Prevent auto approval if metamask is killed and restarted + disapprove(this.channelId); + + // Always need to re-approve connection first. + await this.checkPermissions(); + this.sendAuthorized(true); + } } else if ( !this.initialConnection && this.origin === AppConstants.DEEPLINKS.ORIGIN_DEEPLINK @@ -424,7 +448,7 @@ export class Connection extends EventEmitter2 { // Wait for bridge to be ready before handling messages. // It will wait until user accept/reject the connection request. try { - await this.checkPermissions(message); + await this.checkPermissions({ _message: message }); if (!this.receivedDisconnect) { await waitForConnectionReadiness({ connection: this }); this.sendAuthorized(); @@ -630,9 +654,16 @@ export class Connection extends EventEmitter2 { * @returns {boolean} true when host is approved or user approved the request. * @throws error if the user reject approval request. */ - private async checkPermissions( - _message?: CommunicationLayerMessage, - ): Promise { + private async checkPermissions({ + _message, + lastAuthorized, + }: { + _message?: CommunicationLayerMessage; + lastAuthorized?: number; + } = {}): Promise { + const channelWasActiveRecently = + !!lastAuthorized && Date.now() - lastAuthorized < HOUR_IN_MS; + // only ask approval if needed const approved = this.isApproved({ channelId: this.channelId, @@ -663,6 +694,10 @@ export class Connection extends EventEmitter2 { this.revalidate({ channelId: this.channelId }); } + if (channelWasActiveRecently) { + return true; + } + const approvalRequest = { origin: this.origin, type: ApprovalTypes.CONNECT_ACCOUNTS, @@ -825,6 +860,7 @@ export class SDKConnect extends EventEmitter2 { otherPublicKey, origin, validUntil: Date.now() + DEFAULT_SESSION_TIMEOUT_MS, + lastAuthorized: Date.now(), }; const initialConnection = this.approvedHosts[id] === undefined; @@ -1251,11 +1287,15 @@ export class SDKConnect extends EventEmitter2 { } private _approveHost({ host }: approveHostProps) { + const channelId = host.replace(AppConstants.MM_SDK.SDK_REMOTE_ORIGIN, ''); if (this.disabledHosts[host]) { // Might be useful for future feature. } else { // Host is approved for 24h. this.approvedHosts[host] = Date.now() + DAY_IN_MS; + if (this.connections[channelId]) { + this.connections[channelId].lastAuthorized = Date.now(); + } // Prevent disabled hosts from being persisted. DefaultPreference.set( AppConstants.MM_SDK.SDK_APPROVEDHOSTS, From 2ca8e3d2b67d519605ff7b3b1c4b88f0e4a4bbaf Mon Sep 17 00:00:00 2001 From: Omri Date: Thu, 14 Sep 2023 14:06:13 +0300 Subject: [PATCH 02/26] feat: cleaning --- app/core/SDKConnect/SDKConnect.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/core/SDKConnect/SDKConnect.ts b/app/core/SDKConnect/SDKConnect.ts index 63ac41d7130..e490c972dba 100644 --- a/app/core/SDKConnect/SDKConnect.ts +++ b/app/core/SDKConnect/SDKConnect.ts @@ -448,7 +448,7 @@ export class Connection extends EventEmitter2 { // Wait for bridge to be ready before handling messages. // It will wait until user accept/reject the connection request. try { - await this.checkPermissions({ _message: message }); + await this.checkPermissions({ message }); if (!this.receivedDisconnect) { await waitForConnectionReadiness({ connection: this }); this.sendAuthorized(); @@ -655,10 +655,10 @@ export class Connection extends EventEmitter2 { * @throws error if the user reject approval request. */ private async checkPermissions({ - _message, + message, lastAuthorized, }: { - _message?: CommunicationLayerMessage; + message?: CommunicationLayerMessage; lastAuthorized?: number; } = {}): Promise { const channelWasActiveRecently = From 72b423cf4b36458e49889701ad889c5989144fc9 Mon Sep 17 00:00:00 2001 From: Omri Date: Thu, 14 Sep 2023 14:12:41 +0300 Subject: [PATCH 03/26] feat: cleaning --- app/core/SDKConnect/SDKConnect.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/core/SDKConnect/SDKConnect.ts b/app/core/SDKConnect/SDKConnect.ts index e490c972dba..1978ff2a102 100644 --- a/app/core/SDKConnect/SDKConnect.ts +++ b/app/core/SDKConnect/SDKConnect.ts @@ -153,6 +153,9 @@ export class Connection extends EventEmitter2 { isResumed = false; initialConnection: boolean; + /* + * Timestamp of last activity, used to check if channel is still active and to prevent showing OTP approval modal too often. + */ lastAuthorized: number; /** From c2220226586ebf79a5b5b6da101464669114e5b2 Mon Sep 17 00:00:00 2001 From: Omri Date: Thu, 14 Sep 2023 16:33:17 +0300 Subject: [PATCH 04/26] feat: cleaning --- app/core/SDKConnect/SDKConnect.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/core/SDKConnect/SDKConnect.ts b/app/core/SDKConnect/SDKConnect.ts index 1978ff2a102..d8a8bc178fd 100644 --- a/app/core/SDKConnect/SDKConnect.ts +++ b/app/core/SDKConnect/SDKConnect.ts @@ -2,7 +2,6 @@ import { StackNavigationProp } from '@react-navigation/stack'; import BackgroundTimer from 'react-native-background-timer'; import DefaultPreference from 'react-native-default-preference'; import AppConstants from '../AppConstants'; - import { TransactionController, WalletDevice, @@ -53,7 +52,6 @@ import { waitForEmptyRPCQueue, waitForKeychainUnlocked, } from './utils/wait.util'; - import { Json } from '@metamask/controller-utils'; import { PROTOCOLS } from '../../constants/deeplinks'; import { Minimizer } from '../NativeModules'; @@ -658,6 +656,7 @@ export class Connection extends EventEmitter2 { * @throws error if the user reject approval request. */ private async checkPermissions({ + // eslint-disable-next-line message, lastAuthorized, }: { From 61b0c8b3301eaf475f28c6ae687ecbff8d609c41 Mon Sep 17 00:00:00 2001 From: Omri Date: Wed, 13 Sep 2023 11:15:32 +0300 Subject: [PATCH 05/26] feat: extend the time we resume the session without showing OTP --- app/core/SDKConnect/SDKConnect.ts | 92 ++++++++++++++++++++++--------- 1 file changed, 66 insertions(+), 26 deletions(-) diff --git a/app/core/SDKConnect/SDKConnect.ts b/app/core/SDKConnect/SDKConnect.ts index b6aba28e2fb..63ac41d7130 100644 --- a/app/core/SDKConnect/SDKConnect.ts +++ b/app/core/SDKConnect/SDKConnect.ts @@ -84,6 +84,7 @@ export interface ConnectionProps { initialConnection?: boolean; originatorInfo?: OriginatorInfo; validUntil: number; + lastAuthorized: number; // timestamp of last received activity } export interface ConnectedSessions { [id: string]: Connection; @@ -152,6 +153,8 @@ export class Connection extends EventEmitter2 { isResumed = false; initialConnection: boolean; + lastAuthorized: number; + /** * Prevent double sending 'authorized' message. */ @@ -191,6 +194,7 @@ export class Connection extends EventEmitter2 { rpcQueueManager, originatorInfo, approveHost, + lastAuthorized, getApprovedHosts, disapprove, revalidate, @@ -213,6 +217,7 @@ export class Connection extends EventEmitter2 { super(); this.origin = origin; this.channelId = id; + this.lastAuthorized = lastAuthorized; this.reconnect = reconnect || false; this.isResumed = false; this.originatorInfo = originatorInfo; @@ -324,30 +329,49 @@ export class Connection extends EventEmitter2 { !this.initialConnection && this.origin === AppConstants.DEEPLINKS.ORIGIN_QR_CODE ) { - if (approvalController.get(this.channelId)) { - // cleaning previous pending approval - approvalController.reject( - this.channelId, - ethErrors.provider.userRejectedRequest(), - ); - } - this.approvalPromise = undefined; + const currentTime = Date.now(); + const channelWasActiveRecently = + !!this.lastAuthorized && + currentTime - this.lastAuthorized < HOUR_IN_MS; - if (!this.otps) { - this.otps = generateOTP(); - } - this.sendMessage({ - type: MessageType.OTP, - otpAnswer: this.otps?.[0], - }).catch((err) => { - Logger.log(err, `SDKConnect:: Connection failed to send otp`); - }); - // Prevent auto approval if metamask is killed and restarted - disapprove(this.channelId); + if (channelWasActiveRecently) { + this.approvalPromise = undefined; - // Always need to re-approve connection first. - await this.checkPermissions(); - this.sendAuthorized(true); + // Prevent auto approval if metamask is killed and restarted + disapprove(this.channelId); + + // Always need to re-approve connection first. + await this.checkPermissions({ + lastAuthorized: this.lastAuthorized, + }); + + this.sendAuthorized(true); + } else { + if (approvalController.get(this.channelId)) { + // cleaning previous pending approval + approvalController.reject( + this.channelId, + ethErrors.provider.userRejectedRequest(), + ); + } + this.approvalPromise = undefined; + + if (!this.otps) { + this.otps = generateOTP(); + } + this.sendMessage({ + type: MessageType.OTP, + otpAnswer: this.otps?.[0], + }).catch((err) => { + Logger.log(err, `SDKConnect:: Connection failed to send otp`); + }); + // Prevent auto approval if metamask is killed and restarted + disapprove(this.channelId); + + // Always need to re-approve connection first. + await this.checkPermissions(); + this.sendAuthorized(true); + } } else if ( !this.initialConnection && this.origin === AppConstants.DEEPLINKS.ORIGIN_DEEPLINK @@ -424,7 +448,7 @@ export class Connection extends EventEmitter2 { // Wait for bridge to be ready before handling messages. // It will wait until user accept/reject the connection request. try { - await this.checkPermissions(message); + await this.checkPermissions({ _message: message }); if (!this.receivedDisconnect) { await waitForConnectionReadiness({ connection: this }); this.sendAuthorized(); @@ -630,9 +654,16 @@ export class Connection extends EventEmitter2 { * @returns {boolean} true when host is approved or user approved the request. * @throws error if the user reject approval request. */ - private async checkPermissions( - _message?: CommunicationLayerMessage, - ): Promise { + private async checkPermissions({ + _message, + lastAuthorized, + }: { + _message?: CommunicationLayerMessage; + lastAuthorized?: number; + } = {}): Promise { + const channelWasActiveRecently = + !!lastAuthorized && Date.now() - lastAuthorized < HOUR_IN_MS; + // only ask approval if needed const approved = this.isApproved({ channelId: this.channelId, @@ -663,6 +694,10 @@ export class Connection extends EventEmitter2 { this.revalidate({ channelId: this.channelId }); } + if (channelWasActiveRecently) { + return true; + } + const approvalRequest = { origin: this.origin, type: ApprovalTypes.CONNECT_ACCOUNTS, @@ -825,6 +860,7 @@ export class SDKConnect extends EventEmitter2 { otherPublicKey, origin, validUntil: Date.now() + DEFAULT_SESSION_TIMEOUT_MS, + lastAuthorized: Date.now(), }; const initialConnection = this.approvedHosts[id] === undefined; @@ -1251,11 +1287,15 @@ export class SDKConnect extends EventEmitter2 { } private _approveHost({ host }: approveHostProps) { + const channelId = host.replace(AppConstants.MM_SDK.SDK_REMOTE_ORIGIN, ''); if (this.disabledHosts[host]) { // Might be useful for future feature. } else { // Host is approved for 24h. this.approvedHosts[host] = Date.now() + DAY_IN_MS; + if (this.connections[channelId]) { + this.connections[channelId].lastAuthorized = Date.now(); + } // Prevent disabled hosts from being persisted. DefaultPreference.set( AppConstants.MM_SDK.SDK_APPROVEDHOSTS, From 33fb7e657f5e2b4c4e74ef6eda6e7912dc403466 Mon Sep 17 00:00:00 2001 From: Omri Date: Thu, 14 Sep 2023 14:06:13 +0300 Subject: [PATCH 06/26] feat: cleaning --- app/core/SDKConnect/SDKConnect.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/core/SDKConnect/SDKConnect.ts b/app/core/SDKConnect/SDKConnect.ts index 63ac41d7130..e490c972dba 100644 --- a/app/core/SDKConnect/SDKConnect.ts +++ b/app/core/SDKConnect/SDKConnect.ts @@ -448,7 +448,7 @@ export class Connection extends EventEmitter2 { // Wait for bridge to be ready before handling messages. // It will wait until user accept/reject the connection request. try { - await this.checkPermissions({ _message: message }); + await this.checkPermissions({ message }); if (!this.receivedDisconnect) { await waitForConnectionReadiness({ connection: this }); this.sendAuthorized(); @@ -655,10 +655,10 @@ export class Connection extends EventEmitter2 { * @throws error if the user reject approval request. */ private async checkPermissions({ - _message, + message, lastAuthorized, }: { - _message?: CommunicationLayerMessage; + message?: CommunicationLayerMessage; lastAuthorized?: number; } = {}): Promise { const channelWasActiveRecently = From 510554a337aebf01ace8ef242c30c114d06acf32 Mon Sep 17 00:00:00 2001 From: Omri Date: Thu, 14 Sep 2023 14:12:41 +0300 Subject: [PATCH 07/26] feat: cleaning --- app/core/SDKConnect/SDKConnect.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/core/SDKConnect/SDKConnect.ts b/app/core/SDKConnect/SDKConnect.ts index e490c972dba..1978ff2a102 100644 --- a/app/core/SDKConnect/SDKConnect.ts +++ b/app/core/SDKConnect/SDKConnect.ts @@ -153,6 +153,9 @@ export class Connection extends EventEmitter2 { isResumed = false; initialConnection: boolean; + /* + * Timestamp of last activity, used to check if channel is still active and to prevent showing OTP approval modal too often. + */ lastAuthorized: number; /** From 2baf8c9b658d8510424853f3b32ac9daa3d4c578 Mon Sep 17 00:00:00 2001 From: Omri Date: Thu, 14 Sep 2023 16:33:17 +0300 Subject: [PATCH 08/26] feat: cleaning --- app/core/SDKConnect/SDKConnect.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/core/SDKConnect/SDKConnect.ts b/app/core/SDKConnect/SDKConnect.ts index 1978ff2a102..d8a8bc178fd 100644 --- a/app/core/SDKConnect/SDKConnect.ts +++ b/app/core/SDKConnect/SDKConnect.ts @@ -2,7 +2,6 @@ import { StackNavigationProp } from '@react-navigation/stack'; import BackgroundTimer from 'react-native-background-timer'; import DefaultPreference from 'react-native-default-preference'; import AppConstants from '../AppConstants'; - import { TransactionController, WalletDevice, @@ -53,7 +52,6 @@ import { waitForEmptyRPCQueue, waitForKeychainUnlocked, } from './utils/wait.util'; - import { Json } from '@metamask/controller-utils'; import { PROTOCOLS } from '../../constants/deeplinks'; import { Minimizer } from '../NativeModules'; @@ -658,6 +656,7 @@ export class Connection extends EventEmitter2 { * @throws error if the user reject approval request. */ private async checkPermissions({ + // eslint-disable-next-line message, lastAuthorized, }: { From c7045ac0bdefccd2a85fa49abd6b132c8cd32c87 Mon Sep 17 00:00:00 2001 From: abretonc7s Date: Mon, 18 Sep 2023 18:50:30 +0800 Subject: [PATCH 09/26] feat: improve sdk init process --- app/components/Nav/App/index.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/app/components/Nav/App/index.js b/app/components/Nav/App/index.js index 82e11794470..563cb2d1341 100644 --- a/app/components/Nav/App/index.js +++ b/app/components/Nav/App/index.js @@ -231,6 +231,8 @@ const App = ({ userLoggedIn }) => { const { colors } = useTheme(); const { toastRef } = useContext(ToastContext); const dispatch = useDispatch(); + const sdkInit = useRef(false); + const [onboarded, setOnboarded] = useState(false); const triggerSetCurrentRoute = (route) => { dispatch(setCurrentRoute(route)); if (route === 'Wallet' || route === 'BrowserView') { @@ -349,17 +351,18 @@ const App = ({ userLoggedIn }) => { initAnalytics(); }, []); - const sdkInit = useRef(false); useEffect(() => { - if (navigator && !sdkInit.current) { - sdkInit.current = true; + if (navigator?.getCurrentRoute && !sdkInit.current && onboarded) { SDKConnect.getInstance() .init({ navigation: navigator }) + .then(() => { + sdkInit.current = true; + }) .catch((err) => { console.error(`Cannot initialize SDKConnect`, err); }); } - }, [navigator]); + }, [navigator, onboarded]); useEffect(() => { if (isWC2Enabled) { @@ -372,6 +375,7 @@ const App = ({ userLoggedIn }) => { useEffect(() => { async function checkExisting() { const existingUser = await AsyncStorage.getItem(EXISTING_USER); + setOnboarded(!!existingUser); const route = !existingUser ? Routes.ONBOARDING.ROOT_NAV : Routes.ONBOARDING.LOGIN; From 47b476a44b46b1b2f65792c82a646c32a86cb6fb Mon Sep 17 00:00:00 2001 From: abretonc7s Date: Mon, 18 Sep 2023 21:37:03 +0800 Subject: [PATCH 10/26] feat: remove webrtc references --- app/core/SDKConnect/SDKConnect.ts | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/app/core/SDKConnect/SDKConnect.ts b/app/core/SDKConnect/SDKConnect.ts index d8a8bc178fd..197fb6ccfcd 100644 --- a/app/core/SDKConnect/SDKConnect.ts +++ b/app/core/SDKConnect/SDKConnect.ts @@ -34,16 +34,6 @@ import { } from '@metamask/sdk-communication-layer'; import { ethErrors } from 'eth-rpc-errors'; import { EventEmitter2 } from 'eventemitter2'; -import { - MediaStream, - MediaStreamTrack, - RTCIceCandidate, - RTCPeerConnection, - RTCSessionDescription, - RTCView, - mediaDevices, - registerGlobals, -} from 'react-native-webrtc'; import Routes from '../../../app/constants/navigation/Routes'; import generateOTP from './utils/generateOTP.util'; import { @@ -63,17 +53,6 @@ export const HOUR_IN_MS = MIN_IN_MS * 60; export const DAY_IN_MS = HOUR_IN_MS * 24; export const DEFAULT_SESSION_TIMEOUT_MS = 7 * DAY_IN_MS; -const webrtc = { - RTCPeerConnection, - RTCIceCandidate, - RTCSessionDescription, - RTCView, - MediaStream, - MediaStreamTrack, - mediaDevices, - registerGlobals, -}; - export interface ConnectionProps { id: string; otherPublicKey: string; @@ -239,7 +218,6 @@ export class Connection extends EventEmitter2 { communicationServerUrl: AppConstants.MM_SDK.SERVER_URL, communicationLayerPreference: CommunicationLayerPreference.SOCKET, otherPublicKey, - webRTCLib: webrtc, reconnect, walletInfo: { type: 'MetaMask Mobile', From 0437636a57a9b4ec74490f4d7a9f4f58e3177b7a Mon Sep 17 00:00:00 2001 From: abretonc7s Date: Tue, 19 Sep 2023 22:02:09 +0800 Subject: [PATCH 11/26] fix: do not remember me setting --- app/core/SDKConnect/SDKConnect.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/core/SDKConnect/SDKConnect.ts b/app/core/SDKConnect/SDKConnect.ts index 197fb6ccfcd..1e112aee7c8 100644 --- a/app/core/SDKConnect/SDKConnect.ts +++ b/app/core/SDKConnect/SDKConnect.ts @@ -892,7 +892,8 @@ export class SDKConnect extends EventEmitter2 { connection.remote.on(EventType.CLIENTS_DISCONNECTED, () => { const host = AppConstants.MM_SDK.SDK_REMOTE_ORIGIN + connection.channelId; // Prevent disabled connection ( if user chose do not remember session ) - if (this.disabledHosts[host] !== undefined) { + const isDisabled = this.disabledHosts[host]; // should be 0 when disabled. + if (isDisabled !== undefined) { this.updateSDKLoadingState({ channelId: connection.channelId, loading: false, @@ -902,6 +903,8 @@ export class SDKConnect extends EventEmitter2 { `SDKConnect::watchConnection can't update SDK loading state`, ); }); + // Force terminate connection since it was disabled (do not remember) + this.removeChannel(connection.channelId, true); } }); @@ -1158,7 +1161,7 @@ export class SDKConnect extends EventEmitter2 { /** * Invalidate a channel/session by preventing future connection to be established. - * Instead of removing the channel, it creates sets the session to timeout on next + * Instead of removing the channel, it sets the session to timeout on next * connection which will remove it while conitnuing current session. * * @param channelId From b992025a9c9333e19a78851faf98280e94abd603 Mon Sep 17 00:00:00 2001 From: abretonc7s Date: Wed, 20 Sep 2023 13:31:11 +0800 Subject: [PATCH 12/26] feat: always update public key from deeplink --- app/core/DeeplinkManager.js | 2 ++ app/core/SDKConnect/SDKConnect.ts | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/app/core/DeeplinkManager.js b/app/core/DeeplinkManager.js index 419355981f7..7fa73bbc8cd 100644 --- a/app/core/DeeplinkManager.js +++ b/app/core/DeeplinkManager.js @@ -257,6 +257,7 @@ class DeeplinkManager { } SDKConnect.getInstance().reconnect({ channelId: params.channelId, + otherPublicKey: params.pubkey, context: 'deeplink (universal)', }); } else { @@ -387,6 +388,7 @@ class DeeplinkManager { } SDKConnect.getInstance().reconnect({ channelId: params.channelId, + otherPublicKey: params.pubkey, context: 'deeplink (metamask)', }); } else { diff --git a/app/core/SDKConnect/SDKConnect.ts b/app/core/SDKConnect/SDKConnect.ts index 1e112aee7c8..e229b3db945 100644 --- a/app/core/SDKConnect/SDKConnect.ts +++ b/app/core/SDKConnect/SDKConnect.ts @@ -226,8 +226,8 @@ export class Connection extends EventEmitter2 { context: AppConstants.MM_SDK.PLATFORM, analytics: true, logging: { - eciesLayer: false, - keyExchangeLayer: false, + eciesLayer: true, + keyExchangeLayer: true, remoteLayer: false, serviceLayer: false, // plaintext: true doesn't do anything unless using custom socket server. @@ -827,6 +827,8 @@ export class SDKConnect extends EventEmitter2 { await this.reconnect({ channelId: id, initialConnection: false, + otherPublicKey: + this.connected[id].remote.getKeyInfo()?.ecies.otherPubKey ?? '', context: 'connectToChannel', }); return; @@ -990,10 +992,12 @@ export class SDKConnect extends EventEmitter2 { async reconnect({ channelId, + otherPublicKey, initialConnection, context, }: { channelId: string; + otherPublicKey: string; context?: string; initialConnection: boolean; }) { @@ -1007,6 +1011,7 @@ export class SDKConnect extends EventEmitter2 { } connecting=${connecting} socketConnected=${socketConnected} existingConnection=${ existingConnection !== undefined }`, + otherPublicKey, ); let interruptReason = ''; @@ -1045,6 +1050,7 @@ export class SDKConnect extends EventEmitter2 { this.connecting[channelId] = true; this.connected[channelId] = new Connection({ ...connection, + otherPublicKey, reconnect: true, initialConnection, rpcQueueManager: this.rpcqueueManager, @@ -1063,7 +1069,9 @@ export class SDKConnect extends EventEmitter2 { withKeyExchange: true, }); this.watchConnection(this.connected[channelId]); - this.connecting[channelId] = false; + const afterConnected = + this.connected[channelId].remote.isConnected() ?? false; + this.connecting[channelId] = !afterConnected; // If not connected, it means it's connecting. this.emit('refresh'); } @@ -1077,6 +1085,7 @@ export class SDKConnect extends EventEmitter2 { if (channelId) { this.reconnect({ channelId, + otherPublicKey: this.connections[channelId].otherPublicKey, initialConnection: false, context: 'reconnectAll', }).catch((err) => { From 2a5eb2ed409036a7b4d592e695ed385213eaac2a Mon Sep 17 00:00:00 2001 From: abretonc7s Date: Wed, 20 Sep 2023 17:25:16 +0800 Subject: [PATCH 13/26] feat: disable logs --- app/core/SDKConnect/SDKConnect.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/core/SDKConnect/SDKConnect.ts b/app/core/SDKConnect/SDKConnect.ts index e229b3db945..776fc952e19 100644 --- a/app/core/SDKConnect/SDKConnect.ts +++ b/app/core/SDKConnect/SDKConnect.ts @@ -226,8 +226,8 @@ export class Connection extends EventEmitter2 { context: AppConstants.MM_SDK.PLATFORM, analytics: true, logging: { - eciesLayer: true, - keyExchangeLayer: true, + eciesLayer: false, + keyExchangeLayer: false, remoteLayer: false, serviceLayer: false, // plaintext: true doesn't do anything unless using custom socket server. From e13eaea75612a0ea545dd75506edd1fdbd88bd7f Mon Sep 17 00:00:00 2001 From: abretonc7s Date: Thu, 21 Sep 2023 11:51:58 +0800 Subject: [PATCH 14/26] feat: update comm layer to 0.7.0 --- package.json | 6 +++--- yarn.lock | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index e1acb2a45f5..1f24a3948a8 100644 --- a/package.json +++ b/package.json @@ -175,7 +175,7 @@ "@metamask/phishing-controller": "^3.0.0", "@metamask/ppom-validator": "^0.3.0", "@metamask/preferences-controller": "^3.0.0", - "@metamask/sdk-communication-layer": "^0.5.0", + "@metamask/sdk-communication-layer": "^0.7.0", "@metamask/signature-controller": "4.0.1", "@metamask/swappable-obj-proxy": "^2.1.0", "@metamask/swaps-controller": "^6.8.0", @@ -368,11 +368,13 @@ "@testing-library/react": "14.0.0", "@testing-library/react-hooks": "^8.0.1", "@testing-library/react-native": "12.1.2", + "@types/crypto-js": "^4.1.1", "@types/enzyme": "^3.10.12", "@types/eth-url-parser": "^1.0.0", "@types/i18n-js": "^3.8.4", "@types/is-url": "^1.2.30", "@types/jest": "^28.1.8", + "@types/lodash": "^4.14.184", "@types/node": "^17.0.21", "@types/qs": "^6.9.7", "@types/react": "^17.0.11", @@ -386,8 +388,6 @@ "@types/react-native-video": "^5.0.14", "@types/redux-mock-store": "^1.0.3", "@types/url-parse": "^1.4.8", - "@types/crypto-js": "^4.1.1", - "@types/lodash": "^4.14.184", "@types/valid-url": "^1.0.4", "@typescript-eslint/eslint-plugin": "^5.57.0", "@typescript-eslint/parser": "^5.57.0", diff --git a/yarn.lock b/yarn.lock index ee86c9ccb6f..f9e3d6f7934 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4182,10 +4182,10 @@ resolved "https://registry.yarnpkg.com/@metamask/safe-event-emitter/-/safe-event-emitter-3.0.0.tgz#8c2b9073fe0722d48693143b0dc8448840daa3bd" integrity sha512-j6Z47VOmVyGMlnKXZmL0fyvWfEYtKWCA9yGZkU3FCsGZUT5lHGmvaV9JA5F2Y+010y7+ROtR3WMXIkvl/nVzqQ== -"@metamask/sdk-communication-layer@^0.5.0": - version "0.5.2" - resolved "https://registry.yarnpkg.com/@metamask/sdk-communication-layer/-/sdk-communication-layer-0.5.2.tgz#fd94d457569b7ee984ad40b1c965d509d569269b" - integrity sha512-k4v2L3E+4nROROT1/3RROSiDLUAKNkJeHsi3nN8l2ao4P0c3JuaREFwfc/u3FtXA3gALKRRGnitn2drG4Xw6rA== +"@metamask/sdk-communication-layer@^0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@metamask/sdk-communication-layer/-/sdk-communication-layer-0.7.0.tgz#b97a341d620bc3a75862b5932c9b62e98d093946" + integrity sha512-jIv/9ujLdqZPfRyAc4Qi865TWk0EhORCDeaa36+r5ED4R84BiUIh1qgyZAW5+Kp4IMlWRjrclGfvrx1exiN3Gw== dependencies: cross-fetch "^3.1.5" date-fns "^2.29.3" From f33c229995dcd051d2252a8de9f3fddd1e9ee112 Mon Sep 17 00:00:00 2001 From: Omri Date: Wed, 13 Sep 2023 11:15:32 +0300 Subject: [PATCH 15/26] feat: extend the time we resume the session without showing OTP --- app/core/SDKConnect/SDKConnect.ts | 92 ++++++++++++++++++++++--------- 1 file changed, 66 insertions(+), 26 deletions(-) diff --git a/app/core/SDKConnect/SDKConnect.ts b/app/core/SDKConnect/SDKConnect.ts index b6aba28e2fb..63ac41d7130 100644 --- a/app/core/SDKConnect/SDKConnect.ts +++ b/app/core/SDKConnect/SDKConnect.ts @@ -84,6 +84,7 @@ export interface ConnectionProps { initialConnection?: boolean; originatorInfo?: OriginatorInfo; validUntil: number; + lastAuthorized: number; // timestamp of last received activity } export interface ConnectedSessions { [id: string]: Connection; @@ -152,6 +153,8 @@ export class Connection extends EventEmitter2 { isResumed = false; initialConnection: boolean; + lastAuthorized: number; + /** * Prevent double sending 'authorized' message. */ @@ -191,6 +194,7 @@ export class Connection extends EventEmitter2 { rpcQueueManager, originatorInfo, approveHost, + lastAuthorized, getApprovedHosts, disapprove, revalidate, @@ -213,6 +217,7 @@ export class Connection extends EventEmitter2 { super(); this.origin = origin; this.channelId = id; + this.lastAuthorized = lastAuthorized; this.reconnect = reconnect || false; this.isResumed = false; this.originatorInfo = originatorInfo; @@ -324,30 +329,49 @@ export class Connection extends EventEmitter2 { !this.initialConnection && this.origin === AppConstants.DEEPLINKS.ORIGIN_QR_CODE ) { - if (approvalController.get(this.channelId)) { - // cleaning previous pending approval - approvalController.reject( - this.channelId, - ethErrors.provider.userRejectedRequest(), - ); - } - this.approvalPromise = undefined; + const currentTime = Date.now(); + const channelWasActiveRecently = + !!this.lastAuthorized && + currentTime - this.lastAuthorized < HOUR_IN_MS; - if (!this.otps) { - this.otps = generateOTP(); - } - this.sendMessage({ - type: MessageType.OTP, - otpAnswer: this.otps?.[0], - }).catch((err) => { - Logger.log(err, `SDKConnect:: Connection failed to send otp`); - }); - // Prevent auto approval if metamask is killed and restarted - disapprove(this.channelId); + if (channelWasActiveRecently) { + this.approvalPromise = undefined; - // Always need to re-approve connection first. - await this.checkPermissions(); - this.sendAuthorized(true); + // Prevent auto approval if metamask is killed and restarted + disapprove(this.channelId); + + // Always need to re-approve connection first. + await this.checkPermissions({ + lastAuthorized: this.lastAuthorized, + }); + + this.sendAuthorized(true); + } else { + if (approvalController.get(this.channelId)) { + // cleaning previous pending approval + approvalController.reject( + this.channelId, + ethErrors.provider.userRejectedRequest(), + ); + } + this.approvalPromise = undefined; + + if (!this.otps) { + this.otps = generateOTP(); + } + this.sendMessage({ + type: MessageType.OTP, + otpAnswer: this.otps?.[0], + }).catch((err) => { + Logger.log(err, `SDKConnect:: Connection failed to send otp`); + }); + // Prevent auto approval if metamask is killed and restarted + disapprove(this.channelId); + + // Always need to re-approve connection first. + await this.checkPermissions(); + this.sendAuthorized(true); + } } else if ( !this.initialConnection && this.origin === AppConstants.DEEPLINKS.ORIGIN_DEEPLINK @@ -424,7 +448,7 @@ export class Connection extends EventEmitter2 { // Wait for bridge to be ready before handling messages. // It will wait until user accept/reject the connection request. try { - await this.checkPermissions(message); + await this.checkPermissions({ _message: message }); if (!this.receivedDisconnect) { await waitForConnectionReadiness({ connection: this }); this.sendAuthorized(); @@ -630,9 +654,16 @@ export class Connection extends EventEmitter2 { * @returns {boolean} true when host is approved or user approved the request. * @throws error if the user reject approval request. */ - private async checkPermissions( - _message?: CommunicationLayerMessage, - ): Promise { + private async checkPermissions({ + _message, + lastAuthorized, + }: { + _message?: CommunicationLayerMessage; + lastAuthorized?: number; + } = {}): Promise { + const channelWasActiveRecently = + !!lastAuthorized && Date.now() - lastAuthorized < HOUR_IN_MS; + // only ask approval if needed const approved = this.isApproved({ channelId: this.channelId, @@ -663,6 +694,10 @@ export class Connection extends EventEmitter2 { this.revalidate({ channelId: this.channelId }); } + if (channelWasActiveRecently) { + return true; + } + const approvalRequest = { origin: this.origin, type: ApprovalTypes.CONNECT_ACCOUNTS, @@ -825,6 +860,7 @@ export class SDKConnect extends EventEmitter2 { otherPublicKey, origin, validUntil: Date.now() + DEFAULT_SESSION_TIMEOUT_MS, + lastAuthorized: Date.now(), }; const initialConnection = this.approvedHosts[id] === undefined; @@ -1251,11 +1287,15 @@ export class SDKConnect extends EventEmitter2 { } private _approveHost({ host }: approveHostProps) { + const channelId = host.replace(AppConstants.MM_SDK.SDK_REMOTE_ORIGIN, ''); if (this.disabledHosts[host]) { // Might be useful for future feature. } else { // Host is approved for 24h. this.approvedHosts[host] = Date.now() + DAY_IN_MS; + if (this.connections[channelId]) { + this.connections[channelId].lastAuthorized = Date.now(); + } // Prevent disabled hosts from being persisted. DefaultPreference.set( AppConstants.MM_SDK.SDK_APPROVEDHOSTS, From 0538d66a421159ffd7c1512d753eb5ba982d2553 Mon Sep 17 00:00:00 2001 From: Omri Date: Thu, 14 Sep 2023 14:06:13 +0300 Subject: [PATCH 16/26] feat: cleaning --- app/core/SDKConnect/SDKConnect.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/core/SDKConnect/SDKConnect.ts b/app/core/SDKConnect/SDKConnect.ts index 63ac41d7130..e490c972dba 100644 --- a/app/core/SDKConnect/SDKConnect.ts +++ b/app/core/SDKConnect/SDKConnect.ts @@ -448,7 +448,7 @@ export class Connection extends EventEmitter2 { // Wait for bridge to be ready before handling messages. // It will wait until user accept/reject the connection request. try { - await this.checkPermissions({ _message: message }); + await this.checkPermissions({ message }); if (!this.receivedDisconnect) { await waitForConnectionReadiness({ connection: this }); this.sendAuthorized(); @@ -655,10 +655,10 @@ export class Connection extends EventEmitter2 { * @throws error if the user reject approval request. */ private async checkPermissions({ - _message, + message, lastAuthorized, }: { - _message?: CommunicationLayerMessage; + message?: CommunicationLayerMessage; lastAuthorized?: number; } = {}): Promise { const channelWasActiveRecently = From 774ce2c7ccb54c5b46480a442b027943d70c8eb1 Mon Sep 17 00:00:00 2001 From: Omri Date: Thu, 14 Sep 2023 14:12:41 +0300 Subject: [PATCH 17/26] feat: cleaning --- app/core/SDKConnect/SDKConnect.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/core/SDKConnect/SDKConnect.ts b/app/core/SDKConnect/SDKConnect.ts index e490c972dba..1978ff2a102 100644 --- a/app/core/SDKConnect/SDKConnect.ts +++ b/app/core/SDKConnect/SDKConnect.ts @@ -153,6 +153,9 @@ export class Connection extends EventEmitter2 { isResumed = false; initialConnection: boolean; + /* + * Timestamp of last activity, used to check if channel is still active and to prevent showing OTP approval modal too often. + */ lastAuthorized: number; /** From e7bd536210710917d17a419d0081559efdf36b84 Mon Sep 17 00:00:00 2001 From: Omri Date: Thu, 14 Sep 2023 16:33:17 +0300 Subject: [PATCH 18/26] feat: cleaning --- app/core/SDKConnect/SDKConnect.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/core/SDKConnect/SDKConnect.ts b/app/core/SDKConnect/SDKConnect.ts index 1978ff2a102..d8a8bc178fd 100644 --- a/app/core/SDKConnect/SDKConnect.ts +++ b/app/core/SDKConnect/SDKConnect.ts @@ -2,7 +2,6 @@ import { StackNavigationProp } from '@react-navigation/stack'; import BackgroundTimer from 'react-native-background-timer'; import DefaultPreference from 'react-native-default-preference'; import AppConstants from '../AppConstants'; - import { TransactionController, WalletDevice, @@ -53,7 +52,6 @@ import { waitForEmptyRPCQueue, waitForKeychainUnlocked, } from './utils/wait.util'; - import { Json } from '@metamask/controller-utils'; import { PROTOCOLS } from '../../constants/deeplinks'; import { Minimizer } from '../NativeModules'; @@ -658,6 +656,7 @@ export class Connection extends EventEmitter2 { * @throws error if the user reject approval request. */ private async checkPermissions({ + // eslint-disable-next-line message, lastAuthorized, }: { From 99ee6a61c8ae7085b7f55583b4cbbbf556edac6b Mon Sep 17 00:00:00 2001 From: abretonc7s Date: Mon, 18 Sep 2023 18:50:30 +0800 Subject: [PATCH 19/26] feat: improve sdk init process --- app/components/Nav/App/index.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/app/components/Nav/App/index.js b/app/components/Nav/App/index.js index 82e11794470..563cb2d1341 100644 --- a/app/components/Nav/App/index.js +++ b/app/components/Nav/App/index.js @@ -231,6 +231,8 @@ const App = ({ userLoggedIn }) => { const { colors } = useTheme(); const { toastRef } = useContext(ToastContext); const dispatch = useDispatch(); + const sdkInit = useRef(false); + const [onboarded, setOnboarded] = useState(false); const triggerSetCurrentRoute = (route) => { dispatch(setCurrentRoute(route)); if (route === 'Wallet' || route === 'BrowserView') { @@ -349,17 +351,18 @@ const App = ({ userLoggedIn }) => { initAnalytics(); }, []); - const sdkInit = useRef(false); useEffect(() => { - if (navigator && !sdkInit.current) { - sdkInit.current = true; + if (navigator?.getCurrentRoute && !sdkInit.current && onboarded) { SDKConnect.getInstance() .init({ navigation: navigator }) + .then(() => { + sdkInit.current = true; + }) .catch((err) => { console.error(`Cannot initialize SDKConnect`, err); }); } - }, [navigator]); + }, [navigator, onboarded]); useEffect(() => { if (isWC2Enabled) { @@ -372,6 +375,7 @@ const App = ({ userLoggedIn }) => { useEffect(() => { async function checkExisting() { const existingUser = await AsyncStorage.getItem(EXISTING_USER); + setOnboarded(!!existingUser); const route = !existingUser ? Routes.ONBOARDING.ROOT_NAV : Routes.ONBOARDING.LOGIN; From bc93b377b8396d367c2dfaf302e119b8bcc09641 Mon Sep 17 00:00:00 2001 From: abretonc7s Date: Mon, 18 Sep 2023 21:37:03 +0800 Subject: [PATCH 20/26] feat: remove webrtc references --- app/core/SDKConnect/SDKConnect.ts | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/app/core/SDKConnect/SDKConnect.ts b/app/core/SDKConnect/SDKConnect.ts index d8a8bc178fd..197fb6ccfcd 100644 --- a/app/core/SDKConnect/SDKConnect.ts +++ b/app/core/SDKConnect/SDKConnect.ts @@ -34,16 +34,6 @@ import { } from '@metamask/sdk-communication-layer'; import { ethErrors } from 'eth-rpc-errors'; import { EventEmitter2 } from 'eventemitter2'; -import { - MediaStream, - MediaStreamTrack, - RTCIceCandidate, - RTCPeerConnection, - RTCSessionDescription, - RTCView, - mediaDevices, - registerGlobals, -} from 'react-native-webrtc'; import Routes from '../../../app/constants/navigation/Routes'; import generateOTP from './utils/generateOTP.util'; import { @@ -63,17 +53,6 @@ export const HOUR_IN_MS = MIN_IN_MS * 60; export const DAY_IN_MS = HOUR_IN_MS * 24; export const DEFAULT_SESSION_TIMEOUT_MS = 7 * DAY_IN_MS; -const webrtc = { - RTCPeerConnection, - RTCIceCandidate, - RTCSessionDescription, - RTCView, - MediaStream, - MediaStreamTrack, - mediaDevices, - registerGlobals, -}; - export interface ConnectionProps { id: string; otherPublicKey: string; @@ -239,7 +218,6 @@ export class Connection extends EventEmitter2 { communicationServerUrl: AppConstants.MM_SDK.SERVER_URL, communicationLayerPreference: CommunicationLayerPreference.SOCKET, otherPublicKey, - webRTCLib: webrtc, reconnect, walletInfo: { type: 'MetaMask Mobile', From 306f55df5f99001a60c2979ef9f2c130b1f0bfc5 Mon Sep 17 00:00:00 2001 From: abretonc7s Date: Tue, 19 Sep 2023 22:02:09 +0800 Subject: [PATCH 21/26] fix: do not remember me setting --- app/core/SDKConnect/SDKConnect.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/core/SDKConnect/SDKConnect.ts b/app/core/SDKConnect/SDKConnect.ts index 197fb6ccfcd..1e112aee7c8 100644 --- a/app/core/SDKConnect/SDKConnect.ts +++ b/app/core/SDKConnect/SDKConnect.ts @@ -892,7 +892,8 @@ export class SDKConnect extends EventEmitter2 { connection.remote.on(EventType.CLIENTS_DISCONNECTED, () => { const host = AppConstants.MM_SDK.SDK_REMOTE_ORIGIN + connection.channelId; // Prevent disabled connection ( if user chose do not remember session ) - if (this.disabledHosts[host] !== undefined) { + const isDisabled = this.disabledHosts[host]; // should be 0 when disabled. + if (isDisabled !== undefined) { this.updateSDKLoadingState({ channelId: connection.channelId, loading: false, @@ -902,6 +903,8 @@ export class SDKConnect extends EventEmitter2 { `SDKConnect::watchConnection can't update SDK loading state`, ); }); + // Force terminate connection since it was disabled (do not remember) + this.removeChannel(connection.channelId, true); } }); @@ -1158,7 +1161,7 @@ export class SDKConnect extends EventEmitter2 { /** * Invalidate a channel/session by preventing future connection to be established. - * Instead of removing the channel, it creates sets the session to timeout on next + * Instead of removing the channel, it sets the session to timeout on next * connection which will remove it while conitnuing current session. * * @param channelId From 29c5ac3e07549997db13d53f7a82907046dc0cc9 Mon Sep 17 00:00:00 2001 From: abretonc7s Date: Wed, 20 Sep 2023 13:31:11 +0800 Subject: [PATCH 22/26] feat: always update public key from deeplink --- app/core/DeeplinkManager.js | 2 ++ app/core/SDKConnect/SDKConnect.ts | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/app/core/DeeplinkManager.js b/app/core/DeeplinkManager.js index 419355981f7..7fa73bbc8cd 100644 --- a/app/core/DeeplinkManager.js +++ b/app/core/DeeplinkManager.js @@ -257,6 +257,7 @@ class DeeplinkManager { } SDKConnect.getInstance().reconnect({ channelId: params.channelId, + otherPublicKey: params.pubkey, context: 'deeplink (universal)', }); } else { @@ -387,6 +388,7 @@ class DeeplinkManager { } SDKConnect.getInstance().reconnect({ channelId: params.channelId, + otherPublicKey: params.pubkey, context: 'deeplink (metamask)', }); } else { diff --git a/app/core/SDKConnect/SDKConnect.ts b/app/core/SDKConnect/SDKConnect.ts index 1e112aee7c8..e229b3db945 100644 --- a/app/core/SDKConnect/SDKConnect.ts +++ b/app/core/SDKConnect/SDKConnect.ts @@ -226,8 +226,8 @@ export class Connection extends EventEmitter2 { context: AppConstants.MM_SDK.PLATFORM, analytics: true, logging: { - eciesLayer: false, - keyExchangeLayer: false, + eciesLayer: true, + keyExchangeLayer: true, remoteLayer: false, serviceLayer: false, // plaintext: true doesn't do anything unless using custom socket server. @@ -827,6 +827,8 @@ export class SDKConnect extends EventEmitter2 { await this.reconnect({ channelId: id, initialConnection: false, + otherPublicKey: + this.connected[id].remote.getKeyInfo()?.ecies.otherPubKey ?? '', context: 'connectToChannel', }); return; @@ -990,10 +992,12 @@ export class SDKConnect extends EventEmitter2 { async reconnect({ channelId, + otherPublicKey, initialConnection, context, }: { channelId: string; + otherPublicKey: string; context?: string; initialConnection: boolean; }) { @@ -1007,6 +1011,7 @@ export class SDKConnect extends EventEmitter2 { } connecting=${connecting} socketConnected=${socketConnected} existingConnection=${ existingConnection !== undefined }`, + otherPublicKey, ); let interruptReason = ''; @@ -1045,6 +1050,7 @@ export class SDKConnect extends EventEmitter2 { this.connecting[channelId] = true; this.connected[channelId] = new Connection({ ...connection, + otherPublicKey, reconnect: true, initialConnection, rpcQueueManager: this.rpcqueueManager, @@ -1063,7 +1069,9 @@ export class SDKConnect extends EventEmitter2 { withKeyExchange: true, }); this.watchConnection(this.connected[channelId]); - this.connecting[channelId] = false; + const afterConnected = + this.connected[channelId].remote.isConnected() ?? false; + this.connecting[channelId] = !afterConnected; // If not connected, it means it's connecting. this.emit('refresh'); } @@ -1077,6 +1085,7 @@ export class SDKConnect extends EventEmitter2 { if (channelId) { this.reconnect({ channelId, + otherPublicKey: this.connections[channelId].otherPublicKey, initialConnection: false, context: 'reconnectAll', }).catch((err) => { From 82713940e580baa0da19fd9fc885141dfff0da13 Mon Sep 17 00:00:00 2001 From: abretonc7s Date: Wed, 20 Sep 2023 17:25:16 +0800 Subject: [PATCH 23/26] feat: disable logs --- app/core/SDKConnect/SDKConnect.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/core/SDKConnect/SDKConnect.ts b/app/core/SDKConnect/SDKConnect.ts index e229b3db945..776fc952e19 100644 --- a/app/core/SDKConnect/SDKConnect.ts +++ b/app/core/SDKConnect/SDKConnect.ts @@ -226,8 +226,8 @@ export class Connection extends EventEmitter2 { context: AppConstants.MM_SDK.PLATFORM, analytics: true, logging: { - eciesLayer: true, - keyExchangeLayer: true, + eciesLayer: false, + keyExchangeLayer: false, remoteLayer: false, serviceLayer: false, // plaintext: true doesn't do anything unless using custom socket server. From d3e36e32b555e221c4bbddc22a29223454d4ffb6 Mon Sep 17 00:00:00 2001 From: abretonc7s Date: Thu, 21 Sep 2023 11:51:58 +0800 Subject: [PATCH 24/26] feat: update comm layer to 0.7.0 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index f5276ea6562..fb28638243b 100644 --- a/package.json +++ b/package.json @@ -178,7 +178,7 @@ "@metamask/phishing-controller": "^3.0.0", "@metamask/ppom-validator": "^0.5.0", "@metamask/preferences-controller": "^3.0.0", - "@metamask/sdk-communication-layer": "^0.5.0", + "@metamask/sdk-communication-layer": "^0.7.0", "@metamask/signature-controller": "4.0.1", "@metamask/swappable-obj-proxy": "^2.1.0", "@metamask/swaps-controller": "^6.8.0", diff --git a/yarn.lock b/yarn.lock index 020d08970b1..c2db6f87c24 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4589,10 +4589,10 @@ resolved "https://registry.yarnpkg.com/@metamask/safe-event-emitter/-/safe-event-emitter-3.0.0.tgz#8c2b9073fe0722d48693143b0dc8448840daa3bd" integrity sha512-j6Z47VOmVyGMlnKXZmL0fyvWfEYtKWCA9yGZkU3FCsGZUT5lHGmvaV9JA5F2Y+010y7+ROtR3WMXIkvl/nVzqQ== -"@metamask/sdk-communication-layer@^0.5.0": - version "0.5.2" - resolved "https://registry.yarnpkg.com/@metamask/sdk-communication-layer/-/sdk-communication-layer-0.5.2.tgz#fd94d457569b7ee984ad40b1c965d509d569269b" - integrity sha512-k4v2L3E+4nROROT1/3RROSiDLUAKNkJeHsi3nN8l2ao4P0c3JuaREFwfc/u3FtXA3gALKRRGnitn2drG4Xw6rA== +"@metamask/sdk-communication-layer@^0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@metamask/sdk-communication-layer/-/sdk-communication-layer-0.7.0.tgz#b97a341d620bc3a75862b5932c9b62e98d093946" + integrity sha512-jIv/9ujLdqZPfRyAc4Qi865TWk0EhORCDeaa36+r5ED4R84BiUIh1qgyZAW5+Kp4IMlWRjrclGfvrx1exiN3Gw== dependencies: cross-fetch "^3.1.5" date-fns "^2.29.3" From 54f645cbfe3078a00ca2c44edf67b3d8c0cf6f6a Mon Sep 17 00:00:00 2001 From: Omri Date: Fri, 22 Sep 2023 11:50:15 +0300 Subject: [PATCH 25/26] chore: reset the state 'lastAuthorized' after OTP approved --- app/core/SDKConnect/SDKConnect.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/app/core/SDKConnect/SDKConnect.ts b/app/core/SDKConnect/SDKConnect.ts index 776fc952e19..a1f91e63c99 100644 --- a/app/core/SDKConnect/SDKConnect.ts +++ b/app/core/SDKConnect/SDKConnect.ts @@ -350,6 +350,7 @@ export class Connection extends EventEmitter2 { // Always need to re-approve connection first. await this.checkPermissions(); this.sendAuthorized(true); + this.lastAuthorized = Date.now(); } } else if ( !this.initialConnection && From 8a4e538603d3949b068f7d94d35f4bb330b079a9 Mon Sep 17 00:00:00 2001 From: Christopher Ferreira Date: Tue, 26 Sep 2023 10:07:23 +0100 Subject: [PATCH 26/26] building bitrise --- android/app/build.gradle | 4 ++-- bitrise.yml | 10 +++++----- ios/MetaMask.xcodeproj/project.pbxproj | 16 ++++++++-------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 931328d02e2..9b804ffd6f8 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -137,8 +137,8 @@ android { applicationId "io.metamask" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1171 - versionName "7.7.0" + versionCode 1173 + versionName "7.8.0" testBuildType System.getProperty('testBuildType', 'debug') missingDimensionStrategy 'react-native-camera', 'general' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/bitrise.yml b/bitrise.yml index e3b1df6404b..1993bdded1a 100644 --- a/bitrise.yml +++ b/bitrise.yml @@ -343,7 +343,7 @@ workflows: inputs: - deploy_path: $BITRISE_DEPLOY_DIR - is_compress: true - - zip_name: "E2E_Android_Failure_Screenshots" + - zip_name: 'E2E_Android_Failure_Screenshots' meta: bitrise.io: @@ -407,7 +407,7 @@ workflows: inputs: - deploy_path: $BITRISE_DEPLOY_DIR - is_compress: true - - zip_name: "E2E_IOS_Failure_Screenshots" + - zip_name: 'E2E_IOS_Failure_Screenshots' start_e2e_tests: steps: - build-router-start@0: @@ -765,7 +765,7 @@ workflows: inputs: - deploy_path: browserstack_uploaded_apps.json title: Bitrise Deploy Browserstack Uploaded Apps - + app: envs: - opts: @@ -800,10 +800,10 @@ app: PROJECT_LOCATION_IOS: ios - opts: is_expand: false - VERSION_NAME: 7.7.0 + VERSION_NAME: 7.8.0 - opts: is_expand: false - VERSION_NUMBER: 1171 + VERSION_NUMBER: 1173 - opts: is_expand: false ANDROID_APK_LINK: '' diff --git a/ios/MetaMask.xcodeproj/project.pbxproj b/ios/MetaMask.xcodeproj/project.pbxproj index fc86561f500..821e6fa446d 100644 --- a/ios/MetaMask.xcodeproj/project.pbxproj +++ b/ios/MetaMask.xcodeproj/project.pbxproj @@ -1039,7 +1039,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1171; + CURRENT_PROJECT_VERSION = 1173; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -1073,7 +1073,7 @@ ); LIBRARY_SEARCH_PATHS = "$(inherited)"; LLVM_LTO = YES; - MARKETING_VERSION = 7.7.0; + MARKETING_VERSION = 7.8.0; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ( "$(inherited)", @@ -1105,7 +1105,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1171; + CURRENT_PROJECT_VERSION = 1173; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 48XVW22RCG; @@ -1139,7 +1139,7 @@ ); LIBRARY_SEARCH_PATHS = "$(inherited)"; LLVM_LTO = YES; - MARKETING_VERSION = 7.7.0; + MARKETING_VERSION = 7.8.0; ONLY_ACTIVE_ARCH = NO; OTHER_CFLAGS = ( "$(inherited)", @@ -1251,7 +1251,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1171; + CURRENT_PROJECT_VERSION = 1173; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -1288,7 +1288,7 @@ "\"$(SRCROOT)/MetaMask/System/Library/Frameworks\"", ); LLVM_LTO = YES; - MARKETING_VERSION = 7.7.0; + MARKETING_VERSION = 7.8.0; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ( "$(inherited)", @@ -1320,7 +1320,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1171; + CURRENT_PROJECT_VERSION = 1173; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 48XVW22RCG; @@ -1357,7 +1357,7 @@ "\"$(SRCROOT)/MetaMask/System/Library/Frameworks\"", ); LLVM_LTO = YES; - MARKETING_VERSION = 7.7.0; + MARKETING_VERSION = 7.8.0; ONLY_ACTIVE_ARCH = NO; OTHER_CFLAGS = ( "$(inherited)",