Experiment/upgrade react native 66 (#3509)

* Commit upgrade paths

* Checkpoint: iOS can build

* Reintroduce viewpager library with patch (deprecated)

* Upgrade keyboard aware library to support new RN

* Stabilize Android (WIP) need to patch react-native

* Remove setting NDK. Android auto sets it based on gradle

* Update build gradle + Add postinstall for react-native-codegen

* Add comment for postinstall (react-native-codegen)

* Remove workspace settings

* Upgrade gradle versions. Fix viewpager patch. Revert to support pre-upgrade min sdk versions

* Fix unit tests

* update rn codegen postinstall script

* Fix react-native-scrollable-tab-view with patch

* Update README.md ndk section

* update rn codegen postinstall script

* Update pod file lock

* update allow-scripts

* update yarn.lock

* Remove --strip-components=2

* Update ndk version to 21e

* Upgrade Detox + ignore warnings

* Enable Hermes. Reconfigure Flipper.

* Update pods

* Remove entitlements from copy resources step

* Polyfill Intl for iOS for Hermes

* Remove nvm related code in build phase

* Remove duplicate node from homebrew

* Remove engine version dependencies. Allow bitrise to use any node

* Reintroduce engines in package.json

* Try to unset PREFIX

* Reintroduce nvm compatibility in build phase

* Patch react-native-payments

* Expose removeListener warnings

* Patch react-native-modal removeListner

* Update build number

* Fix virtualization error on send flow

* Update build number to 3.8.2

* Ignore EventEmitter.removeListener

* Update build version for bitrise

* fixing broken e2e tests

* Replace drawer. Update reanimated + webview libraries. Begin fixing browser functionality.

* Hook up reanimated 2 on Android

* Remove traces of react navigation drawer. Refactor tutorial.

* Fix display account name on drawer.

* Fix patches -> fixes Android back button behavior

* Update build version

* Update build version to fix bitrise

* Re run unit tests

* Update readme with Flipper instructions

* Remove requestAnimationFramea and InteractionManager that causes iOS to crash when switching networks

* Update EasingNode

* Hide tab bar

* Fix browser deep link

* Upgrade web3 in controllers to fix app hang up.

* Remove isZero undefined from controllers

* Handle initial and subsequent deeplinks to browser

* Fix svg length undefined issue

* Update build number

* Fix BN function calls + patch swaps controller

* Update build number

* Disable Hermes for iOS.

* Disable hermes for Android

* Update build number

* unset PREFIX on all bitrise steps

* dimissing keyboard in wallet spec

* addressbook,wallet,request payment fix.

* update snapshots

* Remove intl polyfill

Co-authored-by: Ricky Miller <ricky.miller@gmail.com>
Co-authored-by: Curtis <Curtis.David7@gmail.com>
pull/3481/head^2
Cal Leung 1 year ago committed by GitHub
parent d9757b7e16
commit 1f03de0769
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      .editorconfig
  2. 16
      .flowconfig
  3. 4
      .gitattributes
  4. 1
      .gitignore
  5. 60
      README.md
  6. 40
      android/app/build.gradle
  7. 7
      android/app/proguard-rules.pro
  8. 7
      android/app/src/debug/AndroidManifest.xml
  9. 2
      android/app/src/debug/java/com/flipper/ReactNativeFlipper.java
  10. 1
      android/app/src/main/AndroidManifest.xml
  11. 6
      android/app/src/main/java/io/metamask/MainActivity.java
  12. 77
      android/app/src/main/java/io/metamask/MainApplication.java
  13. 3
      android/build.gradle
  14. 3
      android/gradle.properties
  15. 2
      android/gradle/wrapper/gradle-wrapper.properties
  16. 21
      android/gradlew.bat
  17. 17
      android/settings.gradle
  18. 7
      app/actions/navigation/index.ts
  19. 2
      app/components/Base/RemoteImage/__snapshots__/index.test.tsx.snap
  20. 4
      app/components/Base/RemoteImage/index.js
  21. 65
      app/components/Nav/App/index.js
  22. 41
      app/components/Nav/Main/MainNavigator.js
  23. 1
      app/components/UI/AddCustomToken/__snapshots__/index.test.tsx.snap
  24. 1
      app/components/UI/AddCustomToken/index.js
  25. 1
      app/components/UI/ApproveTransactionReview/index.js
  26. 1
      app/components/UI/AssetOverview/index.js
  27. 3
      app/components/UI/BlockingActionModal/__snapshots__/index.test.tsx.snap
  28. 214
      app/components/UI/Drawer/index.tsx
  29. 10
      app/components/UI/Drawer/styles.ts
  30. 42
      app/components/UI/DrawerView/index.js
  31. 12
      app/components/UI/Navbar/index.js
  32. 30
      app/components/UI/NetworkList/index.js
  33. 4
      app/components/UI/Notification/index.js
  34. 16
      app/components/UI/OnboardingWizard/Coachmark/__snapshots__/index.test.tsx.snap
  35. 2
      app/components/UI/OnboardingWizard/Coachmark/index.js
  36. 114
      app/components/UI/OnboardingWizard/Step4/index.js
  37. 123
      app/components/UI/OnboardingWizard/Step5/index.js
  38. 106
      app/components/UI/OnboardingWizard/Step6/index.js
  39. 161
      app/components/UI/OnboardingWizard/index.js
  40. 12
      app/components/UI/ReusableModal/index.tsx
  41. 23
      app/components/UI/Swaps/index.js
  42. 1
      app/components/UI/Swaps/utils/useBalance.js
  43. 3
      app/components/UI/Tokens/index.js
  44. 1
      app/components/UI/TransactionReview/TransactionReviewInformation/index.js
  45. 19
      app/components/Views/ActivityView/index.js
  46. 371
      app/components/Views/Browser/index.js
  47. 9
      app/components/Views/NavigationUnitTest/__snapshots__/TestScreen1.test.js.snap
  48. 18
      app/components/Views/NavigationUnitTest/__snapshots__/TestScreen2.test.js.snap
  49. 27
      app/components/Views/NavigationUnitTest/__snapshots__/TestScreen3.test.js.snap
  50. 4
      app/components/Views/Onboarding/index.js
  51. 3
      app/components/Views/QRScanner/__snapshots__/index.test.tsx.snap
  52. 19
      app/components/Views/SendFlow/AddressList/index.js
  53. 4
      app/components/Views/SendFlow/Amount/index.js
  54. 1
      app/components/Views/SendFlow/Confirm/index.js
  55. 28
      app/components/Views/Wallet/index.tsx
  56. 10
      app/core/DeeplinkManager.js
  57. 3
      app/core/Engine.js
  58. 2
      app/reducers/index.js
  59. 34
      app/reducers/navigation/index.ts
  60. 5
      app/reducers/swaps/index.js
  61. 1
      app/util/general/index.js
  62. 30
      app/util/lodash/index.ts
  63. 2
      app/util/testSetup.js
  64. 2
      babel.config.js
  65. 6
      bitrise.yml
  66. 13
      e2e/pages/AddCustomTokenView.js
  67. 2
      e2e/pages/RequestPaymentView.js
  68. 3
      e2e/specs/wallet-tests.spec.js
  69. 6
      index.js
  70. 54
      ios/MetaMask-tvOS/Info.plist
  71. 24
      ios/MetaMask-tvOSTests/Info.plist
  72. 137
      ios/MetaMask.xcodeproj/project.pbxproj
  73. 43
      ios/MetaMask/AppDelegate.m
  74. 34
      ios/Podfile
  75. 660
      ios/Podfile.lock
  76. 2
      jest.config.js
  77. 39
      locales/i18n.js
  78. 51
      package.json
  79. 25
      patches/@exodus+react-native-payments+1.5.0.patch
  80. 222
      patches/@metamask+controllers+22.0.0.patch
  81. 21
      patches/@metamask+swaps-controller+6.3.0.patch
  82. 12
      patches/@react-native-community+viewpager+3.3.1.patch
  83. 138
      patches/react-native+0.63.4.patch
  84. 83
      patches/react-native+0.66.3.patch
  85. 30
      patches/react-native-modal+12.1.0.patch
  86. 19
      patches/react-native-scrollable-tab-view+1.0.0.patch
  87. 13
      patches/react-native-svg+12.1.1.patch
  88. 13
      patches/xmlhttprequest+1.8.0.patch
  89. 1
      scripts/build.sh
  90. 14
      scripts/postinstall.sh
  91. 4649
      yarn.lock

@ -15,3 +15,7 @@ trim_trailing_whitespace = false
[{package,package-lock}.json]
indent_size = 2
indent_style = space
# Windows files
[*.bat]
end_of_line = crlf

@ -8,10 +8,6 @@
; Ignore polyfills
node_modules/react-native/Libraries/polyfills/.*
; These should not be required directly
; require from fbjs/lib instead: require('fbjs/lib/warning')
node_modules/warning/.*
; Flow doesn't support platforms
.*/Libraries/Utilities/LoadingView.js
@ -27,8 +23,9 @@ node_modules/react-native/flow/
[options]
emoji=true
esproposal.optional_chaining=enable
esproposal.nullish_coalescing=enable
exact_by_default=true
format.bracket_spacing=false
module.file_ext=.js
module.file_ext=.json
@ -44,10 +41,6 @@ suppress_type=$FlowFixMe
suppress_type=$FlowFixMeProps
suppress_type=$FlowFixMeState
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(<VERSION>\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(<VERSION>\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)?:? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
[lints]
sketchy-null-number=warn
sketchy-null-mixed=warn
@ -58,7 +51,6 @@ deprecated-type=warn
unsafe-getters-setters=warn
unnecessary-invariant=warn
signature-verification-failure=warn
deprecated-utility=error
[strict]
deprecated-type
@ -70,4 +62,4 @@ untyped-import
untyped-type-import
[version]
^0.122.0
^0.158.0

4
.gitattributes vendored

@ -1,3 +1,3 @@
*.pbxproj -text
# specific for windows script files
# Windows files should use crlf line endings
# https://help.github.com/articles/dealing-with-line-endings/
*.bat text eol=crlf

1
.gitignore vendored

@ -29,6 +29,7 @@ app/bin
.gradle
local.properties
*.iml
*.hprof
android/.project
android/app/.project
android/app/bin/

@ -62,12 +62,7 @@ yarn watch
- Install the Android SDK, via [Android Studio](https://developer.android.com/studio).
- _MetaMask Only:_ To create production builds, you need to install Google Play Licensing Library via the SDK Manager in Android Studio.
- Install the Android NDK, via [Android Studio](https://developer.android.com/studio)'s SDK Manager.
- In the SDK Manager, select the `SDK Tools` tab and install NDK version `17.2.4988734`. You'll need to click "Show Package Details" in order to select the appropriate version.
- In the `android` directory, update the `local.properties` file by adding line:
```
ndk.dir=/Users/YOUR_HOME_DIRECTORY/Library/Android/sdk/ndk/17.2.4988734
```
_(You may have to create local.properties if it doesn't exist.)_
- In the SDK Manager, select the `SDK Tools` tab and install NDK version `21.4.7075529`. You'll need to click "Show Package Details" in order to select the appropriate version.
- Linux only:
- Ensure that you have the `secret-tool` binary on your machine.
- Part of the [libsecret-tools](https://launchpad.net/ubuntu/bionic/+package/libsecret-tools) package on Debian/Ubuntu based distributions.
@ -130,43 +125,30 @@ First, make sure you have the following running:
- Your Android emulator or iOS simulator
- `yarn start:android` or `yarn start:ios`
Next, check that the React Native Debugger is working:
Next, install the [Flipper](https://fbflipper.com/) desktop app (verified working with v0.127.0)
- Open your emulator or simulator, and select `Debug JS Remotely` (or something similar) from its developer menu
- To open the developer menu:
- iOS Simulator: `Cmd + D`
- Android Emulator
- macOS: `Cmd + M` - Windows, Linux: `Ctrl + M`
- If it doesn't open automatically, try navigating to this URL in Chrome: http://localhost:8081/debugger-ui/
- If these steps do not take you to the React Native Debugger, something is wrong
- Once Flipper is installed, configure your system as follows:
- Install react-devtools: `npm i -g react-devtools@4.22.1`
- Update Android SDK location settings by accessing Flipper's settings via the `Gear Icon` -> `Settings`
- Example SDK path: `/Users/<USER_NAME>/Library/Android/sdk`
#### Debugging iOS (macOS Only)
Finally, check that the debugger is working:
For more details, see [this page](https://medium.com/@mattcroak718/debugging-your-iphone-mobile-web-app-using-safari-development-tools-71240657c487).
- Open your emulator or simulator alongside the Flipper app
- Flipper should auto-detect the device and the application to debug
- You should now be able to access features such as `Logs`
- You should be able to inspect the mobile app using the console in the React Native Debugger in Chrome
- To debug a website (dapp) in the browser:
- Navigate to the website in the app's browser
- Open Safari
- Go to: _Preferences -> Advanced_ and select `Show Develop menu in menu bar`
- Select `Develop` in the menu bar
- Find your simulator in the second section from the top
- Select the relevant WebView from the list
- The simulator will highlight the WebView when you hover over it in Safari
#### Debugging Physical iOS devices
#### Debugging Android
For more details, see [this page](https://developers.google.com/web/tools/chrome-devtools/remote-debugging/webviews).
- You should be able to inspect the mobile app using the console in the React Native Debugger in Chrome
- To debug a website (dapp) in the browser:
- Navigate to the website in the app's browser
- Go to chrome://inspect
- Select the relevant WebView under **Remote Target**
- Debugging physical iOS devices requires `idb` to be installed, which consists of 2 parts
- Install the two idb parts:
1. `brew tap facebook/fb` & `brew install idb-companion`
2. `pip3.9 install fb-idb` (This step may require that you install python3 via `python -m pip3 install --upgrade pip`)
#### Miscellaneous
- [Troubleshooting for React Native](https://facebook.github.io/react-native/docs/troubleshooting#content)
- [Flipper Documentation](https://fbflipper.com/docs/features/react-native/)
### Running Tests
@ -194,11 +176,11 @@ yarn test:e2e:android
Whenever you change dependencies (adding, removing, or updating, either in `package.json` or `yarn.lock`), there are various files that must be kept up-to-date.
* `yarn.lock`:
* Run `yarn setup` again after your changes to ensure `yarn.lock` has been properly updated.
* The `allow-scripts` configuration in `package.json`
* Run `yarn allow-scripts auto` to update the `allow-scripts` configuration automatically. This config determines whether the package's install/postinstall scripts are allowed to run. Review each new package to determine whether the install script needs to run or not, testing if necessary.
* Unfortunately, `yarn allow-scripts auto` will behave inconsistently on different platforms. macOS and Windows users may see extraneous changes relating to optional dependencies.
- `yarn.lock`:
- Run `yarn setup` again after your changes to ensure `yarn.lock` has been properly updated.
- The `allow-scripts` configuration in `package.json`
- Run `yarn allow-scripts auto` to update the `allow-scripts` configuration automatically. This config determines whether the package's install/postinstall scripts are allowed to run. Review each new package to determine whether the install script needs to run or not, testing if necessary.
- Unfortunately, `yarn allow-scripts auto` will behave inconsistently on different platforms. macOS and Windows users may see extraneous changes relating to optional dependencies.
### Architecture

@ -105,7 +105,7 @@ import com.android.build.OutputFile
project.ext.react = [
entryFile: "index.js",
enableHermes: false
enableHermes: false //System.getenv('METAMASK_ENVIRONMENT') == 'production'
]
apply from: "../../node_modules/react-native/react.gradle"
@ -148,21 +148,20 @@ def jscFlavor = 'org.webkit:android-jsc:+'
*/
def enableHermes = project.ext.react.get("enableHermes", false)
android {
compileSdkVersion rootProject.ext.compileSdkVersion
/**
* Architectures to build native code for in debug.
*/
def nativeArchitectures = project.getProperties().get("reactNativeDebugArchitectures")
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
android {
compileSdkVersion rootProject.ext.compileSdkVersion
defaultConfig {
applicationId "io.metamask"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 801
versionName "3.8.0"
versionCode 807
versionName "3.8.4"
multiDexEnabled true
testBuildType System.getProperty('testBuildType', 'debug')
missingDimensionStrategy "minReactNative", "minReactNative46"
@ -210,6 +209,11 @@ android {
debug {
manifestPlaceholders = [isDebug:true]
signingConfig signingConfigs.debug
if (nativeArchitectures) {
ndk {
abiFilters nativeArchitectures.split(',')
}
}
multiDexEnabled true
}
release {
@ -233,7 +237,7 @@ android {
def abi = output.getFilter(OutputFile.ABI)
if (abi != null) { // null for the universal-debug, universal-release variants
output.versionCodeOverride =
versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
defaultConfig.versionCode * 1000 + versionCodes.get(abi)
}
}
}
@ -260,20 +264,20 @@ dependencies {
androidTestImplementation('com.wix:detox:+') { transitive = true }
androidTestImplementation 'junit:junit:4.12'
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
implementation "com.squareup.okhttp3:okhttp:4.9.1"
implementation "com.squareup.okhttp3:logging-interceptor:4.9.1"
implementation "com.squareup.okhttp3:okhttp-urlconnection:4.9.1"
debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
exclude group:'com.facebook.fbjni'
debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
exclude group:'com.facebook.fbjni'
}
debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
exclude group:'com.facebook.flipper'
exclude group:'com.squareup.okhttp3', module:'okhttp'
exclude group:'com.squareup.okhttp3', module:'okhttp'
}
debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") {
exclude group:'com.facebook.flipper'
}
if (enableHermes) {
def hermesPath = "../../node_modules/hermes-engine/android/";
debugImplementation files(hermesPath + "hermes-debug.aar")
@ -286,7 +290,7 @@ dependencies {
// Run this once to be able to run the application with BUCK
// puts all compile dependencies into folder libs for BUCK to use
task copyDownloadableDepsToLibs(type: Copy) {
from configurations.compile
from configurations.implementation
into 'libs'
}

@ -25,3 +25,10 @@
# react-native-svg https://github.com/react-native-svg/react-native-svg#problems-with-proguard
-keep public class com.horcrux.svg.** {*;}
# react-native-reanimated https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/installation
-keep class com.facebook.react.turbomodule.** { *; }
# Hermes
# -keep class com.facebook.hermes.unicode.** { *; }
# -keep class com.facebook.jni.** { *; }#

@ -4,5 +4,10 @@
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<application android:usesCleartextTraffic="true" tools:targetApi="28" tools:ignore="GoogleAppIndexingWarning" />
<application
android:usesCleartextTraffic="true"
tools:targetApi="28"
tools:ignore="GoogleAppIndexingWarning">
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
</application>
</manifest>

@ -4,7 +4,7 @@
* <p>This source code is licensed under the MIT license found in the LICENSE file in the root
* directory of this source tree.
*/
package io.metamask;
package com.flipper;
import android.content.Context;
import com.facebook.flipper.android.AndroidFlipperClient;

@ -101,7 +101,6 @@
<data android:scheme="https" android:host="metamask.io" />
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
<!-- Explicitly opt-in to safe browsing -->
<meta-data android:name="android.webkit.WebView.EnableSafeBrowsing" android:value="true" />
<!-- Branch init -->

@ -1,7 +1,7 @@
package io.metamask;
import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.ReactFragmentActivity;
import com.facebook.react.ReactActivity;
import com.facebook.react.ReactRootView;
import com.mixpanel.android.mpmetrics.MixpanelAPI;
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;
@ -18,7 +18,7 @@ import androidx.annotation.NonNull;
import org.devio.rn.splashscreen.SplashScreen;
public class MainActivity extends ReactFragmentActivity {
public class MainActivity extends ReactActivity {
/**
* Returns the name of the main component registered from JavaScript. This is used to schedule
@ -46,7 +46,7 @@ public class MainActivity extends ReactFragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
SplashScreen.show(this);
SplashScreen.show(this);
super.onCreate(null);
}
@Override

@ -23,6 +23,8 @@ import androidx.multidex.MultiDexApplication;
import android.database.CursorWindow;
import java.lang.reflect.Field;
import com.facebook.react.bridge.JSIModulePackage;
import com.swmansion.reanimated.ReanimatedJSIModulePackage;
public class MainApplication extends MultiDexApplication implements ShareApplication, ReactApplication {
@ -49,6 +51,11 @@ public class MainApplication extends MultiDexApplication implements ShareApplica
protected String getJSMainModuleName() {
return "index";
}
@Override
protected JSIModulePackage getJSIModulePackage() {
return new ReanimatedJSIModulePackage();
}
};
@Override
@ -68,44 +75,46 @@ public class MainApplication extends MultiDexApplication implements ShareApplica
e.printStackTrace();
}
if (BuildConfig.DEBUG)
{ WebView.setWebContentsDebuggingEnabled(true); }
SoLoader.init(this, /* native exopackage */ false);
if (BuildConfig.DEBUG) {
WebView.setWebContentsDebuggingEnabled(true);
}
initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
SoLoader.init(this, /* native exopackage */ false);
RNBranchModule.getAutoInstance(this);
initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
}
/**
* Loads Flipper in React Native templates. Call this in the onCreate method with something like
* initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
*
* @param context
* @param reactInstanceManager
*/
private static void initializeFlipper(
Context context, ReactInstanceManager reactInstanceManager) {
if (BuildConfig.DEBUG) {
try {
/*
We use reflection here to pick up the class that initializes Flipper,
since Flipper library is not available in release mode
*/
Class<?> aClass = Class.forName("com.flipper.ReactNativeFlipper");
aClass
.getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
.invoke(null, context, reactInstanceManager);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
/**
* Loads Flipper in React Native templates. Call this in the onCreate method with something like
* initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
*
* @param context
* @param reactInstanceManager
*/
private static void initializeFlipper(
Context context, ReactInstanceManager reactInstanceManager) {
if (BuildConfig.DEBUG) {
try {
/*
We use reflection here to pick up the class that initializes Flipper,
since Flipper library is not available in release mode
*/
Class<?> aClass = Class.forName("io.metamask.ReactNativeFlipper");
aClass
.getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
.invoke(null, context, reactInstanceManager);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
@Override
public String getFileProviderAuthority() {

@ -12,11 +12,12 @@ buildscript {
}
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
dependencies {
classpath('com.android.tools.build:gradle:4.0.1')
classpath('com.android.tools.build:gradle:4.2.2')
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files

@ -22,5 +22,6 @@ AsyncStorage_db_size_in_MB=10
android.disableResourceValidation=true
android.useAndroidX=true
android.enableJetifier=true
# Version of flipper SDK to use with React Native
FLIPPER_VERSION=0.82.0
FLIPPER_VERSION=0.93.0

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.9-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip

@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@ -54,7 +54,7 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@ -64,28 +64,13 @@ echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell

@ -1,4 +1,14 @@
// At the top of my settings.gradle
pluginManagement {
repositories {
gradlePluginPortal()
mavenLocal()
google()
}
}
rootProject.name = 'MetaMask'
include ':app'
include ':@react-native-community_blur'
project(':@react-native-community_blur').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/blur/android')
include ':lottie-react-native'
@ -8,6 +18,9 @@ project(':react-native-gesture-handler').projectDir = new File(rootProject.proje
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
include ':react-native-video'
project(':react-native-video').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-video/android-exoplayer')
include ':app'
include(":packages:react-native-codegen:android")
project(":packages:react-native-codegen:android").projectDir = new File(rootProject.projectDir,
"../node_modules/react-native/packages/react-native-codegen/android")
includeBuild("../node_modules/react-native/packages/react-native-codegen/android")
include ':ReactAndroid'
project(':ReactAndroid').projectDir = new File(rootProject.projectDir, '../node_modules/react-native/ReactAndroid')
project(':ReactAndroid').projectDir = new File(rootProject.projectDir, '../node_modules/react-native/ReactAndroid')

@ -0,0 +1,7 @@
/* eslint-disable import/prefer-default-export */
import { SET_CURRENT_ROUTE } from '../../reducers/navigation';
/**
* Action Creators
*/
export const setCurrentRoute = (route: string) => ({ type: SET_CURRENT_ROUTE, payload: { route } });

@ -27,7 +27,7 @@ exports[`RemoteImage should render svg correctly 1`] = `
<View
style={Object {}}
>
<SvgCssUri
<SvgUri
fill="black"
height="100%"
source={

@ -4,7 +4,7 @@ import { Image, ViewPropTypes, View } from 'react-native';
import FadeIn from 'react-native-fade-in-image';
// eslint-disable-next-line import/default
import resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource';
import { SvgCssUri } from 'react-native-svg';
import { SvgUri } from 'react-native-svg';
import isUrl from 'is-url';
import ComponentErrorBoundary from '../../UI/ComponentErrorBoundary';
import useIpfsGateway from '../../hooks/useIpfsGateway';
@ -42,7 +42,7 @@ const RemoteImage = (props) => {
return (
<ComponentErrorBoundary onError={props.onError} componentLabel="RemoteImage-SVG">
<View style={style}>
<SvgCssUri {...props} uri={uri} width={'100%'} height={'100%'} fill={'black'} />
<SvgUri {...props} uri={uri} width={'100%'} height={'100%'} fill={'black'} />
</View>
</ComponentErrorBoundary>
);

@ -1,8 +1,7 @@
import React, { useCallback, useEffect, useRef, useState } from 'react';
import React, { useCallback, useEffect, useRef, useMemo, useState } from 'react';
import { NavigationContainer, CommonActions } from '@react-navigation/native';
import { Animated, StyleSheet, View } from 'react-native';
import { createStackNavigator } from '@react-navigation/stack';
import { createDrawerNavigator } from '@react-navigation/drawer';
import AsyncStorage from '@react-native-community/async-storage';
import Login from '../../Views/Login';
import QRScanner from '../../Views/QRScanner';
@ -18,7 +17,6 @@ import ManualBackupStep3 from '../../Views/ManualBackupStep3';
import ImportFromSeed from '../../Views/ImportFromSeed';
import SyncWithExtensionSuccess from '../../Views/SyncWithExtensionSuccess';
import Main from '../Main';
import DrawerView from '../../UI/DrawerView';
import OptinMetrics from '../../UI/OptinMetrics';
import MetaMaskAnimation from '../../UI/MetaMaskAnimation';
import SimpleWebview from '../../Views/SimpleWebview';
@ -34,13 +32,14 @@ import { connect, useSelector, useDispatch } from 'react-redux';
import { EXISTING_USER, CURRENT_APP_VERSION, LAST_APP_VERSION } from '../../../constants/storage';
import { getVersion } from 'react-native-device-info';
import { checkedAuth } from '../../../actions/user';
import { setCurrentRoute } from '../../../actions/navigation';
import { findRouteNameFromNavigatorState } from '../../../util/general';
const styles = StyleSheet.create({
fill: { flex: 1 },
});
const Stack = createStackNavigator();
const Drawer = createDrawerNavigator();
/**
* Stack navigator responsible for the onboarding process
* Create Wallet, Import from Seed and Sync
@ -104,42 +103,6 @@ const OnboardingRootNav = () => (
</Stack.Navigator>
);
/**
* Main app navigator which handles all the screens
* after the user is already onboarded
*/
const HomeNav = () => (
<Drawer.Navigator
drawerContent={(props) => <DrawerView {...props} />}
// eslint-disable-next-line
drawerStyle={{
backgroundColor: 'rgba(0, 0, 0, 0.5)',
width: 315,
}}
>
<Drawer.Screen name="Main" component={Main} />
</Drawer.Navigator>
);
// Is this necessary?
/**
* Drawer status tracking
const defaultGetStateForAction = HomeNav.router.getStateForAction;
DrawerStatusTracker.init();
HomeNav.router.getStateForAction = (action, state) => {
if (action) {
if (action.type === 'Navigation/MARK_DRAWER_SETTLING' && action.willShow) {
DrawerStatusTracker.setStatus('open');
} else if (action.type === 'Navigation/MARK_DRAWER_SETTLING' && !action.willShow) {
DrawerStatusTracker.setStatus('closed');
}
}
return defaultGetStateForAction(action, state);
};
*/
const App = ({ userLoggedIn }) => {
const unsubscribeFromBranch = useRef();
@ -154,6 +117,7 @@ const App = ({ userLoggedIn }) => {
const isAuthChecked = useSelector((state) => state.user.isAuthChecked);
const dispatch = useDispatch();
const triggerCheckedAuth = () => dispatch(checkedAuth('onboarding'));
const triggerSetCurrentRoute = (route) => dispatch(setCurrentRoute(route));
const handleDeeplink = useCallback(({ error, params, uri }) => {
if (error) {
@ -173,10 +137,16 @@ const App = ({ userLoggedIn }) => {
}
}, []);
const branchSubscriber = new BranchSubscriber({
onOpenStart: (opts) => handleDeeplink(opts),
onOpenComplete: (opts) => handleDeeplink(opts),
});
const branchSubscriber = useMemo(
() =>
new BranchSubscriber({
onOpenStart: (opts) => {
handleDeeplink(opts);
},
}),
// eslint-disable-next-line react-hooks/exhaustive-deps
[]
);
useEffect(() => {
SharedDeeplinkManager.init({
@ -287,6 +257,11 @@ const App = ({ userLoggedIn }) => {
onReady={() => {
routingInstrumentation.registerNavigationContainer(navigator);
}}
onStateChange={(state) => {
// Updates redux with latest route. Used by DrawerView component.
const currentRoute = findRouteNameFromNavigatorState(state.routes);
triggerSetCurrentRoute(currentRoute);
}}
>
<Stack.Navigator route={route} initialRouteName={route}>
<Stack.Screen name="Login" component={Login} options={{ headerShown: false }} />
@ -296,7 +271,7 @@ const App = ({ userLoggedIn }) => {
options={{ headerShown: false }}
/>
{userLoggedIn && (
<Stack.Screen name="HomeNav" component={HomeNav} options={{ headerShown: false }} />
<Stack.Screen name="HomeNav" component={Main} options={{ headerShown: false }} />
)}
</Stack.Navigator>
</NavigationContainer>

@ -1,4 +1,4 @@
import React from 'react';
import React, { useRef } from 'react';
import { Image, StyleSheet } from 'react-native';
import { createStackNavigator } from '@react-navigation/stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
@ -50,6 +50,7 @@ import SwapsQuotesView from '../../UI/Swaps/QuotesView';
import GasEducationCarousel from '../../Views/GasEducationCarousel';
import CollectiblesDetails from '../../UI/CollectibleModal';
import OptinMetrics from '../../UI/OptinMetrics';
import Drawer from '../../UI/Drawer';
const Stack = createStackNavigator();
const Tab = createBottomTabNavigator();
@ -73,9 +74,7 @@ const WalletTabHome = () => (
<Stack.Screen name="WalletView" component={Wallet} />
<Stack.Screen name="Asset" component={Asset} options={Asset.navigationOptions} />
<Stack.Screen name="AddAsset" component={AddAsset} options={AddAsset.navigationOptions} />
<Stack.Screen name="Collectible" component={Collectible} options={Collectible.navigationOptions} />
<Stack.Screen
name="RevealPrivateCredentialView"
component={RevealPrivateCredential}
@ -86,23 +85,41 @@ const WalletTabHome = () => (
const BrowserTabHome = () => (
<Stack.Navigator>
<Stack.Screen name="BrowserView" component={Browser} options={Browser.navigationOptions} />
<Stack.Screen name="BrowserView" component={Browser} />
</Stack.Navigator>
);
const TransactionsHome = () => (
<Stack.Navigator>
<Stack.Screen name="TransactionsView" component={ActivityView} options={ActivityView.navigationOptions} />
<Stack.Screen name="TransactionsView" component={ActivityView} />
</Stack.Navigator>
);
const HomeTabs = () => (
<Tab.Navigator initialRouteName={'WalletTabHome'} tabBarOptions={{ style: styles.hidden }}>
<Tab.Screen name="WalletTabHome" component={WalletTabHome} options={{ tabBarVisible: false }} />
<Tab.Screen name="BrowserTabHome" component={BrowserTabHome} options={{ tabBarVisible: false }} />
<Tab.Screen name="TransactionsHome" component={TransactionsHome} options={{ tabBarVisible: false }} />
</Tab.Navigator>
);
export const DrawerContext = React.createContext({ drawerRef: null });
const HomeTabs = () => {
const drawerRef = useRef(null);
return (
<DrawerContext.Provider value={{ drawerRef }}>
<Drawer ref={drawerRef}>
<Tab.Navigator
initialRouteName={'WalletTabHome'}
tabBarOptions={{ style: styles.hidden }}
screenOptions={{ tabBarVisible: false }}
>
<Tab.Screen name="WalletTabHome" component={WalletTabHome} options={{ tabBarVisible: false }} />
<Tab.Screen name="BrowserTabHome" component={BrowserTabHome} options={{ tabBarVisible: false }} />
<Tab.Screen
name="TransactionsHome"
component={TransactionsHome}
options={{ tabBarVisible: false }}
/>
</Tab.Navigator>
</Drawer>
</DrawerContext.Provider>
);
};
const Webview = () => (
<Stack.Navigator>

@ -44,6 +44,7 @@ exports[`AddCustomToken should render correctly 1`] = `
}
}
suppressHighlighting={true}
testID="add-asset-warning-message"
>
scams and security risks.
</Text>

@ -210,6 +210,7 @@ export default class AddCustomToken extends PureComponent {
});
}}
style={styles.warningLink}
testID={'add-asset-warning-message'}
>
{strings('add_asset.warning_link')}
</Text>

@ -713,6 +713,7 @@ class ApproveTransactionReview extends PureComponent {
this.onCancelPress();
this.props.navigation.navigate('BrowserView', {
newTabUrl: mmFaucetUrl,
timestamp: Date.now(),
});
});
};

@ -200,6 +200,7 @@ class AssetOverview extends PureComponent {
screen: 'BrowserView',
params: {
newTabUrl: url,
timestamp: Date.now(),
},
});
}

@ -71,9 +71,6 @@ exports[`BlockingActionModal should render correctly 1`] = `
Please wait
</Text>
<ActivityIndicator
animating={true}
color="#999999"
hidesWhenStopped={true}
size="small"
style={
Object {

@ -0,0 +1,214 @@
/* eslint-disable import/no-extraneous-dependencies, react/display-name, react/display-name, react-hooks/exhaustive-deps, arrow-body-style, react/prop-types */
import React, { ReactNode, forwardRef, useImperativeHandle, useMemo, useCallback } from 'react';
import { View, TouchableOpacity, StyleSheet, ViewStyle, Dimensions, StyleProp } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { PanGestureHandler, State } from 'react-native-gesture-handler';
import Animated, {
eq,
EasingNode,
not,
block,
cond,
clockRunning,
Value,
interpolateNode,
useCode,
set,
Extrapolate,
} from 'react-native-reanimated';
import { onGestureEvent, withSpring, clamp, timing } from 'react-native-redash';
import { colors } from '../../../styles/common';
import { useNavigation } from '@react-navigation/native';
const screenWidth = Dimensions.get('window').width;
import DrawerView from '../DrawerView';
import styles from './styles';
interface DrawerRef {
dismissDrawer: () => void;
showDrawer: () => void;
}
interface Props {
style?: StyleProp<ViewStyle>;
children?: ReactNode;
}
const Drawer = forwardRef<DrawerRef, Props>((props, ref) => {
const { style, children } = props;
const hiddenOffset = -screenWidth;
const visibleOffset = 0;
const navigation = useNavigation();
const safeAreaInsets = useSafeAreaInsets();
// Animation config
const animationConfig: Omit<Animated.SpringConfig, 'toValue'> = {
damping: 100,
overshootClamping: false,
restSpeedThreshold: 5,
restDisplacementThreshold: 5,
stiffness: 800,
mass: 6,
};
// Set up gesture handler
const offset = useMemo(() => new Value(hiddenOffset), []);
const state = useMemo(() => new Value(State.UNDETERMINED), []);
const velocityX = useMemo(() => new Value(0), []);
const translationX = useMemo(() => new Value(0), []);
const gestureHandler = useMemo(() => onGestureEvent({ translationX, state, velocityX }), []);
const clock = useMemo(() => new Animated.Clock(), []);
const translateX = useMemo(
() =>
clamp(
withSpring({
// onSnap: (val) => {
// const offset = val[0];
// if (offset == visibleOffset) {
// // TODO: Use optional chaining once prettier is fixed
// triggerDismissed();
// }
// },
state,
velocity: velocityX,
offset,
value: translationX,
snapPoints: [hiddenOffset, visibleOffset],
config: animationConfig,
}),
hiddenOffset,
visibleOffset
),
[visibleOffset, hiddenOffset, translationX, velocityX]
);
// Programatically trigger hiding and showing
const triggerShowDrawer: Animated.Value<0 | 1> = useMemo(() => new Value(0), []);
const triggerDismissDrawer: Animated.Value<0 | 1> = useMemo(() => new Value(0), []);
// Dismiss overlay
const dismissDrawer = useCallback(() => {
triggerDismissDrawer.setValue(1);
}, []);
// Show overlay
const showDrawer = useCallback(() => {
triggerShowDrawer.setValue(1);
}, []);
// Define animated styles
const animatedStyles: StyleSheet.NamedStyles<any> = useMemo(() => {
return {
overlayBackground: {
backgroundColor: colors.overlay,
...styles.absoluteFill,
opacity: interpolateNode(translateX, {
inputRange: [hiddenOffset + 1, visibleOffset],
outputRange: [0, 1],
}) as any,
transform: [
{
translateX: interpolateNode(translateX, {
inputRange: [hiddenOffset, hiddenOffset + 1],
outputRange: [hiddenOffset, visibleOffset],
extrapolate: Extrapolate.CLAMP,
}) as any,
},
],
},
overlayBackgroundTouchable: {
...StyleSheet.absoluteFillObject,
transform: [
{
translateX: interpolateNode(translateX, {
inputRange: [visibleOffset - 1, visibleOffset],
outputRange: [hiddenOffset, visibleOffset],
}) as any,
},
],
},
modal: {
transform: [{ translateX } as any],
...StyleSheet.absoluteFillObject,
},
};
}, [hiddenOffset, visibleOffset, translateX, safeAreaInsets]);
// Declarative logic that animates overlay
useCode(
() =>
block([
// Animate IN overlay
cond(eq(triggerShowDrawer, new Value(1)), [
set(
offset,
timing({
clock,
from: offset,
easing: EasingNode.inOut(EasingNode.ease) as any,
duration: 250,
to: visibleOffset,
})
),
// Reset value that toggles animating in overlay
cond(not(clockRunning(clock)), block([set(triggerShowDrawer, 0)])),
]),
// Animate OUT overlay
cond(eq(triggerDismissDrawer, new Value(1)), [
set(
offset,
timing({
clock,
from: offset,
easing: EasingNode.inOut(EasingNode.ease) as any,
duration: 200,
to: hiddenOffset,
})
),
// Dismiss overlay after animating out
cond(not(clockRunning(clock)), block([set(triggerDismissDrawer, 0)])),
]),
]),
[]
);
// Expose actions for external components
useImperativeHandle(ref, () => ({
dismissDrawer: () => dismissDrawer(),
showDrawer: () => showDrawer(),
}));
const renderOverlay = useCallback(() => {
return <Animated.View style={animatedStyles.overlayBackground} />;
}, [animatedStyles]);
const renderContent = useCallback(() => {
return (
<PanGestureHandler {...gestureHandler}>
<Animated.View style={[animatedStyles.modal, style]}>
<Animated.View style={animatedStyles.overlayBackgroundTouchable}>
<TouchableOpacity style={styles.fill} onPress={dismissDrawer} />
</Animated.View>
<DrawerView navigation={navigation} onCloseDrawer={dismissDrawer} />
</Animated.View>
</PanGestureHandler>
);
}, [gestureHandler, animatedStyles, style, children, dismissDrawer]);
const renderDrawer = () => {
return (
<React.Fragment>
{renderOverlay()}
{renderContent()}
</React.Fragment>
);
};
return (
<View style={styles.fill}>
{children}
{renderDrawer()}
</View>
);
});
export default Drawer;

@ -0,0 +1,10 @@
import { StyleSheet } from 'react-native';
export default StyleSheet.create({
fill: {
flex: 1,
},
absoluteFill: {
...StyleSheet.absoluteFillObject,
},
});

@ -1,5 +1,5 @@
import React, { PureComponent } from 'react';
import { Alert, TouchableOpacity, View, Image, StyleSheet, Text, ScrollView, InteractionManager } from 'react-native';
import { Alert, TouchableOpacity, View, Image, StyleSheet, Text, InteractionManager } from 'react-native';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import Share from 'react-native-share';
@ -14,7 +14,6 @@ import AccountList from '../AccountList';
import NetworkList from '../NetworkList';
import { renderFromWei, renderFiat } from '../../../util/number';
import { strings } from '../../../../locales/i18n';
import { DrawerActions } from '@react-navigation/native';
import Modal from 'react-native-modal';
import SecureKeychain from '../../../core/SecureKeychain';
import { toggleNetworkModal, toggleAccountsModal, toggleReceiveModal } from '../../../actions/modals';
@ -43,10 +42,14 @@ import AnalyticsV2, { ANALYTICS_EVENTS_V2 } from '../../../util/analyticsV2';
import { isDefaultAccountName, doENSReverseLookup } from '../../../util/ENSUtils';
import ClipboardManager from '../../../core/ClipboardManager';
import { collectiblesSelector } from '../../../reducers/collectibles';
import { getCurrentRoute } from '../../../reducers/navigation';
import { ScrollView } from 'react-native-gesture-handler';
import { isZero } from '../../../util/lodash';
const styles = StyleSheet.create({
wrapper: {
flex: 1,
width: 315,
backgroundColor: colors.white,
},
header: {
@ -369,6 +372,14 @@ class DrawerView extends PureComponent {
*/
protectWalletModalVisible: PropTypes.func,
logOut: PropTypes.func,
/**
* Callback to close drawer
*/
onCloseDrawer: PropTypes.func,
/**
* Latest navigation route
*/
currentRoute: PropTypes.string,
};
state = {
@ -426,7 +437,7 @@ class DrawerView extends PureComponent {
let tokenFound = false;
this.props.tokens.forEach((token) => {
if (this.props.tokenBalances[token.address] && !this.props.tokenBalances[token.address]?.isZero()) {
if (this.props.tokenBalances[token.address] && !isZero(this.props.tokenBalances[token.address])) {
tokenFound = true;
}
});
@ -652,12 +663,7 @@ class DrawerView extends PureComponent {
}
hideDrawer() {
return new Promise((resolve) => {
this.props.navigation.dispatch(DrawerActions.closeDrawer());
setTimeout(() => {
resolve();
}, 300);
});
this.props.onCloseDrawer();
}
onAccountChange = () => {
@ -900,15 +906,23 @@ class DrawerView extends PureComponent {
currentCurrency,
ticker,
seedphraseBackedUp,
currentRoute,
} = this.props;
const {
invalidCustomNetwork,
showProtectWalletModal,
account: { name, ens },
account: { name: nameFromState, ens: ensFromState },
} = this.state;
const account = { address: selectedAddress, ...identities[selectedAddress], ...accounts[selectedAddress] };
const account = {
address: selectedAddress,
name: nameFromState,
ens: ensFromState,
...identities[selectedAddress],
...accounts[selectedAddress],
};
const { name, ens } = account;
account.balance = (accounts[selectedAddress] && renderFromWei(accounts[selectedAddress].balance)) || 0;
const fiatBalance = Engine.getTotalFiatAccountBalance();
if (fiatBalance !== this.previousBalance) {
@ -916,7 +930,8 @@ class DrawerView extends PureComponent {
}
this.currentBalance = fiatBalance;
const fiatBalanceStr = renderFiat(this.currentBalance, currentCurrency);
const currentRoute = findRouteNameFromNavigatorState(this.props.navigation.dangerouslyGetState().routes);
const accountName = isDefaultAccountName(name) && ens ? ens : name;
return (
<View style={styles.wrapper} testID={'drawer-screen'}>
<ScrollView>