Skip to content

Commit

Permalink
chore: transfer 'DeeplinkManager' file to TS
Browse files Browse the repository at this point in the history
  • Loading branch information
omridan159 committed Oct 24, 2023
1 parent d2623c8 commit a34931a
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 50 deletions.
5 changes: 5 additions & 0 deletions app/constants/deeplinks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@ export const PREFIXES = {
[ACTIONS.DAPP]: 'https://',
[ACTIONS.SEND]: 'ethereum:',
[ACTIONS.APPROVE]: 'ethereum:',
[ACTIONS.PAYMENT]: '',
[ACTIONS.FOCUS]: '',
[ACTIONS.WC]: '',
[ACTIONS.CONNECT]: '',
[ACTIONS.ANDROID_SDK]: '',
[ACTIONS.BUY_CRYPTO]: '',
[ACTIONS.EMPTY]: '',
METAMASK: 'metamask://',
};
154 changes: 104 additions & 50 deletions app/core/DeeplinkManager.js → app/core/DeeplinkManager.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,58 @@
'use strict';

import URL from 'url-parse';
import { WalletDevice } from '@metamask/transaction-controller';
import { NavigationProp, ParamListBase } from '@react-navigation/native';
import { StackNavigationProp } from '@react-navigation/stack';
import { RootState } from 'app/reducers';
import { ParseOutput, parse } from 'eth-url-parser';
import qs from 'qs';
import { InteractionManager, Alert } from 'react-native';
import { parse } from 'eth-url-parser';
import AppConstants from './AppConstants';
import Engine from './Engine';
import { generateApproveData } from '../util/transactions';
import { NETWORK_ERROR_MISSING_NETWORK_ID } from '../constants/error';
import { Alert, InteractionManager } from 'react-native';
import { AnyAction, Dispatch, Store } from 'redux';
import UrlParser from 'url-parse';
import { strings } from '../../locales/i18n';
import { getNetworkTypeById, handleNetworkSwitch } from '../util/networks';
import { WalletDevice } from '@metamask/transaction-controller';
import NotificationManager from '../core/NotificationManager';
import { showAlert } from '../actions/alert';
import { isNetworkBuySupported } from '../components/UI/Ramp/utils';
import {
ACTIONS,
ETH_ACTIONS,
PROTOCOLS,
PREFIXES,
PROTOCOLS,
} from '../constants/deeplinks';
import Logger from '../util/Logger';
import { showAlert } from '../actions/alert';
import SDKConnect from '../core/SDKConnect/SDKConnect';
import { NetworkSwitchErrorType } from '../constants/error';
import Routes from '../constants/navigation/Routes';
import { getAddress } from '../util/address';
import WC2Manager from './WalletConnect/WalletConnectV2';
import { chainIdSelector, getRampNetworks } from '../reducers/fiatOrders';
import { isNetworkBuySupported } from '../components/UI/Ramp/utils';
import Logger from '../util/Logger';
import { getAddress } from '../util/address';
import { getNetworkTypeById, handleNetworkSwitch } from '../util/networks';
import { generateApproveData } from '../util/transactions';
import AppConstants from './AppConstants';
import Engine from './Engine';
import { Minimizer } from './NativeModules';
import NotificationManager from './NotificationManager';
import SDKConnect, {
DEFAULT_SESSION_TIMEOUT_MS,
} from './SDKConnect/SDKConnect';
import DevLogger from './SDKConnect/utils/DevLogger';
import WC2Manager from './WalletConnect/WalletConnectV2';

