diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index ad890741574..33d991cd5b3 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -36,7 +36,7 @@
-
diff --git a/android/app/src/main/java/io/metamask/MainActivity.java b/android/app/src/main/java/io/metamask/MainActivity.java
index 8c14d80028b..56b86058cb1 100644
--- a/android/app/src/main/java/io/metamask/MainActivity.java
+++ b/android/app/src/main/java/io/metamask/MainActivity.java
@@ -52,14 +52,22 @@ protected void onCreate(Bundle savedInstanceState) {
@Override
public void onNewIntent(Intent intent) {
- super.onNewIntent(intent);
- if (intent != null &&
- intent.hasExtra("branch_force_new_session") &&
- intent.getBooleanExtra("branch_force_new_session",false)) {
- RNBranchModule.onNewIntent(intent);
- }
+ super.onNewIntent(intent);
+ /*
+ if activity is in foreground (or in backstack but partially visible) launch the same
+ activity will skip onStart, handle this case with reInit
+ if reInit() is called without this flag, you will see the following message:
+ BRANCH_SDK: Warning. Session initialization already happened.
+ To force a new session,
+ set intent extra, "branch_force_new_session", to true.
+ */
+ if (intent != null &&
+ intent.hasExtra("branch_force_new_session") &&
+ intent.getBooleanExtra("branch_force_new_session", false)) {
+ RNBranchModule.onNewIntent(intent);
+ }
}
-
+
@Override
protected ReactActivityDelegate createReactActivityDelegate() {
return new ReactActivityDelegate(this, getMainComponentName()) {
diff --git a/app/components/UI/FiatOrders/PaymentMethodSelector/moonpay.js b/app/components/UI/FiatOrders/PaymentMethodSelector/moonpay.js
index 9a10bdb8552..16e1e1e5169 100644
--- a/app/components/UI/FiatOrders/PaymentMethodSelector/moonpay.js
+++ b/app/components/UI/FiatOrders/PaymentMethodSelector/moonpay.js
@@ -7,7 +7,7 @@ import PaymentMethod from '../components/PaymentMethod';
import Title from '../../../Base/Title';
import Text from '../../../Base/Text';
import { useAssetFromTheme } from '../../../../util/theme';
-import { NETWORKS_CHAIN_ID } from '../../../../constants/on-ramp';
+import { NETWORKS_CHAIN_ID } from '../../../../constants/network';
const styles = StyleSheet.create({
title: {
diff --git a/app/components/UI/FiatOrders/PaymentMethodSelector/transak.js b/app/components/UI/FiatOrders/PaymentMethodSelector/transak.js
index 25b6c97e771..c592335a69d 100644
--- a/app/components/UI/FiatOrders/PaymentMethodSelector/transak.js
+++ b/app/components/UI/FiatOrders/PaymentMethodSelector/transak.js
@@ -8,7 +8,7 @@ import Title from '../../../Base/Title';
import Text from '../../../Base/Text';
import Device from '../../../../util/device';
-import { NETWORKS_CHAIN_ID } from '../../../../constants/on-ramp';
+import { NETWORKS_CHAIN_ID } from '../../../../constants/network';
const styles = StyleSheet.create({
title: {
diff --git a/app/components/UI/FiatOrders/index.js b/app/components/UI/FiatOrders/index.js
index a4e399a18b9..ed00b87fc54 100644
--- a/app/components/UI/FiatOrders/index.js
+++ b/app/components/UI/FiatOrders/index.js
@@ -9,8 +9,8 @@ import { renderNumber } from '../../../util/number';
import {
FIAT_ORDER_PROVIDERS,
FIAT_ORDER_STATES,
- NETWORKS_CHAIN_ID,
} from '../../../constants/on-ramp';
+import { NETWORKS_CHAIN_ID } from '../../../constants/network';
import {
getPendingOrders,
updateFiatOrder,
diff --git a/app/components/UI/FiatOrders/orderProcessor/moonpay.js b/app/components/UI/FiatOrders/orderProcessor/moonpay.js
index 0f995845642..51e46741a7a 100644
--- a/app/components/UI/FiatOrders/orderProcessor/moonpay.js
+++ b/app/components/UI/FiatOrders/orderProcessor/moonpay.js
@@ -5,8 +5,8 @@ import {
FIAT_ORDER_PROVIDERS,
FIAT_ORDER_STATES,
MOONPAY_NETWORK_PARAMETERS,
- NETWORKS_CHAIN_ID,
} from '../../../../constants/on-ramp';
+import { NETWORKS_CHAIN_ID } from '../../../../constants/network';
import AppConstants from '../../../../core/AppConstants';
import Logger from '../../../../util/Logger';
diff --git a/app/components/UI/FiatOrders/orderProcessor/transak.js b/app/components/UI/FiatOrders/orderProcessor/transak.js
index 9cab87f49ac..e62f11d0213 100644
--- a/app/components/UI/FiatOrders/orderProcessor/transak.js
+++ b/app/components/UI/FiatOrders/orderProcessor/transak.js
@@ -6,9 +6,9 @@ import Logger from '../../../../util/Logger';
import {
FIAT_ORDER_PROVIDERS,
FIAT_ORDER_STATES,
- NETWORKS_CHAIN_ID,
TRANSAK_NETWORK_PARAMETERS,
} from '../../../../constants/on-ramp';
+import { NETWORKS_CHAIN_ID } from '../../../../constants/network';
//* env vars
diff --git a/app/components/UI/FiatOrders/orderProcessor/wyreApplePay.js b/app/components/UI/FiatOrders/orderProcessor/wyreApplePay.js
index 4ebc67a97fa..613df1fc63c 100644
--- a/app/components/UI/FiatOrders/orderProcessor/wyreApplePay.js
+++ b/app/components/UI/FiatOrders/orderProcessor/wyreApplePay.js
@@ -10,8 +10,8 @@ import useCurrency from '../../../Base/Keypad/useCurrency';
import {
FIAT_ORDER_PROVIDERS,
FIAT_ORDER_STATES,
- NETWORKS_CHAIN_ID,
} from '../../../../constants/on-ramp';
+import { NETWORKS_CHAIN_ID } from '../../../../constants/network';
//* env vars
diff --git a/app/components/UI/Swaps/QuotesView.js b/app/components/UI/Swaps/QuotesView.js
index 65292c914b9..5d0ab4699fd 100644
--- a/app/components/UI/Swaps/QuotesView.js
+++ b/app/components/UI/Swaps/QuotesView.js
@@ -1,5 +1,6 @@
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import PropTypes from 'prop-types';
+import Eth from 'ethjs-query';
import {
View,
StyleSheet,
@@ -30,8 +31,13 @@ import {
renderFromWei,
toWei,
weiToFiat,
+ calculateEthFeeForMultiLayer,
} from '../../../util/number';
-import { isMainnetByChainId } from '../../../util/networks';
+import {
+ isMainnetByChainId,
+ isMultiLayerFeeNetwork,
+ fetchEstimatedL1FeeOptimism,
+} from '../../../util/networks';
import {
getErrorMessage,
getFetchParams,
@@ -379,6 +385,7 @@ function SwapsQuotesView({
/* State */
const isMainnet = isMainnetByChainId(chainId);
+ const multiLayerFeeNetwork = isMultiLayerFeeNetwork(chainId);
const [firstLoadTime, setFirstLoadTime] = useState(Date.now());
const [isFirstLoad, setIsFirstLoad] = useState(true);
const [shouldFinishFirstLoad, setShouldFinishFirstLoad] = useState(false);
@@ -390,6 +397,7 @@ function SwapsQuotesView({
const [trackedError, setTrackedError] = useState(false);
const [animateOnGasChange, setAnimateOnGasChange] = useState(false);
const [isAnimating, setIsAnimating] = useState(false);
+ const [multiLayerL1FeeTotal, setMultiLayerL1FeeTotal] = useState(null);
/* Selected quote, initially topAggId (see effects) */
const [selectedQuoteId, setSelectedQuoteId] = useState(null);
@@ -464,15 +472,31 @@ function SwapsQuotesView({
() => allQuotes.find((quote) => quote?.aggregator === selectedQuoteId),
[allQuotes, selectedQuoteId],
);
- const selectedQuoteValue = useMemo(
- () => quoteValues[selectedQuoteId],
- [
- // eslint-disable-next-line react-hooks/exhaustive-deps
- quoteValues[selectedQuoteId],
- quoteValues,
- selectedQuoteId,
- ],
- );
+ const selectedQuoteValue = useMemo(() => {
+ if (!quoteValues[selectedQuoteId] || multiLayerL1FeeTotal === null) {
+ return quoteValues[selectedQuoteId];
+ }
+ const fees = {
+ ethFee: calculateEthFeeForMultiLayer({
+ multiLayerL1FeeTotal,
+ ethFee: quoteValues[selectedQuoteId].ethFee,
+ }),
+ maxEthFee: calculateEthFeeForMultiLayer({
+ multiLayerL1FeeTotal,
+ ethFee: quoteValues[selectedQuoteId].maxEthFee,
+ }),
+ };
+ return {
+ ...quoteValues[selectedQuoteId],
+ ...fees,
+ };
+ }, [
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ quoteValues[selectedQuoteId],
+ multiLayerL1FeeTotal,
+ quoteValues,
+ selectedQuoteId,
+ ]);
const gasEstimates = useMemo(
() => customGasEstimate || usedGasEstimate,
@@ -1565,6 +1589,26 @@ function SwapsQuotesView({
handleQuotesErrorMetric(error);
}, [error, handleQuotesErrorMetric, trackedError]);
+ useEffect(() => {
+ if (!multiLayerFeeNetwork || !selectedQuote?.trade) {
+ return;
+ }
+ const getEstimatedL1Fee = async () => {
+ try {
+ const eth = new Eth(Engine.context.NetworkController.provider);
+ const result = await fetchEstimatedL1FeeOptimism(eth, {
+ txParams: selectedQuote.trade,
+ chainId,
+ });
+ setMultiLayerL1FeeTotal(result);
+ } catch (e) {
+ Logger.error(e, 'fetchEstimatedL1FeeOptimism call failed');
+ setMultiLayerL1FeeTotal(null);
+ }
+ };
+ getEstimatedL1Fee();
+ }, [selectedQuote?.trade, multiLayerFeeNetwork, chainId]);
+
const openLinkAboutGas = () =>
Linking.openURL(
'https://community.metamask.io/t/what-is-gas-why-do-transactions-take-so-long/3172',
@@ -1985,19 +2029,12 @@ function SwapsQuotesView({
-
-
- {renderFromWei(
- toWei(selectedQuoteValue?.maxEthFee || '0x0'),
- )}{' '}
- {getTicker(ticker)}
-
-
+
+ {renderFromWei(
+ toWei(selectedQuoteValue?.maxEthFee || '0x0'),
+ )}{' '}
+ {getTicker(ticker)}
+
{` ${
weiToFiat(
@@ -2187,6 +2224,7 @@ function SwapsQuotesView({
selectedQuote={selectedQuoteId}
showOverallValue={hasConversionRate}
ticker={getTicker(ticker)}
+ multiLayerL1FeeTotal={multiLayerL1FeeTotal}
/>
{strings('swaps.estimated_network_fees')}
- {renderFromWei(toWei(selectedDetailsQuoteValues.ethFee))}{' '}
+ {renderFromWei(toWei(selectedDetailsQuoteValuesEthFee))}{' '}
{ticker}
{' '}
(~
{weiToFiat(
- toWei(selectedDetailsQuoteValues.ethFee),
+ toWei(selectedDetailsQuoteValuesEthFee),
conversionRate,
currentCurrency,
)}
@@ -386,6 +393,10 @@ function QuotesModal({
const { aggregator } = quote;
const isSelected = aggregator === selectedQuote;
const quoteValue = quoteValues[aggregator];
+ const quoteEthFee = calculateEthFeeForMultiLayer({
+ multiLayerL1FeeTotal,
+ ethFee: quoteValue?.ethFee,
+ });
return (
{weiToFiat(
- toWei(quoteValue?.ethFee ?? 0),
+ toWei(quoteEthFee),
conversionRate,
currentCurrency,
)}
@@ -504,6 +515,7 @@ QuotesModal.propTypes = {
ticker: PropTypes.string,
quoteValues: PropTypes.object,
showOverallValue: PropTypes.bool,
+ multiLayerL1FeeTotal: PropTypes.string,
};
const mapStateToProps = (state) => ({
diff --git a/app/components/UI/Swaps/utils/index.js b/app/components/UI/Swaps/utils/index.js
index 264e21b1265..83a466b74df 100644
--- a/app/components/UI/Swaps/utils/index.js
+++ b/app/components/UI/Swaps/utils/index.js
@@ -10,6 +10,8 @@ const {
SWAPS_TESTNET_CHAIN_ID,
POLYGON_CHAIN_ID,
AVALANCHE_CHAIN_ID,
+ ARBITRUM_CHAIN_ID,
+ OPTIMISM_CHAIN_ID,
} = swapsUtils;
const allowedChainIds = [
@@ -17,6 +19,8 @@ const allowedChainIds = [
BSC_CHAIN_ID,
POLYGON_CHAIN_ID,
AVALANCHE_CHAIN_ID,
+ ARBITRUM_CHAIN_ID,
+ OPTIMISM_CHAIN_ID,
SWAPS_TESTNET_CHAIN_ID,
];
diff --git a/app/components/UI/TypedSign/index.js b/app/components/UI/TypedSign/index.js
index 2ce5aa4c9eb..6678033fb33 100644
--- a/app/components/UI/TypedSign/index.js
+++ b/app/components/UI/TypedSign/index.js
@@ -114,9 +114,17 @@ class TypedSign extends PureComponent {
);
};
+ walletConnectNotificationTitle = (confirmation, isError) => {
+ if (isError) return strings('notifications.wc_signed_failed_title');
+ return confirmation
+ ? strings('notifications.wc_signed_title')
+ : strings('notifications.wc_signed_rejected_title');
+ };
+
showWalletConnectNotification = (
messageParams = {},
confirmation = false,
+ isError = false,
) => {
InteractionManager.runAfterInteractions(() => {
messageParams.origin &&
@@ -125,9 +133,7 @@ class TypedSign extends PureComponent {
NotificationManager.showSimpleNotification({
status: `simple_notification${!confirmation ? '_rejected' : ''}`,
duration: 5000,
- title: confirmation
- ? strings('notifications.wc_signed_title')
- : strings('notifications.wc_signed_rejected_title'),
+ title: this.walletConnectNotificationTitle(confirmation, isError),
description: strings('notifications.wc_description'),
});
});
@@ -138,15 +144,22 @@ class TypedSign extends PureComponent {
const { KeyringController, TypedMessageManager } = Engine.context;
const messageId = messageParams.metamaskId;
const version = messageParams.version;
- const cleanMessageParams = await TypedMessageManager.approveMessage(
- messageParams,
- );
- const rawSig = await KeyringController.signTypedMessage(
- cleanMessageParams,
- version,
- );
- TypedMessageManager.setMessageStatusSigned(messageId, rawSig);
- this.showWalletConnectNotification(messageParams, true);
+ let rawSig;
+ let cleanMessageParams;
+ try {
+ cleanMessageParams = await TypedMessageManager.approveMessage(
+ messageParams,
+ );
+ rawSig = await KeyringController.signTypedMessage(
+ cleanMessageParams,
+ version,
+ );
+ TypedMessageManager.setMessageStatusSigned(messageId, rawSig);
+ this.showWalletConnectNotification(messageParams, true);
+ } catch (error) {
+ TypedMessageManager.setMessageStatusSigned(messageId, error.message);
+ this.showWalletConnectNotification(messageParams, false, true);
+ }
};
rejectMessage = () => {
diff --git a/app/constants/network.js b/app/constants/network.js
index c10eee256e8..766d30305e7 100644
--- a/app/constants/network.js
+++ b/app/constants/network.js
@@ -7,3 +7,19 @@ export const GOERLI = 'goerli';
export const RPC = 'rpc';
export const NO_RPC_BLOCK_EXPLORER = 'NO_BLOCK_EXPLORER';
export const PRIVATENETWORK = 'PRIVATENETWORK';
+
+/**
+ * @enum {string}
+ */
+export const NETWORKS_CHAIN_ID = {
+ MAINNET: '1',
+ OPTIMISM: '10',
+ KOVAN: '42',
+ BSC: '56',
+ POLYGON: '137',
+ FANTOM: '250',
+ ARBITRUM: '42161',
+ AVAXCCHAIN: '43114',
+ CELO: '42220',
+ HARMONY: '1666600000',
+};
diff --git a/app/constants/on-ramp.js b/app/constants/on-ramp.js
index 19162504dbf..86228110a44 100644
--- a/app/constants/on-ramp.js
+++ b/app/constants/on-ramp.js
@@ -1,3 +1,5 @@
+import { NETWORKS_CHAIN_ID } from './network';
+
/**
* @enum {string}
*/
@@ -37,23 +39,6 @@ export const PAYMENT_CATEGORY = {
MULTIPLE: 'Multiple Options',
};
-/**
- * @enum {string}
- */
-
-export const NETWORKS_CHAIN_ID = {
- MAINNET: '1',
- OPTIMISM: '10',
- KOVAN: '42',
- BSC: '56',
- POLYGON: '137',
- FANTOM: '250',
- ARBITRUM: '42161',
- AVAXCCHAIN: '43114',
- CELO: '42220',
- HARMONY: '1666600000',
-};
-
export const NETWORKS_NAMES = {
[NETWORKS_CHAIN_ID.MAINNET]: 'Ethereum',
[NETWORKS_CHAIN_ID.OPTIMISM]: 'Optimism',
diff --git a/app/core/AppConstants.js b/app/core/AppConstants.js
index 02c92e486e0..9e68ffed882 100644
--- a/app/core/AppConstants.js
+++ b/app/core/AppConstants.js
@@ -143,4 +143,5 @@ export default {
},
CANCEL_RATE: 'Transactions (Cancel)',
SPEED_UP_RATE: 'Transactions (Speed Up)',
+ ETH_SIGN_ERROR: 'eth_sign requires 32 byte message hash',
};
diff --git a/app/core/Engine.js b/app/core/Engine.js
index 96c29b1e610..c80a839a99a 100644
--- a/app/core/Engine.js
+++ b/app/core/Engine.js
@@ -385,6 +385,8 @@ class Engine {
swapsUtils.SWAPS_TESTNET_CHAIN_ID,
swapsUtils.POLYGON_CHAIN_ID,
swapsUtils.AVALANCHE_CHAIN_ID,
+ swapsUtils.ARBITRUM_CHAIN_ID,
+ swapsUtils.OPTIMISM_CHAIN_ID,
],
},
),
diff --git a/app/core/RPCMethods/RPCMethodMiddleware.ts b/app/core/RPCMethods/RPCMethodMiddleware.ts
index 6afa2f1cb05..29d3eaf5c75 100644
--- a/app/core/RPCMethods/RPCMethodMiddleware.ts
+++ b/app/core/RPCMethods/RPCMethodMiddleware.ts
@@ -329,9 +329,8 @@ export const getRpcMethodMiddleware = ({
res.result = rawSig;
} else {
- throw ethErrors.rpc.invalidParams(
- 'eth_sign requires 32 byte message hash',
- );
+ res.result = AppConstants.ETH_SIGN_ERROR;
+ throw ethErrors.rpc.invalidParams(AppConstants.ETH_SIGN_ERROR);
}
},
diff --git a/app/core/RemoteConnection/ECIES.ts b/app/core/RemoteConnection/ECIES.ts
new file mode 100644
index 00000000000..95e45d77120
--- /dev/null
+++ b/app/core/RemoteConnection/ECIES.ts
@@ -0,0 +1,71 @@
+// eslint-disable-next-line @typescript-eslint/ban-ts-comment
+// @ts-nocheck
+// eslint-disable-next-line import/no-nodejs-modules
+import { Buffer } from 'buffer';
+import { encrypt, decrypt, PrivateKey } from 'eciesjs';
+
+/**
+ * Class that exposes methods to generate and compute
+ * Elliptic Curve Integrated Encryption Scheme (ECIES) for key exchange and symmetric encryption/decryption
+ *
+ * It also exposes encryption/decryption methods that are used
+ * by the communication layer to encrypt/decrypt in/out data
+ * The encryption/decryption is made using a symmetric key generated from the ECIES key exchange
+ */
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+export default class ECIES {
+ ecies: any;
+
+ constructor() {
+ this.ecies = null; // ECIES instance
+ }
+
+ /**
+ * Creates ECIES instance
+ *
+ * @returns - Generates ECIES instance
+ */
+ generateECIES(): void {
+ this.ecies = new PrivateKey();
+ }
+
+ /**
+ * Returns ECIES instance public key
+ *
+ * @returns - public key in base64 format
+ */
+ getPublicKey(): string {
+ return this.ecies.publicKey.toHex();
+ }
+
+ /**
+ * Encrypts a data message using the public key of the side to encrypt data for
+ *
+ * @param {string} data - data string to be encrypted
+ * @param {string} otherPublicKey - public key of the side to encrypt data for
+ * @returns - encrypted string in base64
+ */
+ encrypt(data: string, otherPublicKey: string): string {
+ const encryptedData = encrypt(otherPublicKey, Buffer.from(data));
+
+ return Buffer.from(encryptedData).toString('base64');
+ }
+
+ /**
+ * Decrypts a data message using the instance private key
+ *
+ * @param {string} encryptedData - base64 data string to be decrypted
+ * @returns - decrypted data || error message
+ */
+ decrypt(encryptedData: string): string {
+ const payload = Buffer.from(encryptedData, 'base64');
+
+ try {
+ const decrypted = decrypt(this.ecies.toHex(), payload);
+
+ return decrypted.toString();
+ } catch (error: any) {
+ return error.message;
+ }
+ }
+}
diff --git a/app/core/RemoteConnection/KeyExchange.ts b/app/core/RemoteConnection/KeyExchange.ts
new file mode 100644
index 00000000000..50016e19ad7
--- /dev/null
+++ b/app/core/RemoteConnection/KeyExchange.ts
@@ -0,0 +1,115 @@
+// eslint-disable-next-line @typescript-eslint/ban-ts-comment
+// @ts-nocheck
+import { EventEmitter2 } from 'eventemitter2';
+import ECIES from './ECIES';
+
+enum KeySteps {
+ NONE = 'none',
+ SYN = 'key_handshake_SYN',
+ SYNACK = 'key_handshake_SYNACK',
+ ACK = 'key_handshake_ACK',
+}
+
+export default class KeyExchange extends EventEmitter2 {
+ keysExchanged = false;
+
+ myECIES = null;
+
+ otherPublicKey = '';
+
+ CommLayer: any;
+
+ myPublicKey: any;
+
+ sendPublicKey: any;
+
+ step: string = KeySteps.NONE;
+
+ constructor({ CommLayer, otherPublicKey, sendPublicKey }) {
+ super();
+
+ this.myECIES = new ECIES();
+ this.myECIES.generateECIES();
+ this.CommLayer = CommLayer;
+ this.myPublicKey = this.myECIES.getPublicKey();
+
+ if (otherPublicKey) {
+ this.onOtherPublicKey(otherPublicKey);
+ }
+ this.sendPublicKey = sendPublicKey;
+
+ this.CommLayer.on('key_exchange', ({ message }) => {
+ if (this.keysExchanged) {
+ return;
+ }
+
+ if (message.type === KeySteps.SYN) {
+ this.checkStep(KeySteps.NONE);
+ this.step = KeySteps.ACK;
+
+ if (this.sendPublicKey && message.pubkey && !this.otherPublicKey) {
+ this.onOtherPublicKey(message.pubkey);
+ }
+
+ this.CommLayer.sendMessage({
+ type: KeySteps.SYNACK,
+ pubkey: this.myPublicKey,
+ });
+ } else if (message.type === KeySteps.SYNACK) {
+ this.checkStep(KeySteps.SYNACK);
+
+ this.onOtherPublicKey(message.pubkey);
+
+ this.CommLayer.sendMessage({ type: KeySteps.ACK });
+ this.keysExchanged = true;
+ this.emit('keys_exchanged');
+ } else if (message.type === KeySteps.ACK) {
+ this.checkStep(KeySteps.ACK);
+ this.keysExchanged = true;
+ this.emit('keys_exchanged');
+ }
+ });
+ }
+
+ clean(): void {
+ this.step = KeySteps.NONE;
+ this.keysExchanged = false;
+ this.otherPublicKey = '';
+ }
+
+ start(isOriginator: boolean): void {
+ if (isOriginator) {
+ this.clean();
+ }
+ this.checkStep(KeySteps.NONE);
+ this.step = KeySteps.SYNACK;
+ this.CommLayer.sendMessage({
+ type: KeySteps.SYN,
+ pubkey: this.sendPublicKey ? this.myPublicKey : undefined,
+ });
+ }
+
+ checkStep(step: string): void {
+ if (this.step !== step) {
+ throw new Error(`Wrong Step ${this.step} ${step}`);
+ }
+ }
+
+ onOtherPublicKey(pubkey: string): void {
+ this.otherPublicKey = pubkey;
+ }
+
+ encryptMessage(message: string): string {
+ if (!this.otherPublicKey) {
+ throw new Error('Keys not exchanged');
+ }
+ return this.myECIES.encrypt(message, this.otherPublicKey);
+ }
+
+ decryptMessage(message: string): string {
+ if (!this.otherPublicKey) {
+ throw new Error('Keys not exchanged');
+ }
+ return this.myECIES.decrypt(message);
+ }
+}
diff --git a/app/core/RemoteConnection/Socket.ts b/app/core/RemoteConnection/Socket.ts
new file mode 100644
index 00000000000..bc89eaa6f43
--- /dev/null
+++ b/app/core/RemoteConnection/Socket.ts
@@ -0,0 +1,200 @@
+// eslint-disable-next-line @typescript-eslint/ban-ts-comment
+// @ts-nocheck
+import { EventEmitter2 } from 'eventemitter2';
+import io from 'socket.io-client';
+import { v4 as uuidv4 } from 'uuid';
+import KeyExchange from './KeyExchange';
+import { CommunicationLayerPreference } from '.';
+
+export default class Socket extends EventEmitter2 {
+ socket = null;
+
+ clientsConnected = false;
+
+ clientsReady = false;
+
+ isOriginator;
+
+ channelId = null;
+
+ keyExchange: KeyExchange;
+
+ manualDisconnect = false;
+
+ reconnect: boolean;
+
+ commLayer: CommunicationLayerPreference;
+
+ constructor({ otherPublicKey, reconnect, commLayer, transports }) {
+ super();
+
+ this.reconnect = reconnect;
+ this.commLayer = commLayer;
+
+ const options: { transports?: any; autoConnect: boolean } = {
+ autoConnect: false,
+ };
+
+ if (transports) {
+ options.transports = transports;
+ }
+
+ this.socket = io(
+ 'https://metamask-sdk-socket.metafi.codefi.network/',
+ options,
+ );
+
+ const keyExchangeInitParameter = {
+ CommLayer: this,
+ otherPublicKey,
+ sendPublicKey: false,
+ };
+
+ this.keyExchange = new KeyExchange(keyExchangeInitParameter);
+
+ this.keyExchange.on('keys_exchanged', () => {
+ this.emit('clients_ready', {
+ isOriginator: this.isOriginator,
+ });
+ });
+ }
+
+ receiveMessages(channelId) {
+ this.socket.on(`clients_connected-${channelId}`, (id) => {
+ this.channelId = id;
+ this.clientsConnected = true;
+ if (this.isOriginator) {
+ if (!this.keyExchange.keysExchanged) {
+ this.keyExchange.start(this.isOriginator);
+ }
+ }
+
+ if (this.reconnect) {
+ if (this.keyExchange.keysExchanged) {
+ this.sendMessage({ type: 'ready' });
+ if (this.commLayer === CommunicationLayerPreference.WEBRTC) {
+ this.emit('clients_ready', {
+ isOriginator: this.isOriginator,
+ });
+ }
+ } else if (!this.isOriginator) {
+ this.sendMessage({ type: 'key_handshake_start' });
+ }
+ this.reconnect = false;
+ }
+ });
+
+ this.socket.on(`channel_created-${channelId}`, (id) => {
+ this.emit('channel_created', id);
+ });
+
+ this.socket.on(`clients_disconnected-${channelId}`, () => {
+ this.clientsConnected = false;
+ this.emit('clients_disconnected');
+ });
+
+ this.socket.on(`message-${channelId}`, ({ id, message, error }) => {
+ if (error) {
+ throw new Error(error);
+ }
+
+ this.checkSameId(id);
+
+ if (
+ this.isOriginator &&
+ this.keyExchange.keysExchanged &&
+ message?.type === 'key_handshake_start'
+ ) {
+ return this.keyExchange.start(this.isOriginator);
+ }
+
+ if (!this.keyExchange.keysExchanged) {
+ const messageReceived = message;
+ if (messageReceived?.type.startsWith('key_handshake')) {
+ return this.emit('key_exchange', { message: messageReceived });
+ }
+ throw new Error('Keys not exchanged');
+ }
+
+ const decryptedMessage = this.keyExchange.decryptMessage(message);
+ const messageReceived = JSON.parse(decryptedMessage);
+ return this.emit('message', { message: messageReceived });
+ });
+
+ this.socket.on(
+ `clients_waiting_to_join-${channelId}`,
+ (numberUsers: number) => {
+ this.emit('clients_waiting_to_join', numberUsers);
+ },
+ );
+ }
+
+ checkSameId(id) {
+ if (id !== this.channelId) {
+ throw new Error('Wrong id');
+ }
+ }
+
+ send(type, message) {
+ this.socket.emit(type, message);
+ }
+
+ sendMessage(message) {
+ if (!this.channelId) {
+ throw new Error('Create a channel first');
+ }
+
+ if (!this.keyExchange.keysExchanged) {
+ if (message?.type.startsWith('key_handshake')) {
+ return this.socket.emit('message', { id: this.channelId, message });
+ }
+ throw new Error('Keys not exchanged');
+ }
+
+ const encryptedMessage = this.keyExchange.encryptMessage(
+ JSON.stringify(message),
+ );
+
+ return this.socket.emit('message', {
+ id: this.channelId,
+ message: encryptedMessage,
+ });
+ }
+
+ connectToChannel(id) {
+ this.socket.connect();
+ this.channelId = id;
+ this.receiveMessages(this.channelId);
+ this.socket.emit('join_channel', id);
+ }
+
+ createChannel() {
+ this.socket.connect();
+ this.isOriginator = true;
+ const channelId = uuidv4();
+ this.receiveMessages(channelId);
+ this.socket.emit('join_channel', channelId);
+ return { channelId, pubKey: this.keyExchange.myPublicKey };
+ }
+
+ pause() {
+ this.manualDisconnect = true;
+ if (this.keyExchange.keysExchanged) {
+ this.sendMessage({ type: 'pause' });
+ }
+ this.socket.disconnect();
+ }
+
+ resume() {
+ this.manualDisconnect = false;
+ if (this.keyExchange.keysExchanged) {
+ this.reconnect = true;
+ this.socket.connect();
+ this.socket.emit('join_channel', this.channelId);
+ }
+ }
+
+ disconnect() {
+ this.socket.disconnect();
+ }
+}
diff --git a/app/core/RemoteConnection/WebRTC.ts b/app/core/RemoteConnection/WebRTC.ts
new file mode 100644
index 00000000000..dc3fba7eb2b
--- /dev/null
+++ b/app/core/RemoteConnection/WebRTC.ts
@@ -0,0 +1,254 @@
+// eslint-disable-next-line @typescript-eslint/ban-ts-comment
+// @ts-nocheck
+/* eslint-disable no-console */
+import { EventEmitter2 } from 'eventemitter2';
+import Socket from './Socket';
+import KeyExchange from './KeyExchange';
+
+export default class WebRTC extends EventEmitter2 {
+ handshakeDone = false;
+
+ isOriginator = false;
+
+ clientsConnected = false;
+
+ clientsReady = false;
+
+ socket = null;
+
+ webrtc = null;
+
+ dataChannel = null;
+
+ keyExchange: KeyExchange;
+
+ RTCPeerConnection: any;
+
+ RTCSessionDescription: any;
+
+ RTCIceCandidate: any;
+
+ reconnect: boolean;
+
+ constructor({ otherPublicKey, webRTCLib, commLayer, reconnect, transports }) {
+ super();
+ this.reconnect = reconnect;
+ if (webRTCLib) {
+ this.RTCPeerConnection = webRTCLib.RTCPeerConnection;
+ this.RTCSessionDescription = webRTCLib.RTCSessionDescription;
+ this.RTCIceCandidate = webRTCLib.RTCIceCandidate;
+ } else {
+ this.RTCPeerConnection = RTCPeerConnection;
+ this.RTCSessionDescription = RTCSessionDescription;
+ this.RTCIceCandidate = RTCIceCandidate;
+ }
+
+ this.socket = new Socket({
+ otherPublicKey,
+ commLayer,
+ reconnect,
+ transports,
+ });
+
+ const keyExchangeInitParameter = {
+ CommLayer: this,
+ otherPublicKey: null,
+ sendPublicKey: true,
+ };
+
+ this.keyExchange = new KeyExchange(keyExchangeInitParameter);
+
+ this.keyExchange.on('keys_exchanged', () => {
+ this.clientsReady = true;
+ this.emit('clients_ready', {
+ isOriginator: this.isOriginator,
+ });
+ });
+
+ this.socket.on('clients_disconnected', () => {
+ if (!this.clientsConnected) {
+ this.socket.removeAllListeners();
+ return this.emit('clients_disconnected');
+ }
+ return this.clientsConnected;
+ });
+
+ this.socket.on('message', async ({ message }) => {
+ const { offer, answer, candidate, type } = message;
+ if (type === 'offer') {
+ await this.webrtc.setRemoteDescription(
+ new this.RTCSessionDescription(offer),
+ );
+
+ const answerLocal = await this.webrtc.createAnswer();
+ await this.webrtc.setLocalDescription(answerLocal);
+
+ this.socket.sendMessage({ type: 'answer', answer: answerLocal });
+ } else if (type === 'answer') {
+ await this.webrtc.setRemoteDescription(
+ new this.RTCSessionDescription(answer),
+ );
+
+ this.handshakeDone = true;
+ } else if (type === 'candidate') {
+ this.webrtc.addIceCandidate(new this.RTCIceCandidate(candidate));
+ }
+ });
+
+ this.socket.on('clients_ready', async ({ isOriginator }) => {
+ this.setupWebrtc();
+ if (!isOriginator) {
+ return;
+ }
+ const offer = await this.webrtc.createOffer();
+
+ await this.webrtc.setLocalDescription(offer);
+
+ this.isOriginator = isOriginator;
+ this.socket.sendMessage({ type: 'offer', offer });
+ });
+
+ this.socket.on('channel_created', (id) => {
+ this.emit('channel_created', id);
+ });
+
+ this.socket.on('clients_waiting_to_join', (numberUsers) => {
+ this.emit('clients_waiting_to_join', numberUsers);
+ });
+ }
+
+ setupWebrtc() {
+ const configuration = {
+ iceServers: [{ urls: 'stun:15.237.115.65' }],
+ };
+
+ this.webrtc = new this.RTCPeerConnection(configuration);
+
+ this.webrtc.ondatachannel = (evt) => {
+ console.log('Data channel is created!');
+ const receiveChannel = evt.channel;
+ receiveChannel.onopen = () => {
+ console.log('Data channel is open and ready to be used.');
+ this.clientsConnected = true;
+
+ if (this.isOriginator) {
+ if (!this.keyExchange.keysExchanged) {
+ this.keyExchange.start(this.isOriginator);
+ }
+ }
+
+ if (this.reconnect) {
+ if (this.keyExchange.keysExchanged) {
+ this.sendMessage({ type: 'ready' });
+ this.emit('clients_ready', {
+ isOriginator: this.isOriginator,
+ });
+ } else if (!this.isOriginator) {
+ this.sendMessage({ type: 'key_handshake_start' });
+ }
+ this.reconnect = false;
+ }
+ };
+
+ this.onMessage = this.onMessage.bind(this);
+
+ receiveChannel.onmessage = this.onMessage;
+ };
+
+ this.webrtc.onconnectionstatechange = () => {
+ const connectionStatus = this.webrtc.connectionState;
+ console.log('connectionStatus', connectionStatus);
+ if (['disconnected', 'failed', 'closed'].includes(connectionStatus)) {
+ return this.emit('clients_disconnected');
+ }
+
+ return connectionStatus;
+ };
+
+ this.webrtc.onicecandidate = ({ candidate }) => {
+ if (candidate) {
+ this.socket.sendMessage({
+ type: 'candidate',
+ candidate,
+ });
+ }
+ };
+
+ this.webrtc.onicecandidateerror = (error) =>
+ console.log('ICE ERROR', error);
+
+ this.dataChannel = this.webrtc.createDataChannel('messenger');
+
+ this.dataChannel.onerror = (error) => {
+ if (error.error.code === 0) {
+ return this.emit('clients_disconnected');
+ }
+ console.log('ERROR: datachannel', error);
+ return error;
+ };
+ }
+
+ connectToChannel(id) {
+ this.socket.connectToChannel(id);
+ }
+
+ onMessage(message) {
+ /* if (!message.isTrusted) {
+ throw new Error('Message not trusted');
+ }*/
+
+ if (!this.keyExchange.keysExchanged) {
+ const messageReceived = JSON.parse(message.data);
+ if (messageReceived?.type.startsWith('key_handshake')) {
+ return this.emit('key_exchange', { message: messageReceived });
+ }
+ throw new Error('Keys not exchanged');
+ }
+
+ const decryptedMessage = this.keyExchange.decryptMessage(message.data);
+ const messageReceived = JSON.parse(decryptedMessage);
+ return this.emit('message', { message: messageReceived });
+ }
+
+ sendMessage(message) {
+ if (!this.clientsConnected) {
+ throw new Error('Clients not connected');
+ }
+
+ if (!this.keyExchange.keysExchanged) {
+ if (message?.type.startsWith('key_handshake')) {
+ return this.dataChannel.send(JSON.stringify(message));
+ }
+ throw new Error('Keys not exchanged');
+ }
+ const encryptedMessage = this.keyExchange.encryptMessage(
+ JSON.stringify(message),
+ );
+
+ return this.dataChannel.send(encryptedMessage);
+ }
+
+ createChannel() {
+ return this.socket.createChannel();
+ }
+
+ pause() {
+ if (this.keyExchange.keysExchanged) {
+ this.sendMessage({ type: 'pause' });
+ }
+ this.webrtc?.close();
+ // this.removeAllListeners();
+ this.socket.pause();
+ // this.socket.removeAllListeners();
+ }
+
+ resume() {
+ this.reconnect = true;
+ this.socket.resume();
+ }
+
+ disconnect() {
+ this.socket.disconnect();
+ this.webrtc?.close();
+ }
+}
diff --git a/app/core/RemoteConnection/index.ts b/app/core/RemoteConnection/index.ts
new file mode 100644
index 00000000000..fe45d355116
--- /dev/null
+++ b/app/core/RemoteConnection/index.ts
@@ -0,0 +1,247 @@
+// eslint-disable-next-line @typescript-eslint/ban-ts-comment
+// @ts-nocheck
+import { EventEmitter2 } from 'eventemitter2';
+import { validate } from 'uuid';
+import Socket from './Socket';
+import WebRTC from './WebRTC';
+
+export interface DappMetadata {
+ url: string;
+ name: string;
+}
+
+interface RemoteCommunicationOptions {
+ platform: string;
+ commLayer: string;
+ otherPublicKey?: string;
+ webRTCLib?: any;
+ reconnect?: any;
+ dappMetadata?: DappMetadata;
+ transports?: string[];
+}
+
+export enum CommunicationLayerPreference {
+ WEBRTC = 'webrtc',
+ SOCKET = 'socket',
+ WALLETCONNECT = 'wc',
+}
+
+export default class RemoteCommunication extends EventEmitter2 {
+ commLayer = null;
+
+ channelId = null;
+
+ connected = false;
+
+ isOriginator: boolean;
+
+ originatorInfo: any;
+
+ walletInfo: any;
+
+ paused: boolean;
+
+ CommLayer: typeof WebRTC | typeof Socket;
+
+ otherPublicKey: string;
+
+ webRTCLib: any;
+
+ dappMetadata: DappMetadata;
+
+ transports: string[];
+
+ platform: string;
+
+ constructor({
+ platform,
+ commLayer = 'socket',
+ otherPublicKey,
+ webRTCLib,
+ reconnect,
+ dappMetadata,
+ transports,
+ }: RemoteCommunicationOptions) {
+ super();
+
+ const CommLayer =
+ commLayer === CommunicationLayerPreference.WEBRTC ? WebRTC : Socket;
+
+ this.CommLayer = CommLayer;
+ this.otherPublicKey = otherPublicKey;
+ this.webRTCLib = webRTCLib;
+ this.dappMetadata = dappMetadata;
+ this.transports = transports;
+ this.platform = platform;
+
+ this.setupCommLayer({
+ CommLayer,
+ otherPublicKey,
+ webRTCLib,
+ commLayer,
+ reconnect,
+ });
+ }
+
+ setupCommLayer({
+ CommLayer,
+ otherPublicKey,
+ webRTCLib,
+ commLayer,
+ reconnect,
+ }) {
+ this.commLayer = new CommLayer({
+ otherPublicKey,
+ webRTCLib,
+ commLayer,
+ reconnect,
+ transports: this.transports,
+ });
+
+ this.commLayer.on('message', ({ message }) => {
+ this.onMessageCommLayer(message);
+ });
+
+ this.commLayer.on('clients_ready', ({ isOriginator }) => {
+ this.isOriginator = isOriginator;
+
+ if (!isOriginator) {
+ return;
+ }
+
+ let url =
+ (typeof document !== 'undefined' && document.URL) || 'url undefined';
+ let title =
+ (typeof document !== 'undefined' && document.title) ||
+ 'title undefined';
+
+ if (this.dappMetadata?.url) {
+ url = this.dappMetadata.url;
+ }
+
+ if (this.dappMetadata?.name) {
+ title = this.dappMetadata.name;
+ }
+
+ this.commLayer.sendMessage({
+ type: 'originator_info',
+ originatorInfo: { url, title, platform: this.platform },
+ });
+ });
+
+ this.commLayer.on('clients_disconnected', () => {
+ if (this.paused) {
+ return;
+ }
+
+ if (!this.isOriginator) {
+ this.paused = true;
+ return;
+ }
+
+ this.clean();
+ this.commLayer.removeAllListeners();
+ this.setupCommLayer({
+ CommLayer,
+ otherPublicKey,
+ webRTCLib,
+ commLayer: this.commLayer,
+ reconnect: false,
+ });
+ this.emit('clients_disconnected');
+ });
+
+ this.commLayer.on('channel_created', (id) => {
+ this.emit('channel_created', id);
+ });
+
+ this.commLayer.on('clients_waiting_to_join', (numberUsers) => {
+ this.emit('clients_waiting_to_join', numberUsers);
+ });
+ }
+
+ clean() {
+ this.channelId = null;
+ this.connected = false;
+ }
+
+ connectToChannel(id) {
+ if (!validate(id)) {
+ throw new Error('Invalid channel');
+ }
+ this.commLayer.connectToChannel(id);
+ }
+
+ sendMessage(message) {
+ if (this.paused) {
+ this.once('clients_ready', () => {
+ this.commLayer.sendMessage(message);
+ });
+ } else {
+ this.commLayer.sendMessage(message);
+ }
+ }
+
+ onMessageCommLayer(message) {
+ if (message.type === 'originator_info') {
+ this.commLayer.sendMessage({
+ type: 'wallet_info',
+ walletInfo: {
+ type: 'MetaMask',
+ version: 'MetaMask/Mobile',
+ },
+ });
+ this.originatorInfo = message.originatorInfo;
+ this.connected = true;
+ this.emit('clients_ready', {
+ isOriginator: this.isOriginator,
+ originatorInfo: message.originatorInfo,
+ });
+ this.paused = false;
+ return;
+ } else if (message.type === 'wallet_info') {
+ this.walletInfo = message.walletInfo;
+ this.connected = true;
+ this.emit('clients_ready', {
+ isOriginator: this.isOriginator,
+ walletInfo: message.walletInfo,
+ });
+ this.paused = false;
+ return;
+ } else if (message.type === 'pause') {
+ this.paused = true;
+ } else if (message.type === 'ready') {
+ this.paused = false;
+ this.emit('clients_ready', {
+ isOriginator: this.isOriginator,
+ walletInfo: this.walletInfo,
+ });
+ }
+
+ this.emit('message', { message });
+ }
+
+ generateChannelId() {
+ if (this.connected) {
+ throw new Error('Channel already created');
+ }
+
+ this.clean();
+
+ const { channelId, pubKey } = this.commLayer.createChannel();
+ this.channelId = channelId;
+ return { channelId, pubKey };
+ }
+
+ pause() {
+ this.commLayer.pause();
+ }
+
+ resume() {
+ this.commLayer.resume();
+ }
+
+ disconnect() {
+ this.commLayer.disconnect();
+ }
+}
diff --git a/app/core/SDKConnect.ts b/app/core/SDKConnect.ts
index 9068c385563..354aa506f44 100644
--- a/app/core/SDKConnect.ts
+++ b/app/core/SDKConnect.ts
@@ -1,7 +1,7 @@
import BackgroundBridge from './BackgroundBridge/BackgroundBridge';
import RemoteCommunication, {
CommunicationLayerPreference,
-} from '@metamask/sdk-communication-layer';
+} from './RemoteConnection';
import getRpcMethodMiddleware from './RPCMethods/RPCMethodMiddleware';
import AppConstants from './AppConstants';
import Minimizer from 'react-native-minimizer';
diff --git a/app/util/address/index.js b/app/util/address/index.js
index a515aa0a008..8d324424a3e 100644
--- a/app/util/address/index.js
+++ b/app/util/address/index.js
@@ -4,6 +4,7 @@ import {
isHexString,
addHexPrefix,
isValidChecksumAddress,
+ isHexPrefixed,
} from 'ethereumjs-util';
import URL from 'url-parse';
import punycode from 'punycode/punycode';
@@ -424,3 +425,15 @@ export function isValidAddressInputViaQRCode(input) {
}
return isValidHexAddress(input);
}
+
+/** Removes hex prefix from a string if it's there.
+ *
+ * @param {string} str
+ * @returns {string}
+ */
+export const stripHexPrefix = (str) => {
+ if (typeof str !== 'string') {
+ return str;
+ }
+ return isHexPrefixed(str) ? str.slice(2) : str;
+};
diff --git a/app/util/address/index.test.ts b/app/util/address/index.test.ts
index 977d115ec71..dbf31fa0222 100644
--- a/app/util/address/index.test.ts
+++ b/app/util/address/index.test.ts
@@ -4,6 +4,7 @@ import {
formatAddress,
isValidHexAddress,
isValidAddressInputViaQRCode,
+ stripHexPrefix,
} from '.';
describe('isENS', () => {
@@ -122,3 +123,18 @@ describe('isValidAddressInputViaQRCode', () => {
expect(isValidAddressInputViaQRCode(mockInput)).toBe(false);
});
});
+
+describe('stripHexPrefix', () => {
+ const str =
+ '0x4cfd3e90fc78b0f86bf7524722150bb8da9c60cd532564d7ff43f5716514f553';
+ const stripped =
+ '4cfd3e90fc78b0f86bf7524722150bb8da9c60cd532564d7ff43f5716514f553';
+
+ it('returns a string without a hex prefix', () => {
+ expect(stripHexPrefix(str)).toBe(stripped);
+ });
+
+ it('returns the same string since there is no hex prefix', () => {
+ expect(stripHexPrefix(stripped)).toBe(stripped);
+ });
+});
diff --git a/app/util/networks/customNetworks.tsx b/app/util/networks/customNetworks.tsx
index ac853d8b1d7..5a81f9f90a9 100644
--- a/app/util/networks/customNetworks.tsx
+++ b/app/util/networks/customNetworks.tsx
@@ -19,7 +19,7 @@ const PopularList = [
rpcUrl: `https://arbitrum-mainnet.infura.io/v3/${infuraProjectId}`,
ticker: 'ETH',
rpcPrefs: {
- blockExplorerUrl: 'https://explorer.arbitrum.io',
+ blockExplorerUrl: 'https://arbiscan.io',
imageUrl: 'AETH',
},
},
diff --git a/app/util/networks/index.js b/app/util/networks/index.js
index 2b871c47e7b..30a7c5d8c4c 100644
--- a/app/util/networks/index.js
+++ b/app/util/networks/index.js
@@ -1,4 +1,10 @@
import URL from 'url-parse';
+import { utils } from 'ethers';
+import EthContract from 'ethjs-contract';
+import { getContractFactory } from '@eth-optimism/contracts/dist/contract-defs';
+import { predeploys } from '@eth-optimism/contracts/dist/predeploys';
+import { util } from '@metamask/controllers';
+
import AppConstants from '../../core/AppConstants';
import {
MAINNET,
@@ -7,13 +13,13 @@ import {
RINKEBY,
GOERLI,
RPC,
+ NETWORKS_CHAIN_ID,
} from '../../../app/constants/network';
import { NetworkSwitchErrorType } from '../../../app/constants/error';
-import { util } from '@metamask/controllers';
import Engine from '../../core/Engine';
import { toLowerCaseEquals } from './../general';
import { fastSplit } from '../../util/number';
-
+import { buildUnserializedTransaction } from '../../util/transactions/optimismTransaction';
import handleNetworkSwitch from './handleNetworkSwitch';
export { handleNetworkSwitch };
@@ -99,6 +105,9 @@ export const getDecimalChainId = (chainId) => {
export const isMainnetByChainId = (chainId) =>
getDecimalChainId(String(chainId)) === String(1);
+export const isMultiLayerFeeNetwork = (chainId) =>
+ chainId === NETWORKS_CHAIN_ID.OPTIMISM;
+
export const getNetworkName = (id) =>
NetworkListKeys.find((key) => NetworkList[key].networkId === Number(id));
@@ -271,3 +280,30 @@ export function blockTagParamIndex(payload) {
return undefined;
}
}
+
+// The code in this file is largely drawn from https://community.optimism.io/docs/developers/l2/new-fees.html#for-frontend-and-wallet-developers
+const buildOVMGasPriceOracleContract = (eth) => {
+ const OVMGasPriceOracle = getContractFactory('OVM_GasPriceOracle').attach(
+ predeploys.OVM_GasPriceOracle,
+ );
+ const abi = JSON.parse(
+ OVMGasPriceOracle.interface.format(utils.FormatTypes.json),
+ );
+ const contract = new EthContract(eth);
+ return contract(abi).at(OVMGasPriceOracle.address);
+};
+
+/**
+ * It returns an estimated L1 fee for the Optimism network.
+ *
+ * @param {Object} eth
+ * @param {Object} txMeta
+ * @returns {String}
+ */
+export const fetchEstimatedL1FeeOptimism = async (eth, txMeta) => {
+ const contract = buildOVMGasPriceOracleContract(eth);
+ const serializedTransaction =
+ buildUnserializedTransaction(txMeta).serialize();
+ const result = await contract.getL1Fee(serializedTransaction);
+ return result?.[0]?.toString(16);
+};
diff --git a/app/util/number/index.js b/app/util/number/index.js
index 878656d9304..c4023257b10 100644
--- a/app/util/number/index.js
+++ b/app/util/number/index.js
@@ -6,9 +6,10 @@ import { utils as ethersUtils } from 'ethers';
import convert from 'ethjs-unit';
import { util } from '@metamask/controllers';
import numberToBN from 'number-to-bn';
-import currencySymbols from '../currency-symbols.json';
import BigNumber from 'bignumber.js';
+import currencySymbols from '../currency-symbols.json';
+
// Big Number Constants
const BIG_NUMBER_WEI_MULTIPLIER = new BigNumber('1000000000000000000');
const BIG_NUMBER_GWEI_MULTIPLIER = new BigNumber('1000000000');
@@ -741,3 +742,21 @@ export const toHexadecimal = (decimal) => {
if (decimal.startsWith('0x')) return decimal;
return toBigNumber.dec(decimal).toString(16);
};
+
+export const calculateEthFeeForMultiLayer = ({
+ multiLayerL1FeeTotal,
+ ethFee = 0,
+}) => {
+ if (!multiLayerL1FeeTotal) {
+ return ethFee;
+ }
+ const multiLayerL1FeeTotalDecEth = conversionUtil(multiLayerL1FeeTotal, {
+ fromNumericBase: 'hex',
+ toNumericBase: 'dec',
+ fromDenomination: 'WEI',
+ toDenomination: 'ETH',
+ });
+ return new BigNumber(multiLayerL1FeeTotalDecEth)
+ .plus(new BigNumber(ethFee ?? 0))
+ .toString(10);
+};
diff --git a/app/util/number/index.test.ts b/app/util/number/index.test.ts
index fdf07bc3d81..95bcc29e700 100644
--- a/app/util/number/index.test.ts
+++ b/app/util/number/index.test.ts
@@ -24,6 +24,7 @@ import {
safeNumberToBN,
fastSplit,
isNumber,
+ calculateEthFeeForMultiLayer,
} from '.';
describe('Number utils :: BNToHex', () => {
@@ -664,3 +665,23 @@ describe('Number utils :: isNumber', () => {
expect(isNumber(null)).toBe(false);
});
});
+
+describe('Number utils :: calculateEthFeeForMultiLayer', () => {
+ it('returns ethFee if multiLayerL1FeeTotal is falsy', () => {
+ expect(
+ calculateEthFeeForMultiLayer({
+ multiLayerL1FeeTotal: undefined,
+ ethFee: 0.000001,
+ }),
+ ).toBe(0.000001);
+ });
+
+ it('returns a new ETH fee which includes a multiLayerL1FeeTotal fee', () => {
+ expect(
+ calculateEthFeeForMultiLayer({
+ multiLayerL1FeeTotal: 'ce37bdd0b8b8',
+ ethFee: 0.000001,
+ }),
+ ).toBe('0.000227739');
+ });
+});
diff --git a/app/util/test/testSetup.js b/app/util/test/testSetup.js
index 5fc7aa22b3c..3ab92086595 100644
--- a/app/util/test/testSetup.js
+++ b/app/util/test/testSetup.js
@@ -126,6 +126,19 @@ jest.mock(
);
jest.mock('@react-native-cookies/cookies', () => 'RNCookies');
+const mockReactNativeWebRTC = {
+ RTCPeerConnection: () => null,
+ RTCIceCandidate: () => null,
+ RTCSessionDescription: () => null,
+ RTCView: () => null,
+ MediaStream: () => null,
+ MediaStreamTrack: () => null,
+ mediaDevices: () => null,
+ registerGlobals: () => null,
+};
+
+jest.mock('react-native-webrtc', () => mockReactNativeWebRTC);
+
NativeModules.RNGestureHandlerModule = {
attachGestureHandler: jest.fn(),
createGestureHandler: jest.fn(),
diff --git a/app/util/transactions/index.test.ts b/app/util/transactions/index.test.ts
index fcf1f6ab29e..3b0ebeba8d6 100644
--- a/app/util/transactions/index.test.ts
+++ b/app/util/transactions/index.test.ts
@@ -1,9 +1,10 @@
import { swapsUtils } from '@metamask/swaps-controller';
import { util } from '@metamask/controllers';
+import { BN } from 'ethereumjs-util';
+
import { BNToHex } from '../number';
import { UINT256_BN_MAX_VALUE } from '../../constants/transaction';
import { NEGATIVE_TOKEN_DECIMALS } from '../../constants/error';
-
import {
generateTransferData,
decodeApproveData,
@@ -16,6 +17,7 @@ import {
CONTRACT_METHOD_DEPLOY,
TOKEN_METHOD_TRANSFER_FROM,
} from '.';
+import { buildUnserializedTransaction } from './optimismTransaction';
import Engine from '../../core/Engine';
import { strings } from '../../../locales/i18n';
@@ -379,3 +381,28 @@ describe('Transactions utils :: minimumTokenAllowance', () => {
}).toThrow(NEGATIVE_TOKEN_DECIMALS);
});
});
+
+describe('Transactions utils :: buildUnserializedTransaction', () => {
+ it('returns a transaction that can be serialized and fed to an Optimism smart contract', () => {
+ const unserializedTransaction = buildUnserializedTransaction({
+ txParams: {
+ nonce: '0x0',
+ gasPrice: `0x${new BN('100').toString(16)}`,
+ gas: `0x${new BN('21000').toString(16)}`,
+ to: '0x0000000000000000000000000000000000000000',
+ value: `0x${new BN('10000000000000').toString(16)}`,
+ data: '0x0',
+ },
+ chainId: '10',
+ metamaskNetworkId: '10',
+ });
+ expect(unserializedTransaction.toJSON()).toMatchObject({
+ nonce: '0x0',
+ gasPrice: '0x64',
+ gasLimit: '0x5208',
+ to: '0x0000000000000000000000000000000000000000',
+ value: '0x9184e72a000',
+ data: '0x00',
+ });
+ });
+});
diff --git a/app/util/transactions/optimismTransaction.ts b/app/util/transactions/optimismTransaction.ts
new file mode 100644
index 00000000000..54c1ce4d79f
--- /dev/null
+++ b/app/util/transactions/optimismTransaction.ts
@@ -0,0 +1,49 @@
+import { omit } from 'lodash';
+import { BN } from 'ethereumjs-util';
+import Common, { Chain, Hardfork } from '@ethereumjs/common';
+import { TransactionFactory, TxData } from '@ethereumjs/tx';
+
+import { stripHexPrefix } from '../../util/address';
+
+interface TxDataWithGas extends TxData {
+ gas: string;
+}
+
+interface TxMeta {
+ chainId: string;
+ metamaskNetworkId: string;
+ txParams: TxDataWithGas;
+}
+
+const buildTxParams = (txMeta: TxMeta) => ({
+ ...omit(txMeta.txParams, 'gas'),
+ gasLimit: txMeta.txParams.gas,
+});
+
+const buildTransactionCommon = (txMeta: TxMeta) =>
+ // This produces a transaction whose information does not completely match an
+ // Optimism transaction — for instance, DEFAULT_CHAIN is still 'mainnet' and
+ // genesis points to the mainnet genesis, not the Optimism genesis — but
+ // considering that all we want to do is serialize a transaction, this works
+ // fine for our use case.
+ Common.forCustomChain(Chain.Mainnet, {
+ chainId: new BN(stripHexPrefix(txMeta.chainId), 16),
+ networkId: new BN(txMeta.metamaskNetworkId, 10),
+ // Optimism only supports type-0 transactions; it does not support any of
+ // the newer EIPs since EIP-155. Source:
+ //
+ defaultHardfork: Hardfork.SpuriousDragon,
+ });
+
+/**
+ * Returns a transaction that can be serialized and fed to an Optimism smart contract.
+ *
+ * @param {Object} txMeta
+ * @returns {Object}
+ */
+// eslint-disable-next-line import/prefer-default-export
+export const buildUnserializedTransaction = (txMeta: TxMeta) => {
+ const txParams = buildTxParams(txMeta);
+ const common = buildTransactionCommon(txMeta);
+ return TransactionFactory.fromTxData(txParams, { common });
+};
diff --git a/bitrise.yml b/bitrise.yml
index c64a5777a11..9c9c1080851 100644
--- a/bitrise.yml
+++ b/bitrise.yml
@@ -22,11 +22,6 @@ workflows:
- cache_local_deps: 'yes'
- command: setup
title: Yarn Setup
- - yarn@0:
- inputs:
- - cache_local_deps: 'yes'
- - command: setup:react-native-webrtc
- title: Yarn Download WebRTC Bitcode
- yarn@0:
inputs:
- cache_local_deps: 'yes'
@@ -48,11 +43,6 @@ workflows:
- cache_local_deps: 'yes'
- command: setup
title: Yarn Setup
- - yarn@0:
- inputs:
- - cache_local_deps: 'yes'
- - command: setup:react-native-webrtc
- title: Yarn Download WebRTC Bitcode
- yarn@0:
inputs:
- cache_local_deps: 'yes'
diff --git a/ios/MetaMask.xcodeproj/project.pbxproj b/ios/MetaMask.xcodeproj/project.pbxproj
index 916d94e2122..3e0b6a6a5ea 100644
--- a/ios/MetaMask.xcodeproj/project.pbxproj
+++ b/ios/MetaMask.xcodeproj/project.pbxproj
@@ -1142,7 +1142,7 @@
"$(SRCROOT)/../node_modules/react-native-tcp/ios/**",
);
INFOPLIST_FILE = MetaMask/Info.plist;
- IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@@ -1186,6 +1186,7 @@
CURRENT_PROJECT_VERSION = 1018;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = 48XVW22RCG;
+ ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
@@ -1208,7 +1209,7 @@
"$(SRCROOT)/../node_modules/react-native-tcp/ios/**",
);
INFOPLIST_FILE = MetaMask/Info.plist;
- IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@@ -1258,6 +1259,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
+ ENABLE_BITCODE = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
@@ -1300,6 +1302,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = YES;
+ ENABLE_BITCODE = NO;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
@@ -1396,6 +1399,7 @@
CURRENT_PROJECT_VERSION = 1018;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = 48XVW22RCG;
+ ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
diff --git a/ios/MetaMask/Info.plist b/ios/MetaMask/Info.plist
index 3b534004143..6907770e02e 100644
--- a/ios/MetaMask/Info.plist
+++ b/ios/MetaMask/Info.plist
@@ -20,6 +20,13 @@
$(MARKETING_VERSION)
CFBundleSignature
????
+ branch_universal_link_domains
+
+ metamask.app.link
+ metamask-alternate.app.link
+ metamask.test.app.link
+ metamask-alternate.test.app.link
+
CFBundleURLTypes
@@ -115,7 +122,12 @@
UIViewControllerBasedStatusBarAppearance
branch_key
- $(MM_BRANCH_KEY_LIVE)
+
+ live
+ $(MM_BRANCH_KEY_LIVE)
+ test
+ $(MM_BRANCH_KEY_TEST)
+
fox_code
$(MM_FOX_CODE)
mixpanel_token
diff --git a/ios/Podfile b/ios/Podfile
index fb377e1bfea..fd768f67f67 100644
--- a/ios/Podfile
+++ b/ios/Podfile
@@ -1,13 +1,13 @@
require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
-platform :ios, "11.0"
+platform :ios, "12.0"
def react_native_post_install(installer)
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
if Gem::Version.new('9.0') > Gem::Version.new(config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'])
- config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = "11.0"
+ config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = "12.0"
end
config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
end
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 29172c0180a..ad424d03565 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -1,6 +1,6 @@
PODS:
- boost (1.76.0)
- - Branch (1.41.0)
+ - Branch (1.43.2)
- BVLinearGradient (2.5.6):
- React
- CocoaAsyncSocket (7.6.5)
@@ -75,6 +75,7 @@ PODS:
- FlipperKit/FlipperKitNetworkPlugin
- fmt (6.2.1)
- glog (0.3.5)
+ - JitsiWebRTC (106.0.0)
- libevent (2.1.12)
- lottie-ios (2.5.3)
- lottie-react-native (3.1.0):
@@ -297,8 +298,8 @@ PODS:
- React
- react-native-blur (0.8.0):
- React
- - react-native-branch (5.4.0):
- - Branch (= 1.41.0)
+ - react-native-branch (5.6.2):
+ - Branch (= 1.43.2)
- React-Core
- react-native-camera (3.44.3):
- React-Core
@@ -333,7 +334,8 @@ PODS:
- React
- react-native-viewpager (3.3.1):
- React
- - react-native-webrtc (1.100.0):
+ - react-native-webrtc (106.0.0-beta.7):
+ - JitsiWebRTC (~> 106.0.0)
- React-Core
- react-native-webview (11.13.0):
- React-Core
@@ -610,6 +612,7 @@ SPEC REPOS:
- Flipper-RSocket
- FlipperKit
- fmt
+ - JitsiWebRTC
- libevent
- lottie-ios
- OpenSSL-Universal
@@ -774,7 +777,7 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
boost: a7c83b31436843459a1961bfd74b96033dc77234
- Branch: bd6c472d6cab03206877ac86c1241327a3f217d1
+ Branch: 74cc856025984f691833c8fa332834ac38a0cf4e
BVLinearGradient: e3aad03778a456d77928f594a649e96995f1c872
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
DoubleConversion: 831926d9b8bf8166fd87886c4abab286c2422662
@@ -791,6 +794,7 @@ SPEC CHECKSUMS:
FlipperKit: aec2d931adeee48a07bab1ea8bcc8a6bb87dfce4
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
glog: 5337263514dd6f09803962437687240c5dc39aa4
+ JitsiWebRTC: f441eb0e2d67f0588bf24e21c5162e97342714fb
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
lottie-ios: a50d5c0160425cd4b01b852bb9578963e6d92d31
lottie-react-native: 7ca15c46249b61e3f9ffcf114cb4123e907a2156
@@ -811,7 +815,7 @@ SPEC CHECKSUMS:
react-native-aes: ff31f0dd4c791eb423a631ee04570fcf3c618924
react-native-background-timer: 1b6e6b4e10f1b74c367a1fdc3c72b67c619b222b
react-native-blur: cad4d93b364f91e7b7931b3fa935455487e5c33c
- react-native-branch: 5b20bf032b3a1a20d2b76e57215bd3254a137dd5
+ react-native-branch: 4e42fda662d96893afbbd02839806931398e3d2e
react-native-camera: b8cc03e2feec0c04403d0998e37cf519d8fd4c6f
react-native-cookies: f54fcded06bb0cda05c11d86788020b43528a26c
react-native-get-random-values: a6ea6a8a65dc93e96e24a11105b1a9c8cfe1d72a
@@ -824,7 +828,7 @@ SPEC CHECKSUMS:
react-native-video: 0bb76b6d6b77da3009611586c7dbf817b947f30e
react-native-view-shot: 4475fde003fe8a210053d1f98fb9e06c1d834e1c
react-native-viewpager: f730c1d175a2c1ae789464855d4a2c14247d3109
- react-native-webrtc: b8f2769386d51a6a8c89778478618fe311226bc3
+ react-native-webrtc: f73459325441d15812f86071bdbd0bf3376235d1
react-native-webview: 133a6a5149f963259646e710b4545c67ef35d7c9
React-perflogger: 169fb34f60c5fd793b370002ee9c916eba9bc4ae
React-RCTActionSheet: 2355539e02ad5cd4b1328682ab046487e1e1e920
@@ -868,6 +872,6 @@ SPEC CHECKSUMS:
Yoga: b316a990bb6d115afa1b436b5626ac7c61717d17
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
-PODFILE CHECKSUM: 7f7f2a91148820d72060690efb985d8d04e01f4b
+PODFILE CHECKSUM: 74e503a275b4ed097cb01c171027882e9cdc699d
COCOAPODS: 1.11.3
diff --git a/locales/languages/en.json b/locales/languages/en.json
index d36d2327571..750689fed64 100644
--- a/locales/languages/en.json
+++ b/locales/languages/en.json
@@ -1480,6 +1480,7 @@
"wc_sent_tx_title": "Sent transaction",
"wc_connected_rejected_title": "You've rejected the connect request",
"wc_signed_rejected_title": "You've rejected the sign request",
+ "wc_signed_failed_title": "This sign request failed",
"wc_sent_tx_rejected_title": "You've rejected the transaction request",
"wc_description": "Please check the application"
},
diff --git a/package.json b/package.json
index be2c3cfb963..3be4fa82f47 100644
--- a/package.json
+++ b/package.json
@@ -12,11 +12,10 @@
"clean:node": "rm -rf node_modules && yarn --frozen-lockfile",
"clean": "yarn clean:ios && yarn clean:android && yarn clean:node",
"clean-android": "yarn clean:android && yarn clean:node",
- "setup:react-native-webrtc": "cd node_modules/react-native-webrtc/tools && ./downloadBitcode.sh && cd ../../../",
"lint": "eslint '**/*.{js,ts,tsx}' --ignore-path=.prettierignore",
"lint:fix": "eslint '**/*.{js,ts,tsx}' --fix --ignore-path=.prettierignore",
"format": "prettier '**/*.{js,ts,tsx,json}' --write",
- "setup": "yarn clean && yarn setup:react-native-webrtc && yarn pod:install && yarn allow-scripts && ./scripts/postinstall.sh",
+ "setup": "yarn clean && yarn pod:install && yarn allow-scripts && ./scripts/postinstall.sh",
"setup:e2e": "cd wdio && yarn install",
"start:ios": "./scripts/build.sh ios debug",
"start:ios:qa": "./scripts/build.sh ios qaDebug",
@@ -127,6 +126,9 @@
},
"dependencies": {
"@consensys/on-ramp-sdk": "^1.3.1-beta.10",
+ "@eth-optimism/contracts": "0.0.0-2021919175625",
+ "@ethereumjs/common": "^2.3.1",
+ "@ethereumjs/tx": "^3.2.1",
"@exodus/react-native-payments": "git+https://github.com/MetaMask/react-native-payments.git#dbc8cbbed570892d2fea5e3d183bf243e062c1e5",
"@keystonehq/bc-ur-registry-eth": "^0.7.7",
"@keystonehq/metamask-airgapped-keyring": "^0.3.0",
@@ -138,7 +140,7 @@
"@metamask/post-message-stream": "6.0.0",
"@metamask/sdk-communication-layer": "^0.0.1-beta.3",
"@metamask/snap-controllers": "^0.23.0",
- "@metamask/swaps-controller": "^6.6.0",
+ "@metamask/swaps-controller": "^6.7.0",
"@ngraveio/bc-ur": "^1.1.6",
"@react-native-async-storage/async-storage": "1.17.10",
"@react-native-clipboard/clipboard": "^1.8.4",
@@ -200,6 +202,7 @@
"is-url": "^1.2.4",
"json-rpc-engine": "^6.1.0",
"json-rpc-middleware-stream": "3.0.0",
+ "lodash": "^4.17.21",
"lottie-react-native": "git+https://github.com/MetaMask/lottie-react-native.git#7ce6a78ac4ac7b9891bc513cb3f12f8b9c9d9106",
"metro-config": "^0.71.1",
"multihashes": "0.4.14",
@@ -224,7 +227,7 @@
"react-native-animatable": "^1.3.3",
"react-native-animated-fox": "git+https://github.com/MetaMask/react-native-animated-fox.git#16e38d54d829709e497f196e31fa8ff00cdf2aa9",
"react-native-background-timer": "2.1.1",
- "react-native-branch": "5.4.0",
+ "react-native-branch": "^5.6.2",
"react-native-browser-polyfill": "0.1.2",
"react-native-button": "git+https://github.com/MetaMask/react-native-button.git#fd79f4d6c8ced4086ba6e3021b6ed6d4a3e19cf7",
"react-native-camera": "^3.36.0",
@@ -275,7 +278,7 @@
"react-native-vector-icons": "6.4.2",
"react-native-video": "^5.1.1",
"react-native-view-shot": "^3.1.2",
- "react-native-webrtc": "^1.100.0",
+ "react-native-webrtc": "^106.0.0-beta.7",
"react-native-webview": "11.13.0",
"react-redux": "7.2.4",
"readable-stream": "1.0.33",
@@ -285,7 +288,7 @@
"redux-persist-filesystem-storage": "^3.0.0",
"reselect": "^4.0.0",
"rn-fetch-blob": "^0.12.0",
- "socket.io-client": "^4.5.1",
+ "socket.io-client": "^4.5.3",
"stream-browserify": "1.0.0",
"swappable-obj-proxy": "^1.1.0",
"through2": "3.0.1",
@@ -491,7 +494,9 @@
"appium-windows-driver": false,
"chromedriver": false,
"canvas": false,
- "react-native-webrtc": true
+ "react-native-webrtc": true,
+ "node-hid": false,
+ "usb": false
}
}
}
diff --git a/yarn.lock b/yarn.lock
index 5e6013014cb..4f2bb5fc350 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1936,6 +1936,39 @@
minimatch "^3.0.4"
strip-json-comments "^3.1.1"
+"@eth-optimism/contracts@0.0.0-2021919175625":
+ version "0.0.0-2021919175625"
+ resolved "https://registry.yarnpkg.com/@eth-optimism/contracts/-/contracts-0.0.0-2021919175625.tgz#551ed5d98ac4405596e97f723c28ee6376e65546"
+ integrity sha512-vf/rH0lUk5TRvY7/Rq8jAYXfJvAixcgnYyHVPPBdPUdWlOPfnUx1bG5N1xfaBI/zKJ1zen5gsJW4zaM+rUVKsQ==
+ dependencies:
+ "@eth-optimism/core-utils" "^0.0.0-2021919175625"
+ "@ethersproject/abstract-provider" "^5.4.1"
+ "@ethersproject/abstract-signer" "^5.4.1"
+ "@ethersproject/contracts" "^5.4.1"
+ "@ethersproject/hardware-wallets" "^5.4.0"
+
+"@eth-optimism/core-utils@^0.0.0-2021919175625":
+ version "0.0.0-2022819193354"
+ resolved "https://registry.yarnpkg.com/@eth-optimism/core-utils/-/core-utils-0.0.0-2022819193354.tgz#37e799e050ed303369d842f4a14714240e58bd44"
+ integrity sha512-5fgc5QRVk+MINgDCU8N5TxtlR1te4jrjZrFaXa8hQ/XRZ1WfkE9RmYSA5jvv57eCHreK5HxJW1sjF940LzarJw==
+ dependencies:
+ "@ethersproject/abi" "^5.7.0"
+ "@ethersproject/abstract-provider" "^5.7.0"
+ "@ethersproject/address" "^5.7.0"
+ "@ethersproject/bignumber" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/constants" "^5.7.0"
+ "@ethersproject/contracts" "^5.7.0"
+ "@ethersproject/hash" "^5.7.0"
+ "@ethersproject/keccak256" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+ "@ethersproject/providers" "^5.7.0"
+ "@ethersproject/rlp" "^5.7.0"
+ "@ethersproject/transactions" "^5.7.0"
+ "@ethersproject/web" "^5.7.0"
+ bufio "^1.0.7"
+ chai "^4.3.4"
+
"@ethereumjs/common@^2.0.0":
version "2.6.0"
resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.6.0.tgz#feb96fb154da41ee2cc2c5df667621a440f36348"
@@ -2056,7 +2089,7 @@
"@ethersproject/transactions" "^5.4.0"
"@ethersproject/web" "^5.4.0"
-"@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.7.0":
+"@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.4.1", "@ethersproject/abstract-provider@^5.7.0":
version "5.7.0"
resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef"
integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==
@@ -2093,7 +2126,7 @@
"@ethersproject/logger" "^5.4.0"
"@ethersproject/properties" "^5.4.0"
-"@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.7.0":
+"@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.4.1", "@ethersproject/abstract-signer@^5.7.0":
version "5.7.0"
resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2"
integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==
@@ -2238,7 +2271,7 @@
"@ethersproject/properties" "^5.4.0"
"@ethersproject/transactions" "^5.4.0"
-"@ethersproject/contracts@5.7.0", "@ethersproject/contracts@^5.7.0":
+"@ethersproject/contracts@5.7.0", "@ethersproject/contracts@^5.4.1", "@ethersproject/contracts@^5.7.0":
version "5.7.0"
resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e"
integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==
@@ -2254,6 +2287,18 @@
"@ethersproject/properties" "^5.7.0"
"@ethersproject/transactions" "^5.7.0"
+"@ethersproject/hardware-wallets@^5.4.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/hardware-wallets/-/hardware-wallets-5.7.0.tgz#1c902fc255e2f108af44d4c1dc46ec2c34cb669c"
+ integrity sha512-DjMMXIisRc8xFvEoLoYz1w7JDOYmaz/a0X9sp7Zu668RR8U1zCAyj5ow25HLRW+TCzEC5XiFetTXqS5kXonFCQ==
+ dependencies:
+ "@ledgerhq/hw-app-eth" "5.27.2"
+ "@ledgerhq/hw-transport" "5.26.0"
+ "@ledgerhq/hw-transport-u2f" "5.26.0"
+ ethers "^5.7.0"
+ optionalDependencies:
+ "@ledgerhq/hw-transport-node-hid" "5.26.0"
+
"@ethersproject/hash@5.4.0", "@ethersproject/hash@^5.4.0":
version "5.4.0"
resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.4.0.tgz#d18a8e927e828e22860a011f39e429d388344ae0"
@@ -2402,6 +2447,13 @@
dependencies:
"@ethersproject/logger" "^5.7.0"
+"@ethersproject/networks@5.7.1":
+ version "5.7.1"
+ resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6"
+ integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==
+ dependencies:
+ "@ethersproject/logger" "^5.7.0"
+
"@ethersproject/networks@^5.4.0":
version "5.4.1"
resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.4.1.tgz#2ce83b8e42aa85216e5d277a7952d97b6ce8d852"
@@ -2497,7 +2549,7 @@
bech32 "1.1.4"
ws "7.4.6"
-"@ethersproject/providers@^5.7.0":
+"@ethersproject/providers@5.7.2", "@ethersproject/providers@^5.7.0":
version "5.7.2"
resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb"
integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==
@@ -2750,6 +2802,17 @@
"@ethersproject/properties" "^5.7.0"
"@ethersproject/strings" "^5.7.0"
+"@ethersproject/web@5.7.1":
+ version "5.7.1"
+ resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae"
+ integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==
+ dependencies:
+ "@ethersproject/base64" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+ "@ethersproject/strings" "^5.7.0"
+
"@ethersproject/wordlists@5.4.0", "@ethersproject/wordlists@^5.4.0":
version "5.4.0"
resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.4.0.tgz#f34205ec3bbc9e2c49cadaee774cf0b07e7573d7"
@@ -3817,6 +3880,97 @@
resolved "https://registry.yarnpkg.com/@lavamoat/preinstall-always-fail/-/preinstall-always-fail-1.0.0.tgz#e78a6e3d9e212a4fef869ec37d4f5fb498dea373"
integrity sha512-vD2DcC0ffJj1w2y1Lu0OU39wHmlPEd2tCDW04Bm6Kf4LyRnCHCezTsS8yzeSJ+4so7XP+TITuR5FGJRWxPb+GA==
+"@ledgerhq/cryptoassets@^5.27.2":
+ version "5.53.0"
+ resolved "https://registry.yarnpkg.com/@ledgerhq/cryptoassets/-/cryptoassets-5.53.0.tgz#11dcc93211960c6fd6620392e4dd91896aaabe58"
+ integrity sha512-M3ibc3LRuHid5UtL7FI3IC6nMEppvly98QHFoSa7lJU0HDzQxY6zHec/SPM4uuJUC8sXoGVAiRJDkgny54damw==
+ dependencies:
+ invariant "2"
+
+"@ledgerhq/devices@^5.26.0", "@ledgerhq/devices@^5.51.1":
+ version "5.51.1"
+ resolved "https://registry.yarnpkg.com/@ledgerhq/devices/-/devices-5.51.1.tgz#d741a4a5d8f17c2f9d282fd27147e6fe1999edb7"
+ integrity sha512-4w+P0VkbjzEXC7kv8T1GJ/9AVaP9I6uasMZ/JcdwZBS3qwvKo5A5z9uGhP5c7TvItzcmPb44b5Mw2kT+WjUuAA==
+ dependencies:
+ "@ledgerhq/errors" "^5.50.0"
+ "@ledgerhq/logs" "^5.50.0"
+ rxjs "6"
+ semver "^7.3.5"
+
+"@ledgerhq/errors@^5.26.0", "@ledgerhq/errors@^5.50.0":
+ version "5.50.0"
+ resolved "https://registry.yarnpkg.com/@ledgerhq/errors/-/errors-5.50.0.tgz#e3a6834cb8c19346efca214c1af84ed28e69dad9"
+ integrity sha512-gu6aJ/BHuRlpU7kgVpy2vcYk6atjB4iauP2ymF7Gk0ez0Y/6VSMVSJvubeEQN+IV60+OBK0JgeIZG7OiHaw8ow==
+
+"@ledgerhq/hw-app-eth@5.27.2":
+ version "5.27.2"
+ resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-eth/-/hw-app-eth-5.27.2.tgz#65a2ed613a69340e0cd69c942147455ec513d006"
+ integrity sha512-llNdrE894cCN8j6yxJEUniciyLVcLmu5N0UmIJLOObztG+5rOF4bX54h4SreTWK+E10Z0CzHSeyE5Lz/tVcqqQ==
+ dependencies:
+ "@ledgerhq/cryptoassets" "^5.27.2"
+ "@ledgerhq/errors" "^5.26.0"
+ "@ledgerhq/hw-transport" "^5.26.0"
+ bignumber.js "^9.0.1"
+ rlp "^2.2.6"
+
+"@ledgerhq/hw-transport-node-hid-noevents@^5.26.0":
+ version "5.51.1"
+ resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid-noevents/-/hw-transport-node-hid-noevents-5.51.1.tgz#71f37f812e448178ad0bcc2258982150d211c1ab"
+ integrity sha512-9wFf1L8ZQplF7XOY2sQGEeOhpmBRzrn+4X43kghZ7FBDoltrcK+s/D7S+7ffg3j2OySyP6vIIIgloXylao5Scg==
+ dependencies:
+ "@ledgerhq/devices" "^5.51.1"
+ "@ledgerhq/errors" "^5.50.0"
+ "@ledgerhq/hw-transport" "^5.51.1"
+ "@ledgerhq/logs" "^5.50.0"
+ node-hid "2.1.1"
+
+"@ledgerhq/hw-transport-node-hid@5.26.0":
+ version "5.26.0"
+ resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-5.26.0.tgz#69bc4f8067cdd9c09ef4aed0e0b3c58328936e4b"
+ integrity sha512-qhaefZVZatJ6UuK8Wb6WSFNOLWc2mxcv/xgsfKi5HJCIr4bPF/ecIeN+7fRcEaycxj4XykY6Z4A7zDVulfFH4w==
+ dependencies:
+ "@ledgerhq/devices" "^5.26.0"
+ "@ledgerhq/errors" "^5.26.0"
+ "@ledgerhq/hw-transport" "^5.26.0"
+ "@ledgerhq/hw-transport-node-hid-noevents" "^5.26.0"
+ "@ledgerhq/logs" "^5.26.0"
+ lodash "^4.17.20"
+ node-hid "1.3.0"
+ usb "^1.6.3"
+
+"@ledgerhq/hw-transport-u2f@5.26.0":
+ version "5.26.0"
+ resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-u2f/-/hw-transport-u2f-5.26.0.tgz#b7d9d13193eb82b051fd7a838cd652372f907ec5"
+ integrity sha512-QTxP1Rsh+WZ184LUOelYVLeaQl3++V3I2jFik+l9JZtakwEHjD0XqOT750xpYNL/vfHsy31Wlz+oicdxGzFk+w==
+ dependencies:
+ "@ledgerhq/errors" "^5.26.0"
+ "@ledgerhq/hw-transport" "^5.26.0"
+ "@ledgerhq/logs" "^5.26.0"
+ u2f-api "0.2.7"
+
+"@ledgerhq/hw-transport@5.26.0":
+ version "5.26.0"
+ resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-5.26.0.tgz#bfedc3d48400ad2fe48278d9444344b72aa9d0fe"
+ integrity sha512-NFeJOJmyEfAX8uuIBTpocWHcz630sqPcXbu864Q+OCBm4EK5UOKV1h/pX7e0xgNIKY8zhJ/O4p4cIZp9tnXLHQ==
+ dependencies:
+ "@ledgerhq/devices" "^5.26.0"
+ "@ledgerhq/errors" "^5.26.0"
+ events "^3.2.0"
+
+"@ledgerhq/hw-transport@^5.26.0", "@ledgerhq/hw-transport@^5.51.1":
+ version "5.51.1"
+ resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-5.51.1.tgz#8dd14a8e58cbee4df0c29eaeef983a79f5f22578"
+ integrity sha512-6wDYdbWrw9VwHIcoDnqWBaDFyviyjZWv6H9vz9Vyhe4Qd7TIFmbTl/eWs6hZvtZBza9K8y7zD8ChHwRI4s9tSw==
+ dependencies:
+ "@ledgerhq/devices" "^5.51.1"
+ "@ledgerhq/errors" "^5.50.0"
+ events "^3.3.0"
+
+"@ledgerhq/logs@^5.26.0", "@ledgerhq/logs@^5.50.0":
+ version "5.50.0"
+ resolved "https://registry.yarnpkg.com/@ledgerhq/logs/-/logs-5.50.0.tgz#29c6419e8379d496ab6d0426eadf3c4d100cd186"
+ integrity sha512-swKHYCOZUGyVt4ge0u8a7AwNcA//h4nx5wIi0sruGye1IJ5Cva0GyK9L2/WdX+kWVTKp92ZiEo1df31lrWGPgA==
+
"@log4js-node/log4js-api@^1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@log4js-node/log4js-api/-/log4js-api-1.0.2.tgz#7a8143fb33f077df3e579dca7f18fea74a02ec8b"
@@ -4189,10 +4343,10 @@
ses "^0.17.0"
superstruct "^0.16.7"
-"@metamask/swaps-controller@^6.6.0":
- version "6.6.0"
- resolved "https://registry.yarnpkg.com/@metamask/swaps-controller/-/swaps-controller-6.6.0.tgz#328fa32bee32d07521cf0a0fb1cd0b7f0e878e20"
- integrity sha512-vMQpSexx1ONea2q1oYEOC7yUnd6glkkirFdgpXUXp2iILp1euAa9YukljhWRXQ3Juii33TwVhT7sCcE+Y+yEoA==
+"@metamask/swaps-controller@^6.7.0":
+ version "6.7.0"
+ resolved "https://registry.yarnpkg.com/@metamask/swaps-controller/-/swaps-controller-6.7.0.tgz#bcd231e034a30a95c9c89aff4f24c8c1cae1e5f6"
+ integrity sha512-ZgdueQn8fcD5pYl8UuNSWdnXqWMhPsLGC3VobwsRSF1cj3ACSZNwS4Q9lbY46B2lhkvy7Tu6dOt4k0BjgrPDEw==
dependencies:
"@metamask/controllers" "^26.0.0"
abort-controller "^3.0.0"
@@ -6585,6 +6739,11 @@ adbkit-apkreader@^3.1.2:
debug "~4.1.1"
yauzl "^2.7.0"
+adm-zip@0.5.9:
+ version "0.5.9"
+ resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.5.9.tgz#b33691028333821c0cf95c31374c5462f2905a83"
+ integrity sha512-s+3fXLkeeLjZ2kLjCBwQufpI5fuN+kIGBxu6530nVQZGVol0d7Y/M88/xw9HGGUcJjKf8LutN3VPRUBq6N7Ajg==
+
aes-js@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d"
@@ -7661,6 +7820,11 @@ assertion-error-formatter@^3.0.0:
pad-right "^0.2.2"
repeat-string "^1.6.1"
+assertion-error@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b"
+ integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==
+
assign-symbols@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
@@ -8645,6 +8809,11 @@ bufferutil@^4.0.1:
dependencies:
node-gyp-build "^4.3.0"
+bufio@^1.0.7:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/bufio/-/bufio-1.1.3.tgz#7f8e524fd719ced2caa563a09d50550f283f745f"
+ integrity sha512-W0ydG8t+ST+drUpEwl1N+dU9Ije06g8+43CLtvEIzfKo9nPFLXbKqDYE2XSg4w6RugsBcCj7pEU7jOpBC6BqrA==
+
bunyan-debug-stream@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/bunyan-debug-stream/-/bunyan-debug-stream-2.0.1.tgz#9bd7c7e30c7b2cf711317e9d37529b0464c3b164"
@@ -8859,6 +9028,19 @@ cbor-sync@^1.0.4:
resolved "https://registry.yarnpkg.com/cbor-sync/-/cbor-sync-1.0.4.tgz#5a11a1ab75c2a14d1af1b237fd84aa8c1593662f"
integrity sha512-GWlXN4wiz0vdWWXBU71Dvc1q3aBo0HytqwAZnXF1wOwjqNnDWA1vZ1gDMFLlqohak31VQzmhiYfiCX5QSSfagA==
+chai@^4.3.4:
+ version "4.3.7"
+ resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.7.tgz#ec63f6df01829088e8bf55fca839bcd464a8ec51"
+ integrity sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==
+ dependencies:
+ assertion-error "^1.1.0"
+ check-error "^1.0.2"
+ deep-eql "^4.1.2"
+ get-func-name "^2.0.0"
+ loupe "^2.3.1"
+ pathval "^1.1.1"
+ type-detect "^4.0.5"
+
chainsaw@~0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/chainsaw/-/chainsaw-0.1.0.tgz#5eab50b28afe58074d0d58291388828b5e5fbc98"
@@ -8951,6 +9133,11 @@ charenc@0.0.2:
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
integrity sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==
+check-error@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82"
+ integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==
+
checkpoint-store@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/checkpoint-store/-/checkpoint-store-1.1.0.tgz#04e4cb516b91433893581e6d4601a78e9552ea06"
@@ -10139,6 +10326,13 @@ dedent@^0.7.0:
resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=
+deep-eql@^4.1.2:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.2.tgz#270ceb902f87724077e6f6449aed81463f42fc1c"
+ integrity sha512-gT18+YW4CcW/DBNTwAmqTtkJh7f9qqScu2qFVlx7kCoeY9tlBu9cUcr7+I+Z/noG8INehS3xQgLpTtd/QUTn4w==
+ dependencies:
+ type-detect "^4.0.0"
+
deep-equal@*:
version "2.0.5"
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.0.5.tgz#55cd2fe326d83f9cbf7261ef0e060b3f724c5cb9"
@@ -10349,6 +10543,11 @@ detect-browser@^5.2.0:
resolved "https://registry.yarnpkg.com/detect-browser/-/detect-browser-5.3.0.tgz#9705ef2bddf46072d0f7265a1fe300e36fe7ceca"
integrity sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w==
+detect-libc@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
+ integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==
+
detect-libc@^2.0.0, detect-libc@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.1.tgz#e1897aa88fa6ad197862937fbc0441ef352ee0cd"
@@ -12155,6 +12354,42 @@ ethers@^5.4.1:
"@ethersproject/web" "5.4.0"
"@ethersproject/wordlists" "5.4.0"
+ethers@^5.7.0:
+ version "5.7.2"
+ resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e"
+ integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==
+ dependencies:
+ "@ethersproject/abi" "5.7.0"
+ "@ethersproject/abstract-provider" "5.7.0"
+ "@ethersproject/abstract-signer" "5.7.0"
+ "@ethersproject/address" "5.7.0"
+ "@ethersproject/base64" "5.7.0"
+ "@ethersproject/basex" "5.7.0"
+ "@ethersproject/bignumber" "5.7.0"
+ "@ethersproject/bytes" "5.7.0"
+ "@ethersproject/constants" "5.7.0"
+ "@ethersproject/contracts" "5.7.0"
+ "@ethersproject/hash" "5.7.0"
+ "@ethersproject/hdnode" "5.7.0"
+ "@ethersproject/json-wallets" "5.7.0"
+ "@ethersproject/keccak256" "5.7.0"
+ "@ethersproject/logger" "5.7.0"
+ "@ethersproject/networks" "5.7.1"
+ "@ethersproject/pbkdf2" "5.7.0"
+ "@ethersproject/properties" "5.7.0"
+ "@ethersproject/providers" "5.7.2"
+ "@ethersproject/random" "5.7.0"
+ "@ethersproject/rlp" "5.7.0"
+ "@ethersproject/sha2" "5.7.0"
+ "@ethersproject/signing-key" "5.7.0"
+ "@ethersproject/solidity" "5.7.0"
+ "@ethersproject/strings" "5.7.0"
+ "@ethersproject/transactions" "5.7.0"
+ "@ethersproject/units" "5.7.0"
+ "@ethersproject/wallet" "5.7.0"
+ "@ethersproject/web" "5.7.1"
+ "@ethersproject/wordlists" "5.7.0"
+
ethjs-abi@0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/ethjs-abi/-/ethjs-abi-0.2.0.tgz#d3e2c221011520fc499b71682036c14fcc2f5b25"
@@ -12387,7 +12622,7 @@ events@^1.1.1:
resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924"
integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=
-events@^3.0.0:
+events@^3.0.0, events@^3.2.0, events@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
@@ -13364,6 +13599,11 @@ get-caller-file@^2.0.1, get-caller-file@^2.0.5:
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
+get-func-name@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41"
+ integrity sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==
+
get-intrinsic@^1.0.1, get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6"
@@ -14246,7 +14486,7 @@ intersect@~0.0.3:
resolved "https://registry.yarnpkg.com/intersect/-/intersect-0.0.3.tgz#c1a4a5e5eac6ede4af7504cc07e0ada7bc9f4920"
integrity sha1-waSl5erG7eSvdQTMB+Ctp7yfSSA=
-invariant@2.2.4, invariant@^2.2.2, invariant@^2.2.3, invariant@^2.2.4:
+invariant@2, invariant@2.2.4, invariant@^2.2.2, invariant@^2.2.3, invariant@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==
@@ -16407,6 +16647,13 @@ lottie-ios@2.5.0:
prop-types "^15.5.10"
react-native-safe-module "^1.1.0"
+loupe@^2.3.1:
+ version "2.3.6"
+ resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.6.tgz#76e4af498103c532d1ecc9be102036a21f787b53"
+ integrity sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==
+ dependencies:
+ get-func-name "^2.0.0"
+
lower-case@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28"
@@ -17865,6 +18112,13 @@ nocache@^2.1.0:
resolved "https://registry.yarnpkg.com/nocache/-/nocache-2.1.0.tgz#120c9ffec43b5729b1d5de88cd71aa75a0ba491f"
integrity sha512-0L9FvHG3nfnnmaEQPjT9xhfN4ISk0A8/2j4M37Np4mcDesJjHgEUfgPhdCyZuFI954tjokaIj/A3NdpFNdEh4Q==
+node-abi@^2.18.0, node-abi@^2.21.0, node-abi@^2.7.0:
+ version "2.30.1"
+ resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.30.1.tgz#c437d4b1fe0e285aaf290d45b45d4d7afedac4cf"
+ integrity sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==
+ dependencies:
+ semver "^5.4.1"
+
node-abi@^3.3.0:
version "3.22.0"
resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.22.0.tgz#00b8250e86a0816576258227edbce7bbe0039362"
@@ -17877,6 +18131,16 @@ node-addon-api@^2.0.0:
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32"
integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==
+node-addon-api@^3.0.2:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.2.1.tgz#81325e0a2117789c0128dab65e7e38f07ceba161"
+ integrity sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==
+
+node-addon-api@^4.2.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-4.3.0.tgz#52a1a0b475193e0928e98e0426a0d1254782b77f"
+ integrity sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==
+
node-addon-api@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.0.0.tgz#7d7e6f9ef89043befdb20c1989c905ebde18c501"
@@ -17929,6 +18193,25 @@ node-gyp@^7.1.0:
tar "^6.0.2"
which "^2.0.2"
+node-hid@1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/node-hid/-/node-hid-1.3.0.tgz#346a468505cee13d69ccd760052cbaf749f66a41"
+ integrity sha512-BA6G4V84kiNd1uAChub/Z/5s/xS3EHBCxotQ0nyYrUG65mXewUDHE1tWOSqA2dp3N+mV0Ffq9wo2AW9t4p/G7g==
+ dependencies:
+ bindings "^1.5.0"
+ nan "^2.14.0"
+ node-abi "^2.18.0"
+ prebuild-install "^5.3.4"
+
+node-hid@2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/node-hid/-/node-hid-2.1.1.tgz#f83c8aa0bb4e6758b5f7383542477da93f67359d"
+ integrity sha512-Skzhqow7hyLZU93eIPthM9yjot9lszg9xrKxESleEs05V2NcbUptZc5HFqzjOkSmL0sFlZFr3kmvaYebx06wrw==
+ dependencies:
+ bindings "^1.5.0"
+ node-addon-api "^3.0.2"
+ prebuild-install "^6.0.0"
+
node-idevice@^0.1.6:
version "0.1.6"
resolved "https://registry.yarnpkg.com/node-idevice/-/node-idevice-0.1.6.tgz#9411aa768b44bfb7cd25ece5c8a1c8b4b6f1fa44"
@@ -18011,6 +18294,11 @@ noms@0.0.0:
inherits "^2.0.1"
readable-stream "~1.0.31"
+noop-logger@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2"
+ integrity sha512-6kM8CLXvuW5crTxsAtva2YLrRrDaiTIkIePWs9moLHqbFWT94WpNFjwS/5dfLfECg5i/lkmw3aoqVidxt23TEQ==
+
nopt-usage@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/nopt-usage/-/nopt-usage-0.1.0.tgz#b18b8c183e181047ca9e63b7cde7cfc702cca579"
@@ -18109,7 +18397,7 @@ npm-run-path@^4.0.0:
dependencies:
path-key "^3.0.0"
-npmlog@4.x, npmlog@^4.1.2:
+npmlog@4.x, npmlog@^4.0.1, npmlog@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==
@@ -18907,6 +19195,11 @@ path@0.12.7:
process "^0.11.1"
util "^0.10.3"
+pathval@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d"
+ integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==
+
pause-stream@0.0.11:
version "0.0.11"
resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445"
@@ -19156,6 +19449,46 @@ postcss-value-parser@^3.3.0:
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281"
integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==
+prebuild-install@^5.3.4:
+ version "5.3.6"
+ resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-5.3.6.tgz#7c225568d864c71d89d07f8796042733a3f54291"
+ integrity sha512-s8Aai8++QQGi4sSbs/M1Qku62PFK49Jm1CbgXklGz4nmHveDq0wzJkg7Na5QbnO1uNH8K7iqx2EQ/mV0MZEmOg==
+ dependencies:
+ detect-libc "^1.0.3"
+ expand-template "^2.0.3"
+ github-from-package "0.0.0"
+ minimist "^1.2.3"
+ mkdirp-classic "^0.5.3"
+ napi-build-utils "^1.0.1"
+ node-abi "^2.7.0"
+ noop-logger "^0.1.1"
+ npmlog "^4.0.1"
+ pump "^3.0.0"
+ rc "^1.2.7"
+ simple-get "^3.0.3"
+ tar-fs "^2.0.0"
+ tunnel-agent "^0.6.0"
+ which-pm-runs "^1.0.0"
+
+prebuild-install@^6.0.0:
+ version "6.1.4"
+ resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-6.1.4.tgz#ae3c0142ad611d58570b89af4986088a4937e00f"
+ integrity sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ==
+ dependencies:
+ detect-libc "^1.0.3"
+ expand-template "^2.0.3"
+ github-from-package "0.0.0"
+ minimist "^1.2.3"
+ mkdirp-classic "^0.5.3"
+ napi-build-utils "^1.0.1"
+ node-abi "^2.21.0"
+ npmlog "^4.0.1"
+ pump "^3.0.0"
+ rc "^1.2.7"
+ simple-get "^3.0.3"
+ tar-fs "^2.0.0"
+ tunnel-agent "^0.6.0"
+
prebuild-install@^7.1.0:
version "7.1.1"
resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.1.1.tgz#de97d5b34a70a0c81334fd24641f2a1702352e45"
@@ -19900,10 +20233,10 @@ react-native-background-timer@2.1.1:
resolved "https://registry.yarnpkg.com/react-native-background-timer/-/react-native-background-timer-2.1.1.tgz#9a2489681ab2f8033c213c73272e9d4c47572cd5"
integrity sha512-cuXIIv+dcG8a8qkTD8pMzeqOEZCO+UGKglZWIe1osve+yJslmCowYQff+bI9xa7NOt2w+Vtd4L3d9JonlSqODg==
-react-native-branch@5.4.0:
- version "5.4.0"
- resolved "https://registry.yarnpkg.com/react-native-branch/-/react-native-branch-5.4.0.tgz#ba71422e38047b744ae5d88a834e7a7cb5185d68"
- integrity sha512-KuYpFPm6cKzUSTMOpI216w4BYP/5E4g8MH5a/4/xaWPqVqZmeoQS89/GqDxg7YwOG70YMtwdSobulh/wrv2tMw==
+react-native-branch@^5.6.2:
+ version "5.6.2"
+ resolved "https://registry.yarnpkg.com/react-native-branch/-/react-native-branch-5.6.2.tgz#c3ec137a5427a21fcd6559b83f02e6162ea627f6"
+ integrity sha512-plYpedNI1SSquD7bDOJ4UptkPIrGtz4O1NXfFA5tBshGb0AhuUSYS13dNZuHa+Ug+7YaqBcc0SF02vIB0ktZKw==
react-native-browser-polyfill@0.1.2:
version "0.1.2"
@@ -20341,12 +20674,14 @@ react-native-view-shot@^3.1.2:
resolved "https://registry.yarnpkg.com/react-native-view-shot/-/react-native-view-shot-3.1.2.tgz#8c8e84c67a4bc8b603e697dbbd59dbc9b4f84825"
integrity sha512-9u9fPtp6a52UMoZ/UCPrCjKZk8tnkI9To0Eh6yYnLKFEGkRZ7Chm6DqwDJbYJHeZrheCCopaD5oEOnRqhF4L2Q==
-react-native-webrtc@^1.100.0:
- version "1.100.0"
- resolved "https://registry.yarnpkg.com/react-native-webrtc/-/react-native-webrtc-1.100.0.tgz#f81562dc46467fe75f9f96e98dbe311222e83abd"
- integrity sha512-sBLl8Ihj3xfYn0NZJdDxelB/dZ422FWg/kcLdSw6Wk4eM3MeNW3iFwVsqg2dLzeDnuoQ06i7hOdtP7pGAiKsug==
+react-native-webrtc@^106.0.0-beta.7:
+ version "106.0.0-beta.7"
+ resolved "https://registry.yarnpkg.com/react-native-webrtc/-/react-native-webrtc-106.0.0-beta.7.tgz#c333c2a57a5fd2c1ca35f4b401912a95502d850b"
+ integrity sha512-GoIl/99BgVouFCb0gc9BfboPm6tOAQ1skHmpZR6CDtPxCbRxt8pEZXRiRxfvW9LbOm6yTpbSe2DK/kQrffZN3w==
dependencies:
+ adm-zip "0.5.9"
base64-js "1.5.1"
+ debug "4.3.4"
event-target-shim "6.0.2"
tar "6.1.11"
@@ -21316,6 +21651,13 @@ rustbn.js@~0.2.0:
resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca"
integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA==
+rxjs@6, rxjs@^6.4.0, rxjs@^6.6.0, rxjs@^6.6.7:
+ version "6.6.7"
+ resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9"
+ integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==
+ dependencies:
+ tslib "^1.9.0"
+
"rxjs@>= 6":
version "7.2.0"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.2.0.tgz#5cd12409639e9514a71c9f5f9192b2c4ae94de31"
@@ -21323,13 +21665,6 @@ rustbn.js@~0.2.0:
dependencies:
tslib "~2.1.0"
-rxjs@^6.4.0, rxjs@^6.6.0, rxjs@^6.6.7:
- version "6.6.7"
- resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9"
- integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==
- dependencies:
- tslib "^1.9.0"
-
rxjs@^7.5.5:
version "7.5.7"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.7.tgz#2ec0d57fdc89ece220d2e702730ae8f1e49def39"
@@ -21522,7 +21857,7 @@ semver-compare@^1.0.0:
resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc"
integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w=
-"semver@2 || 3 || 4 || 5", semver@^5.0.1, semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.1:
+"semver@2 || 3 || 4 || 5", semver@^5.0.1, semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.1:
version "5.7.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
@@ -21960,7 +22295,7 @@ snapdragon@^0.8.1:
source-map-resolve "^0.5.0"
use "^3.1.0"
-socket.io-client@^4.5.1:
+socket.io-client@^4.5.1, socket.io-client@^4.5.3:
version "4.5.3"
resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-4.5.3.tgz#bed69209d001465b2fea650d2e95c1e82768ab5e"
integrity sha512-I/hqDYpQ6JKwtJOf5ikM+Qz+YujZPMEl6qBLhxiP0nX+TfXKhW4KZZG8lamrD6Y5ngjmYHreESVasVCgi5Kl3A==
@@ -23190,7 +23525,7 @@ type-check@~0.3.2:
dependencies:
prelude-ls "~1.1.2"
-type-detect@4.0.8:
+type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5:
version "4.0.8"
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
@@ -23260,6 +23595,11 @@ typescript@^4.4.2, typescript@^4.6.2:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.2.tgz#fe12d2727b708f4eef40f51598b3398baa9611d4"
integrity sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==
+u2f-api@0.2.7:
+ version "0.2.7"
+ resolved "https://registry.yarnpkg.com/u2f-api/-/u2f-api-0.2.7.tgz#17bf196b242f6bf72353d9858e6a7566cc192720"
+ integrity sha512-fqLNg8vpvLOD5J/z4B6wpPg4Lvowz1nJ9xdHcCzdUPKcFE/qNCceV2gNZxSJd5vhAZemHr/K/hbzVA0zxB5mkg==
+
ua-parser-js@^0.7.18, ua-parser-js@^0.7.21, ua-parser-js@^0.7.24, ua-parser-js@^1.0.1:
version "0.7.31"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.31.tgz#649a656b191dffab4f21d5e053e27ca17cbff5c6"
@@ -23469,6 +23809,14 @@ url@0.11.0:
punycode "1.3.2"
querystring "0.2.0"
+usb@^1.6.3:
+ version "1.9.2"
+ resolved "https://registry.yarnpkg.com/usb/-/usb-1.9.2.tgz#fb6b36f744ecc707a196c45a6ec72442cb6f2b73"
+ integrity sha512-dryNz030LWBPAf6gj8vyq0Iev3vPbCLHCT8dBw3gQRXRzVNsIdeuU+VjPp3ksmSPkeMAl1k+kQ14Ij0QHyeiAg==
+ dependencies:
+ node-addon-api "^4.2.0"
+ node-gyp-build "^4.3.0"
+
use-callback-ref@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.2.5.tgz#6115ed242cfbaed5915499c0a9842ca2912f38a5"
@@ -24077,6 +24425,11 @@ which-module@^2.0.0:
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
+which-pm-runs@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.1.0.tgz#35ccf7b1a0fce87bd8b92a478c9d045785d3bf35"
+ integrity sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==
+
which-typed-array@^1.1.2:
version "1.1.4"
resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.4.tgz#8fcb7d3ee5adf2d771066fba7cf37e32fe8711ff"