class DeeplinkManager {
constructor({ navigation, dispatch }) {
public navigation: NavigationProp<ParamListBase>;
public pendingDeeplink: string | null;
public dispatch: Dispatch<any>;

constructor({
navigation,
dispatch,
}: {
navigation: StackNavigationProp<{
[route: string]: { screen: string };
}>;
dispatch: Store<any, AnyAction>['dispatch'];
}) {
this.navigation = navigation;
this.pendingDeeplink = null;
this.dispatch = dispatch;
}

setDeeplink = (url) => (this.pendingDeeplink = url);
setDeeplink = (url: string) => (this.pendingDeeplink = url);

getPendingDeeplink = () => this.pendingDeeplink;

Expand All @@ -47,8 +63,8 @@ class DeeplinkManager {
*
* @param switchToChainId - Corresponding chain id for new network
*/
_handleNetworkSwitch = (switchToChainId) => {
const networkName = handleNetworkSwitch(switchToChainId);
_handleNetworkSwitch = (switchToChainId: `${number}` | undefined) => {
const networkName = handleNetworkSwitch(switchToChainId as string);

if (!networkName) return;

Expand All @@ -62,12 +78,8 @@ class DeeplinkManager {
);
};

_approveTransaction = async (ethUrl, origin) => {
const {
parameters: { address, uint256 },
target_address,
chain_id,
} = ethUrl;
_approveTransaction = async (ethUrl: ParseOutput, origin: string) => {
const { parameters, target_address, chain_id } = ethUrl;
const { TransactionController, PreferencesController, NetworkController } =
Engine.context;

Expand All @@ -76,7 +88,7 @@ class DeeplinkManager {
NetworkController.setProviderType(newNetworkType);
}

const uint256Number = Number(uint256);
const uint256Number = Number(parameters?.uint256);

if (Number.isNaN(uint256Number))
throw new Error('The parameter uint256 should be a number');
Expand All @@ -85,7 +97,10 @@ class DeeplinkManager {

const value = uint256Number.toString(16);

const spenderAddress = await getAddress(address, chain_id);
const spenderAddress = await getAddress(
parameters?.address as string,
chain_id as string,
);
if (!spenderAddress) {
NotificationManager.showSimpleNotification({
status: 'simple_notification_rejected',
Expand All @@ -109,8 +124,8 @@ class DeeplinkManager {
});
};

async _handleEthereumUrl(url, origin) {
let ethUrl = '';
async _handleEthereumUrl(url: string, origin: string) {
let ethUrl: ParseOutput;
try {
ethUrl = parse(url);
} catch (e) {
Expand Down Expand Up @@ -152,10 +167,10 @@ class DeeplinkManager {
}
}
}
} catch (e) {
} catch (e: any) {
let alertMessage;
switch (e.message) {
case NETWORK_ERROR_MISSING_NETWORK_ID:
case NetworkSwitchErrorType.missingNetworkId:
alertMessage = strings('send.network_missing_id');
break;
default:
Expand All @@ -167,7 +182,7 @@ class DeeplinkManager {
}
}

_handleBrowserUrl(url, callback) {
_handleBrowserUrl(url: string, callback: (url: string) => void) {
InteractionManager.runAfterInteractions(() => {
if (callback) {
callback(url);
Expand All @@ -184,7 +199,7 @@ class DeeplinkManager {
}

_handleBuyCrypto() {
this.dispatch((_, getState) => {
this.dispatch((_: any, getState: Store<RootState, any>['getState']) => {
const state = getState();
// Do nothing for now if use is not in a supported network
if (
Expand All @@ -195,8 +210,19 @@ class DeeplinkManager {
});
}

parse(url, { browserCallBack, origin, onHandled }) {
const urlObj = new URL(
parse(
url: string,
{
browserCallBack,
origin,
onHandled,
}: {
browserCallBack: (url: string) => void;
origin: string;
onHandled?: () => void;
},
) {
const urlObj = new UrlParser(
url
.replace(
`${PROTOCOLS.DAPP}/${PROTOCOLS.HTTPS}://`,
Expand All @@ -207,11 +233,29 @@ class DeeplinkManager {
`${PROTOCOLS.DAPP}/`,
),
);
let params;
let params: {
uri: string;
redirect: string;
channelId: string;
comm: string;
pubkey: string;
} = {
pubkey: '',
uri: '',
redirect: '',
channelId: '',
comm: '',
};

if (urlObj.query.length) {
try {
params = qs.parse(urlObj.query.substring(1));
params = qs.parse(urlObj.query.substring(1)) as {
uri: string;
redirect: string;
channelId: string;
comm: string;
pubkey: string;
};
} catch (e) {
if (e) Alert.alert(strings('deeplink.invalid'), e.toString());
}
Expand All @@ -234,7 +278,7 @@ class DeeplinkManager {

if (urlObj.hostname === MM_UNIVERSAL_LINK_HOST) {
// action is the first part of the pathname
const action = urlObj.pathname.split('/')[1];
const action: ACTIONS = urlObj.pathname.split('/')[1] as ACTIONS;

if (action === ACTIONS.ANDROID_SDK) {
DevLogger.log(
Expand Down Expand Up @@ -262,13 +306,14 @@ class DeeplinkManager {
channelId: params.channelId,
otherPublicKey: params.pubkey,
context: 'deeplink (universal)',
initialConnection: false,
});
} else {
SDKConnect.getInstance().connectToChannel({
id: params.channelId,
commLayer: params.comm,
origin,
otherPublicKey: params.pubkey,
validUntil: Date.now() + DEFAULT_SESSION_TIMEOUT_MS,
});
}
}
Expand All @@ -290,12 +335,12 @@ class DeeplinkManager {
// This is called from WC just to open the app and it's not supposed to do anything
return;
} else if (PREFIXES[action]) {
const url = urlObj.href.replace(
const deeplinkUrl = urlObj.href.replace(
`${DEEP_LINK_BASE}/${action}/`,
PREFIXES[action],
);
// loops back to open the link with the right protocol
this.parse(url, { browserCallBack, origin });
this.parse(deeplinkUrl, { browserCallBack, origin });
} else if (action === ACTIONS.BUY_CRYPTO) {
this._handleBuyCrypto();
} else {
Expand Down Expand Up @@ -393,13 +438,14 @@ class DeeplinkManager {
channelId: params.channelId,
otherPublicKey: params.pubkey,
context: 'deeplink (metamask)',
initialConnection: false,
});
} else {
SDKConnect.getInstance().connectToChannel({
id: params.channelId,
commLayer: params.comm,
origin,
otherPublicKey: params.pubkey,
validUntil: Date.now() + DEFAULT_SESSION_TIMEOUT_MS,
});
}
}
Expand Down Expand Up @@ -444,10 +490,18 @@ class DeeplinkManager {
}
}

let instance = null;
let instance: DeeplinkManager;

const SharedDeeplinkManager = {
init: ({ navigation, dispatch }) => {
init: ({
navigation,
dispatch,
}: {
navigation: StackNavigationProp<{
[route: string]: { screen: string };
}>;
dispatch: Dispatch<any>;
}) => {
if (instance) {
return;
}
Expand All @@ -456,8 +510,8 @@ const SharedDeeplinkManager = {
dispatch,
});
},
parse: (url, args) => instance.parse(url, args),
setDeeplink: (url) => instance.setDeeplink(url),
parse: (url: string, args: any) => instance.parse(url, args),
setDeeplink: (url: string) => instance.setDeeplink(url),
getPendingDeeplink: () => instance.getPendingDeeplink(),
expireDeeplink: () => instance.expireDeeplink(),
};
Expand Down

0 comments on commit a34931a

Please sign in to comment.