diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index f99c7e43b9f..00000000000 --- a/.eslintrc +++ /dev/null @@ -1,44 +0,0 @@ -{ - "parser": "babel-eslint", - "plugins": [ - "react", - "react-native", - "react-native-animation-linter" - ], - "parserOptions": { - "ecmaFeatures": { - "jsx": true, - "modules": true - } - }, - "extends" : [ - "eslint:recommended", - "plugin:react/recommended", - "airbnb-base" - ], - "rules" : { - "arrow-body-style": "warn", - "camelcase": ["error", {ignoreDestructuring: true}], - "class-methods-use-this": "off", - "no-console": "off", - "max-len": ["error", {"code": 160, "comments": 500}], - "no-tabs": "error", - "indent": ["error", 2], - "no-use-before-define": ["error", {"functions": false, "variables": false}], - "no-unused-vars": ["error", {"args": "none"}], - "no-plusplus": ["off"], - "no-underscore-dangle": ["off"], - "arrow-parens": ["off"], - "no-param-reassign": ["off"], - "react-native-animation-linter/must-tear-down-animations": 2, - "sort-keys": ["error", "asc", {"caseSensitive": false, "natural": false}] - }, - "globals": { - "fetch": false - }, - "settings": { - "react": { - "version": "16.5.0" - } - } -} diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 00000000000..950715436a3 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,16 @@ +{ + "extends": "satya164", + "settings": { + "react": { "version": "16" } + }, + "rules": { + "sort-keys": ["error", "asc", {"caseSensitive": false, "natural": false}], + "jest/no-truthy-falsy": 0, + "react-native/no-inline-styles": 0, + "import/named": 0, + "react/display-name": 2, + "jest/no-test-prefixes": 0, //TODO + "jest/no-disabled-tests": 0 //TODO + }, + "env": { "browser": true, "node": true } +} diff --git a/.flowconfig b/.flowconfig index 7ad43751ac2..9edb1be387b 100644 --- a/.flowconfig +++ b/.flowconfig @@ -5,63 +5,71 @@ ; Ignore "BUCK" generated dirs /\.buckd/ -; Ignore unexpected extra "@providesModule" -.*/node_modules/.*/node_modules/fbjs/.* +; Ignore polyfills +node_modules/react-native/Libraries/polyfills/.* -; Ignore duplicate module providers -; For RN Apps installed via npm, "Libraries" folder is inside -; "node_modules/react-native" but in the source repo it is in the root -.*/Libraries/react-native/React.js +; These should not be required directly +; require from fbjs/lib instead: require('fbjs/lib/warning') +node_modules/warning/.* -; Ignore polyfills -.*/Libraries/polyfills/.* +; Flow doesn't support platforms +.*/Libraries/Utilities/LoadingView.js -; Ignore metro -.*/node_modules/metro/.* +[untyped] +.*/node_modules/@react-native-community/cli/.*/.* [include] [libs] node_modules/react-native/Libraries/react-native/react-native-interface.js node_modules/react-native/flow/ -node_modules/react-native/flow-github/ [options] emoji=true -module.system=haste -module.system.haste.use_name_reducers=true -# get basename -module.system.haste.name_reducers='^.*/\([a-zA-Z0-9$_.-]+\.js\(\.flow\)?\)$' -> '\1' -# strip .js or .js.flow suffix -module.system.haste.name_reducers='^\(.*\)\.js\(\.flow\)?$' -> '\1' -# strip .ios suffix -module.system.haste.name_reducers='^\(.*\)\.ios$' -> '\1' -module.system.haste.name_reducers='^\(.*\)\.android$' -> '\1' -module.system.haste.name_reducers='^\(.*\)\.native$' -> '\1' -module.system.haste.paths.blacklist=.*/__tests__/.* -module.system.haste.paths.blacklist=.*/__mocks__/.* -module.system.haste.paths.blacklist=/node_modules/react-native/Libraries/Animated/src/polyfills/.* -module.system.haste.paths.whitelist=/node_modules/react-native/Libraries/.* - -munge_underscores=true - -module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub' +esproposal.optional_chaining=enable +esproposal.nullish_coalescing=enable module.file_ext=.js -module.file_ext=.jsx module.file_ext=.json -module.file_ext=.native.js +module.file_ext=.ios.js + +munge_underscores=true + +module.name_mapper='^react-native$' -> '/node_modules/react-native/Libraries/react-native/react-native-implementation' +module.name_mapper='^react-native/\(.*\)$' -> '/node_modules/react-native/\1' +module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '/node_modules/react-native/Libraries/Image/RelativeImageStub' suppress_type=$FlowIssue suppress_type=$FlowFixMe suppress_type=$FlowFixMeProps suppress_type=$FlowFixMeState -suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\) -suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ -suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy +suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\) +suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(\\)? *\\(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 +sketchy-number=warn +untyped-type-import=warn +nonstrict-import=warn +deprecated-type=warn +unsafe-getters-setters=warn +inexact-spread=warn +unnecessary-invariant=warn +signature-verification-failure=warn +deprecated-utility=error + +[strict] +deprecated-type +nonstrict-import +sketchy-null +unclear-type +unsafe-getters-setters +untyped-import +untyped-type-import + [version] -^0.92.0 +^0.105.0 \ No newline at end of file diff --git a/.gitignore b/.gitignore index f13d7e7ba74..8dc0a7d6a8a 100644 --- a/.gitignore +++ b/.gitignore @@ -45,6 +45,7 @@ yarn-error.log buck-out/ \.buckd/ *.keystore +!debug.keystore # fastlane # diff --git a/.nvmrc b/.nvmrc index a933a5dd767..bce43c253fe 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v11.1.0 +v12.13.0 diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 00000000000..e516059d776 --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,6 @@ +module.exports = { + bracketSpacing: true, + jsxBracketSameLine: false, + singleQuote: true, + trailingComma: 'all', +}; \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index c27cb67ddf9..2061bf4e934 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,9 +8,27 @@ and this project adheres to [Semantic Versioning](http://semver.org/) ## [Unreleased] ### Added +### Removed + +### Changed +## [1.2.3-1](https://github.com/rainbow-me/rainbow/releases/tag/v1.2.3-1) ### Changed +* Better biometric support +* Fix import wallet showing old wallet balances -### Removed +## [1.2.2-4](https://github.com/rainbow-me/rainbow/releases/tag/v1.2.2-4) +### Added +* Uniswap support +* Add to contacts +* Support for deep linking +* Support for Sentry + +### Changed +* Upgraded Firebase + +## [1.1.5-2](https://github.com/rainbow-me/rainbow/releases/tag/v1.1.5-2) +### Changed +* Bugfix for transaction history with null symbol ## [1.1.5-2](https://github.com/rainbow-me/rainbow/releases/tag/v1.1.5-2) ### Changed diff --git a/README.md b/README.md index 93dfaa6b1da..8d7a8f80dec 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,10 @@ -# Rainbow Wallet +![](https://pbs.twimg.com/profile_banners/1103191459409420288/1573207178/1500x500) +### 🌈️ Rainbow +> the pocket robot for your internet money β–π—£π—Όπ˜„π—²π—Ώπ—²π—± π—―π˜† π—˜π˜π—΅π—²π—Ώπ—²π˜‚π—Ίβ– -A mobile wallet for open finance and the decentralized web. +πŸ“²οΈ [Available on the iOS App Store.](https://apps.apple.com/us/app/rainbow-ethereum-wallet/id1457119021) + +🐦️ [Follow us on Twitter](https://twitter.com/rainbowdotme) ## Requirements diff --git a/__tests__/App-test.js b/__tests__/App-test.js deleted file mode 100644 index 178476699b6..00000000000 --- a/__tests__/App-test.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @format - */ - -import 'react-native'; -import React from 'react'; -import App from '../App'; - -// Note: test renderer must be required after react-native. -import renderer from 'react-test-renderer'; - -it('renders correctly', () => { - renderer.create(); -}); diff --git a/__tests__/App.js b/__tests__/App.js deleted file mode 100644 index b5f8100fb5d..00000000000 --- a/__tests__/App.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @format - */ - - import 'react-native'; -import React from 'react'; -import App from '../App'; - - // Note: test renderer must be required after react-native. -import renderer from 'react-test-renderer'; - - it('renders correctly', () => { - renderer.create(); -}); diff --git a/android/app/build.gradle b/android/app/build.gradle index 7efec0dde67..7a996d8df86 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -77,6 +77,7 @@ project.ext.react = [ ] apply from: "../../node_modules/react-native/react.gradle" +apply from: "../../node_modules/@sentry/react-native/sentry.gradle" apply from: "../../node_modules/react-native-code-push/android/codepush.gradle" /** @@ -153,36 +154,22 @@ android { } dependencies { - implementation project(':@react-native-community_masked-view') + implementation project(':react-native-text-input-mask') + implementation project(':react-native-safe-area-context') implementation project(':@segment_analytics-react-native') - implementation project(':react-native-firebase') implementation project(':@staltz_react-native-tcp') implementation project(':@react-native-community_blur') implementation project(':@react-native-community_netinfo') - implementation project(':@react-native-community_async-storage') + implementation project(':@react-native-community_masked-view') implementation project(':react-native-camera') compile project(':react-native-device-info') compile project(':react-native-screens') compile project(':react-native-version-number') compile project(':react-native-matomo') - compile project(':react-native-fast-image') compile project(':react-native-blur') compile project(':react-native-languages') compile project(':react-native-reanimated') - compile project(':react-native-gesture-handler') compile project(':react-native-code-push') - compile project(':react-native-haptic-feedback') - compile project(':react-native-udp') - compile project(':react-native-touch-id') - compile project(':react-native-tcp') - compile project(':react-native-svg') - compile project(':react-native-splash-screen') - compile project(':react-native-randombytes') - compile project(':react-native-radial-gradient') - compile project(':react-native-os') - compile project(':react-native-mail') - compile project(':react-native-linear-gradient') - compile project(':react-native-keychain') compile fileTree(dir: "libs", include: ["*.jar"]) compile "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}" compile "com.facebook.react:react-native:+" // From node_modules diff --git a/android/app/src/main/java/com/rainbow/MainApplication.java b/android/app/src/main/java/com/rainbow/MainApplication.java index c0dcf6a0001..10969facca4 100644 --- a/android/app/src/main/java/com/rainbow/MainApplication.java +++ b/android/app/src/main/java/com/rainbow/MainApplication.java @@ -3,36 +3,24 @@ import android.app.Application; import com.facebook.react.ReactApplication; +import com.RNTextInputMask.RNTextInputMaskPackage; +import com.th3rdwave.safeareacontext.SafeAreaContextPackage; import org.reactnative.maskedview.RNCMaskedViewPackage; +import com.RNTextInputMask.RNTextInputMaskPackage; import com.segment.analytics.reactnative.core.RNAnalyticsPackage; -import io.invertase.firebase.RNFirebasePackage; import react-native-tcp.TcpSocketsModule; import com.cmcewen.blurview.BlurViewPackage; import com.reactnativecommunity.netinfo.NetInfoPackage; -import com.reactnativecommunity.asyncstorage.AsyncStoragePackage; import org.reactnative.camera.RNCameraPackage; import com.learnium.RNDeviceInfo.RNDeviceInfo; import com.swmansion.rnscreens.RNScreensPackage; import com.apsl.versionnumber.RNVersionNumberPackage; import de.bonify.reactnativepiwik.PiwikPackage; -import com.dylanvann.fastimage.FastImageViewPackage; import com.cmcewen.blurview.BlurViewPackage; import com.reactcommunity.rnlanguages.RNLanguagesPackage; import com.swmansion.reanimated.ReanimatedPackage; -import com.swmansion.gesturehandler.react.RNGestureHandlerPackage; import com.microsoft.codepush.react.CodePush; import com.reactlibrary.RNReactNativeHapticFeedbackPackage; -import com.tradle.react.UdpSocketsModule; -import com.rnfingerprint.FingerprintAuthPackage; -import com.peel.react.TcpSocketsModule; -import com.horcrux.svg.SvgPackage; -import org.devio.rn.splashscreen.SplashScreenReactPackage; -import com.bitgo.randombytes.RandomBytesPackage; -import com.surajit.rnrg.RNRadialGradientPackage; -import com.peel.react.rnos.RNOSModule; -import com.chirag.RNMail.RNMail; -import com.BV.LinearGradient.LinearGradientPackage; -import com.oblador.keychain.KeychainPackage; import com.facebook.react.ReactNativeHost; import com.facebook.react.ReactPackage; import com.facebook.react.shell.MainReactPackage; @@ -59,36 +47,23 @@ public boolean getUseDeveloperSupport() { protected List getPackages() { return Arrays.asList( new MainReactPackage(), + new RNTextInputMaskPackage(), + new SafeAreaContextPackage(), new RNCMaskedViewPackage(), + new RNTextInputMaskPackage(), new RNAnalyticsPackage(), - new RNFirebasePackage(), - new TcpSocketsModule(), new BlurViewPackage(), new NetInfoPackage(), - new AsyncStoragePackage(), new RNCameraPackage(), new RNDeviceInfo(), new RNScreensPackage(), new RNVersionNumberPackage(), new PiwikPackage(), - new FastImageViewPackage(), new BlurViewPackage(), new RNLanguagesPackage(), new ReanimatedPackage(), - new RNGestureHandlerPackage(), new CodePush(BuildConfig.CODEPUSH_KEY, getApplicationContext(), BuildConfig.DEBUG), - new RNReactNativeHapticFeedbackPackage(), - new UdpSocketsModule(), - new FingerprintAuthPackage(), - new TcpSocketsModule(), - new SvgPackage(), - new SplashScreenReactPackage(), - new RandomBytesPackage(), - new RNRadialGradientPackage(), - new RNOSModule(), - new RNMail(), - new LinearGradientPackage(), - new KeychainPackage() + new TcpSocketsModule() ); } diff --git a/android/sentry.properties b/android/sentry.properties new file mode 100644 index 00000000000..a8f8225c9b4 --- /dev/null +++ b/android/sentry.properties @@ -0,0 +1,4 @@ +defaults.url=https://sentry.io/ +defaults.org=rainbow-me +defaults.project=rainbow-wallet +cli.executable=node_modules/@sentry/cli/bin/sentry-cli diff --git a/android/settings.gradle b/android/settings.gradle index 68970552dbf..51255462cdc 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -1,18 +1,20 @@ rootProject.name = 'Rainbow' +include ':react-native-text-input-mask' +project(':react-native-text-input-mask').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-text-input-mask/android') +include ':react-native-safe-area-context' +project(':react-native-safe-area-context').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-safe-area-context/android') include ':@react-native-community_masked-view' project(':@react-native-community_masked-view').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/masked-view/android') +include ':react-native-text-input-mask' +project(':react-native-text-input-mask').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-text-input-mask/android') include ':@segment_analytics-react-native' project(':@segment_analytics-react-native').projectDir = new File(rootProject.projectDir, '../node_modules/@segment/analytics-react-native/android') -include ':react-native-firebase' -project(':react-native-firebase').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-firebase/android') include ':@staltz_react-native-tcp' project(':@staltz_react-native-tcp').projectDir = new File(rootProject.projectDir, '../node_modules/@staltz/react-native-tcp/android') include ':@react-native-community_blur' project(':@react-native-community_blur').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/blur/android') include ':@react-native-community_netinfo' project(':@react-native-community_netinfo').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/netinfo/android') -include ':@react-native-community_async-storage' -project(':@react-native-community_async-storage').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/async-storage/android') include ':react-native-camera' project(':react-native-camera').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-camera/android') include ':react-native-device-info' @@ -23,41 +25,13 @@ include ':react-native-version-number' project(':react-native-version-number').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-version-number/android') include ':react-native-matomo' project(':react-native-matomo').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-matomo/android') -include ':react-native-fast-image' -project(':react-native-fast-image').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fast-image/android') include ':react-native-blur' project(':react-native-blur').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-blur/android') include ':react-native-languages' project(':react-native-languages').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-languages/android') include ':react-native-reanimated' project(':react-native-reanimated').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-reanimated/android') -include ':react-native-gesture-handler' -project(':react-native-gesture-handler').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-gesture-handler/android') include ':react-native-code-push' project(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app') -include ':react-native-haptic-feedback' -project(':react-native-haptic-feedback').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-haptic-feedback/android') -include ':react-native-udp' -project(':react-native-udp').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-udp/android') -include ':react-native-touch-id' -project(':react-native-touch-id').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-touch-id/android') -include ':react-native-tcp' -project(':react-native-tcp').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-tcp/android') -include ':react-native-svg' -project(':react-native-svg').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-svg/android') -include ':react-native-splash-screen' -project(':react-native-splash-screen').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-splash-screen/android') -include ':react-native-randombytes' -project(':react-native-randombytes').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-randombytes/android') -include ':react-native-radial-gradient' -project(':react-native-radial-gradient').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-radial-gradient/android') -include ':react-native-os' -project(':react-native-os').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-os/android') -include ':react-native-mail' -project(':react-native-mail').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-mail/android') -include ':react-native-linear-gradient' -project(':react-native-linear-gradient').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-linear-gradient/android') -include ':react-native-keychain' -project(':react-native-keychain').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-keychain/android') include ':app' diff --git a/babel.config.js b/babel.config.js index a46794435a1..06246be49af 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,7 +1,13 @@ +// eslint-disable-next-line import/no-commonjs module.exports = { env: { development: { - plugins: [['transform-remove-console', { exclude: ['disableYellowBox', 'error', 'info', 'log'] }]], + plugins: [ + [ + 'transform-remove-console', + { exclude: ['disableYellowBox', 'error', 'info', 'log'] }, + ], + ], }, production: { plugins: [['transform-remove-console', { exclude: ['error'] }]], diff --git a/config/test/jest-setup.js b/config/test/jest-setup.js index c582ef34605..d7be8046b9a 100644 --- a/config/test/jest-setup.js +++ b/config/test/jest-setup.js @@ -1,7 +1,17 @@ +/* eslint-disable no-undef */ +jest.mock('@segment/analytics-react-native', () => ({ + identify: () => null, + reset: () => null, + setup: () => null, +})); + +jest.mock('@sentry/react-native', () => ({ + captureException: () => null, +})); + jest.autoMockOff(); jest.mock('react-native-keychain', () => ({ - setGenericPassword: jest.fn(), getGenericPassword: jest.fn(), - resetGenericPassword: jest.fn() + resetGenericPassword: jest.fn(), + setGenericPassword: jest.fn(), })); - diff --git a/e2e/Navigation.js b/e2e/Navigation.js index 8a89bd673fd..3a2d21a904d 100644 --- a/e2e/Navigation.js +++ b/e2e/Navigation.js @@ -1,3 +1,4 @@ +/* eslint-disable no-undef */ describe('Basic test', () => { beforeEach(async () => { await device.reloadReactNative(); @@ -8,7 +9,7 @@ describe('Basic test', () => { }); it('should navigate without imported wallet', async () => { - const importButton = element(by.label('Import Wallet')).atIndex(1) + const importButton = element(by.label('Import Wallet')).atIndex(1); await expect(importButton).toBeVisible(); await element(by.label('Balances')).swipe('left', 'fast', 0.5); await expect(element(by.label('Scan to send'))).toBeVisible(); @@ -32,6 +33,5 @@ describe('Basic test', () => { await expect(element(by.label('Scan to send'))).toBeVisible(); await element(by.id('goToBalancesFromScanner')).tap(); await expect(element(by.label('Balances'))).toBeVisible(); - }); }); diff --git a/e2e/init.js b/e2e/init.js index 8f248b7a6df..b188daf4976 100644 --- a/e2e/init.js +++ b/e2e/init.js @@ -1,3 +1,4 @@ +/* eslint-disable import/no-commonjs,no-undef,babel/no-invalid-this */ const detox = require('detox'); const config = require('../package.json').detox; const adapter = require('detox/runners/mocha/adapter'); @@ -7,11 +8,11 @@ before(async () => { await device.launchApp({ permissions: { camera: 'YES' } }); }); -beforeEach(async function () { +beforeEach(async function() { await adapter.beforeEach(this); }); -afterEach(async function () { +afterEach(async function() { await adapter.afterEach(this); }); diff --git a/global.js b/global.js index e20caa5ac01..a3317d7e3f7 100644 --- a/global.js +++ b/global.js @@ -1,11 +1,11 @@ if (typeof btoa === 'undefined') { - global.btoa = function (str) { + global.btoa = function(str) { return new Buffer(str, 'binary').toString('base64'); }; } if (typeof atob === 'undefined') { - global.atob = function (b64Encoded) { + global.atob = function(b64Encoded) { return new Buffer(b64Encoded, 'base64').toString('binary'); }; } diff --git a/icon.png b/icon.png index 431aa4f0eeb..f959168df57 100644 Binary files a/icon.png and b/icon.png differ diff --git a/index.js b/index.js index 470c090cc35..58a904688a6 100644 --- a/index.js +++ b/index.js @@ -1,12 +1,12 @@ +import 'react-native-gesture-handler'; import './global'; import './shim'; -/* eslint-disable import/first */ import RNLanguages from 'react-native-languages'; import lang from 'i18n-js'; import { resources } from './src/languages'; -// eslint-disable-next-line +// eslint-disable-next-line no-unused-vars,import/default import App from './src/App'; // Languages (i18n) @@ -16,7 +16,7 @@ lang.fallbacks = true; lang.translations = Object.assign( {}, - ...Object.keys(resources).map((key, index) => ({ + ...Object.keys(resources).map(key => ({ [key]: resources[key].translation, - })), + })) ); diff --git a/ios/Dummy.swift b/ios/Dummy.swift new file mode 100644 index 00000000000..8cf6d84f43f --- /dev/null +++ b/ios/Dummy.swift @@ -0,0 +1,9 @@ +// +// Dummy.swift +// Rainbow +// +// Created by Jin on 11/17/19. +// Copyright Β© 2019 Facebook. All rights reserved. +// + +import Foundation diff --git a/ios/Gemfile b/ios/Gemfile index 7a118b49be7..cdd3a6b3491 100644 --- a/ios/Gemfile +++ b/ios/Gemfile @@ -1,3 +1,6 @@ source "https://rubygems.org" gem "fastlane" + +plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile') +eval_gemfile(plugins_path) if File.exist?(plugins_path) diff --git a/ios/Gemfile.lock b/ios/Gemfile.lock new file mode 100644 index 00000000000..e65bcd9e17a --- /dev/null +++ b/ios/Gemfile.lock @@ -0,0 +1,161 @@ +GEM + remote: https://rubygems.org/ + specs: + CFPropertyList (3.0.2) + addressable (2.7.0) + public_suffix (>= 2.0.2, < 5.0) + atomos (0.1.3) + babosa (1.0.3) + claide (1.0.3) + colored (1.2) + colored2 (3.1.2) + commander-fastlane (4.4.6) + highline (~> 1.7.2) + declarative (0.0.10) + declarative-option (0.1.0) + digest-crc (0.4.1) + domain_name (0.5.20190701) + unf (>= 0.0.5, < 1.0.0) + dotenv (2.7.5) + emoji_regex (1.0.1) + excon (0.70.0) + faraday (0.17.1) + multipart-post (>= 1.2, < 3) + faraday-cookie_jar (0.0.6) + faraday (>= 0.7.4) + http-cookie (~> 1.0.0) + faraday_middleware (0.13.1) + faraday (>= 0.7.4, < 1.0) + fastimage (2.1.7) + fastlane (2.137.0) + CFPropertyList (>= 2.3, < 4.0.0) + addressable (>= 2.3, < 3.0.0) + babosa (>= 1.0.2, < 2.0.0) + bundler (>= 1.12.0, < 3.0.0) + colored + commander-fastlane (>= 4.4.6, < 5.0.0) + dotenv (>= 2.1.1, < 3.0.0) + emoji_regex (>= 0.1, < 2.0) + excon (>= 0.45.0, < 1.0.0) + faraday (~> 0.17) + faraday-cookie_jar (~> 0.0.6) + faraday_middleware (~> 0.13.1) + fastimage (>= 2.1.0, < 3.0.0) + gh_inspector (>= 1.1.2, < 2.0.0) + google-api-client (>= 0.21.2, < 0.24.0) + google-cloud-storage (>= 1.15.0, < 2.0.0) + highline (>= 1.7.2, < 2.0.0) + json (< 3.0.0) + jwt (~> 2.1.0) + mini_magick (>= 4.9.4, < 5.0.0) + multi_xml (~> 0.5) + multipart-post (~> 2.0.0) + plist (>= 3.1.0, < 4.0.0) + public_suffix (~> 2.0.0) + rubyzip (>= 1.3.0, < 2.0.0) + security (= 0.1.3) + simctl (~> 1.6.3) + slack-notifier (>= 2.0.0, < 3.0.0) + terminal-notifier (>= 2.0.0, < 3.0.0) + terminal-table (>= 1.4.5, < 2.0.0) + tty-screen (>= 0.6.3, < 1.0.0) + tty-spinner (>= 0.8.0, < 1.0.0) + word_wrap (~> 1.0.0) + xcodeproj (>= 1.8.1, < 2.0.0) + xcpretty (~> 0.3.0) + xcpretty-travis-formatter (>= 0.0.3) + fastlane-plugin-sentry (1.6.0) + gh_inspector (1.1.3) + google-api-client (0.23.9) + addressable (~> 2.5, >= 2.5.1) + googleauth (>= 0.5, < 0.7.0) + httpclient (>= 2.8.1, < 3.0) + mime-types (~> 3.0) + representable (~> 3.0) + retriable (>= 2.0, < 4.0) + signet (~> 0.9) + google-cloud-core (1.3.2) + google-cloud-env (~> 1.0) + google-cloud-env (1.2.1) + faraday (~> 0.11) + google-cloud-storage (1.16.0) + digest-crc (~> 0.4) + google-api-client (~> 0.23) + google-cloud-core (~> 1.2) + googleauth (>= 0.6.2, < 0.10.0) + googleauth (0.6.7) + faraday (~> 0.12) + jwt (>= 1.4, < 3.0) + memoist (~> 0.16) + multi_json (~> 1.11) + os (>= 0.9, < 2.0) + signet (~> 0.7) + highline (1.7.10) + http-cookie (1.0.3) + domain_name (~> 0.5) + httpclient (2.8.3) + json (2.3.0) + jwt (2.1.0) + memoist (0.16.2) + mime-types (3.3) + mime-types-data (~> 3.2015) + mime-types-data (3.2019.1009) + mini_magick (4.9.5) + multi_json (1.14.1) + multi_xml (0.6.0) + multipart-post (2.0.0) + nanaimo (0.2.6) + naturally (2.2.0) + os (1.0.1) + plist (3.5.0) + public_suffix (2.0.5) + representable (3.0.4) + declarative (< 0.1.0) + declarative-option (< 0.2.0) + uber (< 0.2.0) + retriable (3.1.2) + rouge (2.0.7) + rubyzip (1.3.0) + security (0.1.3) + signet (0.11.0) + addressable (~> 2.3) + faraday (~> 0.9) + jwt (>= 1.5, < 3.0) + multi_json (~> 1.10) + simctl (1.6.6) + CFPropertyList + naturally + slack-notifier (2.3.2) + terminal-notifier (2.0.0) + terminal-table (1.8.0) + unicode-display_width (~> 1.1, >= 1.1.1) + tty-cursor (0.7.0) + tty-screen (0.7.0) + tty-spinner (0.9.2) + tty-cursor (~> 0.7) + uber (0.1.0) + unf (0.1.4) + unf_ext + unf_ext (0.0.7.6) + unicode-display_width (1.6.0) + word_wrap (1.0.0) + xcodeproj (1.13.0) + CFPropertyList (>= 2.3.3, < 4.0) + atomos (~> 0.1.3) + claide (>= 1.0.2, < 2.0) + colored2 (~> 3.1) + nanaimo (~> 0.2.6) + xcpretty (0.3.0) + rouge (~> 2.0.7) + xcpretty-travis-formatter (1.0.0) + xcpretty (~> 0.2, >= 0.0.7) + +PLATFORMS + ruby + +DEPENDENCIES + fastlane + fastlane-plugin-sentry + +BUNDLED WITH + 1.16.2 diff --git a/ios/Podfile b/ios/Podfile index 87d25b84ac4..5e727a73d3f 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -1,70 +1,62 @@ -platform :ios, '9.0' +platform :ios, '11.0' +require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' # Prevent Cocoapods from collecting stats, which adds time to each pod installation ENV['COCOAPODS_DISABLE_STATS'] = 'true' target 'Rainbow' do - rn_path = '../node_modules/react-native' - - # Crashlytics - pod 'Fabric', '~> 1.7.11' - pod 'Crashlytics', '~> 3.10.7' - - # Firebase - pod 'Firebase/Core', '~> 5.3.0' - pod 'Firebase/Messaging', '~> 5.3.0' - # Core React - pod 'React', :path => "#{rn_path}", :subspecs => [ - 'Core', - 'CxxBridge', # Include this for RN >= 0.47 - 'cxxreact', - 'DevSupport', # Include this to enable In-App Devmenu if RN >= 0.43 - 'fishhook', - 'jsi', - 'jsiexecutor', - 'jsinspector', - 'RCTActionSheet', - 'RCTAnimation', # Needed for FlatList and animations running on native UI thread - 'RCTBlob', - 'RCTImage', - 'RCTLinkingIOS', - 'RCTNetwork', - 'RCTPushNotification', - 'RCTSettings', - 'RCTText', - 'RCTVibration', - 'RCTWebSocket', # needed for debugging - ] - + pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector" + pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec" + pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired" + pod 'RCTTypeSafety', :path => + "../node_modules/react-native/Libraries/TypeSafety" + pod 'React', :path => '../node_modules/react-native/' + pod 'React-Core', :path => '../node_modules/react-native/' + pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules' + pod 'React-Core/DevSupport', :path => '../node_modules/react-native/' + pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS' + pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation' + pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob' + pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image' + pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS' + pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network' + pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings' + pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text' + pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration' + pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/' + + pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact' + pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi' + pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor' + pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector' + # React Third Party - required - pod 'yoga', path: "#{rn_path}/ReactCommon/yoga" - pod 'Folly', :podspec => "#{rn_path}/third-party-podspecs/Folly.podspec" - pod 'DoubleConversion', :podspec => "#{rn_path}/third-party-podspecs/DoubleConversion.podspec" - pod 'glog', :podspec => "#{rn_path}/third-party-podspecs/glog.podspec" - - # React-Native-Community packages - pod 'react-native-blur', :path => '../node_modules/@react-native-community/blur' - pod 'react-native-netinfo', :path => '../node_modules/@react-native-community/netinfo' - pod 'RNCAsyncStorage', :path => '../node_modules/@react-native-community/async-storage' - - # Third Party packages - pod 'react-native-camera', :path => '../node_modules/react-native-camera' - pod 'react-native-fast-image', :path => '../node_modules/react-native-fast-image' - pod 'react-native-version-number', :path => '../node_modules/react-native-version-number' - - pod 'BVLinearGradient', :path => '../node_modules/react-native-linear-gradient' - pod 'RNDeviceInfo', :path => '../node_modules/react-native-device-info' - pod 'RNIOS11DeviceCheck', :path => '../node_modules/react-native-ios11-devicecheck/ios' - pod 'RNLanguages', :path => '../node_modules/react-native-languages' - pod 'RNReanimated', :path => '../node_modules/react-native-reanimated' - pod 'RNScreens', :path => '../node_modules/react-native-screens' - pod 'RNStoreReview', :path => '../node_modules/react-native-store-review/ios' - + pod 'ReactCommon/callinvoker', :path => "../node_modules/react-native/ReactCommon" + pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon" + pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga' + pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec' + pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec' + pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec' pod 'FLAnimatedImage' pod 'libwebp' - pod 'RNAnalytics', :path => '../node_modules/@segment/analytics-react-native' + pod 'CodePush', :path => '../node_modules/react-native-code-push' + pod 'RNInputMask', :path => '../node_modules/react-native-text-input-mask/ios/InputMask' + + use_native_modules! - pod 'RNCMaskedView', :path => '../node_modules/@react-native-community/masked-view' + pod 'RNCPushNotificationIOS', :path => '../node_modules/@react-native-community/push-notification-ios' + +end +post_install do |installer| + # Improve the Pods project setting to match with the ones we want to have for the project + installer.pods_project.targets.each do |target| + target.build_configurations.each do |config| + config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0' + config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)'] + config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'RCT_ENABLE_INSPECTOR=0' + config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'ENABLE_PACKAGER_CONNECTION=0' + end + end end diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 44c0b4cb979..761039e4af9 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1,314 +1,752 @@ PODS: - - Analytics (3.6.10) + - Analytics (3.7.0) + - Base64 (1.1.2) - boost-for-react-native (1.63.0) - BVLinearGradient (2.5.6): - React - - Crashlytics (3.10.9): - - Fabric (~> 1.7.13) + - CodePush (5.7.0): + - Base64 (~> 1.1) + - JWT (~> 3.0.0-beta.7) + - React + - SSZipArchive (~> 2.1) + - Crashlytics (3.12.0): + - Fabric (~> 1.9.0) - DoubleConversion (1.1.6) - - Fabric (1.7.13) - - Firebase/Core (5.3.0): + - Fabric (1.9.0) + - FBLazyVector (1000.0.0) + - FBReactNativeSpec (1000.0.0): + - Folly (= 2018.10.22.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-Core (= 1000.0.0) + - React-jsi (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - Firebase/Core (6.13.0): - Firebase/CoreOnly - - FirebaseAnalytics (= 5.0.1) - - Firebase/CoreOnly (5.3.0): - - FirebaseCore (= 5.0.4) - - Firebase/Messaging (5.3.0): + - FirebaseAnalytics (= 6.1.6) + - Firebase/CoreOnly (6.13.0): + - FirebaseCore (= 6.4.0) + - Firebase/Messaging (6.13.0): - Firebase/CoreOnly - - FirebaseMessaging (= 3.0.2) - - FirebaseAnalytics (5.0.1): - - FirebaseCore (~> 5.0) - - FirebaseInstanceID (~> 3.0) - - "GoogleToolboxForMac/NSData+zlib (~> 2.1)" - - nanopb (~> 0.3) - - FirebaseCore (5.0.4): - - "GoogleToolboxForMac/NSData+zlib (~> 2.1)" - - FirebaseInstanceID (3.1.1): - - FirebaseCore (~> 5.0) - - FirebaseMessaging (3.0.2): - - FirebaseCore (~> 5.0) - - FirebaseInstanceID (~> 3.0) - - GoogleToolboxForMac/Logger (~> 2.1) - - Protobuf (~> 3.1) + - FirebaseMessaging (~> 4.1.9) + - FirebaseAnalytics (6.1.6): + - FirebaseCore (~> 6.4) + - FirebaseInstanceID (~> 4.2) + - GoogleAppMeasurement (= 6.1.6) + - GoogleUtilities/AppDelegateSwizzler (~> 6.0) + - GoogleUtilities/MethodSwizzler (~> 6.0) + - GoogleUtilities/Network (~> 6.0) + - "GoogleUtilities/NSData+zlib (~> 6.0)" + - nanopb (= 0.3.9011) + - FirebaseAnalyticsInterop (1.4.0) + - FirebaseCore (6.4.0): + - FirebaseCoreDiagnostics (~> 1.0) + - FirebaseCoreDiagnosticsInterop (~> 1.0) + - GoogleUtilities/Environment (~> 6.2) + - GoogleUtilities/Logger (~> 6.2) + - FirebaseCoreDiagnostics (1.1.2): + - FirebaseCoreDiagnosticsInterop (~> 1.0) + - GoogleDataTransportCCTSupport (~> 1.0) + - GoogleUtilities/Environment (~> 6.2) + - GoogleUtilities/Logger (~> 6.2) + - nanopb (~> 0.3.901) + - FirebaseCoreDiagnosticsInterop (1.1.0) + - FirebaseInstanceID (4.2.7): + - FirebaseCore (~> 6.0) + - GoogleUtilities/Environment (~> 6.0) + - GoogleUtilities/UserDefaults (~> 6.0) + - FirebaseMessaging (4.1.10): + - FirebaseAnalyticsInterop (~> 1.3) + - FirebaseCore (~> 6.2) + - FirebaseInstanceID (~> 4.1) + - GoogleUtilities/AppDelegateSwizzler (~> 6.2) + - GoogleUtilities/Environment (~> 6.2) + - GoogleUtilities/Reachability (~> 6.2) + - GoogleUtilities/UserDefaults (~> 6.2) + - Protobuf (>= 3.9.2, ~> 3.9) - FLAnimatedImage (1.0.12) - Folly (2018.10.22.00): + - boost-for-react-native + - DoubleConversion + - Folly/Default (= 2018.10.22.00) + - glog + - Folly/Default (2018.10.22.00): - boost-for-react-native - DoubleConversion - glog - glog (0.3.5) - - GoogleToolboxForMac/Defines (2.2.0) - - GoogleToolboxForMac/Logger (2.2.0): - - GoogleToolboxForMac/Defines (= 2.2.0) - - "GoogleToolboxForMac/NSData+zlib (2.2.0)": - - GoogleToolboxForMac/Defines (= 2.2.0) - - libwebp (1.0.2): - - libwebp/core (= 1.0.2) - - libwebp/dec (= 1.0.2) - - libwebp/demux (= 1.0.2) - - libwebp/dsp (= 1.0.2) - - libwebp/enc (= 1.0.2) - - libwebp/mux (= 1.0.2) - - libwebp/utils (= 1.0.2) - - libwebp/webp (= 1.0.2) - - libwebp/core (1.0.2): + - GoogleAppMeasurement (6.1.6): + - GoogleUtilities/AppDelegateSwizzler (~> 6.0) + - GoogleUtilities/MethodSwizzler (~> 6.0) + - GoogleUtilities/Network (~> 6.0) + - "GoogleUtilities/NSData+zlib (~> 6.0)" + - nanopb (= 0.3.9011) + - GoogleDataTransport (3.2.0) + - GoogleDataTransportCCTSupport (1.2.3): + - GoogleDataTransport (~> 3.2) + - nanopb (~> 0.3.901) + - GoogleUtilities/AppDelegateSwizzler (6.4.0): + - GoogleUtilities/Environment + - GoogleUtilities/Logger + - GoogleUtilities/Network + - GoogleUtilities/Environment (6.4.0) + - GoogleUtilities/Logger (6.4.0): + - GoogleUtilities/Environment + - GoogleUtilities/MethodSwizzler (6.4.0): + - GoogleUtilities/Logger + - GoogleUtilities/Network (6.4.0): + - GoogleUtilities/Logger + - "GoogleUtilities/NSData+zlib" + - GoogleUtilities/Reachability + - "GoogleUtilities/NSData+zlib (6.4.0)" + - GoogleUtilities/Reachability (6.4.0): + - GoogleUtilities/Logger + - GoogleUtilities/UserDefaults (6.4.0): + - GoogleUtilities/Logger + - JWT (3.0.0-beta.12): + - Base64 (~> 1.1.2) + - libwebp (1.0.3): + - libwebp/demux (= 1.0.3) + - libwebp/mux (= 1.0.3) + - libwebp/webp (= 1.0.3) + - libwebp/demux (1.0.3): - libwebp/webp - - libwebp/dec (1.0.2): - - libwebp/core - - libwebp/demux (1.0.2): - - libwebp/core - - libwebp/dsp (1.0.2): - - libwebp/core - - libwebp/enc (1.0.2): - - libwebp/core - - libwebp/mux (1.0.2): - - libwebp/core - - libwebp/utils (1.0.2): - - libwebp/core - - libwebp/webp (1.0.2) - - nanopb (0.3.901): - - nanopb/decode (= 0.3.901) - - nanopb/encode (= 0.3.901) - - nanopb/decode (0.3.901) - - nanopb/encode (0.3.901) - - Protobuf (3.7.0) - - React (0.59.9): - - React/Core (= 0.59.9) + - libwebp/mux (1.0.3): + - libwebp/demux + - libwebp/webp (1.0.3) + - nanopb (0.3.9011): + - nanopb/decode (= 0.3.9011) + - nanopb/encode (= 0.3.9011) + - nanopb/decode (0.3.9011) + - nanopb/encode (0.3.9011) + - Protobuf (3.11.2) + - RCTRequired (1000.0.0) + - RCTTypeSafety (1000.0.0): + - FBLazyVector (= 1000.0.0) + - Folly (= 2018.10.22.00) + - RCTRequired (= 1000.0.0) + - React-Core (= 1000.0.0) + - React (1000.0.0): + - React-Core (= 1000.0.0) + - React-Core/DevSupport (= 1000.0.0) + - React-Core/RCTWebSocket (= 1000.0.0) + - React-RCTActionSheet (= 1000.0.0) + - React-RCTAnimation (= 1000.0.0) + - React-RCTBlob (= 1000.0.0) + - React-RCTImage (= 1000.0.0) + - React-RCTLinking (= 1000.0.0) + - React-RCTNetwork (= 1000.0.0) + - React-RCTSettings (= 1000.0.0) + - React-RCTText (= 1000.0.0) + - React-RCTVibration (= 1000.0.0) + - React-Core (1000.0.0): + - Folly (= 2018.10.22.00) + - glog + - React-Core/Default (= 1000.0.0) + - React-cxxreact (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - Yoga + - React-Core/CoreModulesHeaders (1000.0.0): + - Folly (= 2018.10.22.00) + - glog + - React-Core/Default + - React-cxxreact (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - Yoga + - React-Core/Default (1000.0.0): + - Folly (= 2018.10.22.00) + - glog + - React-cxxreact (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - Yoga + - React-Core/DevSupport (1000.0.0): + - Folly (= 2018.10.22.00) + - glog + - React-Core/Default (= 1000.0.0) + - React-Core/RCTWebSocket (= 1000.0.0) + - React-cxxreact (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - React-jsinspector (= 1000.0.0) + - Yoga + - React-Core/RCTActionSheetHeaders (1000.0.0): + - Folly (= 2018.10.22.00) + - glog + - React-Core/Default + - React-cxxreact (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - Yoga + - React-Core/RCTAnimationHeaders (1000.0.0): + - Folly (= 2018.10.22.00) + - glog + - React-Core/Default + - React-cxxreact (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - Yoga + - React-Core/RCTBlobHeaders (1000.0.0): + - Folly (= 2018.10.22.00) + - glog + - React-Core/Default + - React-cxxreact (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - Yoga + - React-Core/RCTImageHeaders (1000.0.0): + - Folly (= 2018.10.22.00) + - glog + - React-Core/Default + - React-cxxreact (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - Yoga + - React-Core/RCTLinkingHeaders (1000.0.0): + - Folly (= 2018.10.22.00) + - glog + - React-Core/Default + - React-cxxreact (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - Yoga + - React-Core/RCTNetworkHeaders (1000.0.0): + - Folly (= 2018.10.22.00) + - glog + - React-Core/Default + - React-cxxreact (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - Yoga + - React-Core/RCTSettingsHeaders (1000.0.0): + - Folly (= 2018.10.22.00) + - glog + - React-Core/Default + - React-cxxreact (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - Yoga + - React-Core/RCTTextHeaders (1000.0.0): + - Folly (= 2018.10.22.00) + - glog + - React-Core/Default + - React-cxxreact (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - Yoga + - React-Core/RCTVibrationHeaders (1000.0.0): + - Folly (= 2018.10.22.00) + - glog + - React-Core/Default + - React-cxxreact (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - Yoga + - React-Core/RCTWebSocket (1000.0.0): + - Folly (= 2018.10.22.00) + - glog + - React-Core/Default (= 1000.0.0) + - React-cxxreact (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - Yoga + - React-CoreModules (1000.0.0): + - FBReactNativeSpec (= 1000.0.0) + - Folly (= 2018.10.22.00) + - RCTTypeSafety (= 1000.0.0) + - React-Core/CoreModulesHeaders (= 1000.0.0) + - React-RCTImage (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-cxxreact (1000.0.0): + - boost-for-react-native (= 1.63.0) + - DoubleConversion + - Folly (= 2018.10.22.00) + - glog + - React-jsinspector (= 1000.0.0) + - React-jsi (1000.0.0): + - boost-for-react-native (= 1.63.0) + - DoubleConversion + - Folly (= 2018.10.22.00) + - glog + - React-jsi/Default (= 1000.0.0) + - React-jsi/Default (1000.0.0): + - boost-for-react-native (= 1.63.0) + - DoubleConversion + - Folly (= 2018.10.22.00) + - glog + - React-jsiexecutor (1000.0.0): + - DoubleConversion + - Folly (= 2018.10.22.00) + - glog + - React-cxxreact (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsinspector (1000.0.0) - react-native-blur (0.8.0): - React - - react-native-camera (2.11.1): + - react-native-camera (3.15.1): - React - - react-native-camera/RCT (= 2.11.1) - - react-native-camera/RN (= 2.11.1) - - react-native-camera/RCT (2.11.1): + - react-native-camera/RCT (= 3.15.1) + - react-native-camera/RN (= 3.15.1) + - react-native-camera/RCT (3.15.1): - React - - react-native-camera/RN (2.11.1): + - react-native-camera/RN (3.15.1): - React - - react-native-fast-image (6.1.1): + - react-native-mail (4.1.0): - React - - SDWebImage (~> 5.0) - - react-native-netinfo (3.2.1): + - react-native-netinfo (5.3.2): + - React + - react-native-randombytes (3.5.3): + - React + - react-native-safe-area-context (0.5.0): + - React + - react-native-splash-screen (3.2.0): + - React + - react-native-text-input-mask (2.0.0): + - React + - RNInputMask + - react-native-udp (2.7.0): - React - react-native-version-number (0.3.6): - React - - React/Core (0.59.9): - - yoga (= 0.59.9.React) - - React/CxxBridge (0.59.9): + - React-RCTActionSheet (1000.0.0): + - React-Core/RCTActionSheetHeaders (= 1000.0.0) + - React-RCTAnimation (1000.0.0): + - FBReactNativeSpec (= 1000.0.0) - Folly (= 2018.10.22.00) - - React/Core - - React/cxxreact - - React/jsiexecutor - - React/cxxreact (0.59.9): - - boost-for-react-native (= 1.63.0) - - DoubleConversion + - RCTTypeSafety (= 1000.0.0) + - React-Core/RCTAnimationHeaders (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-RCTBlob (1000.0.0): + - FBReactNativeSpec (= 1000.0.0) - Folly (= 2018.10.22.00) - - glog - - React/jsinspector - - React/DevSupport (0.59.9): - - React/Core - - React/RCTWebSocket - - React/fishhook (0.59.9) - - React/jsi (0.59.9): + - React-Core/RCTBlobHeaders (= 1000.0.0) + - React-Core/RCTWebSocket (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-RCTNetwork (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-RCTImage (1000.0.0): + - FBReactNativeSpec (= 1000.0.0) + - Folly (= 2018.10.22.00) + - RCTTypeSafety (= 1000.0.0) + - React-Core/RCTImageHeaders (= 1000.0.0) + - React-RCTNetwork (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-RCTLinking (1000.0.0): + - React-Core/RCTLinkingHeaders (= 1000.0.0) + - React-RCTNetwork (1000.0.0): + - FBReactNativeSpec (= 1000.0.0) + - Folly (= 2018.10.22.00) + - RCTTypeSafety (= 1000.0.0) + - React-Core/RCTNetworkHeaders (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-RCTSettings (1000.0.0): + - FBReactNativeSpec (= 1000.0.0) + - Folly (= 2018.10.22.00) + - RCTTypeSafety (= 1000.0.0) + - React-Core/RCTSettingsHeaders (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - React-RCTText (1000.0.0): + - React-Core/RCTTextHeaders (= 1000.0.0) + - React-RCTVibration (1000.0.0): + - FBReactNativeSpec (= 1000.0.0) + - Folly (= 2018.10.22.00) + - React-Core/RCTVibrationHeaders (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) + - ReactCommon/callinvoker (1000.0.0): - DoubleConversion - Folly (= 2018.10.22.00) - glog - - React/jsiexecutor (0.59.9): + - React-cxxreact (= 1000.0.0) + - ReactCommon/turbomodule/core (1000.0.0): - DoubleConversion - Folly (= 2018.10.22.00) - glog - - React/cxxreact - - React/jsi - - React/jsinspector (0.59.9) - - React/RCTActionSheet (0.59.9): - - React/Core - - React/RCTAnimation (0.59.9): - - React/Core - - React/RCTBlob (0.59.9): - - React/Core - - React/RCTImage (0.59.9): - - React/Core - - React/RCTNetwork - - React/RCTLinkingIOS (0.59.9): - - React/Core - - React/RCTNetwork (0.59.9): - - React/Core - - React/RCTPushNotification (0.59.9): - - React/Core - - React/RCTSettings (0.59.9): - - React/Core - - React/RCTText (0.59.9): - - React/Core - - React/RCTVibration (0.59.9): - - React/Core - - React/RCTWebSocket (0.59.9): - - React/Core - - React/fishhook - - React/RCTBlob - - RNAnalytics (1.0.1): + - React-Core (= 1000.0.0) + - React-cxxreact (= 1000.0.0) + - React-jsi (= 1000.0.0) + - ReactCommon/callinvoker (= 1000.0.0) + - ReactNativePermissions (1.2.1): + - React + - RNAnalytics (1.1.0): - Analytics - React - - RNCAsyncStorage (1.5.0): + - RNCAsyncStorage (1.6.2): + - React + - RNCMaskedView (0.1.5): + - React + - RNCPushNotificationIOS (1.0.3): + - React + - RNDeviceInfo (5.3.1): + - React + - RNFastImage (7.0.2): + - React + - SDWebImage (~> 5.0) + - SDWebImageWebPCoder (~> 0.2.3) + - RNFBApp (6.2.0): + - Firebase/Core (~> 6.13.0) + - React + - RNFBCrashlytics (6.2.0): + - Crashlytics (~> 3.12.0) + - Fabric (~> 1.9.0) + - Firebase/Core (~> 6.13.0) - React - - RNCMaskedView (0.1.1): + - RNFBApp + - RNFBMessaging (6.2.0): + - Firebase/Messaging (~> 6.13.0) - React - - RNDeviceInfo (2.3.1): + - RNFBApp + - RNGestureHandler (1.5.2): - React - - RNIOS11DeviceCheck (0.0.3): + - RNInputMask (4.1.0) + - RNKeychain (4.0.3): - React - RNLanguages (3.0.2): - React - - RNReanimated (1.1.0): + - RNOS (1.1.0): + - React + - RNReactNativeHapticFeedback (1.8.2): + - React + - RNReanimated (1.4.0): - React - RNScreens (1.0.0-alpha.23): - React + - RNSentry (1.2.1): + - React + - Sentry (~> 4.4.0) - RNStoreReview (0.1.5): - React - - SDWebImage (5.0.2): - - SDWebImage/Core (= 5.0.2) - - SDWebImage/Core (5.0.2) - - yoga (0.59.9.React) + - RNSVG (9.13.6): + - React + - SDWebImage (5.4.1): + - SDWebImage/Core (= 5.4.1) + - SDWebImage/Core (5.4.1) + - SDWebImageWebPCoder (0.2.5): + - libwebp (~> 1.0) + - SDWebImage/Core (~> 5.0) + - Sentry (4.4.3): + - Sentry/Core (= 4.4.3) + - Sentry/Core (4.4.3) + - SRSRadialGradient (1.0.0): + - React + - SSZipArchive (2.2.2) + - TcpSockets (3.3.2): + - React + - ToolTipMenu (5.2.1): + - React + - Yoga (1.14.0) DEPENDENCIES: - BVLinearGradient (from `../node_modules/react-native-linear-gradient`) - - Crashlytics (~> 3.10.7) + - CodePush (from `../node_modules/react-native-code-push`) - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) - - Fabric (~> 1.7.11) - - Firebase/Core (~> 5.3.0) - - Firebase/Messaging (~> 5.3.0) + - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) + - FBReactNativeSpec (from `../node_modules/react-native/Libraries/FBReactNativeSpec`) - FLAnimatedImage - Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`) - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) - libwebp + - RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`) + - RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`) + - React (from `../node_modules/react-native/`) + - React-Core (from `../node_modules/react-native/`) + - React-Core/DevSupport (from `../node_modules/react-native/`) + - React-Core/RCTWebSocket (from `../node_modules/react-native/`) + - React-CoreModules (from `../node_modules/react-native/React/CoreModules`) + - React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`) + - React-jsi (from `../node_modules/react-native/ReactCommon/jsi`) + - React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`) + - React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`) - "react-native-blur (from `../node_modules/@react-native-community/blur`)" - react-native-camera (from `../node_modules/react-native-camera`) - - react-native-fast-image (from `../node_modules/react-native-fast-image`) + - react-native-mail (from `../node_modules/react-native-mail`) - "react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)" + - react-native-randombytes (from `../node_modules/react-native-randombytes`) + - react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`) + - react-native-splash-screen (from `../node_modules/react-native-splash-screen`) + - react-native-text-input-mask (from `../node_modules/react-native-text-input-mask`) + - react-native-udp (from `../node_modules/react-native-udp`) - react-native-version-number (from `../node_modules/react-native-version-number`) - - React/Core (from `../node_modules/react-native`) - - React/CxxBridge (from `../node_modules/react-native`) - - React/cxxreact (from `../node_modules/react-native`) - - React/DevSupport (from `../node_modules/react-native`) - - React/fishhook (from `../node_modules/react-native`) - - React/jsi (from `../node_modules/react-native`) - - React/jsiexecutor (from `../node_modules/react-native`) - - React/jsinspector (from `../node_modules/react-native`) - - React/RCTActionSheet (from `../node_modules/react-native`) - - React/RCTAnimation (from `../node_modules/react-native`) - - React/RCTBlob (from `../node_modules/react-native`) - - React/RCTImage (from `../node_modules/react-native`) - - React/RCTLinkingIOS (from `../node_modules/react-native`) - - React/RCTNetwork (from `../node_modules/react-native`) - - React/RCTPushNotification (from `../node_modules/react-native`) - - React/RCTSettings (from `../node_modules/react-native`) - - React/RCTText (from `../node_modules/react-native`) - - React/RCTVibration (from `../node_modules/react-native`) - - React/RCTWebSocket (from `../node_modules/react-native`) + - React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`) + - React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`) + - React-RCTBlob (from `../node_modules/react-native/Libraries/Blob`) + - React-RCTImage (from `../node_modules/react-native/Libraries/Image`) + - React-RCTLinking (from `../node_modules/react-native/Libraries/LinkingIOS`) + - React-RCTNetwork (from `../node_modules/react-native/Libraries/Network`) + - React-RCTSettings (from `../node_modules/react-native/Libraries/Settings`) + - React-RCTText (from `../node_modules/react-native/Libraries/Text`) + - React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`) + - ReactCommon/callinvoker (from `../node_modules/react-native/ReactCommon`) + - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) + - ReactNativePermissions (from `../node_modules/react-native-permissions`) - "RNAnalytics (from `../node_modules/@segment/analytics-react-native`)" - "RNCAsyncStorage (from `../node_modules/@react-native-community/async-storage`)" - "RNCMaskedView (from `../node_modules/@react-native-community/masked-view`)" + - "RNCPushNotificationIOS (from `../node_modules/@react-native-community/push-notification-ios`)" - RNDeviceInfo (from `../node_modules/react-native-device-info`) - - RNIOS11DeviceCheck (from `../node_modules/react-native-ios11-devicecheck/ios`) + - RNFastImage (from `../node_modules/react-native-fast-image`) + - "RNFBApp (from `../node_modules/@react-native-firebase/app`)" + - "RNFBCrashlytics (from `../node_modules/@react-native-firebase/crashlytics`)" + - "RNFBMessaging (from `../node_modules/@react-native-firebase/messaging`)" + - RNGestureHandler (from `../node_modules/react-native-gesture-handler`) + - RNInputMask (from `../node_modules/react-native-text-input-mask/ios/InputMask`) + - RNKeychain (from `../node_modules/react-native-keychain`) - RNLanguages (from `../node_modules/react-native-languages`) + - RNOS (from `../node_modules/react-native-os`) + - RNReactNativeHapticFeedback (from `../node_modules/react-native-haptic-feedback`) - RNReanimated (from `../node_modules/react-native-reanimated`) - RNScreens (from `../node_modules/react-native-screens`) + - "RNSentry (from `../node_modules/@sentry/react-native`)" - RNStoreReview (from `../node_modules/react-native-store-review/ios`) - - yoga (from `../node_modules/react-native/ReactCommon/yoga`) + - RNSVG (from `../node_modules/react-native-svg`) + - SRSRadialGradient (from `../node_modules/react-native-radial-gradient/ios`) + - TcpSockets (from `../node_modules/react-native-tcp`) + - ToolTipMenu (from `../node_modules/react-native-tooltip`) + - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) SPEC REPOS: - https://github.com/cocoapods/specs.git: + trunk: - Analytics + - Base64 - boost-for-react-native - Crashlytics - Fabric - Firebase - FirebaseAnalytics + - FirebaseAnalyticsInterop - FirebaseCore + - FirebaseCoreDiagnostics + - FirebaseCoreDiagnosticsInterop - FirebaseInstanceID - FirebaseMessaging - FLAnimatedImage - - GoogleToolboxForMac + - GoogleAppMeasurement + - GoogleDataTransport + - GoogleDataTransportCCTSupport + - GoogleUtilities + - JWT - libwebp - nanopb - Protobuf - SDWebImage + - SDWebImageWebPCoder + - Sentry + - SSZipArchive EXTERNAL SOURCES: BVLinearGradient: :path: "../node_modules/react-native-linear-gradient" + CodePush: + :path: "../node_modules/react-native-code-push" DoubleConversion: :podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec" + FBLazyVector: + :path: "../node_modules/react-native/Libraries/FBLazyVector" + FBReactNativeSpec: + :path: "../node_modules/react-native/Libraries/FBReactNativeSpec" Folly: :podspec: "../node_modules/react-native/third-party-podspecs/Folly.podspec" glog: :podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec" + RCTRequired: + :path: "../node_modules/react-native/Libraries/RCTRequired" + RCTTypeSafety: + :path: "../node_modules/react-native/Libraries/TypeSafety" React: - :path: "../node_modules/react-native" + :path: "../node_modules/react-native/" + React-Core: + :path: "../node_modules/react-native/" + React-CoreModules: + :path: "../node_modules/react-native/React/CoreModules" + React-cxxreact: + :path: "../node_modules/react-native/ReactCommon/cxxreact" + React-jsi: + :path: "../node_modules/react-native/ReactCommon/jsi" + React-jsiexecutor: + :path: "../node_modules/react-native/ReactCommon/jsiexecutor" + React-jsinspector: + :path: "../node_modules/react-native/ReactCommon/jsinspector" react-native-blur: :path: "../node_modules/@react-native-community/blur" react-native-camera: :path: "../node_modules/react-native-camera" - react-native-fast-image: - :path: "../node_modules/react-native-fast-image" + react-native-mail: + :path: "../node_modules/react-native-mail" react-native-netinfo: :path: "../node_modules/@react-native-community/netinfo" + react-native-randombytes: + :path: "../node_modules/react-native-randombytes" + react-native-safe-area-context: + :path: "../node_modules/react-native-safe-area-context" + react-native-splash-screen: + :path: "../node_modules/react-native-splash-screen" + react-native-text-input-mask: + :path: "../node_modules/react-native-text-input-mask" + react-native-udp: + :path: "../node_modules/react-native-udp" react-native-version-number: :path: "../node_modules/react-native-version-number" + React-RCTActionSheet: + :path: "../node_modules/react-native/Libraries/ActionSheetIOS" + React-RCTAnimation: + :path: "../node_modules/react-native/Libraries/NativeAnimation" + React-RCTBlob: + :path: "../node_modules/react-native/Libraries/Blob" + React-RCTImage: + :path: "../node_modules/react-native/Libraries/Image" + React-RCTLinking: + :path: "../node_modules/react-native/Libraries/LinkingIOS" + React-RCTNetwork: + :path: "../node_modules/react-native/Libraries/Network" + React-RCTSettings: + :path: "../node_modules/react-native/Libraries/Settings" + React-RCTText: + :path: "../node_modules/react-native/Libraries/Text" + React-RCTVibration: + :path: "../node_modules/react-native/Libraries/Vibration" + ReactCommon: + :path: "../node_modules/react-native/ReactCommon" + ReactNativePermissions: + :path: "../node_modules/react-native-permissions" RNAnalytics: :path: "../node_modules/@segment/analytics-react-native" RNCAsyncStorage: :path: "../node_modules/@react-native-community/async-storage" RNCMaskedView: :path: "../node_modules/@react-native-community/masked-view" + RNCPushNotificationIOS: + :path: "../node_modules/@react-native-community/push-notification-ios" RNDeviceInfo: :path: "../node_modules/react-native-device-info" - RNIOS11DeviceCheck: - :path: "../node_modules/react-native-ios11-devicecheck/ios" + RNFastImage: + :path: "../node_modules/react-native-fast-image" + RNFBApp: + :path: "../node_modules/@react-native-firebase/app" + RNFBCrashlytics: + :path: "../node_modules/@react-native-firebase/crashlytics" + RNFBMessaging: + :path: "../node_modules/@react-native-firebase/messaging" + RNGestureHandler: + :path: "../node_modules/react-native-gesture-handler" + RNInputMask: + :path: "../node_modules/react-native-text-input-mask/ios/InputMask" + RNKeychain: + :path: "../node_modules/react-native-keychain" RNLanguages: :path: "../node_modules/react-native-languages" + RNOS: + :path: "../node_modules/react-native-os" + RNReactNativeHapticFeedback: + :path: "../node_modules/react-native-haptic-feedback" RNReanimated: :path: "../node_modules/react-native-reanimated" RNScreens: :path: "../node_modules/react-native-screens" + RNSentry: + :path: "../node_modules/@sentry/react-native" RNStoreReview: :path: "../node_modules/react-native-store-review/ios" - yoga: + RNSVG: + :path: "../node_modules/react-native-svg" + SRSRadialGradient: + :path: "../node_modules/react-native-radial-gradient/ios" + TcpSockets: + :path: "../node_modules/react-native-tcp" + ToolTipMenu: + :path: "../node_modules/react-native-tooltip" + Yoga: :path: "../node_modules/react-native/ReactCommon/yoga" SPEC CHECKSUMS: - Analytics: 63744ad4afa65c3bcdcdb7a94b62515bde5b3900 + Analytics: 77fd5fb102a4a5eedafa2c2b0245ceb7b7c15e45 + Base64: cecfb41a004124895a7bcee567a89bae5a89d49b boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c BVLinearGradient: e3aad03778a456d77928f594a649e96995f1c872 - Crashlytics: 55e24fc23989680285a21cb1146578d9d18e432c - DoubleConversion: bb338842f62ab1d708ceb63ec3d999f0f3d98ecd - Fabric: 25d0963b691fc97be566392243ff0ecef5a68338 - Firebase: 76ec2a7cde90fb4037793f83aeeca48451543487 - FirebaseAnalytics: b8bce8d5c40173328b8a4300da18c5c7e0a1908d - FirebaseCore: 31d258ec80ea97e1e8e40ce00a7ba7297afb45c2 - FirebaseInstanceID: 4f7768a98c5c3c5bd9a4c9e431ea98dccc0a51f9 - FirebaseMessaging: 94579ae655d817287f029ebfebd5b0811fbb3a51 + CodePush: d2e54ad42df82a8db65b2d23d8191b950ba945e1 + Crashlytics: 07fb167b1694128c1c9a5a5cc319b0e9c3ca0933 + DoubleConversion: cde416483dac037923206447da6e1454df403714 + Fabric: f988e33c97f08930a413e08123064d2e5f68d655 + FBLazyVector: d9c30190da16f13ea1ff3d9324dcd1fe1a9e4d4b + FBReactNativeSpec: 2e4cef565c6edc250e5dde587263ef39c6c9f88d + Firebase: 458d109512200d1aca2e1b9b6cf7d68a869a4a46 + FirebaseAnalytics: 45f36d9c429fc91d206283900ab75390cd05ee8a + FirebaseAnalyticsInterop: d48b6ab67bcf016a05e55b71fc39c61c0cb6b7f3 + FirebaseCore: 307ea2508df730c5865334e41965bd9ea344b0e5 + FirebaseCoreDiagnostics: 511f4f3ed7d440bb69127e8b97c2bc8befae639e + FirebaseCoreDiagnosticsInterop: e9b1b023157e3a2fc6418b5cb601e79b9af7b3a0 + FirebaseInstanceID: ebd2ea79ee38db0cb5f5167b17a0d387e1cc7b6e + FirebaseMessaging: 089b7a4991425783384acc8bcefcd78c0af913bd FLAnimatedImage: 4a0b56255d9b05f18b6dd7ee06871be5d3b89e31 - Folly: de497beb10f102453a1afa9edbf8cf8a251890de - glog: aefd1eb5dda2ab95ba0938556f34b98e2da3a60d - GoogleToolboxForMac: ff31605b7d66400dcec09bed5861689aebadda4d - libwebp: b068a3bd7c45f7460f6715be7bed1a18fd5d6b48 - nanopb: 2901f78ea1b7b4015c860c2fdd1ea2fee1a18d48 - Protobuf: 7a877b7f3e5964e3fce995e2eb323dbc6831bb5a - React: a86b92f00edbe1873a63e4a212c29b7a7ad5224f + Folly: f1c65c1bdabb35617432cac9cf17d0cad310ce6f + glog: 40a13f7840415b9a77023fbcae0f1e6f43192af3 + GoogleAppMeasurement: dfe55efa543e899d906309eaaac6ca26d249862f + GoogleDataTransport: 8e9b210c97d55fbff306cc5468ff91b9cb32dcf5 + GoogleDataTransportCCTSupport: 202d7cdf9c4a7d81a2bb7f7e7e1ba6faa421b1f2 + GoogleUtilities: 29bd0d8f850efbd28cff6d99e8b7da1f8d236bcf + JWT: 9b5c05abbcc1a0e69c3c91e1655b3387fc7e581d + libwebp: 057912d6d0abfb6357d8bb05c0ea470301f5d61e + nanopb: 18003b5e52dab79db540fe93fe9579f399bd1ccd + Protobuf: dd1aaea7140debfe4dd0683fb8ef208e527ae153 + RCTRequired: e9cece38ac12ef73f95098aacb4c9477d88b58d6 + RCTTypeSafety: c00f94ca04462d6670a8333595691b634740669b + React: 7dd49950772f2c5d0bfb107e0b2079936d3f9682 + React-Core: 11cbdd3f1982d5229b9d4fbe342993c403afd619 + React-CoreModules: 543c0247210e83fc0ef65b86344cedf4a14da049 + React-cxxreact: 8194443ac133545b0c1933a4076b7f2366f3aece + React-jsi: f97b3ef8eb78e320d7a79f531adc9cc7c39194c2 + React-jsiexecutor: a3558d5053317b6fdf5a52d6ab5c4b80d8f8ed53 + React-jsinspector: 4ea920069d9ea95871bcb144636fb6ba4f3639af react-native-blur: cad4d93b364f91e7b7931b3fa935455487e5c33c - react-native-camera: f1fbfc336ba8ca6de5296190341d1b6022c71cff - react-native-fast-image: fdfc612dba58fd73136cf5efdaeb8cfcad7f63b2 - react-native-netinfo: 0da34082d2cec3100c9b5073bb217e35f1142bdd + react-native-camera: 1ba3e7f2375a6b44ae09ce9be70268e0b225bc10 + react-native-mail: a864fb211feaa5845c6c478a3266de725afdce89 + react-native-netinfo: 817823a90f13ced48413875c0820df04c3aae28d + react-native-randombytes: 3638d24759d67c68f6ccba60c52a7a8a8faa6a23 + react-native-safe-area-context: 13004a45f3021328fdd9ee1f987c3131fb65928d + react-native-splash-screen: 200d11d188e2e78cea3ad319964f6142b6384865 + react-native-text-input-mask: 07227297075f9653315f43b0424d596423a01736 + react-native-udp: ff9d13e523f2b58e6bc5d4d32321ac60671b5dc9 react-native-version-number: b415bbec6a13f2df62bf978e85bc0d699462f37f - RNAnalytics: d110195618296fed3907830911f01cb6e9be53d0 - RNCAsyncStorage: 9436928b444c5f5361960a7eea051a697c244b68 - RNCMaskedView: b79e193409a90bf6b5170d421684f437ff4e2278 - RNDeviceInfo: 74ee98a0b3ef57604ea9953f03eca549a9335160 - RNIOS11DeviceCheck: a4a545fdd08230a17a8ce7608e95038ee23a32aa + React-RCTActionSheet: 1c9c8f258be185eab8542ac16cbf4e2d9fe3c7d6 + React-RCTAnimation: f0fbcef774b3a265ba404103bf5c0afb15293526 + React-RCTBlob: 99abe09fb7887572ca3473b016750a56c8277f0c + React-RCTImage: 86a2b0d282dd46cf6c9b6e65567b0cb1f5d7ec69 + React-RCTLinking: 87bef2d27131eb60d3608d9bb6ace61b699aa9ae + React-RCTNetwork: 95ca86d6d46e2162aa957c58cc5d30f48a1c2a36 + React-RCTSettings: fd36d53fbdd61d74eb3b0b8f57c5804bec5b68db + React-RCTText: 46b8f9a64ab6d979567edbd51219162b85381e67 + React-RCTVibration: 1a9cfd9844cd91aa1269a22b10a9ee29cf6cf5ce + ReactCommon: d796609fd38113c37f843f813d3268909bd44a60 + ReactNativePermissions: 7cfad56d13c8961cd2a1005b4955b1400c79ef3e + RNAnalytics: 35a54cb740c472a0a6a3de765176b82cccc2d1ef + RNCAsyncStorage: 60a80e72d95bf02a01cace55d3697d9724f0d77f + RNCMaskedView: dd13f9f7b146a9ad82f9b7eb6c9b5548fcf6e990 + RNCPushNotificationIOS: 83ec11fe19d4ea9e32cc339d8e7d2cc3c88f543e + RNDeviceInfo: 6f20764111df002b4484f90cbe0a861be29bcc6c + RNFastImage: 9b0c22643872bb7494c8d87bbbb66cc4c0d9e7a2 + RNFBApp: 5b215aacc09105a1761de31b9a0eb2abcce06253 + RNFBCrashlytics: 0469cb96b00904e0c9604b9636d8eeab31115b08 + RNFBMessaging: be0b936394416ec5503add603f2c0a641c353063 + RNGestureHandler: 946a7691e41df61e2c4b1884deab41a4cdc3afff + RNInputMask: 815461ebdf396beb62cf58916c35cf6930adb991 + RNKeychain: f5783613aa3095af63345ddb9626a729bd4a3897 RNLanguages: 962e562af0d34ab1958d89bcfdb64fafc37c513e - RNReanimated: 7a52c90473b5e81c13408d40d797b98387eaddde + RNOS: 811de7b4be8824a86a775ade934147a02edb9b5a + RNReactNativeHapticFeedback: e11a4da0ce174e9f88b03cbaf5d76d94633cdee2 + RNReanimated: 8b675a650fc67c87f63d4345a1b2d4a699c25e4f RNScreens: f28b48b8345f2f5f39ed6195518291515032a788 + RNSentry: 9b1d983b2d5d1c215ba6490348fd2a4cc23a8a9d RNStoreReview: 62d6afd7c37db711a594bbffca6b0ea3a812b7a8 - SDWebImage: 6764b5fa0f73c203728052955dbefa2bf1f33282 - yoga: 03ff42a6f223fb88deeaed60249020d80c3091ee + RNSVG: 8ba35cbeb385a52fd960fd28db9d7d18b4c2974f + SDWebImage: 29c340dbdcef342bb13125553f4e19ce056b07a7 + SDWebImageWebPCoder: 947093edd1349d820c40afbd9f42acb6cdecd987 + Sentry: 14bdd673870e8cf64932b149fad5bbbf39a9b390 + SRSRadialGradient: 8fdf3adb76320500bc792390ecebc1b82aac54ec + SSZipArchive: fa16b8cc4cdeceb698e5e5d9f67e9558532fbf23 + TcpSockets: 14306fb79f9750ea7d2ddd02d8bed182abb01797 + ToolTipMenu: 8ac61aded0fbc4acfe7e84a7d0c9479d15a9a382 + Yoga: bd064893d7d42e83f9f9e2861346fc4b1019223a -PODFILE CHECKSUM: 9a1477d30332ab86b10fd2ec7e7842ad52b5382e +PODFILE CHECKSUM: e38b8f3a80d4f969b2bd4796967957156faf7531 -COCOAPODS: 1.6.1 +COCOAPODS: 1.8.4 diff --git a/ios/Rainbow-Bridging-Header.h b/ios/Rainbow-Bridging-Header.h new file mode 100644 index 00000000000..1b2cb5d6d09 --- /dev/null +++ b/ios/Rainbow-Bridging-Header.h @@ -0,0 +1,4 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + diff --git a/ios/Rainbow.xcodeproj/project.pbxproj b/ios/Rainbow.xcodeproj/project.pbxproj index 9a87f5b136e..957ba4743bf 100644 --- a/ios/Rainbow.xcodeproj/project.pbxproj +++ b/ios/Rainbow.xcodeproj/project.pbxproj @@ -7,37 +7,21 @@ objects = { /* Begin PBXBuildFile section */ - 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; }; - 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; }; - 00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */; }; - 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; }; - 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; }; - 00E356F31AD99517003FC87E /* RainbowTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* RainbowTests.m */; }; 03252948A60F4C4C87E4FD9E /* SF-Pro-Display-Ultralight.otf in Resources */ = {isa = PBXBuildFile; fileRef = 35833023DB594F1AA6A72866 /* SF-Pro-Display-Ultralight.otf */; }; 06B78001D9F2456D9C2D4A86 /* Graphik-Medium.otf in Resources */ = {isa = PBXBuildFile; fileRef = DE019D6BCA1A4FF9B7F1E98A /* Graphik-Medium.otf */; }; - 07F258CE8EB84A8A949D4580 /* libTcpSockets.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6747DC29E9EE446C8C2F7B76 /* libTcpSockets.a */; }; 0AB30EE90F554EE59F57DFC1 /* SF-Pro-Display-RegularItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = D880F2D2B7704793A8D141DC /* SF-Pro-Display-RegularItalic.otf */; }; + 0E56AA9A8843EB50FA4BDD4F /* libPods-Rainbow.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6C1814FA03B309E79858CD16 /* libPods-Rainbow.a */; }; 0F4372360E744AF4B37EB905 /* Graphik-Black.otf in Resources */ = {isa = PBXBuildFile; fileRef = 7818F79CD3944D17AF4196A5 /* Graphik-Black.otf */; }; - 133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; }; - 139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; }; - 139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */; }; 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; - 140ED2AC1D01E1AD002B40FF /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; }; - 146834051AC3E58100842450 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; }; - 154AA73429B14ED4BC8E0C72 /* libRNFirebase.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D755E71324B04FEE9C691D14 /* libRNFirebase.a */; }; 16934DFE7F154B06ADAD8A0B /* SF-Pro-Display-ThinItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = C1DB5F252E324925B4145360 /* SF-Pro-Display-ThinItalic.otf */; }; 184EB33331FB47F2960D2507 /* SF-Pro-Display-Heavy.otf in Resources */ = {isa = PBXBuildFile; fileRef = 8D37634EBB294EC79081DFD2 /* SF-Pro-Display-Heavy.otf */; }; - 1A048DFD2F724753902EA40B /* libRNReactNativeHapticFeedback.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D13995EB48584C438A10A161 /* libRNReactNativeHapticFeedback.a */; }; 1AE1684BFC3E487F99128043 /* SF-Pro-Display-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 9165B952731E4502857CC0B4 /* SF-Pro-Display-Regular.otf */; }; 1B1113DAF261410889D80146 /* SF-Pro-Display-Medium.otf in Resources */ = {isa = PBXBuildFile; fileRef = 2AEF0207B9724FE5A27519FF /* SF-Pro-Display-Medium.otf */; }; 216C17A836F44ACE8D79ACC7 /* SF-Pro-Display-Thin.otf in Resources */ = {isa = PBXBuildFile; fileRef = 662C7FD632C1481AB5AB1DB7 /* SF-Pro-Display-Thin.otf */; }; - 22DD8F08F32047C280DFA368 /* libRNRandomBytes.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8C38066021DF4A73845E4A0F /* libRNRandomBytes.a */; }; 23320186D7F747FEB02451C6 /* SF-Pro-Text-HeavyItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = 1DEDF110038147A598C9B152 /* SF-Pro-Text-HeavyItalic.otf */; }; - 2340D4240F794E6DACB53521 /* libRNKeychain.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B86CB964E3AA47029988138C /* libRNKeychain.a */; }; - 24979E8620F84005007EB0DA /* FirebaseInstanceID.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 24979E7B20F84004007EB0DA /* FirebaseInstanceID.framework */; }; 24979E8920F84250007EB0DA /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 24979E7720F84004007EB0DA /* GoogleService-Info.plist */; }; 26095B12C30047F89592D463 /* SF-Pro-Text-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 944CF612F0304DF281E33B66 /* SF-Pro-Text-Regular.otf */; }; 2D7BB74FB1A44EE2A2426373 /* SF-Pro-Text-Light.otf in Resources */ = {isa = PBXBuildFile; fileRef = E672AB1C5404435897615660 /* SF-Pro-Text-Light.otf */; }; @@ -48,36 +32,25 @@ 396C4BA42EEC4D0985CEBB42 /* SF-Pro-Text-SemiboldItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = FA887652F27F43869229AD50 /* SF-Pro-Text-SemiboldItalic.otf */; }; 3C363E14D5DE4A028E43EA38 /* SF-Pro-Display-UltralightItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = DCA738BE00E04734AEDA2F07 /* SF-Pro-Display-UltralightItalic.otf */; }; 3C41C1415A994234A0FF2589 /* SF-Pro-Text-Heavy.otf in Resources */ = {isa = PBXBuildFile; fileRef = 233322FCDC624F6FA60C4B52 /* SF-Pro-Text-Heavy.otf */; }; + 3CBE29CD2381E43900BE05AC /* Dummy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CBE29CC2381E43900BE05AC /* Dummy.swift */; }; 4013198EBD3D4D6F8052D25E /* SF-Pro-Display-Light.otf in Resources */ = {isa = PBXBuildFile; fileRef = 9DF45B9EB38D4E8FA18A04C6 /* SF-Pro-Display-Light.otf */; }; 41804DE52CE94296995264E0 /* SF-Pro-Text-Medium.otf in Resources */ = {isa = PBXBuildFile; fileRef = 35A24AFF4AB449C287EE66A8 /* SF-Pro-Text-Medium.otf */; }; 424410A1E84845328C5A0CAB /* Graphik-RegularItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = 182DC054E3584C83822F2A82 /* Graphik-RegularItalic.otf */; }; 431D3F0FC92B45A7A0B2476B /* Graphik-Semibold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 88A5866DBF924C149CA0C6F4 /* Graphik-Semibold.otf */; }; - 4433A04AF3E942A2894B3933 /* libRNOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 96CCCB016071412E994DFF61 /* libRNOS.a */; }; - 45C6CAEFC1A04F3FB291BE53 /* libBVLinearGradient.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C1324455238847F2AD5C08B4 /* libBVLinearGradient.a */; }; - 4AF3A1B2CEC540D7A1AF957C /* libReactNativePermissions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 51A0A7CFC45344D49BFF6CB9 /* libReactNativePermissions.a */; }; 549287401A7648CCB32F36E0 /* SF-Pro-Display-Semibold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 5842861A013B4B379705CC5A /* SF-Pro-Display-Semibold.otf */; }; 5D1949044DCB413FBE7AE82E /* SFMono-Light.otf in Resources */ = {isa = PBXBuildFile; fileRef = 2C4A4A4FB3D84F14A48989D8 /* SFMono-Light.otf */; }; - 5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */; }; 5F34DEED060F41878C4C5A59 /* SFMono-Heavy.otf in Resources */ = {isa = PBXBuildFile; fileRef = 0A8698C728414E56A3FD89A6 /* SFMono-Heavy.otf */; }; 66620AB752074CB6938E956A /* Graphik-MediumItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = 2DA6F347A6B540399883FF91 /* Graphik-MediumItalic.otf */; }; 6928E7805EA5404480C48640 /* Graphik-LightItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = D551F7BECCAF4CE3BC8C0C3D /* Graphik-LightItalic.otf */; }; - 6E37C5716EC449C1B63D0E06 /* libTouchID.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9E0A11D8843045ECB80C6AB8 /* libTouchID.a */; }; 7287CE1EC33B4913AEE1F4B6 /* SFMono-Medium.otf in Resources */ = {isa = PBXBuildFile; fileRef = 668A9E253DAF444A90ECB997 /* SFMono-Medium.otf */; }; 7E04FF8B32EC4F2BB6BF1403 /* Graphik-ExtralightItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = 273D2D617F3F43E99F8F404B /* Graphik-ExtralightItalic.otf */; }; - 7F911FD5E35D4FD99D48A61D /* libSRSRadialGradient.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2FA917DDE3314475BABEC117 /* libSRSRadialGradient.a */; }; - 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; }; 872630C5E4CA448D8DDC783E /* Graphik-Extralight.otf in Resources */ = {isa = PBXBuildFile; fileRef = 93D62D49D9CA46F292BD9869 /* Graphik-Extralight.otf */; }; - 87808B52A9E224F3D11532B5 /* libPods-Rainbow.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 823BD6129C8AA3FD7CDD46BE /* libPods-Rainbow.a */; }; 8B7F7FDAB33B4D119E087D57 /* Graphik-SemiboldItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = A7F0978B24BA4EC283C580D9 /* Graphik-SemiboldItalic.otf */; }; 8FB4C0E7FE3240F2B2D23CE2 /* SFMono-Bold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 8789D635428240B5ABF282EE /* SFMono-Bold.otf */; }; - 91959ACCE81B4C128AAC8154 /* libRNSVG.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B98C0A69B3614C65B194BC68 /* libRNSVG.a */; }; 9274E6415DE5403A855B59A4 /* Graphik-SuperItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = 51E41940863B4B88BDEF48D7 /* Graphik-SuperItalic.otf */; }; 92D7BFC8AFDA4E649EA6FF08 /* SFMono-Semibold.otf in Resources */ = {isa = PBXBuildFile; fileRef = B1089F835D6A4F578009B47F /* SFMono-Semibold.otf */; }; - 94822FBFCA7246168685FA85 /* libRNMail.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 45B0EAA273D24F15B885A97D /* libRNMail.a */; }; 96E52368EDC94B9B80D1F29C /* SF-Pro-Text-LightItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = D1641F1A96C841C085169B2E /* SF-Pro-Text-LightItalic.otf */; }; - 978F83D3C5E4491F9D9AC2C1 /* libSplashScreen.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EA95F99E656542F790F685B6 /* libSplashScreen.a */; }; 9E8553031AD44F52A814F2AB /* SF-Pro-Display-SemiboldItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = 86B30DBBDA594167BFE4747E /* SF-Pro-Display-SemiboldItalic.otf */; }; - ADBDB9381DFEBF1600ED6528 /* libRCTBlob.a in Frameworks */ = {isa = PBXBuildFile; fileRef = ADBDB9271DFEBF0700ED6528 /* libRCTBlob.a */; }; AE47B46652EA48AFB68E7832 /* SF-Pro-Text-Semibold.otf in Resources */ = {isa = PBXBuildFile; fileRef = AA6B0A8BE2484F46980BE9AC /* SF-Pro-Text-Semibold.otf */; }; AFCABA638327463693E67FD4 /* SF-Pro-Text-RegularItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = 715DAAA3174542BAB93807A6 /* SF-Pro-Text-RegularItalic.otf */; }; AFD75D0B6EC9465C92C493A7 /* SF-Pro-Display-BlackItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = A8AE8DE50B9544B6BC186E6C /* SF-Pro-Display-BlackItalic.otf */; }; @@ -88,527 +61,23 @@ C37D7F7EA236460085DB5BFA /* SF-Pro-Text-BoldItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = 1736F851327A41C3815212E7 /* SF-Pro-Text-BoldItalic.otf */; }; C5D098E8B85D40048FE4946A /* Graphik-Light.otf in Resources */ = {isa = PBXBuildFile; fileRef = 7A9AF25703474604964D6EC1 /* Graphik-Light.otf */; }; C66451ECC2944B439E123CF2 /* SF-Pro-Display-Black.otf in Resources */ = {isa = PBXBuildFile; fileRef = BE239BA93F6B4EDC867B1A41 /* SF-Pro-Display-Black.otf */; }; + C72F456C99A646399192517D /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 98AED33BAB4247CEBEF8464D /* libz.tbd */; }; CAD3BF43528D47159190E17B /* SF-Pro-Display-MediumItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = 3459F05BF10649C4A787D900 /* SF-Pro-Display-MediumItalic.otf */; }; CB988C526B0C48FC9750A038 /* SF-Pro-Display-BoldItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = 84DB92DCDF5D4374B26FFCC6 /* SF-Pro-Display-BoldItalic.otf */; }; - D77132C4B96040C39FED1AD5 /* libUdpSockets.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5AC94663BD4242A29273D66F /* libUdpSockets.a */; }; DBBDEB86E54044EE8712C882 /* Graphik-BlackItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = CEC826911B5641B8AF788BB3 /* Graphik-BlackItalic.otf */; }; E98BBF45029948B38545996F /* Graphik-Bold.otf in Resources */ = {isa = PBXBuildFile; fileRef = E6F010E529544E518E1792C7 /* Graphik-Bold.otf */; }; - EA8076A8481B4CB4BBA566EF /* libRNStoreReview.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 91A43F69E797469687978D51 /* libRNStoreReview.a */; }; - ECF14FECD39C459D86EDCB82 /* libCodePush.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 22E39434CDDE4C54848FBFD5 /* libCodePush.a */; }; ED2971652150620600B7C4FE /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ED2971642150620600B7C4FE /* JavaScriptCore.framework */; }; - ED8A2571BF074F6DB6D09045 /* libToolTipMenu.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A014AE1645874354A732EB35 /* libToolTipMenu.a */; }; - F35098D973414A09939FB3F8 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D1A86E696CA24D4F9D3F7F0F /* libz.tbd */; }; - F4E8A17A670147F4A5EC177E /* libRNGestureHandler.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A7E5E09E14B4EA4B52CC6EE /* libRNGestureHandler.a */; }; F9EB9219ED9A4C72826A5908 /* Graphik-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = A6EEFE6EA9354456B0DB4520 /* Graphik-Regular.otf */; }; F9EF1D44351840B8A380BD3E /* SF-Pro-Display-Bold.otf in Resources */ = {isa = PBXBuildFile; fileRef = BA31E8CEDBCC417CA50BC57B /* SF-Pro-Display-Bold.otf */; }; FBDF4EF177284CF4826D7BF9 /* SF-Pro-Display-HeavyItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = D7BFD847B72D414D9BE734A0 /* SF-Pro-Display-HeavyItalic.otf */; }; /* End PBXBuildFile section */ -/* Begin PBXContainerItemProxy section */ - 00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 134814201AA4EA6300B7C361; - remoteInfo = RCTActionSheet; - }; - 00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 134814201AA4EA6300B7C361; - remoteInfo = RCTGeolocation; - }; - 00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 58B5115D1A9E6B3D00147676; - remoteInfo = RCTImage; - }; - 00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 58B511DB1A9E6C8500147676; - remoteInfo = RCTNetwork; - }; - 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 832C81801AAF6DEF007FA2F7; - remoteInfo = RCTVibration; - }; - 00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 13B07F861A680F5B00A75B9A; - remoteInfo = Rainbow; - }; - 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 134814201AA4EA6300B7C361; - remoteInfo = RCTSettings; - }; - 139FDEF31B06529B00C62182 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 3C86DF461ADF2C930047B81A; - remoteInfo = RCTWebSocket; - }; - 146834031AC3E56700842450 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192; - remoteInfo = React; - }; - 243A893D225F092800A13C7E /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 171CDF49E32841EDA7D557DB /* RNGestureHandler.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = B5C32A36220C603B000FFB8D; - remoteInfo = "RNGestureHandler-tvOS"; - }; - 244C64092108794F007A5856 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 1A7B7E90124047F8A3CA4B84 /* RNReactNativeHapticFeedback.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 134814201AA4EA6300B7C361; - remoteInfo = RNReactNativeHapticFeedback; - }; - 247947BA22568EAA006BBF56 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = EDEBC6D6214B3E7000DD5AC8; - remoteInfo = jsi; - }; - 247947BC22568EAA006BBF56 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = EDEBC73B214B45A300DD5AC8; - remoteInfo = jsiexecutor; - }; - 247947BE22568EAA006BBF56 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = ED296FB6214C9A0900B7C4FE; - remoteInfo = "jsi-tvOS"; - }; - 247947C022568EAA006BBF56 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = ED296FEE214C9CF800B7C4FE; - remoteInfo = "jsiexecutor-tvOS"; - }; - 2481F3202261753900D0349A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = C779B11FB4664662AD0EBEA6 /* RNFirebase.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 134814201AA4EA6300B7C361; - remoteInfo = RNFirebase; - }; - 2488BC2C22E97316006847C7 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 3182AEA93A7847CCB729F641 /* RNStoreReview.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 134814201AA4EA6300B7C361; - remoteInfo = RNStoreReview; - }; - 24979D5C20F83E3E007EB0DA /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 8AC83A50CE8F4EE782376063 /* BVLinearGradient.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 134814201AA4EA6300B7C361; - remoteInfo = BVLinearGradient; - }; - 24979D5E20F83E3E007EB0DA /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 8AC83A50CE8F4EE782376063 /* BVLinearGradient.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 64AA15081EF7F30100718508; - remoteInfo = "BVLinearGradient-tvOS"; - }; - 24979D6720F83E3E007EB0DA /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 02CF70769C034001B5CBC1EF /* ReactNativePermissions.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 9D23B34F1C767B80008B4819; - remoteInfo = ReactNativePermissions; - }; - 24979D6D20F83E3E007EB0DA /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = AEED489341644A6888669239 /* RNFIRMessaging.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 134814201AA4EA6300B7C361; - remoteInfo = RNFIRMessaging; - }; - 24979D7120F83E3E007EB0DA /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 50B1B80F51614673AFD8A804 /* RNKeychain.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 5D82366F1B0CE05B005A9EF3; - remoteInfo = RNKeychain; - }; - 24979D7320F83E3E007EB0DA /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 50B1B80F51614673AFD8A804 /* RNKeychain.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 6478985F1F38BF9100DA1C12; - remoteInfo = "RNKeychain-tvOS"; - }; - 24979D7720F83E3E007EB0DA /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BC297F456F414298BFBB0C30 /* RNMail.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 46FEDE7F1AFF192F00D3261C; - remoteInfo = RNMail; - }; - 24979D7920F83E3E007EB0DA /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BC297F456F414298BFBB0C30 /* RNMail.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 46FEDE8A1AFF192F00D3261C; - remoteInfo = RNMailTests; - }; - 24979D7C20F83E3E007EB0DA /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BEE6BF249EAB410AB20BBB98 /* RNOS.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 134814201AA4EA6300B7C361; - remoteInfo = RNOS; - }; - 24979D8020F83E3E007EB0DA /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 28B88B43D75F4B529A711317 /* RNRandomBytes.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 73EEC9391BFE4B1D00D468EB; - remoteInfo = RNRandomBytes; - }; - 24979D8220F83E3E007EB0DA /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 28B88B43D75F4B529A711317 /* RNRandomBytes.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 163CDE4E2087CAD3001065FB; - remoteInfo = "RNRandomBytes-tvOS"; - }; - 24979D8920F83E3E007EB0DA /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 3A545B8C781B47AC8A7CD956 /* RNSVG.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 0CF68AC11AF0540F00FF9E5C; - remoteInfo = RNSVG; - }; - 24979D8B20F83E3E007EB0DA /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 3A545B8C781B47AC8A7CD956 /* RNSVG.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 94DDAC5C1F3D024300EED511; - remoteInfo = "RNSVG-tvOS"; - }; - 24979D8E20F83E3E007EB0DA /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 2DB932A7706945C787DE22A6 /* SplashScreen.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 3D7682761D8E76B80014119E; - remoteInfo = SplashScreen; - }; - 24979D9120F83E3E007EB0DA /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 137BEEE47D2E4F7AB452C0BD /* SRSRadialGradient.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 134814201AA4EA6300B7C361; - remoteInfo = SRSRadialGradient; - }; - 24979D9420F83E3E007EB0DA /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 35B7B17127FD476C81EA97E3 /* TcpSockets.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 134814201AA4EA6300B7C361; - remoteInfo = TcpSockets; - }; - 24979D9820F83E3E007EB0DA /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 22B35A6AE60F41D093A35939 /* ToolTipMenu.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 4681C0211B05271A004D67D4; - remoteInfo = ToolTipMenu; - }; - 24979D9A20F83E3E007EB0DA /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 22B35A6AE60F41D093A35939 /* ToolTipMenu.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 4681C02C1B05271A004D67D4; - remoteInfo = ToolTipMenuTests; - }; - 24979D9D20F83E3E007EB0DA /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 969D4F061E6A446F9EEE2F02 /* TouchID.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 134814201AA4EA6300B7C361; - remoteInfo = TouchID; - }; - 24979DA020F83E3E007EB0DA /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 46EFC4C16BAF4873BE45393E /* UdpSockets.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 134814201AA4EA6300B7C361; - remoteInfo = UdpSockets; - }; - 249E5FD822613ABC0095F6B7 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 249E5FA722613ABC0095F6B7 /* RNCAsyncStorage.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 134814201AA4EA6300B7C361; - remoteInfo = RNCAsyncStorage; - }; - 24D171E1212F57110090F180 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 171CDF49E32841EDA7D557DB /* RNGestureHandler.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 134814201AA4EA6300B7C361; - remoteInfo = RNGestureHandler; - }; - 2C867629211152560067D47A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4A9E14039D3A4590A2F32D92 /* CodePush.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 134814201AA4EA6300B7C361; - remoteInfo = CodePush; - }; - 2C86762B211152560067D47A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4A9E14039D3A4590A2F32D92 /* CodePush.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = F886647B1F4ADB500036D01B; - remoteInfo = "CodePush-tvOS"; - }; - 2D16E6711FA4F8DC00B85C8A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = ADD01A681E09402E00F6D226; - remoteInfo = "RCTBlob-tvOS"; - }; - 2D16E6831FA4F8DC00B85C8A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 3DBE0D001F3B181A0099AA32; - remoteInfo = fishhook; - }; - 2D16E6851FA4F8DC00B85C8A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 3DBE0D0D1F3B181C0099AA32; - remoteInfo = "fishhook-tvOS"; - }; - 2DF0FFDE2056DD460020B375 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = EBF21BDC1FC498900052F4D5; - remoteInfo = jsinspector; - }; - 2DF0FFE02056DD460020B375 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = EBF21BFA1FC4989A0052F4D5; - remoteInfo = "jsinspector-tvOS"; - }; - 2DF0FFE22056DD460020B375 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 139D7ECE1E25DB7D00323FB7; - remoteInfo = "third-party"; - }; - 2DF0FFE42056DD460020B375 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 3D383D3C1EBD27B6005632C8; - remoteInfo = "third-party-tvOS"; - }; - 2DF0FFE62056DD460020B375 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 139D7E881E25C6D100323FB7; - remoteInfo = "double-conversion"; - }; - 2DF0FFE82056DD460020B375 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 3D383D621EBD27B9005632C8; - remoteInfo = "double-conversion-tvOS"; - }; - 3C39C26F218BBE66004C763F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 3C39C266218BBE66004C763F /* FastImage.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = A287971D1DE0C0A60081BDFA; - remoteInfo = FastImage; - }; - 3C48F38222CD0CDE00368A91 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 3C39C266218BBE66004C763F /* FastImage.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = FD751C4D229EB44C002BE1F4; - remoteInfo = "FastImage-tvOS"; - }; - 3CD4E8CC216989E8000FA5BD /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 137BEEE47D2E4F7AB452C0BD /* SRSRadialGradient.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 47413E2820DBB5D000CCDA85; - remoteInfo = "SRSRadialGradien-tvOS"; - }; - 3DAD3E831DF850E9000B6D8A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 2D2A283A1D9B042B00D4039D; - remoteInfo = "RCTImage-tvOS"; - }; - 3DAD3E871DF850E9000B6D8A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 2D2A28471D9B043800D4039D; - remoteInfo = "RCTLinking-tvOS"; - }; - 3DAD3E8B1DF850E9000B6D8A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 2D2A28541D9B044C00D4039D; - remoteInfo = "RCTNetwork-tvOS"; - }; - 3DAD3E8F1DF850E9000B6D8A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 2D2A28611D9B046600D4039D; - remoteInfo = "RCTSettings-tvOS"; - }; - 3DAD3E931DF850E9000B6D8A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 2D2A287B1D9B048500D4039D; - remoteInfo = "RCTText-tvOS"; - }; - 3DAD3E981DF850E9000B6D8A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 2D2A28881D9B049200D4039D; - remoteInfo = "RCTWebSocket-tvOS"; - }; - 3DAD3EA21DF850E9000B6D8A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 2D2A28131D9B038B00D4039D; - remoteInfo = "React-tvOS"; - }; - 3DAD3EA41DF850E9000B6D8A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 3D3C059A1DE3340900C268FA; - remoteInfo = yoga; - }; - 3DAD3EA61DF850E9000B6D8A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 3D3C06751DE3340C00C268FA; - remoteInfo = "yoga-tvOS"; - }; - 3DAD3EA81DF850E9000B6D8A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 3D3CD9251DE5FBEC00167DC4; - remoteInfo = cxxreact; - }; - 3DAD3EAA1DF850E9000B6D8A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 3D3CD9321DE5FBEE00167DC4; - remoteInfo = "cxxreact-tvOS"; - }; - 5E9157321DD0AC6500FF2AA8 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 134814201AA4EA6300B7C361; - remoteInfo = RCTAnimation; - }; - 5E9157341DD0AC6500FF2AA8 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 2D2A28201D9B03D100D4039D; - remoteInfo = "RCTAnimation-tvOS"; - }; - 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 134814201AA4EA6300B7C361; - remoteInfo = RCTLinking; - }; - 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 58B5119B1A9E6C1200147676; - remoteInfo = RCTText; - }; - ADBDB9261DFEBF0700ED6528 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 358F4ED71D1E81A9004DF814; - remoteInfo = RCTBlob; - }; -/* End PBXContainerItemProxy section */ - /* Begin PBXFileReference section */ 008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = ""; }; - 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = "../node_modules/react-native/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj"; sourceTree = ""; }; - 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = "../node_modules/react-native/Libraries/Geolocation/RCTGeolocation.xcodeproj"; sourceTree = ""; }; - 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = "../node_modules/react-native/Libraries/Image/RCTImage.xcodeproj"; sourceTree = ""; }; - 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = "../node_modules/react-native/Libraries/Network/RCTNetwork.xcodeproj"; sourceTree = ""; }; - 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = "../node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj"; sourceTree = ""; }; - 00E356EE1AD99517003FC87E /* RainbowTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RainbowTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 00E356F21AD99517003FC87E /* RainbowTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RainbowTests.m; sourceTree = ""; }; - 02CF70769C034001B5CBC1EF /* ReactNativePermissions.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = ReactNativePermissions.xcodeproj; path = "../node_modules/react-native-permissions/ios/ReactNativePermissions.xcodeproj"; sourceTree = ""; }; - 069784542A6B83E8BB774757 /* Pods-Rainbow.localrelease.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rainbow.localrelease.xcconfig"; path = "Target Support Files/Pods-Rainbow/Pods-Rainbow.localrelease.xcconfig"; sourceTree = ""; }; - 06E14A994B1D3A2E1CCBA545 /* Pods-Rainbow.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rainbow.debug.xcconfig"; path = "Target Support Files/Pods-Rainbow/Pods-Rainbow.debug.xcconfig"; sourceTree = ""; }; + 0642ECCC7CB044FDB5A3CC32 /* libRNTextInputMask.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNTextInputMask.a; sourceTree = ""; }; 0A8698C728414E56A3FD89A6 /* SFMono-Heavy.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "SFMono-Heavy.otf"; path = "../src/assets/fonts/SFMono-Heavy.otf"; sourceTree = ""; }; - 0E0889DFA1224AA48F1A5301 /* libRNRandomBytes-tvOS.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = "libRNRandomBytes-tvOS.a"; sourceTree = ""; }; - 0EBA050ADF8AD8CB6B14A162 /* Pods-Rainbow.staging.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rainbow.staging.xcconfig"; path = "Target Support Files/Pods-Rainbow/Pods-Rainbow.staging.xcconfig"; sourceTree = ""; }; - 137BEEE47D2E4F7AB452C0BD /* SRSRadialGradient.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = SRSRadialGradient.xcodeproj; path = "../node_modules/react-native-radial-gradient/ios/SRSRadialGradient.xcodeproj"; sourceTree = ""; }; - 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = "../node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj"; sourceTree = ""; }; - 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = "../node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj"; sourceTree = ""; }; 13B07F961A680F5B00A75B9A /* Rainbow.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Rainbow.app; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = Rainbow/AppDelegate.h; sourceTree = ""; }; 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = Rainbow/AppDelegate.m; sourceTree = ""; }; @@ -616,14 +85,10 @@ 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = Rainbow/Images.xcassets; sourceTree = ""; }; 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Rainbow/Info.plist; sourceTree = ""; }; 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Rainbow/main.m; sourceTree = ""; }; - 146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = ""; }; - 171CDF49E32841EDA7D557DB /* RNGestureHandler.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNGestureHandler.xcodeproj; path = "../node_modules/react-native-gesture-handler/ios/RNGestureHandler.xcodeproj"; sourceTree = ""; }; + 15B240C971E54630F3158955 /* Pods-Rainbow.localrelease.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rainbow.localrelease.xcconfig"; path = "Target Support Files/Pods-Rainbow/Pods-Rainbow.localrelease.xcconfig"; sourceTree = ""; }; 1736F851327A41C3815212E7 /* SF-Pro-Text-BoldItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "SF-Pro-Text-BoldItalic.otf"; path = "../src/assets/fonts/SF-Pro-Text-BoldItalic.otf"; sourceTree = ""; }; 182DC054E3584C83822F2A82 /* Graphik-RegularItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Graphik-RegularItalic.otf"; path = "../src/assets/fonts/Graphik-RegularItalic.otf"; sourceTree = ""; }; - 1A7B7E90124047F8A3CA4B84 /* RNReactNativeHapticFeedback.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNReactNativeHapticFeedback.xcodeproj; path = "../node_modules/react-native-haptic-feedback/ios/RNReactNativeHapticFeedback.xcodeproj"; sourceTree = ""; }; 1DEDF110038147A598C9B152 /* SF-Pro-Text-HeavyItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "SF-Pro-Text-HeavyItalic.otf"; path = "../src/assets/fonts/SF-Pro-Text-HeavyItalic.otf"; sourceTree = ""; }; - 22B35A6AE60F41D093A35939 /* ToolTipMenu.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = ToolTipMenu.xcodeproj; path = "../node_modules/react-native-tooltip/ToolTipMenu.xcodeproj"; sourceTree = ""; }; - 22E39434CDDE4C54848FBFD5 /* libCodePush.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libCodePush.a; sourceTree = ""; }; 233322FCDC624F6FA60C4B52 /* SF-Pro-Text-Heavy.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "SF-Pro-Text-Heavy.otf"; path = "../src/assets/fonts/SF-Pro-Text-Heavy.otf"; sourceTree = ""; }; 24979E3620F84003007EB0DA /* Protobuf.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Protobuf.framework; path = Frameworks/Protobuf.framework; sourceTree = ""; }; 24979E7420F84004007EB0DA /* FirebaseAnalytics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FirebaseAnalytics.framework; path = Frameworks/FirebaseAnalytics.framework; sourceTree = ""; }; @@ -637,95 +102,63 @@ 24979E7C20F84004007EB0DA /* FirebaseCoreDiagnostics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FirebaseCoreDiagnostics.framework; path = Frameworks/FirebaseCoreDiagnostics.framework; sourceTree = ""; }; 24979E7D20F84005007EB0DA /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; name = module.modulemap; path = Frameworks/module.modulemap; sourceTree = ""; }; 24979E7E20F84005007EB0DA /* nanopb.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = nanopb.framework; path = Frameworks/nanopb.framework; sourceTree = ""; }; - 249E5FA722613ABC0095F6B7 /* RNCAsyncStorage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RNCAsyncStorage.xcodeproj; path = "../node_modules/@react-native-community/async-storage/ios/RNCAsyncStorage.xcodeproj"; sourceTree = ""; }; 24A867FF226181F9005DCF78 /* libFirebaseInstanceID.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libFirebaseInstanceID.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 25992DBB7F97481A95784B0F /* RNMailTests.xctest */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = RNMailTests.xctest; sourceTree = ""; }; 273D2D617F3F43E99F8F404B /* Graphik-ExtralightItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Graphik-ExtralightItalic.otf"; path = "../src/assets/fonts/Graphik-ExtralightItalic.otf"; sourceTree = ""; }; - 28B88B43D75F4B529A711317 /* RNRandomBytes.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNRandomBytes.xcodeproj; path = "../node_modules/react-native-randombytes/RNRandomBytes.xcodeproj"; sourceTree = ""; }; 2AEF0207B9724FE5A27519FF /* SF-Pro-Display-Medium.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "SF-Pro-Display-Medium.otf"; path = "../src/assets/fonts/SF-Pro-Display-Medium.otf"; sourceTree = ""; }; 2C4A4A4FB3D84F14A48989D8 /* SFMono-Light.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "SFMono-Light.otf"; path = "../src/assets/fonts/SFMono-Light.otf"; sourceTree = ""; }; 2D16E6891FA4F8E400B85C8A /* libReact.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libReact.a; sourceTree = BUILT_PRODUCTS_DIR; }; 2DA6F347A6B540399883FF91 /* Graphik-MediumItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Graphik-MediumItalic.otf"; path = "../src/assets/fonts/Graphik-MediumItalic.otf"; sourceTree = ""; }; - 2DB932A7706945C787DE22A6 /* SplashScreen.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = SplashScreen.xcodeproj; path = "../node_modules/react-native-splash-screen/ios/SplashScreen.xcodeproj"; sourceTree = ""; }; - 2FA917DDE3314475BABEC117 /* libSRSRadialGradient.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libSRSRadialGradient.a; sourceTree = ""; }; - 3182AEA93A7847CCB729F641 /* RNStoreReview.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNStoreReview.xcodeproj; path = "../node_modules/react-native-store-review/ios/RNStoreReview.xcodeproj"; sourceTree = ""; }; 3459F05BF10649C4A787D900 /* SF-Pro-Display-MediumItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "SF-Pro-Display-MediumItalic.otf"; path = "../src/assets/fonts/SF-Pro-Display-MediumItalic.otf"; sourceTree = ""; }; 35833023DB594F1AA6A72866 /* SF-Pro-Display-Ultralight.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "SF-Pro-Display-Ultralight.otf"; path = "../src/assets/fonts/SF-Pro-Display-Ultralight.otf"; sourceTree = ""; }; 35A24AFF4AB449C287EE66A8 /* SF-Pro-Text-Medium.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "SF-Pro-Text-Medium.otf"; path = "../src/assets/fonts/SF-Pro-Text-Medium.otf"; sourceTree = ""; }; - 35B7B17127FD476C81EA97E3 /* TcpSockets.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = TcpSockets.xcodeproj; path = "../node_modules/react-native-tcp/ios/TcpSockets.xcodeproj"; sourceTree = ""; }; - 3A545B8C781B47AC8A7CD956 /* RNSVG.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNSVG.xcodeproj; path = "../node_modules/react-native-svg/ios/RNSVG.xcodeproj"; sourceTree = ""; }; - 3A7E5E09E14B4EA4B52CC6EE /* libRNGestureHandler.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNGestureHandler.a; sourceTree = ""; }; 3C379D5D20FD1F92009AF81F /* Rainbow.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = Rainbow.entitlements; path = Rainbow/Rainbow.entitlements; sourceTree = ""; }; - 3C39C266218BBE66004C763F /* FastImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = FastImage.xcodeproj; path = "../node_modules/react-native-fast-image/ios/FastImage.xcodeproj"; sourceTree = ""; }; + 3CBE29CB2381E43800BE05AC /* Rainbow-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Rainbow-Bridging-Header.h"; sourceTree = ""; }; + 3CBE29CC2381E43900BE05AC /* Dummy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dummy.swift; sourceTree = ""; }; 3CC4B790228B298400D827EB /* libSDWebImage.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libSDWebImage.a; sourceTree = BUILT_PRODUCTS_DIR; }; 3CE850D5210FEA8F00672599 /* libGoogleToolboxForMac.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libGoogleToolboxForMac.a; sourceTree = BUILT_PRODUCTS_DIR; }; 3CE850D7210FEACE00672599 /* libnanopb.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libnanopb.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 3E98BFA4968FAACF85C68AB5 /* Pods-Rainbow.staging.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rainbow.staging.xcconfig"; path = "Pods/Target Support Files/Pods-Rainbow/Pods-Rainbow.staging.xcconfig"; sourceTree = ""; }; 3EA8003C5E2D46E38184714B /* Graphik-ThinItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Graphik-ThinItalic.otf"; path = "../src/assets/fonts/Graphik-ThinItalic.otf"; sourceTree = ""; }; - 45B0EAA273D24F15B885A97D /* libRNMail.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNMail.a; sourceTree = ""; }; - 46EFC4C16BAF4873BE45393E /* UdpSockets.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = UdpSockets.xcodeproj; path = "../node_modules/react-native-udp/ios/UdpSockets.xcodeproj"; sourceTree = ""; }; - 4A9E14039D3A4590A2F32D92 /* CodePush.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = CodePush.xcodeproj; path = "../node_modules/react-native-code-push/ios/CodePush.xcodeproj"; sourceTree = ""; }; - 50137FC674DB782F454AFA32 /* Pods-Rainbow.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rainbow.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Rainbow/Pods-Rainbow.debug.xcconfig"; sourceTree = ""; }; - 50750D914B8810145768DC57 /* Pods-Rainbow.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rainbow.release.xcconfig"; path = "Target Support Files/Pods-Rainbow/Pods-Rainbow.release.xcconfig"; sourceTree = ""; }; - 50B1B80F51614673AFD8A804 /* RNKeychain.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNKeychain.xcodeproj; path = "../node_modules/react-native-keychain/RNKeychain.xcodeproj"; sourceTree = ""; }; - 51A0A7CFC45344D49BFF6CB9 /* libReactNativePermissions.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libReactNativePermissions.a; sourceTree = ""; }; 51E41940863B4B88BDEF48D7 /* Graphik-SuperItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Graphik-SuperItalic.otf"; path = "../src/assets/fonts/Graphik-SuperItalic.otf"; sourceTree = ""; }; 5842861A013B4B379705CC5A /* SF-Pro-Display-Semibold.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "SF-Pro-Display-Semibold.otf"; path = "../src/assets/fonts/SF-Pro-Display-Semibold.otf"; sourceTree = ""; }; - 5AC94663BD4242A29273D66F /* libUdpSockets.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libUdpSockets.a; sourceTree = ""; }; - 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimation.xcodeproj; path = "../node_modules/react-native/Libraries/NativeAnimation/RCTAnimation.xcodeproj"; sourceTree = ""; }; + 6613987F23689A430097D1D5 /* libReact-Core.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = "libReact-Core.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6613988123689A430097D1D5 /* libReact-CoreModules.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = "libReact-CoreModules.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6613988323689A430097D1D5 /* libReact-cxxreact.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = "libReact-cxxreact.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6613988523689A430097D1D5 /* libReact-jsi.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = "libReact-jsi.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 66139B432368A9AE0097D1D5 /* libRNFirebase.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libRNFirebase.a; sourceTree = BUILT_PRODUCTS_DIR; }; 662C7FD632C1481AB5AB1DB7 /* SF-Pro-Display-Thin.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "SF-Pro-Display-Thin.otf"; path = "../src/assets/fonts/SF-Pro-Display-Thin.otf"; sourceTree = ""; }; 668A9E253DAF444A90ECB997 /* SFMono-Medium.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "SFMono-Medium.otf"; path = "../src/assets/fonts/SFMono-Medium.otf"; sourceTree = ""; }; - 6747DC29E9EE446C8C2F7B76 /* libTcpSockets.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libTcpSockets.a; sourceTree = ""; }; + 66C5D39A1EDC48A6255FF83C /* Pods-Rainbow.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rainbow.debug.xcconfig"; path = "Target Support Files/Pods-Rainbow/Pods-Rainbow.debug.xcconfig"; sourceTree = ""; }; + 66CA6CFD237C27E200C8E3D6 /* InputMask.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = InputMask.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 6C1814FA03B309E79858CD16 /* libPods-Rainbow.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Rainbow.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 715DAAA3174542BAB93807A6 /* SF-Pro-Text-RegularItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "SF-Pro-Text-RegularItalic.otf"; path = "../src/assets/fonts/SF-Pro-Text-RegularItalic.otf"; sourceTree = ""; }; 7818F79CD3944D17AF4196A5 /* Graphik-Black.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Graphik-Black.otf"; path = "../src/assets/fonts/Graphik-Black.otf"; sourceTree = ""; }; - 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = ""; }; - 7A19C32218BC469EA9228F2E /* libRNSVG-tvOS.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = "libRNSVG-tvOS.a"; sourceTree = ""; }; 7A9AF25703474604964D6EC1 /* Graphik-Light.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Graphik-Light.otf"; path = "../src/assets/fonts/Graphik-Light.otf"; sourceTree = ""; }; 7CD46377E5FC4E5EBFD57D71 /* Graphik-Super.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Graphik-Super.otf"; path = "../src/assets/fonts/Graphik-Super.otf"; sourceTree = ""; }; 7CEEDA7A68C24426BBAA8D77 /* Graphik-BoldItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Graphik-BoldItalic.otf"; path = "../src/assets/fonts/Graphik-BoldItalic.otf"; sourceTree = ""; }; - 823BD6129C8AA3FD7CDD46BE /* libPods-Rainbow.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Rainbow.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = ""; }; 84DB92DCDF5D4374B26FFCC6 /* SF-Pro-Display-BoldItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "SF-Pro-Display-BoldItalic.otf"; path = "../src/assets/fonts/SF-Pro-Display-BoldItalic.otf"; sourceTree = ""; }; 86B30DBBDA594167BFE4747E /* SF-Pro-Display-SemiboldItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "SF-Pro-Display-SemiboldItalic.otf"; path = "../src/assets/fonts/SF-Pro-Display-SemiboldItalic.otf"; sourceTree = ""; }; 8789D635428240B5ABF282EE /* SFMono-Bold.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "SFMono-Bold.otf"; path = "../src/assets/fonts/SFMono-Bold.otf"; sourceTree = ""; }; 88A5866DBF924C149CA0C6F4 /* Graphik-Semibold.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Graphik-Semibold.otf"; path = "../src/assets/fonts/Graphik-Semibold.otf"; sourceTree = ""; }; - 8AC83A50CE8F4EE782376063 /* BVLinearGradient.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = BVLinearGradient.xcodeproj; path = "../node_modules/react-native-linear-gradient/BVLinearGradient.xcodeproj"; sourceTree = ""; }; - 8C38066021DF4A73845E4A0F /* libRNRandomBytes.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNRandomBytes.a; sourceTree = ""; }; 8D37634EBB294EC79081DFD2 /* SF-Pro-Display-Heavy.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "SF-Pro-Display-Heavy.otf"; path = "../src/assets/fonts/SF-Pro-Display-Heavy.otf"; sourceTree = ""; }; 9165B952731E4502857CC0B4 /* SF-Pro-Display-Regular.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "SF-Pro-Display-Regular.otf"; path = "../src/assets/fonts/SF-Pro-Display-Regular.otf"; sourceTree = ""; }; - 91A43F69E797469687978D51 /* libRNStoreReview.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNStoreReview.a; sourceTree = ""; }; 93D62D49D9CA46F292BD9869 /* Graphik-Extralight.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Graphik-Extralight.otf"; path = "../src/assets/fonts/Graphik-Extralight.otf"; sourceTree = ""; }; 944CF612F0304DF281E33B66 /* SF-Pro-Text-Regular.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "SF-Pro-Text-Regular.otf"; path = "../src/assets/fonts/SF-Pro-Text-Regular.otf"; sourceTree = ""; }; 95F2888C850F40C8A26E083B /* SFMono-Regular.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "SFMono-Regular.otf"; path = "../src/assets/fonts/SFMono-Regular.otf"; sourceTree = ""; }; - 969D4F061E6A446F9EEE2F02 /* TouchID.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = TouchID.xcodeproj; path = "../node_modules/react-native-touch-id/TouchID.xcodeproj"; sourceTree = ""; }; - 96CCCB016071412E994DFF61 /* libRNOS.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNOS.a; sourceTree = ""; }; + 98AED33BAB4247CEBEF8464D /* libz.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; 9DEADFA4826D4D0BAA950D21 /* libRNFIRMessaging.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNFIRMessaging.a; sourceTree = ""; }; 9DF45B9EB38D4E8FA18A04C6 /* SF-Pro-Display-Light.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "SF-Pro-Display-Light.otf"; path = "../src/assets/fonts/SF-Pro-Display-Light.otf"; sourceTree = ""; }; - 9E0A11D8843045ECB80C6AB8 /* libTouchID.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libTouchID.a; sourceTree = ""; }; - A014AE1645874354A732EB35 /* libToolTipMenu.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libToolTipMenu.a; sourceTree = ""; }; - A0BA96258CF7FFF7BBE552F4 /* Pods-Rainbow.localrelease.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rainbow.localrelease.xcconfig"; path = "Pods/Target Support Files/Pods-Rainbow/Pods-Rainbow.localrelease.xcconfig"; sourceTree = ""; }; + A671DF9861FA8D2C9A6FCB91 /* Pods-Rainbow.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rainbow.release.xcconfig"; path = "Target Support Files/Pods-Rainbow/Pods-Rainbow.release.xcconfig"; sourceTree = ""; }; A6EEFE6EA9354456B0DB4520 /* Graphik-Regular.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Graphik-Regular.otf"; path = "../src/assets/fonts/Graphik-Regular.otf"; sourceTree = ""; }; A7F0978B24BA4EC283C580D9 /* Graphik-SemiboldItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Graphik-SemiboldItalic.otf"; path = "../src/assets/fonts/Graphik-SemiboldItalic.otf"; sourceTree = ""; }; A8AE8DE50B9544B6BC186E6C /* SF-Pro-Display-BlackItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "SF-Pro-Display-BlackItalic.otf"; path = "../src/assets/fonts/SF-Pro-Display-BlackItalic.otf"; sourceTree = ""; }; AA6B0A8BE2484F46980BE9AC /* SF-Pro-Text-Semibold.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "SF-Pro-Text-Semibold.otf"; path = "../src/assets/fonts/SF-Pro-Text-Semibold.otf"; sourceTree = ""; }; - ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTBlob.xcodeproj; path = "../node_modules/react-native/Libraries/Blob/RCTBlob.xcodeproj"; sourceTree = ""; }; - AEED489341644A6888669239 /* RNFIRMessaging.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNFIRMessaging.xcodeproj; path = "../node_modules/react-native-fcm/ios/RNFIRMessaging.xcodeproj"; sourceTree = ""; }; - AF52B697F8A6DEC07D4A82AB /* Pods-Rainbow.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rainbow.release.xcconfig"; path = "Pods/Target Support Files/Pods-Rainbow/Pods-Rainbow.release.xcconfig"; sourceTree = ""; }; B0C692B061D7430D8194DC98 /* ToolTipMenuTests.xctest */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = ToolTipMenuTests.xctest; sourceTree = ""; }; B1089F835D6A4F578009B47F /* SFMono-Semibold.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "SFMono-Semibold.otf"; path = "../src/assets/fonts/SFMono-Semibold.otf"; sourceTree = ""; }; - B86CB964E3AA47029988138C /* libRNKeychain.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNKeychain.a; sourceTree = ""; }; - B98C0A69B3614C65B194BC68 /* libRNSVG.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNSVG.a; sourceTree = ""; }; BA31E8CEDBCC417CA50BC57B /* SF-Pro-Display-Bold.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "SF-Pro-Display-Bold.otf"; path = "../src/assets/fonts/SF-Pro-Display-Bold.otf"; sourceTree = ""; }; - BC297F456F414298BFBB0C30 /* RNMail.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNMail.xcodeproj; path = "../node_modules/react-native-mail/RNMail.xcodeproj"; sourceTree = ""; }; BE239BA93F6B4EDC867B1A41 /* SF-Pro-Display-Black.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "SF-Pro-Display-Black.otf"; path = "../src/assets/fonts/SF-Pro-Display-Black.otf"; sourceTree = ""; }; - BEE6BF249EAB410AB20BBB98 /* RNOS.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNOS.xcodeproj; path = "../node_modules/react-native-os/ios/RNOS.xcodeproj"; sourceTree = ""; }; - C1324455238847F2AD5C08B4 /* libBVLinearGradient.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libBVLinearGradient.a; sourceTree = ""; }; C1DB5F252E324925B4145360 /* SF-Pro-Display-ThinItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "SF-Pro-Display-ThinItalic.otf"; path = "../src/assets/fonts/SF-Pro-Display-ThinItalic.otf"; sourceTree = ""; }; - C779B11FB4664662AD0EBEA6 /* RNFirebase.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNFirebase.xcodeproj; path = "../node_modules/react-native-firebase/ios/RNFirebase.xcodeproj"; sourceTree = ""; }; CEC826911B5641B8AF788BB3 /* Graphik-BlackItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Graphik-BlackItalic.otf"; path = "../src/assets/fonts/Graphik-BlackItalic.otf"; sourceTree = ""; }; - D13995EB48584C438A10A161 /* libRNReactNativeHapticFeedback.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNReactNativeHapticFeedback.a; sourceTree = ""; }; D1641F1A96C841C085169B2E /* SF-Pro-Text-LightItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "SF-Pro-Text-LightItalic.otf"; path = "../src/assets/fonts/SF-Pro-Text-LightItalic.otf"; sourceTree = ""; }; - D1A86E696CA24D4F9D3F7F0F /* libz.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; D518658CFF8B491991A06426 /* SF-Pro-Text-MediumItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "SF-Pro-Text-MediumItalic.otf"; path = "../src/assets/fonts/SF-Pro-Text-MediumItalic.otf"; sourceTree = ""; }; D551F7BECCAF4CE3BC8C0C3D /* Graphik-LightItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Graphik-LightItalic.otf"; path = "../src/assets/fonts/Graphik-LightItalic.otf"; sourceTree = ""; }; D755E71324B04FEE9C691D14 /* libRNFirebase.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNFirebase.a; sourceTree = ""; }; @@ -736,7 +169,7 @@ E672AB1C5404435897615660 /* SF-Pro-Text-Light.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "SF-Pro-Text-Light.otf"; path = "../src/assets/fonts/SF-Pro-Text-Light.otf"; sourceTree = ""; }; E6F010E529544E518E1792C7 /* Graphik-Bold.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Graphik-Bold.otf"; path = "../src/assets/fonts/Graphik-Bold.otf"; sourceTree = ""; }; E8E3CE2A4AD34CB991CD61EE /* SF-Pro-Display-LightItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "SF-Pro-Display-LightItalic.otf"; path = "../src/assets/fonts/SF-Pro-Display-LightItalic.otf"; sourceTree = ""; }; - EA95F99E656542F790F685B6 /* libSplashScreen.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libSplashScreen.a; sourceTree = ""; }; + E93A96605FE51CFC31676801 /* Pods-Rainbow.staging.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rainbow.staging.xcconfig"; path = "Target Support Files/Pods-Rainbow/Pods-Rainbow.staging.xcconfig"; sourceTree = ""; }; EB48DC1D46D449759B9C61D4 /* Graphik-Thin.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Graphik-Thin.otf"; path = "../src/assets/fonts/Graphik-Thin.otf"; sourceTree = ""; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; ED2971642150620600B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS12.0.sdk/System/Library/Frameworks/JavaScriptCore.framework; sourceTree = DEVELOPER_DIR; }; @@ -745,101 +178,19 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 00E356EB1AD99517003FC87E /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 140ED2AC1D01E1AD002B40FF /* libReact.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 13B07F8C1A680F5B00A75B9A /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ED2971652150620600B7C4FE /* JavaScriptCore.framework in Frameworks */, - ADBDB9381DFEBF1600ED6528 /* libRCTBlob.a in Frameworks */, - 5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */, - 146834051AC3E58100842450 /* libReact.a in Frameworks */, - 5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */, - 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */, - 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */, - 00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */, - 133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */, - 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */, - 139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */, - 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */, - 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */, - 139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */, - 2340D4240F794E6DACB53521 /* libRNKeychain.a in Frameworks */, - 45C6CAEFC1A04F3FB291BE53 /* libBVLinearGradient.a in Frameworks */, - 94822FBFCA7246168685FA85 /* libRNMail.a in Frameworks */, - 4433A04AF3E942A2894B3933 /* libRNOS.a in Frameworks */, - 24979E8620F84005007EB0DA /* FirebaseInstanceID.framework in Frameworks */, - 4AF3A1B2CEC540D7A1AF957C /* libReactNativePermissions.a in Frameworks */, - 7F911FD5E35D4FD99D48A61D /* libSRSRadialGradient.a in Frameworks */, - 22DD8F08F32047C280DFA368 /* libRNRandomBytes.a in Frameworks */, - 978F83D3C5E4491F9D9AC2C1 /* libSplashScreen.a in Frameworks */, - 91959ACCE81B4C128AAC8154 /* libRNSVG.a in Frameworks */, - 07F258CE8EB84A8A949D4580 /* libTcpSockets.a in Frameworks */, - ED8A2571BF074F6DB6D09045 /* libToolTipMenu.a in Frameworks */, - 6E37C5716EC449C1B63D0E06 /* libTouchID.a in Frameworks */, - D77132C4B96040C39FED1AD5 /* libUdpSockets.a in Frameworks */, - 1A048DFD2F724753902EA40B /* libRNReactNativeHapticFeedback.a in Frameworks */, - F4E8A17A670147F4A5EC177E /* libRNGestureHandler.a in Frameworks */, - ECF14FECD39C459D86EDCB82 /* libCodePush.a in Frameworks */, - F35098D973414A09939FB3F8 /* libz.tbd in Frameworks */, - 154AA73429B14ED4BC8E0C72 /* libRNFirebase.a in Frameworks */, - 87808B52A9E224F3D11532B5 /* libPods-Rainbow.a in Frameworks */, - EA8076A8481B4CB4BBA566EF /* libRNStoreReview.a in Frameworks */, + 0E56AA9A8843EB50FA4BDD4F /* libPods-Rainbow.a in Frameworks */, + C72F456C99A646399192517D /* libz.tbd in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 00C302A81ABCB8CE00DB3ED1 /* Products */ = { - isa = PBXGroup; - children = ( - 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */, - ); - name = Products; - sourceTree = ""; - }; - 00C302B61ABCB90400DB3ED1 /* Products */ = { - isa = PBXGroup; - children = ( - 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */, - ); - name = Products; - sourceTree = ""; - }; - 00C302BC1ABCB91800DB3ED1 /* Products */ = { - isa = PBXGroup; - children = ( - 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */, - 3DAD3E841DF850E9000B6D8A /* libRCTImage-tvOS.a */, - ); - name = Products; - sourceTree = ""; - }; - 00C302D41ABCB9D200DB3ED1 /* Products */ = { - isa = PBXGroup; - children = ( - 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */, - 3DAD3E8C1DF850E9000B6D8A /* libRCTNetwork-tvOS.a */, - ); - name = Products; - sourceTree = ""; - }; - 00C302E01ABCB9EE00DB3ED1 /* Products */ = { - isa = PBXGroup; - children = ( - 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */, - ); - name = Products; - sourceTree = ""; - }; 00E356EF1AD99517003FC87E /* RainbowTests */ = { isa = PBXGroup; children = ( @@ -857,26 +208,6 @@ name = "Supporting Files"; sourceTree = ""; }; - 139105B71AF99BAD00B5F7CC /* Products */ = { - isa = PBXGroup; - children = ( - 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */, - 3DAD3E901DF850E9000B6D8A /* libRCTSettings-tvOS.a */, - ); - name = Products; - sourceTree = ""; - }; - 139FDEE71B06529A00C62182 /* Products */ = { - isa = PBXGroup; - children = ( - 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */, - 3DAD3E991DF850E9000B6D8A /* libRCTWebSocket-tvOS.a */, - 2D16E6841FA4F8DC00B85C8A /* libfishhook.a */, - 2D16E6861FA4F8DC00B85C8A /* libfishhook-tvOS.a */, - ); - name = Products; - sourceTree = ""; - }; 13B07FAE1A68108700A75B9A /* Rainbow */ = { isa = PBXGroup; children = ( @@ -888,235 +219,32 @@ 13B07FB61A68108700A75B9A /* Info.plist */, 13B07FB11A68108700A75B9A /* LaunchScreen.xib */, 13B07FB71A68108700A75B9A /* main.m */, + 3CBE29CC2381E43900BE05AC /* Dummy.swift */, + 3CBE29CB2381E43800BE05AC /* Rainbow-Bridging-Header.h */, ); name = Rainbow; sourceTree = ""; }; - 146834001AC3E56700842450 /* Products */ = { - isa = PBXGroup; - children = ( - 146834041AC3E56700842450 /* libReact.a */, - 3DAD3EA31DF850E9000B6D8A /* libReact.a */, - 3DAD3EA51DF850E9000B6D8A /* libyoga.a */, - 3DAD3EA71DF850E9000B6D8A /* libyoga.a */, - 3DAD3EA91DF850E9000B6D8A /* libcxxreact.a */, - 3DAD3EAB1DF850E9000B6D8A /* libcxxreact.a */, - 2DF0FFDF2056DD460020B375 /* libjsinspector.a */, - 2DF0FFE12056DD460020B375 /* libjsinspector-tvOS.a */, - 2DF0FFE32056DD460020B375 /* libthird-party.a */, - 2DF0FFE52056DD460020B375 /* libthird-party.a */, - 2DF0FFE72056DD460020B375 /* libdouble-conversion.a */, - 2DF0FFE92056DD460020B375 /* libdouble-conversion.a */, - 247947BB22568EAA006BBF56 /* libjsi.a */, - 247947BD22568EAA006BBF56 /* libjsiexecutor.a */, - 247947BF22568EAA006BBF56 /* libjsi-tvOS.a */, - 247947C122568EAA006BBF56 /* libjsiexecutor-tvOS.a */, - ); - name = Products; - sourceTree = ""; - }; - 244C64062108794F007A5856 /* Products */ = { - isa = PBXGroup; - children = ( - 244C640A2108794F007A5856 /* libRNReactNativeHapticFeedback.a */, - ); - name = Products; - sourceTree = ""; - }; - 2481F31D2261753900D0349A /* Products */ = { - isa = PBXGroup; - children = ( - 2481F3212261753900D0349A /* libRNFirebase.a */, - ); - name = Products; - sourceTree = ""; - }; - 2488BC2922E97315006847C7 /* Products */ = { - isa = PBXGroup; - children = ( - 2488BC2D22E97316006847C7 /* libRNStoreReview.a */, - ); - name = Products; - sourceTree = ""; - }; 24979D1220F83E3D007EB0DA /* Recovered References */ = { isa = PBXGroup; children = ( 9DEADFA4826D4D0BAA950D21 /* libRNFIRMessaging.a */, - B86CB964E3AA47029988138C /* libRNKeychain.a */, - C1324455238847F2AD5C08B4 /* libBVLinearGradient.a */, - 45B0EAA273D24F15B885A97D /* libRNMail.a */, - 25992DBB7F97481A95784B0F /* RNMailTests.xctest */, - 96CCCB016071412E994DFF61 /* libRNOS.a */, - 51A0A7CFC45344D49BFF6CB9 /* libReactNativePermissions.a */, - 2FA917DDE3314475BABEC117 /* libSRSRadialGradient.a */, - 8C38066021DF4A73845E4A0F /* libRNRandomBytes.a */, - EA95F99E656542F790F685B6 /* libSplashScreen.a */, - B98C0A69B3614C65B194BC68 /* libRNSVG.a */, - 6747DC29E9EE446C8C2F7B76 /* libTcpSockets.a */, - A014AE1645874354A732EB35 /* libToolTipMenu.a */, B0C692B061D7430D8194DC98 /* ToolTipMenuTests.xctest */, - 9E0A11D8843045ECB80C6AB8 /* libTouchID.a */, - 5AC94663BD4242A29273D66F /* libUdpSockets.a */, - 0E0889DFA1224AA48F1A5301 /* libRNRandomBytes-tvOS.a */, - 7A19C32218BC469EA9228F2E /* libRNSVG-tvOS.a */, - D13995EB48584C438A10A161 /* libRNReactNativeHapticFeedback.a */, - 3A7E5E09E14B4EA4B52CC6EE /* libRNGestureHandler.a */, - 22E39434CDDE4C54848FBFD5 /* libCodePush.a */, D755E71324B04FEE9C691D14 /* libRNFirebase.a */, - 91A43F69E797469687978D51 /* libRNStoreReview.a */, + 0642ECCC7CB044FDB5A3CC32 /* libRNTextInputMask.a */, ); name = "Recovered References"; sourceTree = ""; }; - 24979D3820F83E3E007EB0DA /* Products */ = { - isa = PBXGroup; - children = ( - 24979D9520F83E3E007EB0DA /* libTcpSockets.a */, - ); - name = Products; - sourceTree = ""; - }; - 24979D3A20F83E3E007EB0DA /* Products */ = { - isa = PBXGroup; - children = ( - 24979D9E20F83E3E007EB0DA /* libTouchID.a */, - ); - name = Products; - sourceTree = ""; - }; - 24979D3E20F83E3E007EB0DA /* Products */ = { - isa = PBXGroup; - children = ( - 24979D6E20F83E3E007EB0DA /* libRNFIRMessaging.a */, - ); - name = Products; - sourceTree = ""; - }; - 24979D4020F83E3E007EB0DA /* Products */ = { - isa = PBXGroup; - children = ( - 24979D7220F83E3E007EB0DA /* libRNKeychain.a */, - 24979D7420F83E3E007EB0DA /* libRNKeychain.a */, - ); - name = Products; - sourceTree = ""; - }; - 24979D4220F83E3E007EB0DA /* Products */ = { - isa = PBXGroup; - children = ( - 24979D5D20F83E3E007EB0DA /* libBVLinearGradient.a */, - 24979D5F20F83E3E007EB0DA /* libBVLinearGradient.a */, - ); - name = Products; - sourceTree = ""; - }; - 24979D4420F83E3E007EB0DA /* Products */ = { - isa = PBXGroup; - children = ( - 24979D7820F83E3E007EB0DA /* libRNMail.a */, - 24979D7A20F83E3E007EB0DA /* RNMailTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 24979D4820F83E3E007EB0DA /* Products */ = { - isa = PBXGroup; - children = ( - 24979D7D20F83E3E007EB0DA /* libRNOS.a */, - ); - name = Products; - sourceTree = ""; - }; - 24979D4A20F83E3E007EB0DA /* Products */ = { - isa = PBXGroup; - children = ( - 24979D6820F83E3E007EB0DA /* libReactNativePermissions.a */, - ); - name = Products; - sourceTree = ""; - }; - 24979D4C20F83E3E007EB0DA /* Products */ = { - isa = PBXGroup; - children = ( - 24979D9220F83E3E007EB0DA /* libSRSRadialGradient.a */, - 3CD4E8CD216989E8000FA5BD /* libSRSRadialGradien-tvOS.a */, - ); - name = Products; - sourceTree = ""; - }; - 24979D4E20F83E3E007EB0DA /* Products */ = { - isa = PBXGroup; - children = ( - 24979D8120F83E3E007EB0DA /* libRNRandomBytes.a */, - 24979D8320F83E3E007EB0DA /* libRNRandomBytes-tvOS.a */, - ); - name = Products; - sourceTree = ""; - }; - 24979D5020F83E3E007EB0DA /* Products */ = { - isa = PBXGroup; - children = ( - 24979D8F20F83E3E007EB0DA /* libSplashScreen.a */, - ); - name = Products; - sourceTree = ""; - }; - 24979D5420F83E3E007EB0DA /* Products */ = { - isa = PBXGroup; - children = ( - 24979D8A20F83E3E007EB0DA /* libRNSVG.a */, - 24979D8C20F83E3E007EB0DA /* libRNSVG-tvOS.a */, - ); - name = Products; - sourceTree = ""; - }; - 24979D5620F83E3E007EB0DA /* Products */ = { - isa = PBXGroup; - children = ( - 24979D9920F83E3E007EB0DA /* libToolTipMenu.a */, - 24979D9B20F83E3E007EB0DA /* ToolTipMenuTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 24979D5820F83E3E007EB0DA /* Products */ = { - isa = PBXGroup; - children = ( - 24979DA120F83E3E007EB0DA /* libUdpSockets.a */, - ); - name = Products; - sourceTree = ""; - }; - 249E5FA822613ABC0095F6B7 /* Products */ = { - isa = PBXGroup; - children = ( - 249E5FD922613ABC0095F6B7 /* libRNCAsyncStorage.a */, - ); - name = Products; - sourceTree = ""; - }; - 24D171DE212F57100090F180 /* Products */ = { - isa = PBXGroup; - children = ( - 24D171E2212F57110090F180 /* libRNGestureHandler.a */, - 243A893E225F092800A13C7E /* libRNGestureHandler-tvOS.a */, - ); - name = Products; - sourceTree = ""; - }; - 2C867625211152550067D47A /* Products */ = { - isa = PBXGroup; - children = ( - 2C86762A211152560067D47A /* libCodePush.a */, - 2C86762C211152560067D47A /* libCodePush.a */, - ); - name = Products; - sourceTree = ""; - }; 2D16E6871FA4F8E400B85C8A /* Frameworks */ = { isa = PBXGroup; children = ( + 66139B432368A9AE0097D1D5 /* libRNFirebase.a */, + 6613987F23689A430097D1D5 /* libReact-Core.a */, + 66CA6CFD237C27E200C8E3D6 /* InputMask.framework */, + 6613988123689A430097D1D5 /* libReact-CoreModules.a */, + 6613988323689A430097D1D5 /* libReact-cxxreact.a */, + 6613988523689A430097D1D5 /* libReact-jsi.a */, 3CC4B790228B298400D827EB /* libSDWebImage.a */, 24A867FF226181F9005DCF78 /* libFirebaseInstanceID.a */, ED297162215061F000B7C4FE /* JavaScriptCore.framework */, @@ -1136,88 +264,19 @@ 24979E7E20F84005007EB0DA /* nanopb.framework */, 24979E3620F84003007EB0DA /* Protobuf.framework */, 2D16E6891FA4F8E400B85C8A /* libReact.a */, - D1A86E696CA24D4F9D3F7F0F /* libz.tbd */, - 823BD6129C8AA3FD7CDD46BE /* libPods-Rainbow.a */, + 6C1814FA03B309E79858CD16 /* libPods-Rainbow.a */, + 98AED33BAB4247CEBEF8464D /* libz.tbd */, ); name = Frameworks; sourceTree = ""; }; - 3C39C267218BBE66004C763F /* Products */ = { - isa = PBXGroup; - children = ( - 3C39C270218BBE66004C763F /* libFastImage.a */, - 3C48F38322CD0CDE00368A91 /* libFastImage-tvOS.a */, - ); - name = Products; - sourceTree = ""; - }; - 5E91572E1DD0AC6500FF2AA8 /* Products */ = { - isa = PBXGroup; - children = ( - 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */, - 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation.a */, - ); - name = Products; - sourceTree = ""; - }; - 78C398B11ACF4ADC00677621 /* Products */ = { - isa = PBXGroup; - children = ( - 78C398B91ACF4ADC00677621 /* libRCTLinking.a */, - 3DAD3E881DF850E9000B6D8A /* libRCTLinking-tvOS.a */, - ); - name = Products; - sourceTree = ""; - }; 832341AE1AAA6A7D00B99B32 /* Libraries */ = { isa = PBXGroup; children = ( - 8AC83A50CE8F4EE782376063 /* BVLinearGradient.xcodeproj */, - 4A9E14039D3A4590A2F32D92 /* CodePush.xcodeproj */, - 3C39C266218BBE66004C763F /* FastImage.xcodeproj */, - 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */, - 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */, - ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */, - 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */, - 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */, - 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */, - 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */, - 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */, - 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */, - 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */, - 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */, - 146833FF1AC3E56700842450 /* React.xcodeproj */, - 02CF70769C034001B5CBC1EF /* ReactNativePermissions.xcodeproj */, - 249E5FA722613ABC0095F6B7 /* RNCAsyncStorage.xcodeproj */, - C779B11FB4664662AD0EBEA6 /* RNFirebase.xcodeproj */, - AEED489341644A6888669239 /* RNFIRMessaging.xcodeproj */, - 171CDF49E32841EDA7D557DB /* RNGestureHandler.xcodeproj */, - 50B1B80F51614673AFD8A804 /* RNKeychain.xcodeproj */, - BC297F456F414298BFBB0C30 /* RNMail.xcodeproj */, - BEE6BF249EAB410AB20BBB98 /* RNOS.xcodeproj */, - 28B88B43D75F4B529A711317 /* RNRandomBytes.xcodeproj */, - 1A7B7E90124047F8A3CA4B84 /* RNReactNativeHapticFeedback.xcodeproj */, - 3A545B8C781B47AC8A7CD956 /* RNSVG.xcodeproj */, - 2DB932A7706945C787DE22A6 /* SplashScreen.xcodeproj */, - 137BEEE47D2E4F7AB452C0BD /* SRSRadialGradient.xcodeproj */, - 35B7B17127FD476C81EA97E3 /* TcpSockets.xcodeproj */, - 22B35A6AE60F41D093A35939 /* ToolTipMenu.xcodeproj */, - 969D4F061E6A446F9EEE2F02 /* TouchID.xcodeproj */, - 46EFC4C16BAF4873BE45393E /* UdpSockets.xcodeproj */, - 3182AEA93A7847CCB729F641 /* RNStoreReview.xcodeproj */, ); name = Libraries; sourceTree = ""; }; - 832341B11AAA6A8300B99B32 /* Products */ = { - isa = PBXGroup; - children = ( - 832341B51AAA6A8300B99B32 /* libRCTText.a */, - 3DAD3E941DF850E9000B6D8A /* libRCTText-tvOS.a */, - ); - name = Products; - sourceTree = ""; - }; 83CBB9F61A601CBA00E9B192 = { isa = PBXGroup; children = ( @@ -1239,16 +298,6 @@ isa = PBXGroup; children = ( 13B07F961A680F5B00A75B9A /* Rainbow.app */, - 00E356EE1AD99517003FC87E /* RainbowTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - ADBDB9201DFEBF0600ED6528 /* Products */ = { - isa = PBXGroup; - children = ( - ADBDB9271DFEBF0700ED6528 /* libRCTBlob.a */, - 2D16E6721FA4F8DC00B85C8A /* libRCTBlob-tvOS.a */, ); name = Products; sourceTree = ""; @@ -1256,14 +305,10 @@ C640359C0E6575CE0A7ECD73 /* Pods */ = { isa = PBXGroup; children = ( - 06E14A994B1D3A2E1CCBA545 /* Pods-Rainbow.debug.xcconfig */, - 50750D914B8810145768DC57 /* Pods-Rainbow.release.xcconfig */, - 069784542A6B83E8BB774757 /* Pods-Rainbow.localrelease.xcconfig */, - 0EBA050ADF8AD8CB6B14A162 /* Pods-Rainbow.staging.xcconfig */, - 50137FC674DB782F454AFA32 /* Pods-Rainbow.debug.xcconfig */, - AF52B697F8A6DEC07D4A82AB /* Pods-Rainbow.release.xcconfig */, - A0BA96258CF7FFF7BBE552F4 /* Pods-Rainbow.localrelease.xcconfig */, - 3E98BFA4968FAACF85C68AB5 /* Pods-Rainbow.staging.xcconfig */, + 66C5D39A1EDC48A6255FF83C /* Pods-Rainbow.debug.xcconfig */, + A671DF9861FA8D2C9A6FCB91 /* Pods-Rainbow.release.xcconfig */, + 15B240C971E54630F3158955 /* Pods-Rainbow.localrelease.xcconfig */, + E93A96605FE51CFC31676801 /* Pods-Rainbow.staging.xcconfig */, ); path = Pods; sourceTree = ""; @@ -1332,34 +377,18 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 00E356ED1AD99517003FC87E /* RainbowTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "RainbowTests" */; - buildPhases = ( - 00E356EA1AD99517003FC87E /* Sources */, - 00E356EB1AD99517003FC87E /* Frameworks */, - 00E356EC1AD99517003FC87E /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 00E356F51AD99517003FC87E /* PBXTargetDependency */, - ); - name = RainbowTests; - productName = RainbowTests; - productReference = 00E356EE1AD99517003FC87E /* RainbowTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; 13B07F861A680F5B00A75B9A /* Rainbow */ = { isa = PBXNativeTarget; buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Rainbow" */; buildPhases = ( - 862FF20A142EFD912DF7FAA5 /* [CP] Check Pods Manifest.lock */, + B448B1B66A188D3AC6DA3639 /* [CP] Check Pods Manifest.lock */, 13B07F871A680F5B00A75B9A /* Sources */, 13B07F8C1A680F5B00A75B9A /* Frameworks */, 13B07F8E1A680F5B00A75B9A /* Resources */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, 3CF823D3218F310D0024B77B /* ShellScript */, + 7D8EDE895DE18700A743F64E /* [CP-User] [RNFB] Core Configuration */, + 8C1D9934C43085FED5C8B69C /* [CP-User] [RNFB] Crashlytics Configuration */, ); buildRules = ( ); @@ -1379,14 +408,9 @@ LastUpgradeCheck = 610; ORGANIZATIONNAME = Facebook; TargetAttributes = { - 00E356ED1AD99517003FC87E = { - CreatedOnToolsVersion = 6.2; - DevelopmentTeam = L74NQAQB8H; - ProvisioningStyle = Automatic; - TestTargetID = 13B07F861A680F5B00A75B9A; - }; 13B07F861A680F5B00A75B9A = { DevelopmentTeam = L74NQAQB8H; + LastSwiftMigration = 1120; ProvisioningStyle = Automatic; SystemCapabilities = { com.apple.Push = { @@ -1411,635 +435,14 @@ mainGroup = 83CBB9F61A601CBA00E9B192; productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; projectDirPath = ""; - projectReferences = ( - { - ProductGroup = 24979D4220F83E3E007EB0DA /* Products */; - ProjectRef = 8AC83A50CE8F4EE782376063 /* BVLinearGradient.xcodeproj */; - }, - { - ProductGroup = 2C867625211152550067D47A /* Products */; - ProjectRef = 4A9E14039D3A4590A2F32D92 /* CodePush.xcodeproj */; - }, - { - ProductGroup = 3C39C267218BBE66004C763F /* Products */; - ProjectRef = 3C39C266218BBE66004C763F /* FastImage.xcodeproj */; - }, - { - ProductGroup = 00C302A81ABCB8CE00DB3ED1 /* Products */; - ProjectRef = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */; - }, - { - ProductGroup = 5E91572E1DD0AC6500FF2AA8 /* Products */; - ProjectRef = 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */; - }, - { - ProductGroup = ADBDB9201DFEBF0600ED6528 /* Products */; - ProjectRef = ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */; - }, - { - ProductGroup = 00C302B61ABCB90400DB3ED1 /* Products */; - ProjectRef = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */; - }, - { - ProductGroup = 00C302BC1ABCB91800DB3ED1 /* Products */; - ProjectRef = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */; - }, - { - ProductGroup = 78C398B11ACF4ADC00677621 /* Products */; - ProjectRef = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */; - }, - { - ProductGroup = 00C302D41ABCB9D200DB3ED1 /* Products */; - ProjectRef = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */; - }, - { - ProductGroup = 139105B71AF99BAD00B5F7CC /* Products */; - ProjectRef = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */; - }, - { - ProductGroup = 832341B11AAA6A8300B99B32 /* Products */; - ProjectRef = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */; - }, - { - ProductGroup = 00C302E01ABCB9EE00DB3ED1 /* Products */; - ProjectRef = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */; - }, - { - ProductGroup = 139FDEE71B06529A00C62182 /* Products */; - ProjectRef = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */; - }, - { - ProductGroup = 146834001AC3E56700842450 /* Products */; - ProjectRef = 146833FF1AC3E56700842450 /* React.xcodeproj */; - }, - { - ProductGroup = 24979D4A20F83E3E007EB0DA /* Products */; - ProjectRef = 02CF70769C034001B5CBC1EF /* ReactNativePermissions.xcodeproj */; - }, - { - ProductGroup = 249E5FA822613ABC0095F6B7 /* Products */; - ProjectRef = 249E5FA722613ABC0095F6B7 /* RNCAsyncStorage.xcodeproj */; - }, - { - ProductGroup = 2481F31D2261753900D0349A /* Products */; - ProjectRef = C779B11FB4664662AD0EBEA6 /* RNFirebase.xcodeproj */; - }, - { - ProductGroup = 24979D3E20F83E3E007EB0DA /* Products */; - ProjectRef = AEED489341644A6888669239 /* RNFIRMessaging.xcodeproj */; - }, - { - ProductGroup = 24D171DE212F57100090F180 /* Products */; - ProjectRef = 171CDF49E32841EDA7D557DB /* RNGestureHandler.xcodeproj */; - }, - { - ProductGroup = 24979D4020F83E3E007EB0DA /* Products */; - ProjectRef = 50B1B80F51614673AFD8A804 /* RNKeychain.xcodeproj */; - }, - { - ProductGroup = 24979D4420F83E3E007EB0DA /* Products */; - ProjectRef = BC297F456F414298BFBB0C30 /* RNMail.xcodeproj */; - }, - { - ProductGroup = 24979D4820F83E3E007EB0DA /* Products */; - ProjectRef = BEE6BF249EAB410AB20BBB98 /* RNOS.xcodeproj */; - }, - { - ProductGroup = 24979D4E20F83E3E007EB0DA /* Products */; - ProjectRef = 28B88B43D75F4B529A711317 /* RNRandomBytes.xcodeproj */; - }, - { - ProductGroup = 244C64062108794F007A5856 /* Products */; - ProjectRef = 1A7B7E90124047F8A3CA4B84 /* RNReactNativeHapticFeedback.xcodeproj */; - }, - { - ProductGroup = 2488BC2922E97315006847C7 /* Products */; - ProjectRef = 3182AEA93A7847CCB729F641 /* RNStoreReview.xcodeproj */; - }, - { - ProductGroup = 24979D5420F83E3E007EB0DA /* Products */; - ProjectRef = 3A545B8C781B47AC8A7CD956 /* RNSVG.xcodeproj */; - }, - { - ProductGroup = 24979D5020F83E3E007EB0DA /* Products */; - ProjectRef = 2DB932A7706945C787DE22A6 /* SplashScreen.xcodeproj */; - }, - { - ProductGroup = 24979D4C20F83E3E007EB0DA /* Products */; - ProjectRef = 137BEEE47D2E4F7AB452C0BD /* SRSRadialGradient.xcodeproj */; - }, - { - ProductGroup = 24979D3820F83E3E007EB0DA /* Products */; - ProjectRef = 35B7B17127FD476C81EA97E3 /* TcpSockets.xcodeproj */; - }, - { - ProductGroup = 24979D5620F83E3E007EB0DA /* Products */; - ProjectRef = 22B35A6AE60F41D093A35939 /* ToolTipMenu.xcodeproj */; - }, - { - ProductGroup = 24979D3A20F83E3E007EB0DA /* Products */; - ProjectRef = 969D4F061E6A446F9EEE2F02 /* TouchID.xcodeproj */; - }, - { - ProductGroup = 24979D5820F83E3E007EB0DA /* Products */; - ProjectRef = 46EFC4C16BAF4873BE45393E /* UdpSockets.xcodeproj */; - }, - ); projectRoot = ""; targets = ( 13B07F861A680F5B00A75B9A /* Rainbow */, - 00E356ED1AD99517003FC87E /* RainbowTests */, ); }; /* End PBXProject section */ -/* Begin PBXReferenceProxy section */ - 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRCTActionSheet.a; - remoteRef = 00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRCTGeolocation.a; - remoteRef = 00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRCTImage.a; - remoteRef = 00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRCTNetwork.a; - remoteRef = 00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRCTVibration.a; - remoteRef = 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRCTSettings.a; - remoteRef = 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRCTWebSocket.a; - remoteRef = 139FDEF31B06529B00C62182 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 146834041AC3E56700842450 /* libReact.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libReact.a; - remoteRef = 146834031AC3E56700842450 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 243A893E225F092800A13C7E /* libRNGestureHandler-tvOS.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = "libRNGestureHandler-tvOS.a"; - remoteRef = 243A893D225F092800A13C7E /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 244C640A2108794F007A5856 /* libRNReactNativeHapticFeedback.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRNReactNativeHapticFeedback.a; - remoteRef = 244C64092108794F007A5856 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 247947BB22568EAA006BBF56 /* libjsi.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libjsi.a; - remoteRef = 247947BA22568EAA006BBF56 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 247947BD22568EAA006BBF56 /* libjsiexecutor.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libjsiexecutor.a; - remoteRef = 247947BC22568EAA006BBF56 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 247947BF22568EAA006BBF56 /* libjsi-tvOS.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = "libjsi-tvOS.a"; - remoteRef = 247947BE22568EAA006BBF56 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 247947C122568EAA006BBF56 /* libjsiexecutor-tvOS.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = "libjsiexecutor-tvOS.a"; - remoteRef = 247947C022568EAA006BBF56 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 2481F3212261753900D0349A /* libRNFirebase.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRNFirebase.a; - remoteRef = 2481F3202261753900D0349A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 2488BC2D22E97316006847C7 /* libRNStoreReview.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRNStoreReview.a; - remoteRef = 2488BC2C22E97316006847C7 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 24979D5D20F83E3E007EB0DA /* libBVLinearGradient.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libBVLinearGradient.a; - remoteRef = 24979D5C20F83E3E007EB0DA /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 24979D5F20F83E3E007EB0DA /* libBVLinearGradient.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libBVLinearGradient.a; - remoteRef = 24979D5E20F83E3E007EB0DA /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 24979D6820F83E3E007EB0DA /* libReactNativePermissions.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libReactNativePermissions.a; - remoteRef = 24979D6720F83E3E007EB0DA /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 24979D6E20F83E3E007EB0DA /* libRNFIRMessaging.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRNFIRMessaging.a; - remoteRef = 24979D6D20F83E3E007EB0DA /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 24979D7220F83E3E007EB0DA /* libRNKeychain.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRNKeychain.a; - remoteRef = 24979D7120F83E3E007EB0DA /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 24979D7420F83E3E007EB0DA /* libRNKeychain.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRNKeychain.a; - remoteRef = 24979D7320F83E3E007EB0DA /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 24979D7820F83E3E007EB0DA /* libRNMail.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRNMail.a; - remoteRef = 24979D7720F83E3E007EB0DA /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 24979D7A20F83E3E007EB0DA /* RNMailTests.xctest */ = { - isa = PBXReferenceProxy; - fileType = wrapper.cfbundle; - path = RNMailTests.xctest; - remoteRef = 24979D7920F83E3E007EB0DA /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 24979D7D20F83E3E007EB0DA /* libRNOS.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRNOS.a; - remoteRef = 24979D7C20F83E3E007EB0DA /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 24979D8120F83E3E007EB0DA /* libRNRandomBytes.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRNRandomBytes.a; - remoteRef = 24979D8020F83E3E007EB0DA /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 24979D8320F83E3E007EB0DA /* libRNRandomBytes-tvOS.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = "libRNRandomBytes-tvOS.a"; - remoteRef = 24979D8220F83E3E007EB0DA /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 24979D8A20F83E3E007EB0DA /* libRNSVG.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRNSVG.a; - remoteRef = 24979D8920F83E3E007EB0DA /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 24979D8C20F83E3E007EB0DA /* libRNSVG-tvOS.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = "libRNSVG-tvOS.a"; - remoteRef = 24979D8B20F83E3E007EB0DA /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 24979D8F20F83E3E007EB0DA /* libSplashScreen.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libSplashScreen.a; - remoteRef = 24979D8E20F83E3E007EB0DA /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 24979D9220F83E3E007EB0DA /* libSRSRadialGradient.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libSRSRadialGradient.a; - remoteRef = 24979D9120F83E3E007EB0DA /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 24979D9520F83E3E007EB0DA /* libTcpSockets.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libTcpSockets.a; - remoteRef = 24979D9420F83E3E007EB0DA /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 24979D9920F83E3E007EB0DA /* libToolTipMenu.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libToolTipMenu.a; - remoteRef = 24979D9820F83E3E007EB0DA /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 24979D9B20F83E3E007EB0DA /* ToolTipMenuTests.xctest */ = { - isa = PBXReferenceProxy; - fileType = wrapper.cfbundle; - path = ToolTipMenuTests.xctest; - remoteRef = 24979D9A20F83E3E007EB0DA /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 24979D9E20F83E3E007EB0DA /* libTouchID.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libTouchID.a; - remoteRef = 24979D9D20F83E3E007EB0DA /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 24979DA120F83E3E007EB0DA /* libUdpSockets.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libUdpSockets.a; - remoteRef = 24979DA020F83E3E007EB0DA /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 249E5FD922613ABC0095F6B7 /* libRNCAsyncStorage.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRNCAsyncStorage.a; - remoteRef = 249E5FD822613ABC0095F6B7 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 24D171E2212F57110090F180 /* libRNGestureHandler.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRNGestureHandler.a; - remoteRef = 24D171E1212F57110090F180 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 2C86762A211152560067D47A /* libCodePush.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libCodePush.a; - remoteRef = 2C867629211152560067D47A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 2C86762C211152560067D47A /* libCodePush.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libCodePush.a; - remoteRef = 2C86762B211152560067D47A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 2D16E6721FA4F8DC00B85C8A /* libRCTBlob-tvOS.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = "libRCTBlob-tvOS.a"; - remoteRef = 2D16E6711FA4F8DC00B85C8A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 2D16E6841FA4F8DC00B85C8A /* libfishhook.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libfishhook.a; - remoteRef = 2D16E6831FA4F8DC00B85C8A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 2D16E6861FA4F8DC00B85C8A /* libfishhook-tvOS.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = "libfishhook-tvOS.a"; - remoteRef = 2D16E6851FA4F8DC00B85C8A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 2DF0FFDF2056DD460020B375 /* libjsinspector.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libjsinspector.a; - remoteRef = 2DF0FFDE2056DD460020B375 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 2DF0FFE12056DD460020B375 /* libjsinspector-tvOS.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = "libjsinspector-tvOS.a"; - remoteRef = 2DF0FFE02056DD460020B375 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 2DF0FFE32056DD460020B375 /* libthird-party.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = "libthird-party.a"; - remoteRef = 2DF0FFE22056DD460020B375 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 2DF0FFE52056DD460020B375 /* libthird-party.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = "libthird-party.a"; - remoteRef = 2DF0FFE42056DD460020B375 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 2DF0FFE72056DD460020B375 /* libdouble-conversion.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = "libdouble-conversion.a"; - remoteRef = 2DF0FFE62056DD460020B375 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 2DF0FFE92056DD460020B375 /* libdouble-conversion.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = "libdouble-conversion.a"; - remoteRef = 2DF0FFE82056DD460020B375 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 3C39C270218BBE66004C763F /* libFastImage.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libFastImage.a; - remoteRef = 3C39C26F218BBE66004C763F /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 3C48F38322CD0CDE00368A91 /* libFastImage-tvOS.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = "libFastImage-tvOS.a"; - remoteRef = 3C48F38222CD0CDE00368A91 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 3CD4E8CD216989E8000FA5BD /* libSRSRadialGradien-tvOS.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = "libSRSRadialGradien-tvOS.a"; - remoteRef = 3CD4E8CC216989E8000FA5BD /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 3DAD3E841DF850E9000B6D8A /* libRCTImage-tvOS.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = "libRCTImage-tvOS.a"; - remoteRef = 3DAD3E831DF850E9000B6D8A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 3DAD3E881DF850E9000B6D8A /* libRCTLinking-tvOS.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = "libRCTLinking-tvOS.a"; - remoteRef = 3DAD3E871DF850E9000B6D8A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 3DAD3E8C1DF850E9000B6D8A /* libRCTNetwork-tvOS.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = "libRCTNetwork-tvOS.a"; - remoteRef = 3DAD3E8B1DF850E9000B6D8A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 3DAD3E901DF850E9000B6D8A /* libRCTSettings-tvOS.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = "libRCTSettings-tvOS.a"; - remoteRef = 3DAD3E8F1DF850E9000B6D8A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 3DAD3E941DF850E9000B6D8A /* libRCTText-tvOS.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = "libRCTText-tvOS.a"; - remoteRef = 3DAD3E931DF850E9000B6D8A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 3DAD3E991DF850E9000B6D8A /* libRCTWebSocket-tvOS.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = "libRCTWebSocket-tvOS.a"; - remoteRef = 3DAD3E981DF850E9000B6D8A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 3DAD3EA31DF850E9000B6D8A /* libReact.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libReact.a; - remoteRef = 3DAD3EA21DF850E9000B6D8A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 3DAD3EA51DF850E9000B6D8A /* libyoga.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libyoga.a; - remoteRef = 3DAD3EA41DF850E9000B6D8A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 3DAD3EA71DF850E9000B6D8A /* libyoga.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libyoga.a; - remoteRef = 3DAD3EA61DF850E9000B6D8A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 3DAD3EA91DF850E9000B6D8A /* libcxxreact.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libcxxreact.a; - remoteRef = 3DAD3EA81DF850E9000B6D8A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 3DAD3EAB1DF850E9000B6D8A /* libcxxreact.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libcxxreact.a; - remoteRef = 3DAD3EAA1DF850E9000B6D8A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRCTAnimation.a; - remoteRef = 5E9157321DD0AC6500FF2AA8 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRCTAnimation.a; - remoteRef = 5E9157341DD0AC6500FF2AA8 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 78C398B91ACF4ADC00677621 /* libRCTLinking.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRCTLinking.a; - remoteRef = 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 832341B51AAA6A8300B99B32 /* libRCTText.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRCTText.a; - remoteRef = 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - ADBDB9271DFEBF0700ED6528 /* libRCTBlob.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRCTBlob.a; - remoteRef = ADBDB9261DFEBF0700ED6528 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; -/* End PBXReferenceProxy section */ - /* Begin PBXResourcesBuildPhase section */ - 00E356EC1AD99517003FC87E /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; 13B07F8E1A680F5B00A75B9A /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -2119,7 +522,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "export NODE_ARGS=--max-old-space-size=2048\n../node_modules/react-native/scripts/react-native-xcode.sh\n"; + shellScript = "export SENTRY_PROPERTIES=sentry.properties\nexport NODE_ARGS=--max-old-space-size=2048\n../node_modules/@sentry/cli/bin/sentry-cli react-native xcode ../node_modules/react-native/scripts/react-native-xcode.sh\n"; }; 3CF823D3218F310D0024B77B /* ShellScript */ = { isa = PBXShellScriptBuildPhase; @@ -2135,7 +538,27 @@ shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Fabric/run\"\n"; }; - 862FF20A142EFD912DF7FAA5 /* [CP] Check Pods Manifest.lock */ = { + 7D8EDE895DE18700A743F64E /* [CP-User] [RNFB] Core Configuration */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + name = "[CP-User] [RNFB] Core Configuration"; + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "#!/usr/bin/env bash\n#\n# Copyright (c) 2016-present Invertase Limited & Contributors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this library except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\nset -e\n\n_MAX_LOOKUPS=2;\n_SEARCH_RESULT=''\n_RN_ROOT_EXISTS=''\n_CURRENT_LOOKUPS=1\n_JSON_ROOT=\"'react-native'\"\n_JSON_FILE_NAME='firebase.json'\n_JSON_OUTPUT_BASE64='e30=' # { }\n_CURRENT_SEARCH_DIR=${PROJECT_DIR}\n_PLIST_BUDDY=/usr/libexec/PlistBuddy\n_TARGET_PLIST=\"${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}\"\n_DSYM_PLIST=\"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Info.plist\"\n\n# plist arrays\n_PLIST_ENTRY_KEYS=()\n_PLIST_ENTRY_TYPES=()\n_PLIST_ENTRY_VALUES=()\n\nfunction setPlistValue {\n echo \"info: setting plist entry '$1' of type '$2' in file '$4'\"\n ${_PLIST_BUDDY} -c \"Add :$1 $2 '$3'\" $4 || echo \"info: '$1' already exists\"\n}\n\nfunction getFirebaseJsonKeyValue () {\n if [[ ${_RN_ROOT_EXISTS} ]]; then\n ruby -e \"require 'rubygems';require 'json'; output=JSON.parse('$1'); puts output[$_JSON_ROOT]['$2']\"\n else\n echo \"\"\n fi;\n}\n\nfunction jsonBoolToYesNo () {\n if [[ $1 == \"false\" ]]; then\n echo \"NO\"\n elif [[ $1 == \"true\" ]]; then\n echo \"YES\"\n else echo \"NO\"\n fi\n}\n\necho \"info: -> RNFB build script started\"\necho \"info: 1) Locating ${_JSON_FILE_NAME} file:\"\n\nif [[ -z ${_CURRENT_SEARCH_DIR} ]]; then\n _CURRENT_SEARCH_DIR=$(pwd)\nfi;\n\nwhile true; do\n _CURRENT_SEARCH_DIR=$(dirname \"$_CURRENT_SEARCH_DIR\")\n if [[ \"$_CURRENT_SEARCH_DIR\" == \"/\" ]] || [[ ${_CURRENT_LOOKUPS} -gt ${_MAX_LOOKUPS} ]]; then break; fi;\n echo \"info: ($_CURRENT_LOOKUPS of $_MAX_LOOKUPS) Searching in '$_CURRENT_SEARCH_DIR' for a ${_JSON_FILE_NAME} file.\"\n _SEARCH_RESULT=$(find \"$_CURRENT_SEARCH_DIR\" -maxdepth 2 -name ${_JSON_FILE_NAME} -print | head -n 1)\n if [[ ${_SEARCH_RESULT} ]]; then\n echo \"info: ${_JSON_FILE_NAME} found at $_SEARCH_RESULT\"\n break;\n fi;\n _CURRENT_LOOKUPS=$((_CURRENT_LOOKUPS+1))\ndone\n\nif [[ ${_SEARCH_RESULT} ]]; then\n _JSON_OUTPUT_RAW=$(cat \"${_SEARCH_RESULT}\")\n _RN_ROOT_EXISTS=$(ruby -e \"require 'rubygems';require 'json'; output=JSON.parse('$_JSON_OUTPUT_RAW'); puts output[$_JSON_ROOT]\" || echo '')\n\n if [[ ${_RN_ROOT_EXISTS} ]]; then\n _JSON_OUTPUT_BASE64=$(python -c 'import json,sys,base64;print(base64.b64encode(json.dumps(json.loads(open('\"'${_SEARCH_RESULT}'\"').read())['${_JSON_ROOT}'])))' || echo \"e30=\")\n fi\n\n _PLIST_ENTRY_KEYS+=(\"firebase_json_raw\")\n _PLIST_ENTRY_TYPES+=(\"string\")\n _PLIST_ENTRY_VALUES+=(\"$_JSON_OUTPUT_BASE64\")\n\n # config.messaging_auto_init_enabled\n _MESSAGING_AUTO_INIT=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"messaging_auto_init_enabled\")\n if [[ $_MESSAGING_AUTO_INIT ]]; then\n _PLIST_ENTRY_KEYS+=(\"FirebaseMessagingAutoInitEnabled\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_MESSAGING_AUTO_INIT\")\")\n fi\n\n # config.crashlytics_disable_auto_disabler - undocumented for now - mainly for debugging, document if becomes usful\n _CRASHLYTICS_AUTO_DISABLE_ENABLED=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"crashlytics_disable_auto_disabler\")\n if [[ $_CRASHLYTICS_AUTO_DISABLE_ENABLED == \"true\" ]]; then\n echo \"Disabled Crashlytics auto disabler.\" # do nothing\n else\n _PLIST_ENTRY_KEYS+=(\"firebase_crashlytics_collection_enabled\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"NO\")\n fi\n\n # config.admob_delay_app_measurement_init\n _ADMOB_DELAY_APP_MEASUREMENT=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"admob_delay_app_measurement_init\")\n if [[ $_ADMOB_DELAY_APP_MEASUREMENT == \"true\" ]]; then\n _PLIST_ENTRY_KEYS+=(\"GADDelayAppMeasurementInit\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"YES\")\n fi\n\n # config.admob_ios_app_id\n _ADMOB_IOS_APP_ID=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"admob_ios_app_id\")\n if [[ $_ADMOB_IOS_APP_ID ]]; then\n _PLIST_ENTRY_KEYS+=(\"GADApplicationIdentifier\")\n _PLIST_ENTRY_TYPES+=(\"string\")\n _PLIST_ENTRY_VALUES+=(\"$_ADMOB_IOS_APP_ID\")\n fi\nelse\n _PLIST_ENTRY_KEYS+=(\"firebase_json_raw\")\n _PLIST_ENTRY_TYPES+=(\"string\")\n _PLIST_ENTRY_VALUES+=(\"$_JSON_OUTPUT_BASE64\")\n echo \"warning: A firebase.json file was not found, whilst this file is optional it is recommended to include it to configure firebase services in React Native Firebase.\"\nfi;\n\necho \"info: 2) Injecting Info.plist entries: \"\n\n# Log out the keys we're adding\nfor i in \"${!_PLIST_ENTRY_KEYS[@]}\"; do\n echo \" -> $i) ${_PLIST_ENTRY_KEYS[$i]}\" \"${_PLIST_ENTRY_TYPES[$i]}\" \"${_PLIST_ENTRY_VALUES[$i]}\"\ndone\n\nfor plist in ${_TARGET_PLIST} ${_DSYM_PLIST} ; do\n if [[ -f ${plist} ]]; then\n for i in \"${!_PLIST_ENTRY_KEYS[@]}\"; do\n setPlistValue \"${_PLIST_ENTRY_KEYS[$i]}\" \"${_PLIST_ENTRY_TYPES[$i]}\" \"${_PLIST_ENTRY_VALUES[$i]}\" \"${plist}\"\n done\n else\n echo \"warning: A Info.plist build output file was not found (${plist})\"\n fi\ndone\n\necho \"info: <- RNFB build script finished\"\n\n\n\n"; + }; + 8C1D9934C43085FED5C8B69C /* [CP-User] [RNFB] Crashlytics Configuration */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + name = "[CP-User] [RNFB] Crashlytics Configuration"; + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "#!/usr/bin/env bash\n#\n# Copyright (c) 2016-present Invertase Limited & Contributors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this library except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\nset -e\n\nif [[ ${PODS_ROOT} ]]; then\n echo \"info: Exec Fabric Run from Pods\"\n \"${PODS_ROOT}/Fabric/run\"\nelse\n echo \"info: Exec Fabric Run from framework\"\n \"${PROJECT_DIR}/Fabric.framework/run\"\nfi\n"; + }; + B448B1B66A188D3AC6DA3639 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -2160,33 +583,18 @@ /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 00E356EA1AD99517003FC87E /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 00E356F31AD99517003FC87E /* RainbowTests.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 13B07F871A680F5B00A75B9A /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */, + 3CBE29CD2381E43900BE05AC /* Dummy.swift in Sources */, 13B07FC11A68108700A75B9A /* main.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ -/* Begin PBXTargetDependency section */ - 00E356F51AD99517003FC87E /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 13B07F861A680F5B00A75B9A /* Rainbow */; - targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - /* Begin PBXVariantGroup section */ 13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = { isa = PBXVariantGroup; @@ -2200,148 +608,47 @@ /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ - 00E356F61AD99517003FC87E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = L74NQAQB8H; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "$(SRCROOT)/../node_modules/react-native-fcm/ios", - "$(SRCROOT)/../node_modules/react-native-keychain/RNKeychainManager", - "$(SRCROOT)/../node_modules/react-native-linear-gradient/BVLinearGradient", - "$(SRCROOT)/../node_modules/react-native-mail/RNMail", - "$(SRCROOT)/../node_modules/react-native-os/ios", - "$(SRCROOT)/../node_modules/react-native-permissions/ios/**", - "$(SRCROOT)/../node_modules/react-native-radial-gradient/ios", - "$(SRCROOT)/../node_modules/react-native-randombytes", - "$(SRCROOT)/../node_modules/react-native-splash-screen/ios", - "$(SRCROOT)/../node_modules/react-native-svg/ios/**", - "$(SRCROOT)/../node_modules/react-native-tcp/ios/**", - "$(SRCROOT)/../node_modules/react-native-tooltip/ToolTipMenu", - "$(SRCROOT)/../node_modules/react-native-touch-id", - "$(SRCROOT)/../node_modules/react-native-udp/ios/**", - "$(SRCROOT)/../node_modules/react-native-haptic-feedback/ios", - "$(SRCROOT)/../node_modules/react-native-gesture-handler/ios/**", - "$(SRCROOT)/../node_modules/react-native-code-push/ios/CodePush/**", - "$(SRCROOT)/../node_modules/@ledgerhq/react-native-passcode-auth", - "$(SRCROOT)/../node_modules/react-native-firebase/ios/RNFirebase/**", - "$(SRCROOT)/../node_modules/react-native-store-review/ios", - ); - INFOPLIST_FILE = RainbowTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/$(TARGET_NAME)\"", - "\"$(SRCROOT)/$(TARGET_NAME)\"", - ); - OTHER_LDFLAGS = ( - "-ObjC", - "-lc++", - ); - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Rainbow.app/Rainbow"; - }; - name = Debug; - }; - 00E356F71AD99517003FC87E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Automatic; - COPY_PHASE_STRIP = NO; - DEVELOPMENT_TEAM = L74NQAQB8H; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "$(SRCROOT)/../node_modules/react-native-fcm/ios", - "$(SRCROOT)/../node_modules/react-native-keychain/RNKeychainManager", - "$(SRCROOT)/../node_modules/react-native-linear-gradient/BVLinearGradient", - "$(SRCROOT)/../node_modules/react-native-mail/RNMail", - "$(SRCROOT)/../node_modules/react-native-os/ios", - "$(SRCROOT)/../node_modules/react-native-permissions/ios/**", - "$(SRCROOT)/../node_modules/react-native-radial-gradient/ios", - "$(SRCROOT)/../node_modules/react-native-randombytes", - "$(SRCROOT)/../node_modules/react-native-splash-screen/ios", - "$(SRCROOT)/../node_modules/react-native-svg/ios/**", - "$(SRCROOT)/../node_modules/react-native-tcp/ios/**", - "$(SRCROOT)/../node_modules/react-native-tooltip/ToolTipMenu", - "$(SRCROOT)/../node_modules/react-native-touch-id", - "$(SRCROOT)/../node_modules/react-native-udp/ios/**", - "$(SRCROOT)/../node_modules/react-native-haptic-feedback/ios", - "$(SRCROOT)/../node_modules/react-native-gesture-handler/ios/**", - "$(SRCROOT)/../node_modules/react-native-code-push/ios/CodePush/**", - "$(SRCROOT)/../node_modules/@ledgerhq/react-native-passcode-auth", - "$(SRCROOT)/../node_modules/react-native-firebase/ios/RNFirebase/**", - "$(SRCROOT)/../node_modules/react-native-store-review/ios", - ); - INFOPLIST_FILE = RainbowTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/$(TARGET_NAME)\"", - "\"$(SRCROOT)/$(TARGET_NAME)\"", - ); - OTHER_LDFLAGS = ( - "-ObjC", - "-lc++", - ); - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Rainbow.app/Rainbow"; - }; - name = Release; - }; 13B07F941A680F5B00A75B9A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 06E14A994B1D3A2E1CCBA545 /* Pods-Rainbow.debug.xcconfig */; + baseConfigurationReference = 66C5D39A1EDC48A6255FF83C /* Pods-Rainbow.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_OPTIMIZATION = time; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Rainbow/Rainbow.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + COPY_PHASE_STRIP = YES; + CURRENT_PROJECT_VERSION = 4; DEAD_CODE_STRIPPING = NO; - DEVELOPMENT_TEAM = L74NQAQB8H; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = ""; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Frameworks", ); + GCC_PRECOMPILE_PREFIX_HEADER = NO; + GCC_UNROLL_LOOPS = NO; HEADER_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Frameworks", - "$(SRCROOT)/../node_modules/react-native-keychain/RNKeychainManager", - "$(SRCROOT)/../node_modules/react-native-linear-gradient/BVLinearGradient", - "$(SRCROOT)/../node_modules/react-native-mail/RNMail", - "$(SRCROOT)/../node_modules/react-native-os/ios", - "$(SRCROOT)/../node_modules/react-native-permissions/ios/**", - "$(SRCROOT)/../node_modules/react-native-radial-gradient/ios", - "$(SRCROOT)/../node_modules/react-native-randombytes", - "$(SRCROOT)/../node_modules/react-native-splash-screen/ios", - "$(SRCROOT)/../node_modules/react-native-svg/ios/**", - "$(SRCROOT)/../node_modules/react-native-tcp/ios/**", "$(SRCROOT)/../node_modules/react-native-tooltip/ToolTipMenu", - "$(SRCROOT)/../node_modules/react-native-touch-id", - "$(SRCROOT)/../node_modules/react-native-udp/ios/**", - "$(SRCROOT)/../node_modules/react-native-haptic-feedback/ios", - "$(SRCROOT)/../node_modules/react-native-gesture-handler/ios/**", "$(SRCROOT)/../node_modules/react-native-code-push/ios/**", "$(SRCROOT)/../node_modules/@ledgerhq/react-native-passcode-auth", "$(SRCROOT)/../node_modules/react-native-firebase/ios/RNFirebase/**", "$(SRCROOT)/../node_modules/react-native/Libraries/LinkingIOS/**", - "$(SRCROOT)/../node_modules/react-native-store-review/ios", + "$(SRCROOT)/../node_modules/react-native-text-input-mask/ios/**", ); INFOPLIST_FILE = Rainbow/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "\"$(SRCROOT)/Rainbow\"", + ); + LLVM_LTO = YES; + MARKETING_VERSION = 1.2.2; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", @@ -2351,51 +658,53 @@ PRODUCT_NAME = Rainbow; PROVISIONING_PROFILE = ""; PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "Rainbow-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; }; name = Debug; }; 13B07F951A680F5B00A75B9A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 50750D914B8810145768DC57 /* Pods-Rainbow.release.xcconfig */; + baseConfigurationReference = A671DF9861FA8D2C9A6FCB91 /* Pods-Rainbow.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_OPTIMIZATION = ""; + CLANG_ENABLE_MODULES = YES; CODEPUSH_KEY = "CHq9hB40PBZqHTxL-f-Wd_rK4anl1e7a8912-936f-4ce7-8505-32a075039f51"; CODE_SIGN_ENTITLEMENTS = Rainbow/Rainbow.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = L74NQAQB8H; + CURRENT_PROJECT_VERSION = 4; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = ""; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Frameworks", ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_UNROLL_LOOPS = YES; HEADER_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Frameworks", - "$(SRCROOT)/../node_modules/react-native-keychain/RNKeychainManager", - "$(SRCROOT)/../node_modules/react-native-linear-gradient/BVLinearGradient", - "$(SRCROOT)/../node_modules/react-native-mail/RNMail", - "$(SRCROOT)/../node_modules/react-native-os/ios", - "$(SRCROOT)/../node_modules/react-native-permissions/ios/**", - "$(SRCROOT)/../node_modules/react-native-radial-gradient/ios", - "$(SRCROOT)/../node_modules/react-native-randombytes", - "$(SRCROOT)/../node_modules/react-native-splash-screen/ios", - "$(SRCROOT)/../node_modules/react-native-svg/ios/**", - "$(SRCROOT)/../node_modules/react-native-tcp/ios/**", "$(SRCROOT)/../node_modules/react-native-tooltip/ToolTipMenu", - "$(SRCROOT)/../node_modules/react-native-touch-id", - "$(SRCROOT)/../node_modules/react-native-udp/ios/**", - "$(SRCROOT)/../node_modules/react-native-haptic-feedback/ios", - "$(SRCROOT)/../node_modules/react-native-gesture-handler/ios/**", "$(SRCROOT)/../node_modules/react-native-code-push/ios/**", "$(SRCROOT)/../node_modules/@ledgerhq/react-native-passcode-auth", "$(SRCROOT)/../node_modules/react-native-firebase/ios/RNFirebase/**", "$(SRCROOT)/../node_modules/react-native/Libraries/LinkingIOS/**", - "$(SRCROOT)/../node_modules/react-native-store-review/ios", + "$(SRCROOT)/../node_modules/react-native-text-input-mask/ios/**", ); INFOPLIST_FILE = Rainbow/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "\"$(SRCROOT)/Rainbow\"", + ); + LLVM_LTO = YES; + MARKETING_VERSION = 1.2.2; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", @@ -2405,6 +714,8 @@ PRODUCT_NAME = Rainbow; PROVISIONING_PROFILE = ""; PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "Rainbow-Bridging-Header.h"; + SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; }; name = Release; @@ -2448,43 +759,43 @@ }; 2C6A799821127ED9003AFB37 /* Staging */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 0EBA050ADF8AD8CB6B14A162 /* Pods-Rainbow.staging.xcconfig */; + baseConfigurationReference = E93A96605FE51CFC31676801 /* Pods-Rainbow.staging.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_OPTIMIZATION = ""; + CLANG_ENABLE_MODULES = YES; CODEPUSH_KEY = "Xf8eimmB0-W22TRNCwL9tZNO9xev1e7a8912-936f-4ce7-8505-32a075039f51"; CODE_SIGN_ENTITLEMENTS = Rainbow/Rainbow.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = L74NQAQB8H; + CURRENT_PROJECT_VERSION = 4; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = ""; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Frameworks", ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_UNROLL_LOOPS = YES; HEADER_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Frameworks", - "$(SRCROOT)/../node_modules/react-native-keychain/RNKeychainManager", - "$(SRCROOT)/../node_modules/react-native-linear-gradient/BVLinearGradient", - "$(SRCROOT)/../node_modules/react-native-mail/RNMail", - "$(SRCROOT)/../node_modules/react-native-os/ios", - "$(SRCROOT)/../node_modules/react-native-permissions/ios/**", - "$(SRCROOT)/../node_modules/react-native-radial-gradient/ios", - "$(SRCROOT)/../node_modules/react-native-randombytes", - "$(SRCROOT)/../node_modules/react-native-splash-screen/ios", - "$(SRCROOT)/../node_modules/react-native-svg/ios/**", - "$(SRCROOT)/../node_modules/react-native-tcp/ios/**", "$(SRCROOT)/../node_modules/react-native-tooltip/ToolTipMenu", - "$(SRCROOT)/../node_modules/react-native-touch-id", - "$(SRCROOT)/../node_modules/react-native-udp/ios/**", - "$(SRCROOT)/../node_modules/react-native-haptic-feedback/ios", "$(SRCROOT)/../node_modules/react-native-code-push/ios/**", "$(SRCROOT)/../node_modules/@ledgerhq/react-native-passcode-auth", "$(SRCROOT)/../node_modules/react-native-firebase/ios/RNFirebase/**", - "$(SRCROOT)/../node_modules/react-native-store-review/ios", + "$(SRCROOT)/../node_modules/react-native-text-input-mask/ios/**", ); INFOPLIST_FILE = Rainbow/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "\"$(SRCROOT)/Rainbow\"", + ); + LLVM_LTO = YES; + MARKETING_VERSION = 1.2.2; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", @@ -2494,58 +805,12 @@ PRODUCT_NAME = Rainbow; PROVISIONING_PROFILE = ""; PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "Rainbow-Bridging-Header.h"; + SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; }; name = Staging; }; - 2C6A799921127ED9003AFB37 /* Staging */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Automatic; - COPY_PHASE_STRIP = NO; - DEVELOPMENT_TEAM = L74NQAQB8H; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "$(SRCROOT)/../node_modules/react-native-fcm/ios", - "$(SRCROOT)/../node_modules/react-native-keychain/RNKeychainManager", - "$(SRCROOT)/../node_modules/react-native-linear-gradient/BVLinearGradient", - "$(SRCROOT)/../node_modules/react-native-mail/RNMail", - "$(SRCROOT)/../node_modules/react-native-os/ios", - "$(SRCROOT)/../node_modules/react-native-permissions/ios/**", - "$(SRCROOT)/../node_modules/react-native-radial-gradient/ios", - "$(SRCROOT)/../node_modules/react-native-randombytes", - "$(SRCROOT)/../node_modules/react-native-splash-screen/ios", - "$(SRCROOT)/../node_modules/react-native-svg/ios/**", - "$(SRCROOT)/../node_modules/react-native-tcp/ios/**", - "$(SRCROOT)/../node_modules/react-native-tooltip/ToolTipMenu", - "$(SRCROOT)/../node_modules/react-native-touch-id", - "$(SRCROOT)/../node_modules/react-native-udp/ios/**", - "$(SRCROOT)/../node_modules/react-native-haptic-feedback/ios", - "$(SRCROOT)/../node_modules/react-native-code-push/ios/CodePush/**", - "$(SRCROOT)/../node_modules/@ledgerhq/react-native-passcode-auth", - "$(SRCROOT)/../node_modules/react-native-firebase/ios/RNFirebase/**", - "$(SRCROOT)/../node_modules/react-native-store-review/ios", - ); - INFOPLIST_FILE = RainbowTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/$(TARGET_NAME)\"", - "\"$(SRCROOT)/$(TARGET_NAME)\"", - ); - OTHER_LDFLAGS = ( - "-ObjC", - "-lc++", - ); - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Rainbow.app/Rainbow"; - }; - name = Staging; - }; 2C87B7992197FA1900682EC4 /* LocalRelease */ = { isa = XCBuildConfiguration; buildSettings = { @@ -2586,44 +851,43 @@ }; 2C87B79A2197FA1900682EC4 /* LocalRelease */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 069784542A6B83E8BB774757 /* Pods-Rainbow.localrelease.xcconfig */; + baseConfigurationReference = 15B240C971E54630F3158955 /* Pods-Rainbow.localrelease.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_OPTIMIZATION = time; + CLANG_ENABLE_MODULES = YES; CODEPUSH_KEY = ""; CODE_SIGN_ENTITLEMENTS = Rainbow/Rainbow.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = L74NQAQB8H; + CURRENT_PROJECT_VERSION = 4; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = ""; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Frameworks", ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_UNROLL_LOOPS = YES; HEADER_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Frameworks", - "$(SRCROOT)/../node_modules/react-native-keychain/RNKeychainManager", - "$(SRCROOT)/../node_modules/react-native-linear-gradient/BVLinearGradient", - "$(SRCROOT)/../node_modules/react-native-mail/RNMail", - "$(SRCROOT)/../node_modules/react-native-os/ios", - "$(SRCROOT)/../node_modules/react-native-permissions/ios/**", - "$(SRCROOT)/../node_modules/react-native-radial-gradient/ios", - "$(SRCROOT)/../node_modules/react-native-randombytes", - "$(SRCROOT)/../node_modules/react-native-splash-screen/ios", - "$(SRCROOT)/../node_modules/react-native-svg/ios/**", - "$(SRCROOT)/../node_modules/react-native-tcp/ios/**", "$(SRCROOT)/../node_modules/react-native-tooltip/ToolTipMenu", - "$(SRCROOT)/../node_modules/react-native-touch-id", - "$(SRCROOT)/../node_modules/react-native-udp/ios/**", - "$(SRCROOT)/../node_modules/react-native-haptic-feedback/ios", - "$(SRCROOT)/../node_modules/react-native-gesture-handler/ios/**", "$(SRCROOT)/../node_modules/react-native-code-push/ios/**", "$(SRCROOT)/../node_modules/@ledgerhq/react-native-passcode-auth", "$(SRCROOT)/../node_modules/react-native-firebase/ios/RNFirebase/**", - "$(SRCROOT)/../node_modules/react-native-store-review/ios", + "$(SRCROOT)/../node_modules/react-native-text-input-mask/ios/**", ); INFOPLIST_FILE = Rainbow/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "\"$(SRCROOT)/Rainbow\"", + ); + LLVM_LTO = YES; + MARKETING_VERSION = 1.2.2; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", @@ -2633,59 +897,12 @@ PRODUCT_NAME = Rainbow; PROVISIONING_PROFILE = ""; PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "Rainbow-Bridging-Header.h"; + SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; }; name = LocalRelease; }; - 2C87B79B2197FA1900682EC4 /* LocalRelease */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Automatic; - COPY_PHASE_STRIP = NO; - DEVELOPMENT_TEAM = L74NQAQB8H; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "$(SRCROOT)/../node_modules/react-native-fcm/ios", - "$(SRCROOT)/../node_modules/react-native-keychain/RNKeychainManager", - "$(SRCROOT)/../node_modules/react-native-linear-gradient/BVLinearGradient", - "$(SRCROOT)/../node_modules/react-native-mail/RNMail", - "$(SRCROOT)/../node_modules/react-native-os/ios", - "$(SRCROOT)/../node_modules/react-native-permissions/ios/**", - "$(SRCROOT)/../node_modules/react-native-radial-gradient/ios", - "$(SRCROOT)/../node_modules/react-native-randombytes", - "$(SRCROOT)/../node_modules/react-native-splash-screen/ios", - "$(SRCROOT)/../node_modules/react-native-svg/ios/**", - "$(SRCROOT)/../node_modules/react-native-tcp/ios/**", - "$(SRCROOT)/../node_modules/react-native-tooltip/ToolTipMenu", - "$(SRCROOT)/../node_modules/react-native-touch-id", - "$(SRCROOT)/../node_modules/react-native-udp/ios/**", - "$(SRCROOT)/../node_modules/react-native-haptic-feedback/ios", - "$(SRCROOT)/../node_modules/react-native-gesture-handler/ios/**", - "$(SRCROOT)/../node_modules/react-native-code-push/ios/CodePush/**", - "$(SRCROOT)/../node_modules/@ledgerhq/react-native-passcode-auth", - "$(SRCROOT)/../node_modules/react-native-firebase/ios/RNFirebase/**", - "$(SRCROOT)/../node_modules/react-native-store-review/ios", - ); - INFOPLIST_FILE = RainbowTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/$(TARGET_NAME)\"", - "\"$(SRCROOT)/$(TARGET_NAME)\"", - ); - OTHER_LDFLAGS = ( - "-ObjC", - "-lc++", - ); - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Rainbow.app/Rainbow"; - }; - name = LocalRelease; - }; 83CBBA201A601CBA00E9B192 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -2767,17 +984,6 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "RainbowTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 00E356F61AD99517003FC87E /* Debug */, - 00E356F71AD99517003FC87E /* Release */, - 2C87B79B2197FA1900682EC4 /* LocalRelease */, - 2C6A799921127ED9003AFB37 /* Staging */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Rainbow" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/ios/Rainbow.xcodeproj/xcshareddata/xcschemes/Rainbow.xcscheme b/ios/Rainbow.xcodeproj/xcshareddata/xcschemes/Rainbow.xcscheme index 0d412b7196d..a8093514504 100644 --- a/ios/Rainbow.xcodeproj/xcshareddata/xcschemes/Rainbow.xcscheme +++ b/ios/Rainbow.xcodeproj/xcshareddata/xcschemes/Rainbow.xcscheme @@ -3,7 +3,7 @@ LastUpgradeVersion = "0620" version = "1.3"> + ReferencedContainer = "container:Pods/Pods.xcodeproj"> + + + + @@ -67,17 +76,6 @@ - - - - - - - - + + + + BuildSystemType + Original + PreviewsEnabled + + + diff --git a/ios/Rainbow/AppDelegate.m b/ios/Rainbow/AppDelegate.m index da84b28a998..16151f7b516 100644 --- a/ios/Rainbow/AppDelegate.m +++ b/ios/Rainbow/AppDelegate.m @@ -5,24 +5,21 @@ * LICENSE file in the root directory of this source tree. */ +@import Firebase; #import "AppDelegate.h" #import #import #import #import #import -#import -#import "RNFirebaseMessaging.h" -#import "RNFirebaseNotifications.h" +#import #import "RNSplashScreen.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Firebase - Push Notifications [FIRApp configure]; - [RNFirebaseNotifications configure]; [application registerForRemoteNotifications]; // React Native - Defaults @@ -48,22 +45,23 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge { #if DEBUG - return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; + return [NSURL URLWithString:[[[[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil] absoluteString] stringByAppendingString:@"&inlineSourceMap=true" ]]; #else return [CodePush bundleURL]; #endif } -- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification { - [[RNFirebaseNotifications instance] didReceiveLocalNotification:notification]; -} - -- (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler{ - [[RNFirebaseNotifications instance] didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler]; +// Required for the notification event. You must call the completion handler after handling the remote notification. +- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo +fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler +{ + [RNCPushNotificationIOS didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler]; } -- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings { - [[RNFirebaseMessaging instance] didRegisterUserNotificationSettings:notificationSettings]; +// Required for the localNotification event. +- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification +{ + [RNCPushNotificationIOS didReceiveLocalNotification:notification]; } - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url diff --git a/ios/Rainbow/Base.lproj/LaunchScreen.xib b/ios/Rainbow/Base.lproj/LaunchScreen.xib index 1522ebb1834..6afe45ef89b 100644 --- a/ios/Rainbow/Base.lproj/LaunchScreen.xib +++ b/ios/Rainbow/Base.lproj/LaunchScreen.xib @@ -15,18 +15,18 @@ - - + + - + - + diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/1024.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/1024.png new file mode 100644 index 00000000000..f959168df57 Binary files /dev/null and b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/1024.png differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/120-1.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/120-1.png new file mode 100644 index 00000000000..fcdad3ca425 Binary files /dev/null and b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/120-1.png differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/120.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/120.png new file mode 100644 index 00000000000..fcdad3ca425 Binary files /dev/null and b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/120.png differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/180.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/180.png new file mode 100644 index 00000000000..7140362b0aa Binary files /dev/null and b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/180.png differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/29.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/29.png new file mode 100644 index 00000000000..e667af9b311 Binary files /dev/null and b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/29.png differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/40.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/40.png new file mode 100644 index 00000000000..0e39e75481a Binary files /dev/null and b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/40.png differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/58.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/58.png new file mode 100644 index 00000000000..4eb6ed946af Binary files /dev/null and b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/58.png differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/60.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/60.png new file mode 100644 index 00000000000..a84ec4449e6 Binary files /dev/null and b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/60.png differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/80.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/80.png new file mode 100644 index 00000000000..0a827a3a7bd Binary files /dev/null and b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/80.png differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/87.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/87.png new file mode 100644 index 00000000000..50a463dc542 Binary files /dev/null and b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/87.png differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/Contents.json b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/Contents.json index 9189bb8250a..8641b203f13 100644 --- a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/Contents.json @@ -1,158 +1,143 @@ { - "images": [ + "images" : [ { - "size": "1024x1024", - "idiom": "ios-marketing", - "scale": "1x", - "filename": "ios-marketing-1024x1024-1x.png" + "size" : "20x20", + "idiom" : "iphone", + "filename" : "40.png", + "scale" : "2x" }, { - "size": "20x20", - "idiom": "ipad", - "scale": "1x", - "filename": "ipad-20x20-1x.png" + "size" : "20x20", + "idiom" : "iphone", + "filename" : "60.png", + "scale" : "3x" }, { - "size": "20x20", - "idiom": "ipad", - "scale": "2x", - "filename": "ipad-20x20-2x.png" + "size" : "29x29", + "idiom" : "iphone", + "filename" : "29.png", + "scale" : "1x" }, { - "size": "29x29", - "idiom": "ipad", - "scale": "1x", - "filename": "ipad-29x29-1x.png" + "size" : "29x29", + "idiom" : "iphone", + "filename" : "58.png", + "scale" : "2x" }, { - "size": "29x29", - "idiom": "ipad", - "scale": "2x", - "filename": "ipad-29x29-2x.png" + "size" : "29x29", + "idiom" : "iphone", + "filename" : "87.png", + "scale" : "3x" }, { - "size": "40x40", - "idiom": "ipad", - "scale": "1x", - "filename": "ipad-40x40-1x.png" + "size" : "40x40", + "idiom" : "iphone", + "filename" : "80.png", + "scale" : "2x" }, { - "size": "40x40", - "idiom": "ipad", - "scale": "2x", - "filename": "ipad-40x40-2x.png" + "size" : "40x40", + "idiom" : "iphone", + "filename" : "120.png", + "scale" : "3x" }, { - "size": "50x50", - "idiom": "ipad", - "scale": "1x", - "filename": "ipad-50x50-1x.png" + "idiom" : "iphone", + "size" : "57x57", + "scale" : "1x" }, { - "size": "50x50", - "idiom": "ipad", - "scale": "2x", - "filename": "ipad-50x50-2x.png" + "idiom" : "iphone", + "size" : "57x57", + "scale" : "2x" }, { - "size": "72x72", - "idiom": "ipad", - "scale": "1x", - "filename": "ipad-72x72-1x.png" + "size" : "60x60", + "idiom" : "iphone", + "filename" : "120-1.png", + "scale" : "2x" }, { - "size": "72x72", - "idiom": "ipad", - "scale": "2x", - "filename": "ipad-72x72-2x.png" + "size" : "60x60", + "idiom" : "iphone", + "filename" : "180.png", + "scale" : "3x" }, { - "size": "76x76", - "idiom": "ipad", - "scale": "1x", - "filename": "ipad-76x76-1x.png" + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" }, { - "size": "76x76", - "idiom": "ipad", - "scale": "2x", - "filename": "ipad-76x76-2x.png" + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" }, { - "size": "83.5x83.5", - "idiom": "ipad", - "scale": "2x", - "filename": "ipad-83.5x83.5-2x.png" + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" }, { - "size": "20x20", - "idiom": "iphone", - "scale": "2x", - "filename": "iphone-20x20-2x.png" + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" }, { - "size": "20x20", - "idiom": "iphone", - "scale": "3x", - "filename": "iphone-20x20-3x.png" + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" }, { - "size": "29x29", - "idiom": "iphone", - "scale": "1x", - "filename": "iphone-29x29-1x.png" + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" }, { - "size": "29x29", - "idiom": "iphone", - "scale": "2x", - "filename": "iphone-29x29-2x.png" + "idiom" : "ipad", + "size" : "50x50", + "scale" : "1x" }, { - "size": "29x29", - "idiom": "iphone", - "scale": "3x", - "filename": "iphone-29x29-3x.png" + "idiom" : "ipad", + "size" : "50x50", + "scale" : "2x" }, { - "size": "40x40", - "idiom": "iphone", - "scale": "2x", - "filename": "iphone-40x40-2x.png" + "idiom" : "ipad", + "size" : "72x72", + "scale" : "1x" }, { - "size": "40x40", - "idiom": "iphone", - "scale": "3x", - "filename": "iphone-40x40-3x.png" + "idiom" : "ipad", + "size" : "72x72", + "scale" : "2x" }, { - "size": "57x57", - "idiom": "iphone", - "scale": "1x", - "filename": "iphone-57x57-1x.png" + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" }, { - "size": "57x57", - "idiom": "iphone", - "scale": "2x", - "filename": "iphone-57x57-2x.png" + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" }, { - "size": "60x60", - "idiom": "iphone", - "scale": "2x", - "filename": "iphone-60x60-2x.png" + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" }, { - "size": "60x60", - "idiom": "iphone", - "scale": "3x", - "filename": "iphone-60x60-3x.png" + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "1024.png", + "scale" : "1x" } ], - "info": { - "version": 1, - "author": "xcode" + "info" : { + "version" : 1, + "author" : "xcode" } } \ No newline at end of file diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ios-marketing-1024x1024-1x.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ios-marketing-1024x1024-1x.png deleted file mode 100644 index 54f3c12159b..00000000000 Binary files a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ios-marketing-1024x1024-1x.png and /dev/null differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-20x20-1x.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-20x20-1x.png deleted file mode 100644 index c8c422bf40a..00000000000 Binary files a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-20x20-1x.png and /dev/null differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-20x20-2x.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-20x20-2x.png deleted file mode 100644 index bd4c8fbe17d..00000000000 Binary files a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-20x20-2x.png and /dev/null differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-29x29-1x.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-29x29-1x.png deleted file mode 100644 index bb2f5b4e477..00000000000 Binary files a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-29x29-1x.png and /dev/null differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-29x29-2x.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-29x29-2x.png deleted file mode 100644 index f25055666d9..00000000000 Binary files a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-29x29-2x.png and /dev/null differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-40x40-1x.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-40x40-1x.png deleted file mode 100644 index bd4c8fbe17d..00000000000 Binary files a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-40x40-1x.png and /dev/null differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-40x40-2x.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-40x40-2x.png deleted file mode 100644 index 5c5081f871e..00000000000 Binary files a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-40x40-2x.png and /dev/null differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-50x50-1x.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-50x50-1x.png deleted file mode 100644 index 38a5814d147..00000000000 Binary files a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-50x50-1x.png and /dev/null differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-50x50-2x.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-50x50-2x.png deleted file mode 100644 index a6cbc674a47..00000000000 Binary files a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-50x50-2x.png and /dev/null differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-72x72-1x.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-72x72-1x.png deleted file mode 100644 index 966310f7b12..00000000000 Binary files a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-72x72-1x.png and /dev/null differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-72x72-2x.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-72x72-2x.png deleted file mode 100644 index 06b6bdda9b1..00000000000 Binary files a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-72x72-2x.png and /dev/null differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-76x76-1x.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-76x76-1x.png deleted file mode 100644 index 3c234f6d497..00000000000 Binary files a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-76x76-1x.png and /dev/null differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-76x76-2x.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-76x76-2x.png deleted file mode 100644 index 095acb2b3cf..00000000000 Binary files a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-76x76-2x.png and /dev/null differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-83.5x83.5-2x.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-83.5x83.5-2x.png deleted file mode 100644 index 982751c5c00..00000000000 Binary files a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/ipad-83.5x83.5-2x.png and /dev/null differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-20x20-2x.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-20x20-2x.png deleted file mode 100644 index bd4c8fbe17d..00000000000 Binary files a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-20x20-2x.png and /dev/null differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-20x20-3x.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-20x20-3x.png deleted file mode 100644 index ad991862aea..00000000000 Binary files a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-20x20-3x.png and /dev/null differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-29x29-1x.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-29x29-1x.png deleted file mode 100644 index bb2f5b4e477..00000000000 Binary files a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-29x29-1x.png and /dev/null differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-29x29-2x.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-29x29-2x.png deleted file mode 100644 index e7bc0877272..00000000000 Binary files a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-29x29-2x.png and /dev/null differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-29x29-3x.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-29x29-3x.png deleted file mode 100644 index 7a4c48d60bb..00000000000 Binary files a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-29x29-3x.png and /dev/null differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-40x40-2x.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-40x40-2x.png deleted file mode 100644 index 5c5081f871e..00000000000 Binary files a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-40x40-2x.png and /dev/null differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-40x40-3x.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-40x40-3x.png deleted file mode 100644 index eb09e21036f..00000000000 Binary files a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-40x40-3x.png and /dev/null differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-57x57-1x.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-57x57-1x.png deleted file mode 100644 index 4f1dcd273ca..00000000000 Binary files a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-57x57-1x.png and /dev/null differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-57x57-2x.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-57x57-2x.png deleted file mode 100644 index bc95d6a55ac..00000000000 Binary files a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-57x57-2x.png and /dev/null differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-60x60-2x.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-60x60-2x.png deleted file mode 100644 index 49c032f9b70..00000000000 Binary files a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-60x60-2x.png and /dev/null differ diff --git a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-60x60-3x.png b/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-60x60-3x.png deleted file mode 100644 index 17a22bdf457..00000000000 Binary files a/ios/Rainbow/Images.xcassets/AppIcon.appiconset/iphone-60x60-3x.png and /dev/null differ diff --git a/ios/Rainbow/Images.xcassets/SplashIcon.imageset/Contents.json b/ios/Rainbow/Images.xcassets/SplashIcon.imageset/Contents.json index 79dee6228e2..1de46191585 100644 --- a/ios/Rainbow/Images.xcassets/SplashIcon.imageset/Contents.json +++ b/ios/Rainbow/Images.xcassets/SplashIcon.imageset/Contents.json @@ -2,17 +2,17 @@ "images" : [ { "idiom" : "universal", - "filename" : "splashscreen-icon.png", + "filename" : "splash-icon.png", "scale" : "1x" }, { "idiom" : "universal", - "filename" : "splashscreen-icon@2x.png", + "filename" : "splash-icon@2x.png", "scale" : "2x" }, { "idiom" : "universal", - "filename" : "splashscreen-icon@3x.png", + "filename" : "splash-icon@3x.png", "scale" : "3x" } ], diff --git a/ios/Rainbow/Images.xcassets/SplashIcon.imageset/splash-icon.png b/ios/Rainbow/Images.xcassets/SplashIcon.imageset/splash-icon.png new file mode 100644 index 00000000000..6b0f5a735b5 Binary files /dev/null and b/ios/Rainbow/Images.xcassets/SplashIcon.imageset/splash-icon.png differ diff --git a/ios/Rainbow/Images.xcassets/SplashIcon.imageset/splash-icon@2x.png b/ios/Rainbow/Images.xcassets/SplashIcon.imageset/splash-icon@2x.png new file mode 100644 index 00000000000..2081b54bdfa Binary files /dev/null and b/ios/Rainbow/Images.xcassets/SplashIcon.imageset/splash-icon@2x.png differ diff --git a/ios/Rainbow/Images.xcassets/SplashIcon.imageset/splash-icon@3x.png b/ios/Rainbow/Images.xcassets/SplashIcon.imageset/splash-icon@3x.png new file mode 100644 index 00000000000..608ffbf32d8 Binary files /dev/null and b/ios/Rainbow/Images.xcassets/SplashIcon.imageset/splash-icon@3x.png differ diff --git a/ios/Rainbow/Images.xcassets/SplashIcon.imageset/splashscreen-icon.png b/ios/Rainbow/Images.xcassets/SplashIcon.imageset/splashscreen-icon.png deleted file mode 100644 index 2b71ed8ede3..00000000000 Binary files a/ios/Rainbow/Images.xcassets/SplashIcon.imageset/splashscreen-icon.png and /dev/null differ diff --git a/ios/Rainbow/Images.xcassets/SplashIcon.imageset/splashscreen-icon@2x.png b/ios/Rainbow/Images.xcassets/SplashIcon.imageset/splashscreen-icon@2x.png deleted file mode 100644 index 69d8385378a..00000000000 Binary files a/ios/Rainbow/Images.xcassets/SplashIcon.imageset/splashscreen-icon@2x.png and /dev/null differ diff --git a/ios/Rainbow/Images.xcassets/SplashIcon.imageset/splashscreen-icon@3x.png b/ios/Rainbow/Images.xcassets/SplashIcon.imageset/splashscreen-icon@3x.png deleted file mode 100644 index fa4c5fc6dfe..00000000000 Binary files a/ios/Rainbow/Images.xcassets/SplashIcon.imageset/splashscreen-icon@3x.png and /dev/null differ diff --git a/ios/Rainbow/Info.plist b/ios/Rainbow/Info.plist index 99cd258d0c8..abc00b1dea4 100644 --- a/ios/Rainbow/Info.plist +++ b/ios/Rainbow/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.1.7 + $(MARKETING_VERSION) CFBundleSignature ???? CFBundleURLTypes @@ -34,7 +34,7 @@ CFBundleVersion - 1 + $(CURRENT_PROJECT_VERSION) CodePushDeploymentKey $(CODEPUSH_KEY) ITSAppUsesNonExemptEncryption @@ -60,12 +60,16 @@ NSAppleMusicUsageDescription Rainbow + NSBluetoothAlwaysUsageDescription + Rainbow NSBluetoothPeripheralUsageDescription Rainbow NSCalendarsUsageDescription Rainbow NSCameraUsageDescription Used to scan QR codes + NSContactsUsageDescription + Rainbow NSFaceIDUsageDescription Used to sign transactions NSLocationAlwaysUsageDescription @@ -76,6 +80,8 @@ Rainbow NSMotionUsageDescription Rainbow + NSPhotoLibraryUsageDescription + Rainbow NSSpeechRecognitionUsageDescription Rainbow UIAppFonts @@ -145,12 +151,16 @@ armv7 + UIStatusBarHidden + UIStatusBarStyle - UIStatusBarStyleLightContent + UIStatusBarStyleDarkContent UISupportedInterfaceOrientations UIInterfaceOrientationPortrait + UIUserInterfaceStyle + Light UIViewControllerBasedStatusBarAppearance diff --git a/ios/fastlane/Fastfile b/ios/fastlane/Fastfile index 327293eb805..ec587a75f2c 100644 --- a/ios/fastlane/Fastfile +++ b/ios/fastlane/Fastfile @@ -15,8 +15,9 @@ default_platform(:ios) platform :ios do desc "Refresh dSYMs" lane :refresh_dsyms do - download_dsyms + download_dsyms(version: "latest") upload_symbols_to_crashlytics + sentry_upload_dsym clean_build_artifacts end @@ -44,37 +45,6 @@ platform :ios do pilot( app_identifier: "me.rainbow" ) - download_dsyms - upload_symbols_to_crashlytics - clean_build_artifacts - end - - desc "Submit a new Internal build to Apple TestFlight" - lane :internal do - update_info_plist( - plist_path: "Rainbow/Info.plist", - display_name: "Internal" - ) - update_app_identifier( - app_identifier: "me.rainbow.internal", - xcodeproj: "Rainbow.xcodeproj", - plist_path: "Rainbow/Info.plist", - ) - match( - type: "appstore", - app_identifier: "me.rainbow.internal", - git_url: "git@github.com:rainbow-me/rainbow-code-signing.git" - ) - gym( - scheme: "Rainbow", - export_method: "app-store", - include_symbols: true, - ) - pilot( - app_identifier: "me.rainbow.internal" - ) - download_dsyms - upload_symbols_to_crashlytics - clean_build_artifacts + refresh_dsyms end end diff --git a/ios/fastlane/Pluginfile b/ios/fastlane/Pluginfile new file mode 100644 index 00000000000..a152560f423 --- /dev/null +++ b/ios/fastlane/Pluginfile @@ -0,0 +1,5 @@ +# Autogenerated by fastlane +# +# Ensure this file is checked in to source control! + +gem 'fastlane-plugin-sentry' diff --git a/ios/fastlane/README.md b/ios/fastlane/README.md index 75c01d65a04..a3d69dc0be7 100644 --- a/ios/fastlane/README.md +++ b/ios/fastlane/README.md @@ -26,11 +26,6 @@ Refresh dSYMs fastlane ios beta ``` Submit a new Beta build to Apple TestFlight -### ios internal -``` -fastlane ios internal -``` -Submit a new Internal build to Apple TestFlight ---- diff --git a/ios/sentry.properties b/ios/sentry.properties new file mode 100644 index 00000000000..a8f8225c9b4 --- /dev/null +++ b/ios/sentry.properties @@ -0,0 +1,4 @@ +defaults.url=https://sentry.io/ +defaults.org=rainbow-me +defaults.project=rainbow-wallet +cli.executable=node_modules/@sentry/cli/bin/sentry-cli diff --git a/metro.config.js b/metro.config.js index 6a1d15808f0..d9f14d4436c 100644 --- a/metro.config.js +++ b/metro.config.js @@ -5,6 +5,7 @@ * @format */ +// eslint-disable-next-line import/no-commonjs module.exports = { transformer: { getTransformOptions: async () => ({ diff --git a/package.json b/package.json index b71db7be238..9e4b276ac12 100644 --- a/package.json +++ b/package.json @@ -1,36 +1,50 @@ { "name": "Rainbow", - "version": "1.1.7-1", + "version": "1.2.3-1", "private": true, "scripts": { - "clean": "react-native-clean-project", - "start": "node node_modules/react-native/local-cli/cli.js start", + "android": "react-native run-android", + "clean": "react-native clean-project-auto", + "start": "react-native start", "test": "jest test.js", "install-pods": "cd ios && pod install && cd ..", "ios": "react-native run-ios --simulator='iPhone X'", - "lint": "eslint './**/*.js'", + "lint": "eslint --ext '.js,.jsx' .", "nodeify": "./node_modules/.bin/rn-nodeify --install \"crypto\" --hack", "postinstall": "patch-package && rn-nodeify --install --hack" }, + "husky": { + "hooks": { + "pre-commit": "yarn lint && yarn test" + } + }, "dependencies": { + "@bankify/react-native-animate-number": "^0.2.1", "@hocs/omit-props": "^0.4.0", "@hocs/safe-timers": "^0.4.0", "@hocs/with-view-layout-props": "^0.2.0", - "@react-native-community/async-storage": "1.5.0", - "@react-native-community/blur": "^3.3.1", - "@react-native-community/masked-view": "^0.1.1", - "@react-native-community/netinfo": "^3.2.1", + "@react-native-community/async-storage": "1.6.2", + "@react-native-community/blur": "^3.4.1", + "@react-native-community/masked-view": "^0.1.5", + "@react-native-community/netinfo": "^5.0.0", + "@react-native-community/push-notification-ios": "^1.0.3", + "@react-native-firebase/app": "^6.2.0", + "@react-native-firebase/crashlytics": "^6.2.0", + "@react-native-firebase/messaging": "^6.2.0", "@segment/analytics-react-native": "^1.0.1", + "@sentry/react-native": "^1.2.0", "@staltz/react-native-tcp": "^3.3.1", "@tradle/react-native-http": "^2.0.1", + "@uniswap/sdk": "^1.0.0-beta.4", "@walletconnect/react-native": "^1.0.0-beta.29", + "@walletconnect/utils": "^1.0.0-beta.36", "assert": "^1.4.1", "asyncstorage-down": "^4.2.0", "axios": "^0.19.0", "bignumber.js": "^9.0.0", "browserify-zlib": "^0.1.4", "buffer": "^4.9.1", - "chroma-js": "^1.3.7", + "chroma-js": "^2.1.0", "code-push": "^2.0.6", "console-browserify": "^1.1.0", "constants-browserify": "^1.0.0", @@ -38,18 +52,22 @@ "delay": "^4.3.0", "dns.js": "^1.0.1", "domain-browser": "^1.2.0", - "eth-contract-metadata": "^1.9.2", - "ethers": "^4.0.33", + "eth-contract-metadata": "^1.9.3", + "ethers": "^4.0.39", "events": "^1.1.1", "global": "^4.3.2", + "grapheme-splitter": "^1.0.4", "https-browserify": "0.0.1", + "husky": "^2.4.0", "i18n-js": "^3.0.11", "i18next": "^17.0.3", - "immer": "^3.1.3", + "immer": "^5.0.0", "inherits": "^2.0.3", "lodash": "^4.17.15", - "nanoid": "^2.0.3", - "patch-package": "^6.1.2", + "match-sorter": "^4.0.2", + "nanoid": "^2.1.6", + "parse-ms": "^2.1.0", + "patch-package": "^6.2.0", "path-browserify": "0.0.0", "postcss": "^7.0.13", "postinstall-postinstall": "^2.0.0", @@ -57,49 +75,54 @@ "prop-types": "^15.7.2", "punycode": "^1.4.1", "querystring-es3": "^0.2.1", - "react": "16.8.3", - "react-coin-icon": "^0.1.9", - "react-native": "0.59.9", + "react": "16.11.0", + "react-coin-icon": "0.1.14", + "react-fast-compare": "^2.0.4", + "react-native": "facebook/react-native", "react-native-actionsheet": "^2.4.2", - "react-native-camera": "^2.11.0", - "react-native-circular-progress": "^1.1.0", + "react-native-camera": "^3.9.0", + "react-native-circular-progress": "^1.3.4", "react-native-code-push": "^5.6.0", - "react-native-crypto": "^2.1.2", - "react-native-device-info": "^2.1.3", + "react-native-crypto": "^2.2.0", + "react-native-device-info": "5.3.1", "react-native-dotenv": "^0.2.0", "react-native-emoji": "1.5.0", - "react-native-fast-image": "^6.0.3", - "react-native-firebase": "^4.3.8", - "react-native-gesture-handler": "^1.3.0", + "react-native-fast-image": "andrewschenk-linx/react-native-fast-image#fix-ios-xcode-proj", + "react-native-gesture-handler": "1.5.2", "react-native-haptic-feedback": "^1.8.2", - "react-native-indicators": "^0.13.0", + "react-native-indicators": "0.17.0", "react-native-ios11-devicecheck": "^0.0.3", "react-native-iphone-x-helper": "^1.2.1", - "react-native-keychain": "^3.1.3", + "react-native-keychain": "4.0.3", "react-native-languages": "^3.0.0", "react-native-level-fs": "^3.0.1", - "react-native-linear-gradient": "^2.5.4", - "react-native-mail": "^3.0.6", - "react-native-os": "^1.2.2", - "react-native-permissions": "^1.1.1", + "react-native-linear-gradient": "^2.5.6", + "react-native-mail": "^4.1.0", + "react-native-os": "icxcat/react-native-os#master", + "react-native-permissions": "^1.2.1", "react-native-qrcode-scanner": "mikedemarais/react-native-qrcode-scanner#2ca70b8c64afb87e712aba578e11409c6406069e", "react-native-qrcode-svg": "git+https://github.com/mikedemarais/react-native-qrcode-svg.git", "react-native-radial-gradient": "shkatulo/react-native-radial-gradient", "react-native-randombytes": "^3.5.3", - "react-native-reanimated": "1.1.0", - "react-native-redash": "^7.2.1", + "react-native-reanimated": "software-mansion/react-native-reanimated", + "react-native-redash": "9.0.0", + "react-native-safe-area-context": "^0.5.0", "react-native-safe-area-view": "mikedemarais/react-native-safe-area-view", "react-native-screens": "^1.0.0-alpha.23", "react-native-splash-screen": "^3.2.0", "react-native-storage": "^1.0.1", "react-native-store-review": "^0.1.5", - "react-native-svg": "^9.5.1", - "react-native-tcp": "^3.3.0", - "react-native-tooltip": "^5.2.0", - "react-native-touch-id": "^4.4.1", + "react-native-svg": "9.13.6", + "react-native-tcp": "^3.3.2", + "react-native-text-input-mask": "waqas19921/react-native-text-input-mask", + "react-native-tooltip": "marcosrdz/react-native-tooltip#master", "react-native-udp": "^2.6.1", "react-native-version-number": "^0.3.6", - "react-navigation": "^3.11.1", + "react-navigation": "4.0.10", + "react-navigation-hooks": "^1.1.0", + "react-navigation-stack": "2.0.0-alpha.39", + "react-navigation-tabs": "2.6.2", + "react-navigation-tabs-v1": "1.2.0", "react-primitives": "^0.8.0", "react-redux": "^5.0.7", "react-spring": "^5.7.2", @@ -107,16 +130,16 @@ "readable-stream": "^1.0.33", "recompact": "^3.4.0", "recompose": "^0.30.0", - "recyclerlistview": "^2.0.1-alpha.1", + "recyclerlistview": "2.0.1-alpha.1", "redux": "^4.0.1", "redux-devtools-extension": "^2.13.8", "redux-thunk": "^2.3.0", "reselect": "^4.0.0", - "rn-nodeify": "^10.0.1", + "rn-nodeify": "10.2.0", "socket.io-client": "^2.2.0", "stream-browserify": "^1.0.0", "string_decoder": "^0.10.31", - "styled-components": "^5.0.0-beta.8", + "styled-components": "5.0.0-beta.9", "stylelint": "^10.1.0", "svgs": "^4.1.0", "timers-browserify": "^1.4.2", @@ -126,31 +149,27 @@ "vm-browserify": "0.0.4" }, "devDependencies": { - "@babel/core": "^7.4.5", - "@babel/runtime": "^7.4.5", - "@react-native-community/cli": "2.0.0-rc.2", - "@react-native-community/eslint-config": "^0.0.5", + "@babel/core": "^7.7.2", + "@babel/runtime": "^7.7.2", + "@react-native-community/cli": "3.0.4", "babel-core": "7.0.0-bridge.0", - "babel-eslint": "^8.2.2", - "babel-jest": "^24.8.0", + "babel-eslint": "^10.0.3", + "babel-jest": "^24.9.0", "babel-plugin-date-fns": "^0.2.1", "babel-plugin-lodash": "^3.3.4", - "babel-plugin-styled-components": "^1.10.6", "babel-plugin-rewire": "^1.2.0", + "babel-plugin-styled-components": "^1.10.6", "babel-plugin-transform-remove-console": "^6.9.4", "detox": "^12.8.0", - "eslint": "^5.16.0", - "eslint-config-airbnb-base": "^13.1.0", - "eslint-plugin-import": "^2.14.0", - "eslint-plugin-react": "^7.13.0", - "eslint-plugin-react-native": "^3.7.0", - "eslint-plugin-react-native-animation-linter": "^0.1.2", - "jest": "^24.8.0", - "metro-react-native-babel-preset": "^0.55.0", - "mocha": "^6.1.4", + "eslint": "^6.6.0", + "eslint-config-satya164": "^2.4.1", + "jest": "^24.9.0", + "metro-react-native-babel-preset": "^0.57.0", + "mocha": "^6.2.2", + "react-native-bundle-visualizer": "^2.0.1", "react-native-clean-project": "^3.1.0", - "react-test-renderer": "16.8.3", - "schedule": "0.4.0" + "react-test-renderer": "16.9.0", + "schedule": "0.5.0" }, "resolutions": { "**/eslint-plugin-import": "2.14.0", diff --git a/patches/react-native-gesture-handler+1.5.2.patch b/patches/react-native-gesture-handler+1.5.2.patch new file mode 100644 index 00000000000..ccdc338ff08 --- /dev/null +++ b/patches/react-native-gesture-handler+1.5.2.patch @@ -0,0 +1,82 @@ +diff --git a/node_modules/react-native-gesture-handler/Swipeable.js b/node_modules/react-native-gesture-handler/Swipeable.js +index 7da6911..a3f64a3 100644 +--- a/node_modules/react-native-gesture-handler/Swipeable.js ++++ b/node_modules/react-native-gesture-handler/Swipeable.js +@@ -176,8 +176,8 @@ export default class Swipeable extends Component { + rightThreshold = rightWidth / 2, + } = this.props; + +- const startOffsetX = this._currentOffset() + dragX / friction; +- const translationX = (dragX + DRAG_TOSS * velocityX) / friction; ++ const startOffsetX = this._currentOffset() + dragX; ++ const translationX = dragX + DRAG_TOSS * velocityX; + + let toValue = 0; + if (rowState === 0) { +@@ -198,7 +198,7 @@ export default class Swipeable extends Component { + } + } + +- this._animateRow(startOffsetX, toValue, velocityX / friction); ++ this._animateRow(startOffsetX, toValue, velocityX); + }; + + _animateRow = (fromValue, toValue, velocityX) => { +diff --git a/node_modules/react-native-gesture-handler/createHandler.js b/node_modules/react-native-gesture-handler/createHandler.js +index 1fc1bbe..fc151c9 100644 +--- a/node_modules/react-native-gesture-handler/createHandler.js ++++ b/node_modules/react-native-gesture-handler/createHandler.js +@@ -2,6 +2,7 @@ import React from 'react'; + import { + findNodeHandle as findNodeHandleRN, + NativeModules, ++ NativeEventEmitter, + Touchable, + Platform, + } from 'react-native'; +@@ -16,6 +17,20 @@ function findNodeHandle(node) { + + const { UIManager = {} } = NativeModules; + ++// We need to hook up one listener so that react-native will call ++// into our module and bless our events declared there in supportedEvents ++// of RNGestureHandlerModule.m. Otherwise when we start sending ++// events later, we might crash (seemingly only in release builds) with ++// an error like: ++// Unsupported top level event type "onGestureHandlerEvent" ++// Fixes: https://github.com/kmagiera/react-native-gesture-handler/issues/320 ++const unusedEmitter = new NativeEventEmitter(NativeModules.RNGestureHandlerModule) ++// It's not enough to create an emitter -- you must also add a listener because ++// react-native does this initialization lazily ++const subscription = unusedEmitter.addListener("onGestureHandlerEvent",function(next){}) ++// Now that our events are blessed by the system we can let go of the listener ++subscription.remove() ++ + const customGHEventsConfig = { + onGestureHandlerEvent: { registrationName: 'onGestureHandlerEvent' }, + onGestureHandlerStateChange: { +diff --git a/node_modules/react-native-gesture-handler/ios/RNGestureHandler.xcodeproj/xcuserdata/christian.xcuserdatad/xcschemes/xcschememanagement.plist b/node_modules/react-native-gesture-handler/ios/RNGestureHandler.xcodeproj/xcuserdata/christian.xcuserdatad/xcschemes/xcschememanagement.plist +new file mode 100644 +index 0000000..cf96c26 +--- /dev/null ++++ b/node_modules/react-native-gesture-handler/ios/RNGestureHandler.xcodeproj/xcuserdata/christian.xcuserdatad/xcschemes/xcschememanagement.plist +@@ -0,0 +1,19 @@ ++ ++ ++ ++ ++ SchemeUserState ++ ++ RNGestureHandler-tvOS.xcscheme_^#shared#^_ ++ ++ orderHint ++ 86 ++ ++ RNGestureHandler.xcscheme_^#shared#^_ ++ ++ orderHint ++ 85 ++ ++ ++ ++ diff --git a/patches/react-native-keychain+4.0.3.patch b/patches/react-native-keychain+4.0.3.patch new file mode 100644 index 00000000000..7fa4f9a8ad3 --- /dev/null +++ b/patches/react-native-keychain+4.0.3.patch @@ -0,0 +1,13 @@ +diff --git a/node_modules/react-native-keychain/RNKeychainManager/RNKeychainManager.m b/node_modules/react-native-keychain/RNKeychainManager/RNKeychainManager.m +index c4ad7e5..ada736b 100644 +--- a/node_modules/react-native-keychain/RNKeychainManager/RNKeychainManager.m ++++ b/node_modules/react-native-keychain/RNKeychainManager/RNKeychainManager.m +@@ -270,7 +270,7 @@ - (OSStatus)deleteCredentialsForServer:(NSString *)server + { + NSError *aerr = nil; + LAContext *context = [LAContext new]; +- BOOL canBeProtected = [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthentication error:&aerr]; ++ BOOL canBeProtected = [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&aerr]; + + if (!aerr && canBeProtected) { + if (@available(iOS 11, *)) { diff --git a/patches/react-native-tooltip+5.2.1.patch b/patches/react-native-tooltip+5.2.1.patch new file mode 100644 index 00000000000..8426b6bbb0a --- /dev/null +++ b/patches/react-native-tooltip+5.2.1.patch @@ -0,0 +1,43 @@ +diff --git a/node_modules/react-native-tooltip/ToolTip.ios.js b/node_modules/react-native-tooltip/ToolTip.ios.js +index c6754e2..997d584 100644 +--- a/node_modules/react-native-tooltip/ToolTip.ios.js ++++ b/node_modules/react-native-tooltip/ToolTip.ios.js +@@ -57,20 +57,6 @@ export default class ToolTip extends PureComponent { + return null; + }; + +- getTouchableHighlightProps = () => { +- const props = {}; +- +- Object.keys(TouchableHighlight.propTypes).forEach((key) => props[key] = this.props[key]); +- +- if (this.props.longPress) { +- props.onLongPress = this.showMenu; +- } else { +- props.onPress = this.showMenu; +- } +- +- return props; +- }; +- + handleToolTipTextChange = (event) => { + const callback = this.getCallback(event.nativeEvent.text); + if (callback) { +@@ -83,13 +69,13 @@ export default class ToolTip extends PureComponent { + }; + + render() { ++ const { children, ...props } = this.props; ++ + return ( + +- ++ + +- {this.props.children} ++ {children} + + + diff --git a/patches/recyclerlistview+2.0.1-alpha.1.patch b/patches/recyclerlistview+2.0.1-alpha.1.patch index afda92693bc..f4d9d630724 100644 --- a/patches/recyclerlistview+2.0.1-alpha.1.patch +++ b/patches/recyclerlistview+2.0.1-alpha.1.patch @@ -1,18 +1,3 @@ -diff --git a/node_modules/recyclerlistview/dist/reactnative/core/ViewabilityTracker.js b/node_modules/recyclerlistview/dist/reactnative/core/ViewabilityTracker.js -index 26e19af..e2a2913 100644 ---- a/node_modules/recyclerlistview/dist/reactnative/core/ViewabilityTracker.js -+++ b/node_modules/recyclerlistview/dist/reactnative/core/ViewabilityTracker.js -@@ -36,9 +36,8 @@ var ViewabilityTracker = /** @class */ (function () { - this._windowBound = isHorizontal ? dimension.width : dimension.height; - }; - ViewabilityTracker.prototype.forceRefresh = function () { -- var shouldForceScroll = this._currentOffset >= (this._maxOffset - this._windowBound); - this.forceRefreshWithOffset(this._currentOffset); -- return shouldForceScroll; -+ return false; - }; - ViewabilityTracker.prototype.forceRefreshWithOffset = function (offset) { - this._currentOffset = -1; diff --git a/node_modules/recyclerlistview/dist/reactnative/core/StickyContainer.js b/node_modules/recyclerlistview/dist/reactnative/core/StickyContainer.js index e3af431..8de1ec4 100644 --- a/node_modules/recyclerlistview/dist/reactnative/core/StickyContainer.js @@ -34,6 +19,21 @@ index e3af431..8de1ec4 100644 _this._stickyFooterRef = stickyFooterRef; // TODO: Resetting state once ref is initialized. Can look for better solution. _this._callStickyObjectsOnVisibleIndicesChanged(_this._visibleIndicesAll); +diff --git a/node_modules/recyclerlistview/dist/reactnative/core/ViewabilityTracker.js b/node_modules/recyclerlistview/dist/reactnative/core/ViewabilityTracker.js +index 26e19af..e2a2913 100644 +--- a/node_modules/recyclerlistview/dist/reactnative/core/ViewabilityTracker.js ++++ b/node_modules/recyclerlistview/dist/reactnative/core/ViewabilityTracker.js +@@ -36,9 +36,8 @@ var ViewabilityTracker = /** @class */ (function () { + this._windowBound = isHorizontal ? dimension.width : dimension.height; + }; + ViewabilityTracker.prototype.forceRefresh = function () { +- var shouldForceScroll = this._currentOffset >= (this._maxOffset - this._windowBound); + this.forceRefreshWithOffset(this._currentOffset); +- return shouldForceScroll; ++ return false; + }; + ViewabilityTracker.prototype.forceRefreshWithOffset = function (offset) { + this._currentOffset = -1; diff --git a/node_modules/recyclerlistview/dist/reactnative/core/layoutmanager/LayoutManager.js b/node_modules/recyclerlistview/dist/reactnative/core/layoutmanager/LayoutManager.js index 3851852..23075a0 100644 --- a/node_modules/recyclerlistview/dist/reactnative/core/layoutmanager/LayoutManager.js @@ -63,7 +63,7 @@ index 7074f36..5e72f6e 100644 return StickyHeader; }(StickyObject_1.default)); diff --git a/node_modules/recyclerlistview/dist/reactnative/core/sticky/StickyObject.js b/node_modules/recyclerlistview/dist/reactnative/core/sticky/StickyObject.js -index 8da004f..417bf8c 100644 +index 8da004f..6964e85 100644 --- a/node_modules/recyclerlistview/dist/reactnative/core/sticky/StickyObject.js +++ b/node_modules/recyclerlistview/dist/reactnative/core/sticky/StickyObject.js @@ -32,6 +32,7 @@ var StickyObject = /** @class */ (function (_super) { @@ -108,6 +108,16 @@ index 8da004f..417bf8c 100644 this._initParams(); this._offsetY = offsetY; this.boundaryProcessing(offsetY, this.props.getDistanceFromWindow(), this._windowBound); +@@ -179,6 +189,9 @@ var StickyObject = /** @class */ (function (_super) { + var _stickyLayoutType = this.props.getLayoutTypeForIndex(this.currentStickyIndex); + var _extendedState = this.props.getExtendedState(); + var _rowRenderer = this.props.getRowRenderer(); ++ if(_stickyData) { ++ _stickyData.isSticky = true; ++ } + if (this.props.overrideRowRenderer) { + return this.props.overrideRowRenderer(_stickyLayoutType, _stickyData, this.currentStickyIndex, _extendedState); + } diff --git a/node_modules/recyclerlistview/dist/reactnative/utils/BinarySearch.js b/node_modules/recyclerlistview/dist/reactnative/utils/BinarySearch.js index 0ad973f..74f37c5 100644 --- a/node_modules/recyclerlistview/dist/reactnative/utils/BinarySearch.js diff --git a/shim.js b/shim.js index d541c845e2a..61dfabb3a92 100644 --- a/shim.js +++ b/shim.js @@ -27,6 +27,7 @@ process.browser = false; if (typeof Buffer === 'undefined') global.Buffer = require('buffer').Buffer; // global.location = global.location || { port: 80 } +// eslint-disable-next-line no-undef const isDev = typeof __DEV__ === 'boolean' && __DEV__; process.env.NODE_ENV = isDev ? 'development' : 'production'; if (typeof localStorage !== 'undefined') { @@ -35,4 +36,5 @@ if (typeof localStorage !== 'undefined') { // If using the crypto shim, uncomment the following line to ensure // crypto is loaded first, so it can populate global.crypto +// eslint-disable-next-line import/no-commonjs require('crypto'); diff --git a/src/App.js b/src/App.js index 905737cae4c..8fd49fc9325 100644 --- a/src/App.js +++ b/src/App.js @@ -1,26 +1,29 @@ +// eslint-disable-next-line import/default +import PushNotificationIOS from '@react-native-community/push-notification-ios'; import analytics from '@segment/analytics-react-native'; +import { init as initSentry, setRelease } from '@sentry/react-native'; import { get, last } from 'lodash'; import PropTypes from 'prop-types'; import nanoid from 'nanoid/non-secure'; import React, { Component } from 'react'; -import { - AppRegistry, - AppState, - Linking, -} from 'react-native'; +import { AppRegistry, AppState, Linking } from 'react-native'; +// eslint-disable-next-line import/default import CodePush from 'react-native-code-push'; -import { REACT_APP_SEGMENT_API_WRITE_KEY } from 'react-native-dotenv'; -import firebase from 'react-native-firebase'; +import { + REACT_APP_SEGMENT_API_WRITE_KEY, + SENTRY_ENDPOINT, + SENTRY_ENVIRONMENT, +} from 'react-native-dotenv'; +// eslint-disable-next-line import/default import RNIOS11DeviceCheck from 'react-native-ios11-devicecheck'; +import { SafeAreaProvider } from 'react-native-safe-area-context'; +// eslint-disable-next-line import/no-unresolved import { useScreens } from 'react-native-screens'; import { connect, Provider } from 'react-redux'; import { compose, withProps } from 'recompact'; import { FlexItem } from './components/layout'; import OfflineBadge from './components/OfflineBadge'; -import { - withWalletConnectConnections, - withWalletConnectOnSessionRequest, -} from './hoc'; +import { withDeepLink, withWalletConnectOnSessionRequest } from './hoc'; import { registerTokenRefreshListener, saveFCMToken } from './model/firebase'; import * as keychain from './model/keychain'; import { Navigation } from './navigation'; @@ -31,54 +34,89 @@ import { parseQueryParams } from './utils'; if (process.env.NODE_ENV === 'development') { console.disableYellowBox = true; +} else { + initSentry({ dsn: SENTRY_ENDPOINT, environment: SENTRY_ENVIRONMENT }); } -useScreens(); +CodePush.getUpdateMetadata().then(update => { + if (update) { + setRelease(update.appVersion + '-codepush:' + update.label); + } +}); + +useScreens(false); class App extends Component { static propTypes = { - appInitTimestamp: PropTypes.number, + addDeepLinkRequest: PropTypes.func, requestsForTopic: PropTypes.func, - sortedWalletConnectors: PropTypes.arrayOf(PropTypes.object), - walletConnectClearTimestamp: PropTypes.func, walletConnectOnSessionRequest: PropTypes.func, - walletConnectUpdateTimestamp: PropTypes.func, + }; + + state = { appState: AppState.currentState }; + + async componentDidMount() { + AppState.addEventListener('change', this.handleAppStateChange); + Linking.addEventListener('url', this.handleOpenLinkingURL); + await this.handleInitializeAnalytics(); + saveFCMToken(); + this.onTokenRefreshListener = registerTokenRefreshListener(); + PushNotificationIOS.addEventListener( + 'notification', + this.onRemoteNotification + ); } - state = { appState: AppState.currentState } + componentWillUnmount() { + AppState.removeEventListener('change', this.handleAppStateChange); + Linking.removeEventListener('url', this.handleOpenLinkingURL); + PushNotificationIOS.removeEventListener( + 'notification', + this.onRemoteNotification + ); + this.onTokenRefreshListener(); + } + + onRemoteNotification = notification => { + const { appState } = this.state; + const topic = get(notification, '_data.topic'); + notification.finish(PushNotificationIOS.FetchResult.NoData); + const shouldOpenAutomatically = + appState === 'active' || appState === 'inactive'; + this.onPushNotificationOpened(topic, shouldOpenAutomatically); + }; handleOpenLinkingURL = ({ url }) => { - Linking.canOpenURL(url).then((supported) => { + const { addDeepLinkRequest, walletConnectOnSessionRequest } = this.props; + Linking.canOpenURL(url).then(supported => { if (supported) { - const { uri, redirectUrl } = parseQueryParams(url); - - const redirect = () => Linking.openURL(redirectUrl); - this.props.walletConnectOnSessionRequest(uri, redirect); + const { type, ...remainingParams } = parseQueryParams(url); + if (type && type === 'walletconnect') { + const { uri, redirectUrl } = remainingParams; + const redirect = () => Linking.openURL(redirectUrl); + walletConnectOnSessionRequest(uri, redirect); + } else { + addDeepLinkRequest(remainingParams); + } } }); - } + }; - onPushNotificationOpened = (topic, autoOpened = false, fromLocal = false) => { - const { appInitTimestamp, requestsForTopic } = this.props; + onPushNotificationOpened = (topic, openAutomatically = false) => { + const { requestsForTopic } = this.props; const requests = requestsForTopic(topic); - if (requests && requests.length === 1) { - const request = requests[0]; - - const transactionTimestamp = get(request, 'displayDetails.timestampInMs'); - const isNewTransaction = appInitTimestamp && (transactionTimestamp > appInitTimestamp); - - if (!autoOpened || isNewTransaction) { - return Navigation.handleAction({ - params: { autoOpened, transactionDetails: request }, - routeName: 'ConfirmRequest', - }); - } + if (openAutomatically && requests) { + return Navigation.handleAction({ + params: { openAutomatically, transactionDetails: last(requests) }, + routeName: 'ConfirmRequest', + }); } - if (fromLocal) { + if (requests && requests.length === 1) { + const request = requests[0]; return Navigation.handleAction({ - params: { autoOpened, transactionDetails: last(requests) }, + params: { openAutomatically, transactionDetails: request }, routeName: 'ConfirmRequest', }); } @@ -86,49 +124,14 @@ class App extends Component { return Navigation.handleAction({ routeName: 'ProfileScreen' }); }; - async componentDidMount() { - AppState.addEventListener('change', this.handleAppStateChange); - Linking.addEventListener('url', this.handleOpenLinkingURL); - await this.handleInitializeAnalytics(); - firebase.notifications().getInitialNotification().then(notificationOpen => { - if (notificationOpen) { - const topic = get(notificationOpen, 'notification.data.topic'); - this.onPushNotificationOpened(topic, false); - } - }); - - saveFCMToken(); - this.onTokenRefreshListener = registerTokenRefreshListener(); - - // notification while app in foreground - this.notificationListener = firebase.notifications().onNotification(notification => { - const route = Navigation.getActiveRouteName(); - if (route === 'ConfirmRequest') { - const localNotification = new firebase.notifications.Notification() - .setTitle(notification.title) - .setBody(notification.body) - .setData({ ...notification.data, fromLocal: true }); - firebase.notifications().displayNotification(localNotification); - } else { - const topic = get(notification, 'data.topic'); - this.onPushNotificationOpened(topic, true); - } - }); - - // notification opened from background - this.notificationOpenedListener = firebase.notifications().onNotificationOpened(notificationOpen => { - const topic = get(notificationOpen, 'notification.data.topic'); - const fromLocal = get(notificationOpen, 'notification.data.fromLocal', false); - this.onPushNotificationOpened(topic, false, fromLocal); - }); - } - handleInitializeAnalytics = async () => { - const storedIdentifier = await keychain.loadString('analyticsUserIdentifier'); + const storedIdentifier = await keychain.loadString( + 'analyticsUserIdentifier' + ); if (!storedIdentifier) { const identifier = await RNIOS11DeviceCheck.getToken() - .then((deviceId) => deviceId) + .then(deviceId => deviceId) .catch(() => nanoid()); await keychain.saveString('analyticsUserIdentifier', identifier); analytics.identify(identifier); @@ -141,51 +144,37 @@ class App extends Component { trackAppLifecycleEvents: true, trackAttributionData: true, }); - } + }; - handleAppStateChange = async (nextAppState) => { + handleAppStateChange = async nextAppState => { if (nextAppState === 'active') { - this.props.walletConnectUpdateTimestamp(); - await firebase.notifications().removeAllDeliveredNotifications(); - } - if (nextAppState === 'background') { - this.props.walletConnectClearTimestamp(); + PushNotificationIOS.removeAllDeliveredNotifications(); } this.setState({ appState: nextAppState }); - } - - componentWillUnmount() { - AppState.removeEventListener('change', this.handleAppStateChange); - Linking.removeEventListener('url', this.handleOpenLinkingURL); - this.notificationListener(); - this.notificationOpenedListener(); - this.onTokenRefreshListener(); - } + }; - handleNavigatorRef = (navigatorRef) => Navigation.setTopLevelNavigator(navigatorRef) + handleNavigatorRef = navigatorRef => + Navigation.setTopLevelNavigator(navigatorRef); render = () => ( - - - - - - - ) + + + + + + + + + ); } const AppWithRedux = compose( withProps({ store }), - withWalletConnectConnections, + withDeepLink, withWalletConnectOnSessionRequest, - connect( - ({ walletconnect: { appInitTimestamp } }) => ({ appInitTimestamp }), - { - requestsForTopic, - }, - ), + connect(null, { + requestsForTopic, + }) )(App); const AppWithCodePush = CodePush({ diff --git a/src/assets/addContactIcon.png b/src/assets/addContactIcon.png new file mode 100755 index 00000000000..bf1989f0b8e Binary files /dev/null and b/src/assets/addContactIcon.png differ diff --git a/src/assets/addContactIcon@2x.png b/src/assets/addContactIcon@2x.png new file mode 100755 index 00000000000..4721b93e612 Binary files /dev/null and b/src/assets/addContactIcon@2x.png differ diff --git a/src/assets/addContactIcon@3x.png b/src/assets/addContactIcon@3x.png new file mode 100755 index 00000000000..4eedb8144c6 Binary files /dev/null and b/src/assets/addContactIcon@3x.png differ diff --git a/src/assets/family-dropdown-arrow.png b/src/assets/family-dropdown-arrow.png index 112863ed817..a800285173f 100644 Binary files a/src/assets/family-dropdown-arrow.png and b/src/assets/family-dropdown-arrow.png differ diff --git a/src/assets/family-dropdown-arrow@2x.png b/src/assets/family-dropdown-arrow@2x.png index 9c2ec6cb03c..0579ce1de4d 100644 Binary files a/src/assets/family-dropdown-arrow@2x.png and b/src/assets/family-dropdown-arrow@2x.png differ diff --git a/src/assets/family-dropdown-arrow@3x.png b/src/assets/family-dropdown-arrow@3x.png index 34736a21065..2669f8bed6c 100644 Binary files a/src/assets/family-dropdown-arrow@3x.png and b/src/assets/family-dropdown-arrow@3x.png differ diff --git a/src/assets/show-all-arrow.png b/src/assets/show-all-arrow.png new file mode 100644 index 00000000000..2f510be4f86 Binary files /dev/null and b/src/assets/show-all-arrow.png differ diff --git a/src/assets/show-all-arrow@2x.png b/src/assets/show-all-arrow@2x.png new file mode 100644 index 00000000000..b991867e1d3 Binary files /dev/null and b/src/assets/show-all-arrow@2x.png differ diff --git a/src/assets/show-all-arrow@3x.png b/src/assets/show-all-arrow@3x.png new file mode 100644 index 00000000000..8e560ca904c Binary files /dev/null and b/src/assets/show-all-arrow@3x.png differ diff --git a/src/assets/spinner.png b/src/assets/spinner.png index d6a6fb0b6ce..a43b62f33de 100644 Binary files a/src/assets/spinner.png and b/src/assets/spinner.png differ diff --git a/src/assets/spinner@2x.png b/src/assets/spinner@2x.png index 18eec35d4ac..8ddd537bd96 100644 Binary files a/src/assets/spinner@2x.png and b/src/assets/spinner@2x.png differ diff --git a/src/assets/spinner@3x.png b/src/assets/spinner@3x.png index aa0dfa68961..ddbf2629ba1 100644 Binary files a/src/assets/spinner@3x.png and b/src/assets/spinner@3x.png differ diff --git a/src/assets/swipeToDelete.png b/src/assets/swipeToDelete.png new file mode 100755 index 00000000000..974666e83bc Binary files /dev/null and b/src/assets/swipeToDelete.png differ diff --git a/src/assets/swipeToDelete@2x.png b/src/assets/swipeToDelete@2x.png new file mode 100755 index 00000000000..2a3b0814630 Binary files /dev/null and b/src/assets/swipeToDelete@2x.png differ diff --git a/src/assets/swipeToDelete@3x.png b/src/assets/swipeToDelete@3x.png new file mode 100755 index 00000000000..b9b876e756b Binary files /dev/null and b/src/assets/swipeToDelete@3x.png differ diff --git a/src/assets/swipeToEdit.png b/src/assets/swipeToEdit.png new file mode 100755 index 00000000000..dc19362c3ab Binary files /dev/null and b/src/assets/swipeToEdit.png differ diff --git a/src/assets/swipeToEdit@2x.png b/src/assets/swipeToEdit@2x.png new file mode 100755 index 00000000000..88473d73a2e Binary files /dev/null and b/src/assets/swipeToEdit@2x.png differ diff --git a/src/assets/swipeToEdit@3x.png b/src/assets/swipeToEdit@3x.png new file mode 100755 index 00000000000..ad3ecb0d3b9 Binary files /dev/null and b/src/assets/swipeToEdit@3x.png differ diff --git a/src/components/ActivityIndicator.js b/src/components/ActivityIndicator.js index bbc150788c4..38af1b9bce4 100644 --- a/src/components/ActivityIndicator.js +++ b/src/components/ActivityIndicator.js @@ -3,15 +3,9 @@ import React from 'react'; import { UIActivityIndicator } from 'react-native-indicators'; import { View } from 'react-primitives'; import stylePropType from 'react-style-proptype'; -import { pure } from 'recompact'; import { colors, position } from '../styles'; -const ActivityIndicator = ({ - color, - isInteraction, - size, - style, -}) => ( +const ActivityIndicator = ({ color, isInteraction, size, style }) => ( true; +export default React.memo(ActivityIndicator, neverRerender); diff --git a/src/components/AddFundsInterstitial.js b/src/components/AddFundsInterstitial.js index 5d952dad81f..4f2314cb197 100644 --- a/src/components/AddFundsInterstitial.js +++ b/src/components/AddFundsInterstitial.js @@ -41,7 +41,7 @@ const Paragraph = styled(Text).attrs({ const buildInterstitialTransform = offsetY => ({ transform: [ { translateX: (ButtonContainerWidth / 2) * -1 }, - { translateY: ((ButtonContainerHeight / 2) * -1) + 25 + offsetY }, + { translateY: (ButtonContainerHeight / 2) * -1 + 25 + offsetY }, ], }); @@ -62,7 +62,8 @@ const AddFundsInterstitial = ({ Import Wallet - Use your 12 to 24 word seed phrase from an existing wallet. + Use your private key or 12 to 24 word seed phrase from an existing + wallet. @@ -82,7 +83,9 @@ export default compose( pure, withNavigation, withHandlers({ - onPressAddFunds: ({ navigation }) => () => navigation.navigate('ReceiveModal'), - onPressImportWallet: ({ navigation }) => () => navigation.navigate('ImportSeedPhraseSheet'), - }), + onPressAddFunds: ({ navigation }) => () => + navigation.navigate('ReceiveModal'), + onPressImportWallet: ({ navigation }) => () => + navigation.navigate('ImportSeedPhraseSheet'), + }) )(AddFundsInterstitial); diff --git a/src/components/Avatar.js b/src/components/Avatar.js index 9c38e561241..0633d4dce6a 100644 --- a/src/components/Avatar.js +++ b/src/components/Avatar.js @@ -9,7 +9,7 @@ import { ShadowStack } from './shadow-stack'; const Container = styled(Centered)` ${position.cover} - background-color: ${colors.lightGrey}; + background-color: ${colors.lighterGrey}; border-radius: ${({ size }) => size}; `; @@ -29,10 +29,7 @@ const Avatar = ({ size, source }) => ( style={position.sizeAsObject(size)} /> ) : ( - + )} diff --git a/src/components/BlurOverlay.js b/src/components/BlurOverlay.js deleted file mode 100644 index 7e09ef5184e..00000000000 --- a/src/components/BlurOverlay.js +++ /dev/null @@ -1,57 +0,0 @@ -import { VibrancyView } from '@react-native-community/blur'; -import PropTypes from 'prop-types'; -import React from 'react'; -import { Animated, StyleSheet } from 'react-native'; -import { pure } from 'recompact'; -import { position } from '../styles'; - -const styles = StyleSheet.create({ - overlay: { - ...position.coverAsObject, - zIndex: 1, - }, -}); - -const BlurOverlay = ({ - backgroundColor, - blurAmount, - blurType, - opacity, - translateX, - translateY, -}) => ( - - - -); - -BlurOverlay.propTypes = { - backgroundColor: PropTypes.string, - blurAmount: PropTypes.number, - blurType: PropTypes.oneOf(['dark', 'light', 'xlight']).isRequired, - opacity: PropTypes.object, - translateX: PropTypes.any, - translateY: PropTypes.any, -}; - -BlurOverlay.defaultProps = { - blurAmount: 15, - blurType: 'dark', - translateX: 0, - translateY: 0, -}; - -export default pure(BlurOverlay); diff --git a/src/components/ContextMenu.js b/src/components/ContextMenu.js index 30474d50714..b0c69df530f 100644 --- a/src/components/ContextMenu.js +++ b/src/components/ContextMenu.js @@ -26,29 +26,31 @@ class ContextMenu extends PureComponent { options: PropTypes.arrayOf(PropTypes.string).isRequired, setIsActionSheetOpen: PropTypes.func, title: PropTypes.string, - } + }; static defaultProps = { options: [], - } + }; - actionSheetRef = null + actionSheetRef = null; - handleActionSheetRef = (ref) => { this.actionSheetRef = ref; } + handleActionSheetRef = ref => { + this.actionSheetRef = ref; + }; showActionSheet = () => { if (this.props.isActionSheetOpen) return; this.props.setIsActionSheetOpen(true); this.actionSheetRef.show(); - } + }; - handlePressActionSheet = (buttonIndex) => { + handlePressActionSheet = buttonIndex => { if (this.props.onPressActionSheet) { this.props.onPressActionSheet(buttonIndex); } this.props.setIsActionSheetOpen(false); - } + }; render = () => ( @@ -63,12 +65,14 @@ class ContextMenu extends PureComponent { - ) + ); } export default withActionSheetManager(ContextMenu); diff --git a/src/components/CopyTooltip.js b/src/components/CopyTooltip.js index 028e84f5160..73939a17fc3 100644 --- a/src/components/CopyTooltip.js +++ b/src/components/CopyTooltip.js @@ -10,46 +10,49 @@ class CopyTooltip extends PureComponent { static propTypes = { activeOpacity: PropTypes.number, navigation: PropTypes.object, + setSafeTimeout: PropTypes.func, textToCopy: PropTypes.string, tooltipText: PropTypes.string, - } + }; static defaultProps = { activeOpacity: 0.666, tooltipText: 'Copy', - } - - tooltip = null + }; componentDidUpdate = () => { if (this.props.navigation.state.isTransitioning) { this.handleHideTooltip(); } - } + }; + + componentWillUnmount = () => this.handleHideTooltip(); - componentWillUnmount = () => this.handleHideTooltip() + tooltip = null; - handleCopy = () => Clipboard.setString(this.props.textToCopy) + handleCopy = () => Clipboard.setString(this.props.textToCopy); - handleHideTooltip = () => this.tooltip.hideMenu() + handleHideTooltip = () => this.tooltip.hideMenu(); - handlePressIn = () => this.tooltip.showMenu() + handlePress = () => this.tooltip.showMenu(); - handleRef = (ref) => { this.tooltip = ref; } + handleRef = ref => { + this.tooltip = ref; + }; render = () => ( - ) + ); } export default compose( withNavigation, - onlyUpdateForKeys(['textToCopy', 'tooltipText']), + onlyUpdateForKeys(['textToCopy', 'tooltipText']) )(CopyTooltip); diff --git a/src/components/Divider.js b/src/components/Divider.js index ffa5b1b68bb..af915fc2049 100644 --- a/src/components/Divider.js +++ b/src/components/Divider.js @@ -1,9 +1,4 @@ -import { - constant, - isNil, - isNumber, - times, -} from 'lodash'; +import { constant, isNil, isNumber, times } from 'lodash'; import PropTypes from 'prop-types'; import React from 'react'; import { onlyUpdateForKeys } from 'recompact'; @@ -12,7 +7,7 @@ import { borders, colors, position } from '../styles'; const DefaultDividerSize = 2; -const buildInsetFromProps = (inset) => { +const buildInsetFromProps = inset => { if (!inset) return times(4, constant(0)); if (isNumber(inset)) return times(4, inset); @@ -26,14 +21,14 @@ const buildInsetFromProps = (inset) => { ]; }; -const horizontalBorderLineStyles = (inset) => css` +const horizontalBorderLineStyles = inset => css` ${inset[3] ? borders.buildRadius('left', 2) : null} ${inset[1] ? borders.buildRadius('right', 2) : null} left: ${inset[3]}; right: ${inset[1]}; `; -const verticalBorderLineStyles = (inset) => css` +const verticalBorderLineStyles = inset => css` ${inset[2] ? borders.buildRadius('bottom', 2) : null} ${inset[0] ? borders.buildRadius('top', 2) : null} bottom: ${inset[2]}; @@ -42,18 +37,17 @@ const verticalBorderLineStyles = (inset) => css` const BorderLine = styled.View` ${position.cover}; - ${({ horizontal, inset }) => ( + ${({ horizontal, inset }) => horizontal ? horizontalBorderLineStyles(inset) - : verticalBorderLineStyles(inset) - )}; + : verticalBorderLineStyles(inset)}; background-color: ${({ color }) => color}; bottom: 0; top: 0; `; const Container = styled.View` - background-color: ${({ backgroundColor }) => (backgroundColor || colors.white)}; + background-color: ${({ backgroundColor }) => backgroundColor || colors.white}; flex-shrink: 0; height: ${({ horizontal, size }) => (horizontal ? size : '100%')}; width: ${({ horizontal, size }) => (horizontal ? '100%' : size)}; @@ -61,13 +55,7 @@ const Container = styled.View` const enhance = onlyUpdateForKeys(['color', 'inset']); -const Divider = enhance(({ - color, - horizontal, - inset, - size, - ...props -}) => ( +const Divider = enhance(({ color, horizontal, inset, size, ...props }) => ( { + const tab = React.useRef(null); + const pan = React.useRef(null); + + const onHandlerStateChange = event([ + { + nativeEvent: { + state: s => cond(cond(cond(eq(State.END, s), call([], onTouchEnd)))), + }, + }, + ]); + + return ( + + + + + + + + + + ); +}; + +GestureBlocker.propTypes = { + onTouchEnd: PropTypes.func, + type: PropTypes.string, +}; + +GestureBlocker.defaultProps = { + onTouchEnd: () => null, +}; + +export default React.memo(GestureBlocker); diff --git a/src/components/Highlight.js b/src/components/Highlight.js index 5ef58f593ec..944fc857269 100644 --- a/src/components/Highlight.js +++ b/src/components/Highlight.js @@ -4,12 +4,7 @@ import { onlyUpdateForKeys } from 'recompact'; import { View } from 'react-primitives'; import { colors, position } from '../styles'; -const Highlight = ({ - backgroundColor, - borderRadius, - visible, - ...props -}) => ( +const Highlight = ({ backgroundColor, borderRadius, visible, ...props }) => ( event => { + onLoad: ({ id, imageDimensionsCache, onLoad, updateCache }) => event => { event.persist(); - const { nativeEvent: { height, width } } = event; + const { + nativeEvent: { height, width }, + } = event; if (!imageDimensionsCache[id]) { updateCache({ @@ -29,7 +26,7 @@ const ImageWithCachedDimensions = compose( onLoad(event); } }, - }), + }) )(FastImage); export default ImageWithCachedDimensions; diff --git a/src/components/InnerBorder.js b/src/components/InnerBorder.js index 4b097c8c0da..9b04652382c 100644 --- a/src/components/InnerBorder.js +++ b/src/components/InnerBorder.js @@ -4,13 +4,7 @@ import { View } from 'react-primitives'; import { onlyUpdateForPropTypes } from 'recompact'; import { colors, position } from '../styles'; -const InnerBorder = ({ - color, - opacity, - radius, - width, - ...props -}) => ( +const InnerBorder = ({ color, opacity, radius, width, ...props }) => ( this.runAnimation() - - componentDidUpdate = () => this.runAnimation() - - runAnimation = () => { - const { isConnected } = this.props; +const OfflineBadge = () => { + const isConnected = useInternetStatus(); - return spring(this.animation, { - damping: 14, - mass: 1, - overshootClamping: false, - restDisplacementThreshold: 0.001, - restSpeedThreshold: 0.001, - stiffness: 121.6, - toValue: isConnected ? DefaultAnimationValue : 0, - }).start(({ finished }) => { - if (!finished) return null; - return isConnected - ? analytics.track('Reconnected after offline') - : analytics.track('Offline / lost connection'); - }); - } + const animation = useSpringTransition(bin(isConnected), { + damping: 14, + mass: 1, + overshootClamping: false, + restDisplacementThreshold: 0.001, + restSpeedThreshold: 0.001, + stiffness: 121.6, + }); - render = () => ( - - - - Offline - - - ) -} + + + + Offline + + + + ); +}; -export default compose( - withNetInfo, - onlyUpdateForKeys(['isConnected']), -)(OfflineBadge); +const neverRerender = () => true; +export default React.memo(OfflineBadge, neverRerender); diff --git a/src/components/QRCodeDisplay.js b/src/components/QRCodeDisplay.js index 0cb058f17a5..42731fc27e7 100644 --- a/src/components/QRCodeDisplay.js +++ b/src/components/QRCodeDisplay.js @@ -4,11 +4,7 @@ import QRCode from 'react-native-qrcode-svg'; import { onlyUpdateForPropTypes } from 'recompact'; const QRCodeDisplay = ({ size, value, ...props }) => ( - + ); QRCodeDisplay.propTypes = { diff --git a/src/components/SendComponentWithData.js b/src/components/SendComponentWithData.js index d731c257bcf..b1e6e860db1 100644 --- a/src/components/SendComponentWithData.js +++ b/src/components/SendComponentWithData.js @@ -1,10 +1,13 @@ -import React, { Component } from 'react'; +import { get } from 'lodash'; import PropTypes from 'prop-types'; +import React, { Component } from 'react'; import { connect } from 'react-redux'; import { compose } from 'recompact'; -import { get } from 'lodash'; +import { estimateGasLimit } from '../handlers/web3'; +import { greaterThan } from '../helpers/utilities'; +import { checkIsValidAddress } from '../helpers/validators'; +import { withAccountData, withGas, withUniqueTokens } from '../hoc'; import lang from '../languages'; -import { withAccountData, withUniqueTokens } from '../hoc'; import { sendClearFields, sendMaxBalance, @@ -12,13 +15,10 @@ import { sendToggleConfirmationView, sendTransaction, sendUpdateAssetAmount, - sendUpdateGasPrice, sendUpdateNativeAmount, sendUpdateRecipient, sendUpdateSelected, } from '../redux/send'; -import { isValidAddress } from '../helpers/validators'; -import { greaterThan } from '../helpers/utilities'; import { ethereumUtils } from '../utils'; const mapStateToProps = ({ send, settings }) => ({ @@ -27,12 +27,7 @@ const mapStateToProps = ({ send, settings }) => ({ assetAmount: send.assetAmount, confirm: send.confirm, fetching: send.fetching, - gasLimit: send.gasLimit, - gasPrice: send.gasPrice, - gasPriceOption: send.gasPriceOption, - gasPrices: send.gasPrices, isSufficientBalance: send.isSufficientBalance, - isSufficientGas: send.isSufficientGas, nativeAmount: send.nativeAmount, nativeCurrency: settings.nativeCurrency, network: settings.network, @@ -52,16 +47,16 @@ const mapStateToProps = ({ send, settings }) => ({ export const withSendComponentWithData = (SendComponent, options) => { class SendComponentWithData extends Component { static propTypes = { - accountType: PropTypes.string.isRequired, + accountType: PropTypes.string, address: PropTypes.string, assetAmount: PropTypes.string.isRequired, assets: PropTypes.array.isRequired, confirm: PropTypes.bool.isRequired, fetching: PropTypes.bool.isRequired, - gasLimit: PropTypes.number.isRequired, - gasPrice: PropTypes.object.isRequired, - gasPriceOption: PropTypes.string.isRequired, + gasLimit: PropTypes.number, gasPrices: PropTypes.object.isRequired, + gasUpdateDefaultGasLimit: PropTypes.func.isRequired, + gasUpdateTxFee: PropTypes.func.isRequired, isSufficientBalance: PropTypes.bool.isRequired, isSufficientGas: PropTypes.bool.isRequired, nativeAmount: PropTypes.string.isRequired, @@ -69,16 +64,18 @@ export const withSendComponentWithData = (SendComponent, options) => { network: PropTypes.string.isRequired, recipient: PropTypes.string.isRequired, selected: PropTypes.object.isRequired, + selectedGasPrice: PropTypes.shape({ txFee: PropTypes.object }), + selectedGasPriceOption: PropTypes.string.isRequired, sendClearFields: PropTypes.func.isRequired, sendMaxBalance: PropTypes.func.isRequired, sendModalInit: PropTypes.func.isRequired, sendToggleConfirmationView: PropTypes.func.isRequired, sendTransaction: PropTypes.func.isRequired, sendUpdateAssetAmount: PropTypes.func.isRequired, - sendUpdateGasPrice: PropTypes.func.isRequired, sendUpdateNativeAmount: PropTypes.func.isRequired, sendUpdateRecipient: PropTypes.func.isRequired, sendUpdateSelected: PropTypes.func.isRequired, + txFees: PropTypes.object.isRequired, txHash: PropTypes.string.isRequired, }; @@ -92,26 +89,45 @@ export const withSendComponentWithData = (SendComponent, options) => { this.defaultAsset = options.defaultAsset; this.gasFormat = options.gasFormat || 'long'; - this.sendTransactionCallback = options.sendTransactionCallback || function noop() {}; + this.sendTransactionCallback = + options.sendTransactionCallback || function noop() {}; } componentDidMount() { - this.props.sendModalInit({ defaultAsset: this.defaultAsset, gasFormat: this.gasFormat }); + this.props.sendModalInit({ + defaultAsset: this.defaultAsset, + gasFormat: this.gasFormat, + }); + this.props.gasUpdateDefaultGasLimit(); } async componentDidUpdate(prevProps) { - const { assetAmount, recipient, selected } = this.props; + const { address, assetAmount, recipient, selected } = this.props; if (recipient !== prevProps.recipient) { - const validAddress = await isValidAddress(recipient); + const validAddress = await checkIsValidAddress(recipient); + // eslint-disable-next-line react/no-did-update-set-state this.setState({ isValidAddress: validAddress }); } if (this.state.isValidAddress) { - if ((selected.symbol !== prevProps.selected.symbol) - || (recipient !== prevProps.recipient) - || (assetAmount !== prevProps.assetAmount)) { - this.props.sendUpdateGasPrice(); + if ( + selected.symbol !== prevProps.selected.symbol || + recipient !== prevProps.recipient || + assetAmount !== prevProps.assetAmount + ) { + estimateGasLimit({ + address, + amount: assetAmount, + asset: selected, + recipient, + }) + .then(gasLimit => { + this.props.gasUpdateTxFee(gasLimit); + }) + .catch(() => { + this.props.gasUpdateTxFee(); + }); } } } @@ -119,14 +135,14 @@ export const withSendComponentWithData = (SendComponent, options) => { onAddressInputFocus = async () => { const { recipient } = this.props; - const validAddress = await isValidAddress(recipient); + const validAddress = await checkIsValidAddress(recipient); this.setState({ isValidAddress: validAddress }); }; onAddressInputBlur = async () => { const { recipient } = this.props; - const validAddress = await isValidAddress(recipient); + const validAddress = await checkIsValidAddress(recipient); this.setState({ isValidAddress: validAddress }); }; @@ -140,27 +156,31 @@ export const withSendComponentWithData = (SendComponent, options) => { this.props.sendModalInit({ defaultAsset: this.defaultAsset }); }; - onSubmit = async (event) => { + onSubmit = async event => { if (event && typeof event.preventDefault === 'function') { event.preventDefault(); } - if (!this.props.gasPrice.txFee) { + if (!this.props.selectedGasPrice.txFee) { return; } // Balance checks if (!this.props.confirm) { - const isAddressValid = await isValidAddress(this.props.recipient); + const isAddressValid = await checkIsValidAddress(this.props.recipient); if (!isAddressValid) { console.log(lang.t('notification.error.invalid_address')); return; } if (this.props.selected.address === 'eth') { - const { requestedAmount, balance, amountWithFees } = ethereumUtils.transactionData( + const { + requestedAmount, + balance, + amountWithFees, + } = ethereumUtils.transactionData( this.props.assets, this.props.assetAmount, - this.props.gasPrice, + this.props.selectedGasPrice ); if (greaterThan(requestedAmount, balance)) { @@ -170,10 +190,14 @@ export const withSendComponentWithData = (SendComponent, options) => { return; } } else if (!this.props.selected.isNft) { - const { requestedAmount, balance, txFee } = ethereumUtils.transactionData( + const { + requestedAmount, + balance, + txFee, + } = ethereumUtils.transactionData( this.props.assets, this.props.assetAmount, - this.props.gasPrice, + this.props.selectedGasPrice ); const tokenBalance = get(this.props, 'selected.balance.amount'); @@ -188,41 +212,40 @@ export const withSendComponentWithData = (SendComponent, options) => { this.props.sendToggleConfirmationView(true); - return this.props.sendTransaction({ - address: this.props.address, - amount: this.props.assetAmount, - asset: this.props.selected, - gasLimit: this.props.gasLimit, - gasPrice: this.props.gasPrice, - recipient: this.props.recipient, - }, this.sendTransactionCallback); + return this.props.sendTransaction( + { + address: this.props.address, + amount: this.props.assetAmount, + asset: this.props.selected, + gasLimit: this.props.gasLimit, + gasPrice: this.props.selectedGasPrice, + recipient: this.props.recipient, + }, + this.sendTransactionCallback + ); } }; - updateGasPrice = gasPrice => { - this.props.sendUpdateGasPrice(gasPrice); - }; - onClose = () => { this.props.sendClearFields(); }; - updateGasPrice = gasPrice => { - this.props.sendUpdateGasPrice(gasPrice); - }; - // QR Code Reader Handlers - toggleQRCodeReader = () => this.setState({ showQRCodeReader: !this.state.showQRCodeReader }); + toggleQRCodeReader = () => + this.setState(prevState => ({ + showQRCodeReader: !prevState.showQRCodeReader, + })); - onQRCodeValidate = async (rawData) => { + onQRCodeValidate = async rawData => { const data = rawData.match(/0x\w{40}/g) ? rawData.match(/0x\w{40}/g)[0] : null; let result = false; if (data) { - result = await isValidAddress(data); + result = await checkIsValidAddress(data); } - const onError = () => console.log(lang.t('notification.error.invalid_address_scanned')); + const onError = () => + console.log(lang.t('notification.error.invalid_address_scanned')); return { data, onError, result }; }; @@ -239,17 +262,16 @@ export const withSendComponentWithData = (SendComponent, options) => { return ( ); @@ -264,12 +286,12 @@ export const withSendComponentWithData = (SendComponent, options) => { sendToggleConfirmationView, sendTransaction, sendUpdateAssetAmount, - sendUpdateGasPrice, sendUpdateNativeAmount, sendUpdateRecipient, sendUpdateSelected, }), + withGas, withAccountData, - withUniqueTokens, + withUniqueTokens )(SendComponentWithData); }; diff --git a/src/components/Spinner.js b/src/components/Spinner.js new file mode 100644 index 00000000000..3b04b315cb1 --- /dev/null +++ b/src/components/Spinner.js @@ -0,0 +1,33 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import FastImage from 'react-native-fast-image'; +import SpinnerImageSource from '../assets/spinner.png'; +import { colors, position } from '../styles'; +import { SpinAnimation } from './animations'; +import { Centered } from './layout'; + +const Spinner = ({ color, duration, size, ...props }) => ( + + + + + +); + +Spinner.propTypes = { + color: PropTypes.string, + duration: PropTypes.number, + size: PropTypes.number, +}; + +Spinner.defaultProps = { + color: colors.white, + duration: 1500, + size: 20, +}; + +export default React.memo(Spinner); diff --git a/src/components/Tag.js b/src/components/Tag.js index d8d46f1316e..4815c834304 100644 --- a/src/components/Tag.js +++ b/src/components/Tag.js @@ -51,7 +51,7 @@ const enhance = compose( text: upperFirst(text), title: upperCase(title), })), - onlyUpdateForKeys(['text', 'title']), + onlyUpdateForKeys(['text', 'title']) ); const Tag = enhance(({ text, title, ...props }) => ( diff --git a/src/components/TouchableBackdrop.js b/src/components/TouchableBackdrop.js index 1ea865bed17..34853a4a6ad 100644 --- a/src/components/TouchableBackdrop.js +++ b/src/components/TouchableBackdrop.js @@ -1,17 +1,16 @@ import PropTypes from 'prop-types'; import React from 'react'; import { BorderlessButton } from 'react-native-gesture-handler'; -import { withNeverRerender } from '../hoc'; import { colors, position } from '../styles'; -const TouchableBackdrop = props => ( +const TouchableBackdrop = ({ zIndex, ...props }) => ( (zIndex)}; - `} {...props} + {...position.centeredAsObject} + {...position.coverAsObject} + activeOpacity={1} + backgroundColor={colors.transparent} + zIndex={zIndex} /> ); @@ -23,4 +22,5 @@ TouchableBackdrop.defaultProps = { zIndex: 0, }; -export default withNeverRerender(TouchableBackdrop); +const neverRerender = () => true; +export default React.memo(TouchableBackdrop, neverRerender); diff --git a/src/components/activity-list/ActivityList.js b/src/components/activity-list/ActivityList.js index cbcb13f8d13..a36a52970b2 100644 --- a/src/components/activity-list/ActivityList.js +++ b/src/components/activity-list/ActivityList.js @@ -1,16 +1,11 @@ import PropTypes from 'prop-types'; import React from 'react'; -import { - compose, - mapProps, - onlyUpdateForKeys, - withProps, -} from 'recompact'; +import { compose, mapProps, onlyUpdateForKeys, withProps } from 'recompact'; import { buildTransactionsSectionsSelector } from '../../helpers/transactions'; import { - withAccountAddress, withAccountSettings, withAccountTransactions, + withContacts, } from '../../hoc'; import RecyclerActivityList from './RecyclerActivityList'; @@ -25,24 +20,21 @@ const ActivityList = ({ header, isEmpty, sections }) => ( ActivityList.propTypes = { header: PropTypes.node, isEmpty: PropTypes.bool, - sections: PropTypes.arrayOf(PropTypes.shape({ - data: PropTypes.array, - renderItem: PropTypes.func, - title: PropTypes.string.isRequired, - })), + sections: PropTypes.arrayOf( + PropTypes.shape({ + data: PropTypes.array, + renderItem: PropTypes.func, + title: PropTypes.string.isRequired, + }) + ), }; export default compose( - withAccountAddress, withAccountSettings, withAccountTransactions, + withContacts, withProps(buildTransactionsSectionsSelector), - mapProps(({ - nativeCurrency, - requests, - sections, - ...props - }) => { + mapProps(({ nativeCurrency, requests, sections, ...props }) => { let pendingTransactionsCount = 0; const pendingTxSection = sections[requests.length ? 1 : 0]; @@ -59,9 +51,10 @@ export default compose( }; }), onlyUpdateForKeys([ + 'contacts', 'isEmpty', 'nativeCurrency', 'pendingTransactionsCount', 'sections', - ]), + ]) )(ActivityList); diff --git a/src/components/activity-list/ActivityListHeader.js b/src/components/activity-list/ActivityListHeader.js index 11007823242..c88fd71db3f 100644 --- a/src/components/activity-list/ActivityListHeader.js +++ b/src/components/activity-list/ActivityListHeader.js @@ -1,9 +1,4 @@ -import { - compose, - onlyUpdateForKeys, - pickProps, - withProps, -} from 'recompact'; +import { compose, onlyUpdateForKeys, pickProps, withProps } from 'recompact'; import { ListHeader } from '../list'; import { Text } from '../text'; @@ -15,9 +10,10 @@ const titleRenderer = withProps({ export default compose( pickProps(Object.keys(ListHeader.propTypes)), withProps({ + isSticky: true, shouldRasterizeIOS: true, showDivider: false, titleRenderer, }), - onlyUpdateForKeys(['title']), + onlyUpdateForKeys(['title']) )(ListHeader); diff --git a/src/components/activity-list/RecyclerActivityList.js b/src/components/activity-list/RecyclerActivityList.js index 62addde8af6..c098da593a9 100644 --- a/src/components/activity-list/RecyclerActivityList.js +++ b/src/components/activity-list/RecyclerActivityList.js @@ -1,12 +1,20 @@ import { get, times } from 'lodash'; import PropTypes from 'prop-types'; import React, { PureComponent } from 'react'; -import { RecyclerListView, DataProvider, LayoutProvider } from 'recyclerlistview'; +import { + RecyclerListView, + DataProvider, + LayoutProvider, +} from 'recyclerlistview'; import StickyContainer from 'recyclerlistview/dist/reactnative/core/StickyContainer'; import styled from 'styled-components/primitives/dist/styled-components-primitives.esm'; import { buildTransactionUniqueIdentifier } from '../../helpers/transactions'; import { colors } from '../../styles'; -import { deviceUtils, isNewValueForPath, safeAreaInsetValues } from '../../utils'; +import { + deviceUtils, + isNewValueForPath, + safeAreaInsetValues, +} from '../../utils'; import { AssetListItemSkeleton } from '../asset-list'; import { ContractInteractionCoinRow, @@ -35,38 +43,50 @@ const LoadingState = ({ children }) => ( {children} - + - {times(11, index => )} + {times(11, index => ( + + ))} ); const hasRowChanged = (r1, r2) => { - if (r1.hash === '_header' && isNewValueForPath(r1, r2, 'header.props.accountAddress')) { + if ( + r1.hash === '_header' && + isNewValueForPath(r1, r2, 'header.props.accountAddress') + ) { return true; } const r1Key = r1.hash ? r1.hash : get(r1, 'displayDetails.timestampInMs', ''); const r2Key = r2.hash ? r2.hash : get(r2, 'displayDetails.timestampInMs', ''); - return (r1Key !== r2Key) - || isNewValueForPath(r1, r2, 'native.symbol') - || isNewValueForPath(r1, r2, 'pending'); + return ( + r1Key !== r2Key || + isNewValueForPath(r1, r2, 'contact') || + isNewValueForPath(r1, r2, 'native.symbol') || + isNewValueForPath(r1, r2, 'pending') + ); }; export default class RecyclerActivityList extends PureComponent { static propTypes = { header: PropTypes.node, isLoading: PropTypes.bool, - sections: PropTypes.arrayOf(PropTypes.shape({ - data: PropTypes.array, - title: PropTypes.string.isRequired, - })), + sections: PropTypes.arrayOf( + PropTypes.shape({ + data: PropTypes.array, + title: PropTypes.string.isRequired, + }) + ), }; constructor(args) { @@ -103,24 +123,31 @@ export default class RecyclerActivityList extends PureComponent { } else if (type === ViewTypes.HEADER) { dim.height = 35; } else { - dim.height = this.props.isLoading ? deviceUtils.dimensions.height : 204; + dim.height = this.props.isLoading + ? deviceUtils.dimensions.height + : 204; } - }, + } ); } static getDerivedStateFromProps(props, state) { const headersIndices = []; - const items = props.sections.reduce((ctx, section) => { - headersIndices.push(ctx.length); - return ctx - .concat([{ - hash: section.title, - title: section.title, - }]) - .concat(section.data) - .concat([{ hash: `${section.title}_end` }]); // footer - }, [{ hash: '_header', header: props.header }]); // header + const items = props.sections.reduce( + (ctx, section) => { + headersIndices.push(ctx.length); + return ctx + .concat([ + { + hash: section.title, + title: section.title, + }, + ]) + .concat(section.data) + .concat([{ hash: `${section.title}_end` }]); // footer + }, + [{ hash: '_header', header: props.header }] + ); // header if (items.length > 1) { items.pop(); // remove last footer } @@ -130,25 +157,28 @@ export default class RecyclerActivityList extends PureComponent { }; } - getStableId = (index) => { + getStableId = index => { const row = get(this.state, `dataProvider._data[${index}]`); return buildTransactionUniqueIdentifier(row); }; rowRenderer = (type, data) => { if (type === ViewTypes.COMPONENT_HEADER) { - return this.props.isLoading - ? {data.header} - : data.header; + return this.props.isLoading ? ( + {data.header} + ) : ( + data.header + ); } if (type === ViewTypes.HEADER) return ; if (type === ViewTypes.FOOTER) return ; if (!data) return null; if (!data.hash) return ; - if (!data.symbol && data.dappName) return ; + if (!data.symbol && data.dappName) + return ; return ; - } + }; render = () => ( @@ -165,5 +195,5 @@ export default class RecyclerActivityList extends PureComponent { /> - ) + ); } diff --git a/src/components/alerts/Alert.js b/src/components/alerts/Alert.js index 4b1564e6762..de9b3df78d7 100644 --- a/src/components/alerts/Alert.js +++ b/src/components/alerts/Alert.js @@ -1,8 +1,9 @@ import BaseAlert from './BaseAlert'; -const Alert = (options) => BaseAlert({ - ...options, - alertType: 'alert', -}); +const Alert = options => + BaseAlert({ + ...options, + alertType: 'alert', + }); export default Alert; diff --git a/src/components/alerts/BaseAlert.js b/src/components/alerts/BaseAlert.js index e4bd083c106..49e55ed5954 100644 --- a/src/components/alerts/BaseAlert.js +++ b/src/components/alerts/BaseAlert.js @@ -1,22 +1,18 @@ import PropTypes from 'prop-types'; import { Alert } from 'react-native'; -const BaseAlert = ({ - alertType, - buttons, - callback, - message, - title, - type, -}) => Alert[alertType](title, message, buttons || callback, type); +const BaseAlert = ({ alertType, buttons, callback, message, title, type }) => + Alert[alertType](title, message, buttons || callback, type); BaseAlert.propTypes = { alertType: PropTypes.oneOf(['alert', 'prompt']).isRequired, - buttons: PropTypes.arrayOf(PropTypes.shape({ - onPress: PropTypes.func, - style: PropTypes.oneOf(['cancel', 'default', 'destructive']), - text: PropTypes.string.isRequired, - })), + buttons: PropTypes.arrayOf( + PropTypes.shape({ + onPress: PropTypes.func, + style: PropTypes.oneOf(['cancel', 'default', 'destructive']), + text: PropTypes.string.isRequired, + }) + ), callback: PropTypes.func, message: PropTypes.string, title: PropTypes.string.isRequired, diff --git a/src/components/alerts/Prompt.js b/src/components/alerts/Prompt.js index 5838eaa8d45..f3ba639dd03 100644 --- a/src/components/alerts/Prompt.js +++ b/src/components/alerts/Prompt.js @@ -1,8 +1,9 @@ import BaseAlert from './BaseAlert'; -const Prompt = (options) => BaseAlert({ - ...options, - alertType: 'prompt', -}); +const Prompt = options => + BaseAlert({ + ...options, + alertType: 'prompt', + }); export default Prompt; diff --git a/src/components/animations/ButtonPressAnimation.js b/src/components/animations/ButtonPressAnimation.js index cb145ac14fa..edf990ca71d 100644 --- a/src/components/animations/ButtonPressAnimation.js +++ b/src/components/animations/ButtonPressAnimation.js @@ -1,181 +1,339 @@ -import { compact } from 'lodash'; +import { omit, pick } from 'lodash'; import PropTypes from 'prop-types'; -import React, { PureComponent } from 'react'; -import { Animated } from 'react-native'; -import { State, TapGestureHandler } from 'react-native-gesture-handler'; +import React, { Fragment, Component } from 'react'; +import { InteractionManager } from 'react-native'; +import { + createNativeWrapper, + PureNativeButton, + State, +} from 'react-native-gesture-handler'; import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; -import { animations } from '../../styles'; +import Animated, { Easing } from 'react-native-reanimated'; +import { transformOrigin as transformOriginUtil } from 'react-native-redash'; +import stylePropType from 'react-style-proptype'; +import { animations, colors } from '../../styles'; import { directionPropType } from '../../utils'; +import { contains, interpolate, timing } from './procs'; -const ButtonKeyframes = animations.keyframes.button; +const { + and, + block, + call, + Clock, + cond, + createAnimatedComponent, + divide, + eq, + event, + greaterThan, + lessThan, + onChange, + or, + proc, + set, + stopClock, + Value, +} = Animated; -const DefaultAnimatedValues = { - opacity: 1, - scale: ButtonKeyframes.from.scale, - transX: 0, +const { ACTIVE, CANCELLED, END, FAILED, UNDETERMINED } = State; + +const AnimatedRawButton = createNativeWrapper( + createAnimatedComponent(PureNativeButton), + { + shouldActivateOnStart: true, + shouldCancelWhenOutside: true, + } +); + +const AnimatedRawButtonPropBlacklist = [ + 'onLongPress', + 'onPress', + 'onPressStart', +]; + +const NOOP = () => undefined; + +const HapticFeedbackTypes = { + impactHeavy: 'impactHeavy', + impactLight: 'impactLight', + impactMedium: 'impactMedium', + notificationError: 'notificationError', + notificationSuccess: 'notificationSuccess', + notificationWarning: 'notificationWarning', + selection: 'selection', }; -let buttonExcludingMutex = null; +const isBetweenProc = proc( + (scaleTo, defaultScale, lessThanCondition, greaterThanCondition) => + or( + and(lessThan(scaleTo, defaultScale), lessThanCondition), + and(greaterThan(scaleTo, defaultScale), greaterThanCondition) + ) +); -export default class ButtonPressAnimation extends PureComponent { +export default class ButtonPressAnimation extends Component { static propTypes = { activeOpacity: PropTypes.number, children: PropTypes.any, + defaultScale: PropTypes.number, disabled: PropTypes.bool, + duration: PropTypes.number, + easing: PropTypes.func, enableHapticFeedback: PropTypes.bool, + exclusive: PropTypes.bool, + hapticType: PropTypes.oneOf(Object.keys(HapticFeedbackTypes)), + isInteraction: PropTypes.bool, + minLongPressDuration: PropTypes.number, + onLongPress: PropTypes.func, onPress: PropTypes.func, + onPressStart: PropTypes.func, scaleTo: PropTypes.number, - style: PropTypes.oneOfType([PropTypes.array, PropTypes.object]), + style: stylePropType, tapRef: PropTypes.object, transformOrigin: directionPropType, - waitFor: PropTypes.any, - } + }; static defaultProps = { + activeOpacity: 1, + defaultScale: animations.keyframes.button.from.scale, + duration: 200, + easing: Easing.bezier(0.25, 0.46, 0.45, 0.94), enableHapticFeedback: true, - scaleTo: ButtonKeyframes.to.scale, - } - - state = { scaleOffsetX: null } + exclusive: true, + hapticType: HapticFeedbackTypes.selection, + minLongPressDuration: 500, + scaleTo: animations.keyframes.button.to.scale, + }; - opacity = new Animated.Value(DefaultAnimatedValues.opacity) + constructor(props) { + super(props); - scale = new Animated.Value(DefaultAnimatedValues.scale) + this.clock = new Clock(); + this.clockReversed = new Clock(); + this.delayClock = new Clock(); + this.gestureState = new Value(UNDETERMINED); + this.handle = undefined; + this.longPressDetected = false; + this.longPressTimeout = undefined; + this.scale = new Value(1); + this.shouldSpring = new Value(-1); - transX = new Animated.Value(DefaultAnimatedValues.transX) + this.state = { + height: 0, + width: 0, + }; - componentWillUnmount = () => { - this.opacity.stopAnimation(); - this.scale.stopAnimation(); - this.transX.stopAnimation(); + this.onGestureEvent = event([ + { + nativeEvent: { + state: this.gestureState, + }, + }, + ]); } - handleLayout = ({ nativeEvent: { layout } }) => { - const { scaleTo, transformOrigin } = this.props; + componentWillUnmount = () => { + this.reset(); + }; - if (transformOrigin) { - const width = Math.floor(layout.width); - const scaleOffsetX = (width - (width * scaleTo)) / 2; - this.setState({ scaleOffsetX }); + clearInteraction = () => { + if (this.props.isInteraction && this.handle) { + InteractionManager.clearInteractionHandle(this.handle); + this.handle = undefined; } - } - - handleStateChange = ({ nativeEvent: { state, absoluteX, absoluteY } }) => { - const { - activeOpacity, - enableHapticFeedback, - onPress, - scaleTo, - transformOrigin, - } = this.props; - const { scaleOffsetX } = this.state; - - const isActive = state === State.BEGAN; + }; - if (buttonExcludingMutex !== this) { - if (buttonExcludingMutex === null && isActive) { - buttonExcludingMutex = this; - } else { - return; - } - } - if (state === State.END || state === State.FAILED || state === State.CANCELLED) { - buttonExcludingMutex = null; + clearLongPressListener = () => { + if (this.longPressTimeout) { + clearTimeout(this.longPressTimeout); } + }; - const animationsArray = [ - // Default spring animation - animations.buildSpring({ - config: { - isInteraction: false, - }, - from: ButtonKeyframes.from.scale, - isActive, - to: scaleTo, - value: this.scale, - }), - ]; - - if (activeOpacity) { - // Opacity animation - animationsArray.push(animations.buildSpring({ - config: { - isInteraction: false, - }, - from: DefaultAnimatedValues.opacity, - isActive, - to: activeOpacity, - value: this.opacity, - })); + createInteraction = () => { + if (this.props.isInteraction && !this.handle) { + this.handle = InteractionManager.createInteractionHandle(); } + }; - if (scaleOffsetX) { - // Fake 'transform-origin' support by abusing translateX - const directionMultiple = (transformOrigin === 'left') ? -1 : 1; - animationsArray.push(animations.buildSpring({ - config: { - isInteraction: false, - }, - from: DefaultAnimatedValues.transX, - isActive, - to: scaleOffsetX * (directionMultiple), - value: this.transX, - })); + createLongPressListener = () => { + this.longPressDetected = false; + const { minLongPressDuration, onLongPress } = this.props; + if (onLongPress) { + this.longPressTimeout = setTimeout( + this.handleDetectedLongPress, + minLongPressDuration + ); } + }; - // Start animations - Animated.parallel(animationsArray).start(); + handleHaptic = () => { + const { enableHapticFeedback, hapticType } = this.props; + if (enableHapticFeedback) { + ReactNativeHapticFeedback.trigger(hapticType); + } + }; - if (enableHapticFeedback && state === State.ACTIVE) { - ReactNativeHapticFeedback.trigger('selection'); + handleLayout = ({ nativeEvent: { layout } }) => { + // only setState if height+width dont already exist + if (!Object.values(this.state).reduce((a, b) => a + b)) { + this.setState(prevState => pick(layout, Object.keys(prevState))); } + }; + + handleDetectedLongPress = () => { + this.longPressDetected = true; + clearTimeout(this.longPressTimeout); + this.handleHaptic(); + this.props.onLongPress(); + }; - if (isActive) { - this.initPos = { absoluteX, absoluteY }; + handlePress = () => { + if (!this.longPressDetected && this.props.onPress) { + this.handleHaptic(); + this.props.onPress(); } + }; - if (state === State.END && onPress) { - // condition below covers issue when tap is simultaneous with pan - if (Math.abs(this.initPos.absoluteX - absoluteX) < 5 && Math.abs(this.initPos.absoluteY - absoluteY) < 5) { - onPress(); - } + handlePressStart = () => { + if (this.props.onPressStart) { + this.props.onPressStart(); } - } + }; - buildAnimationStyles = () => { - const { activeOpacity, transformOrigin } = this.props; - return ({ - ...(activeOpacity ? { opacity: this.opacity } : {}), - transform: compact([ - transformOrigin ? { translateX: this.transX } : null, - { scale: this.scale }, - ]), - }); - } + reset = () => { + this.clearInteraction(); + this.clearLongPressListener(); + }; render = () => { const { + activeOpacity, children, disabled, + exclusive, style, tapRef, - waitFor, + transformOrigin, + ...props } = this.props; + const { height, width } = this.state; + + let offsetX = 0; + let offsetY = 0; + + if (transformOrigin === 'left' || transformOrigin === 'right') { + offsetX = Math.floor(width / 2) * (transformOrigin === 'left' ? -1 : 1); + } else if (transformOrigin === 'bottom' || transformOrigin === 'top') { + offsetY = Math.floor(height / 2) * (transformOrigin === 'top' ? -1 : 1); + } + + const scaleDiff = + this.props.defaultScale - + (this.props.defaultScale - this.props.scaleTo) / 2; + + const opacity = + this.props.scaleTo > this.props.defaultScale + ? activeOpacity + : interpolate(divide(this.scale, this.props.defaultScale), { + inputRange: [this.props.scaleTo, this.props.defaultScale], + outputRange: [activeOpacity, 1], + }); + return ( - - + - {children} - - + + {children} + + + + ); - } + }; } diff --git a/src/components/animations/FadeInAnimation.js b/src/components/animations/FadeInAnimation.js deleted file mode 100644 index ea3597c1310..00000000000 --- a/src/components/animations/FadeInAnimation.js +++ /dev/null @@ -1,93 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { PureComponent } from 'react'; -import { InteractionManager } from 'react-native'; -import Animated, { Easing } from 'react-native-reanimated'; - -const { - block, - call, - Clock, - clockRunning, - cond, - set, - startClock, - stopClock, - timing, - Value, -} = Animated; - -export default class FadeInAnimation extends PureComponent { - static propTypes = { - children: PropTypes.node, - duration: PropTypes.number, - easing: PropTypes.func, - from: PropTypes.number, - isInteraction: PropTypes.bool, - style: PropTypes.object, - to: PropTypes.number, - } - - static defaultProps = { - duration: 315, - easing: Easing.bezier(0.19, 1, 0.22, 1), - from: 0, - isInteraction: false, - to: 1, - } - - runTiming = () => { - const { - duration, - easing, - from, - isInteraction, - to, - } = this.props; - - const handle = isInteraction && InteractionManager.createInteractionHandle(); - - const state = { - finished: new Value(0), - frameTime: new Value(0), - position: new Value(0), - time: new Value(0), - }; - - const clock = new Clock(); - - const config = { - duration, - easing, - toValue: new Value(0), - }; - - return block([ - cond(clockRunning(clock), 0, [ - set(state.finished, 0), - set(state.time, 0), - set(state.position, from), - set(state.frameTime, 0), - set(config.toValue, to), - startClock(clock), - ]), - timing(clock, state, config), - cond(state.finished, [ - stopClock(clock), - call([], () => isInteraction && InteractionManager.clearInteractionHandle(handle)), - ]), - state.position, - ]); - } - - animatedOpacity = this.runTiming(); - - render = () => ( - - ) -} diff --git a/src/components/animations/FlyInAnimation.js b/src/components/animations/FlyInAnimation.js index 18fa2836fb4..ab0b19be1d5 100644 --- a/src/components/animations/FlyInAnimation.js +++ b/src/components/animations/FlyInAnimation.js @@ -1,16 +1,16 @@ import PropTypes from 'prop-types'; import React, { PureComponent } from 'react'; import Animated, { Easing } from 'react-native-reanimated'; +import { interpolate } from './procs'; -const buildAnimation = (value, toValue) => ( +const buildAnimation = (value, toValue) => Animated.timing(value, { duration: 175, easing: Easing.bezier(0.165, 0.84, 0.44, 1), isInteraction: false, toValue, useNativeDriver: true, - }).start() -); + }).start(); export default class FlyInAnimation extends PureComponent { static propTypes = { @@ -18,18 +18,17 @@ export default class FlyInAnimation extends PureComponent { style: PropTypes.object, }; - animation = new Animated.Value(0) + componentDidMount = () => buildAnimation(this.animation, 1); - componentDidMount = () => buildAnimation(this.animation, 1) + componentWillUnmount = () => buildAnimation(this.animation, 0); - componentWillUnmount = () => buildAnimation(this.animation, 0) + animation = new Animated.Value(0); - buildInterpolation = outputRange => ( - Animated.interpolate(this.animation, { + buildInterpolation = outputRange => + interpolate(this.animation, { inputRange: [0, 1], outputRange, - }) - ) + }); render = () => ( {this.props.children} - ) + ); } diff --git a/src/components/animations/OpacityToggler.js b/src/components/animations/OpacityToggler.js new file mode 100644 index 00000000000..cb108468deb --- /dev/null +++ b/src/components/animations/OpacityToggler.js @@ -0,0 +1,123 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import Animated from 'react-native-reanimated'; +import { interpolate } from './procs'; + +const { + add, + block, + Clock, + clockRunning, + cond, + multiply, + set, + spring, + SpringUtils, + startClock, + Value, +} = Animated; + +function runTiming(clock, value, dest, friction, tension) { + const state = { + finished: new Value(1), + position: new Value(value), + time: new Value(0), + velocity: new Value(0), + }; + + const config = Animated.SpringUtils.makeConfigFromOrigamiTensionAndFriction({ + ...SpringUtils.makeDefaultConfig(), + friction, + tension, + }); + + const reset = [ + set(state.finished, 0), + set(state.time, 0), + set(state.velocity, 0), + ]; + + return block([ + cond(state.finished, [...reset, set(config.toValue, dest)]), + cond(clockRunning(clock), 0, startClock(clock)), + spring(clock, state, config), + state.position, + ]); +} + +export default class OpacityToggler extends Component { + static propTypes = { + animationNode: PropTypes.any, + children: PropTypes.any, + endingOpacity: PropTypes.number, + friction: PropTypes.number, + isVisible: PropTypes.bool, + startingOpacity: PropTypes.number, + tension: PropTypes.number, + }; + + static defaultProps = { + endingOpacity: 0, + friction: 20, + startingOpacity: 1, + tension: 200, + }; + + componentWillMount() { + if (!this.props.animationNode) { + this._isVisible = this.props.isVisible; + } + } + + componentWillUpdate(prevProps) { + const { + animationNode, + endingOpacity, + friction, + isVisible, + startingOpacity, + tension, + } = this.props; + + if ( + prevProps.isVisible !== undefined && + prevProps.isVisible !== isVisible && + !animationNode + ) { + const clock = new Clock(); + const base = runTiming( + clock, + isVisible ? -1 : 1, + isVisible ? 1 : -1, + friction, + tension + ); + this._opacity = interpolate(base, { + inputRange: [-1, 1], + outputRange: [endingOpacity, startingOpacity], + }); + } + } + + render() { + const { + animationNode, + children, + endingOpacity, + startingOpacity, + } = this.props; + + let opacity = !this._isVisible ? startingOpacity : endingOpacity; + + if (animationNode) { + opacity = + startingOpacity === 0 + ? animationNode + : multiply(add(animationNode, -1), -1); + } else if (this._opacity) { + opacity = this._opacity; + } + + return {children}; + } +} diff --git a/src/components/animations/RotationArrow.js b/src/components/animations/RotationArrow.js new file mode 100644 index 00000000000..7679457b342 --- /dev/null +++ b/src/components/animations/RotationArrow.js @@ -0,0 +1,117 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import Animated from 'react-native-reanimated'; +import { interpolate } from './procs'; + +const { + block, + Clock, + clockRunning, + concat, + cond, + multiply, + set, + spring, + SpringUtils, + startClock, + sub, + Value, +} = Animated; + +function runTiming(clock, value, dest, friction, tension) { + const state = { + finished: new Value(1), + position: new Value(value), + time: new Value(0), + velocity: new Value(0), + }; + + const config = Animated.SpringUtils.makeConfigFromOrigamiTensionAndFriction({ + ...SpringUtils.makeDefaultConfig(), + friction, + tension, + }); + + const reset = [ + set(state.finished, 0), + set(state.time, 0), + set(state.velocity, 0), + ]; + + return block([ + cond(state.finished, [...reset, set(config.toValue, dest)]), + cond(clockRunning(clock), 0, startClock(clock)), + spring(clock, state, config), + state.position, + ]); +} + +export default class RotationArrow extends Component { + static propTypes = { + children: PropTypes.any, + endingOffset: PropTypes.number, + endingPosition: PropTypes.number, + friction: PropTypes.number, + isOpen: PropTypes.bool, + tension: PropTypes.number, + }; + + static defaultProps = { + friction: 20, + tension: 200, + }; + + componentWillMount() { + if (!this.props.isOpen === true) { + this._transform = new Value(1); + } else { + this._transform = new Value(0); + } + } + + componentWillUpdate(prevProps) { + const { friction, isOpen, tension } = this.props; + + if (prevProps.isOpen !== undefined && prevProps.isOpen !== isOpen) { + const clock = new Clock(); + const base = runTiming( + clock, + isOpen ? -1 : 1, + isOpen ? 1 : -1, + friction, + tension + ); + this._transform = interpolate(base, { + inputRange: [-1, 1], + outputRange: [0, 1], + }); + } + } + + render() { + const { children, endingOffset, endingPosition } = this.props; + + let translateX = 0; + if (endingOffset) { + translateX = this._transform + ? sub(endingOffset, multiply(this._transform, endingOffset)) + : endingOffset; + } + + let rotate = `${endingPosition}deg`; + if (this._transform) { + rotate = concat( + sub(endingPosition, multiply(this._transform, endingPosition)), + 'deg' + ); + } + + return ( + + + {children} + + + ); + } +} diff --git a/src/components/animations/RoundButtonSizeToggler.js b/src/components/animations/RoundButtonSizeToggler.js new file mode 100644 index 00000000000..ec7e70e3f80 --- /dev/null +++ b/src/components/animations/RoundButtonSizeToggler.js @@ -0,0 +1,164 @@ +import { isNil } from 'lodash'; +import PropTypes from 'prop-types'; +import React, { PureComponent } from 'react'; +import Animated from 'react-native-reanimated'; +import { View } from 'react-primitives'; +import styled from 'styled-components/primitives'; +import { borders, colors, position } from '../../styles'; +import { interpolate } from './procs'; + +const { + add, + block, + Clock, + clockRunning, + cond, + divide, + multiply, + set, + spring, + SpringUtils, + startClock, + sub, + Value, +} = Animated; + +const RoundButtonCapSize = 30; +const RoundButtonCap = styled(Animated.View)` + ${({ capDirection }) => + borders.buildRadius(capDirection, RoundButtonCapSize / 2)}; + ${position.size(RoundButtonCapSize)}; + background-color: ${({ color }) => color}; +`; + +function runTiming(clock, value, dest, friction, tension) { + const state = { + finished: new Value(1), + position: new Value(value), + time: new Value(0), + velocity: new Value(0), + }; + + const config = SpringUtils.makeConfigFromOrigamiTensionAndFriction({ + ...SpringUtils.makeDefaultConfig(), + friction, + tension, + }); + + const reset = [ + set(state.finished, 0), + set(state.time, 0), + set(state.velocity, 0), + ]; + + return block([ + cond(state.finished, [...reset, set(config.toValue, dest)]), + cond(clockRunning(clock), 0, startClock(clock)), + spring(clock, state, config), + state.position, + ]); +} + +export default class RoundButtonSizeToggler extends PureComponent { + static propTypes = { + animationNode: PropTypes.any, + color: PropTypes.string, + endingWidth: PropTypes.number, + friction: PropTypes.number, + isAbsolute: PropTypes.bool, + reversed: PropTypes.bool, + startingWidth: PropTypes.number, + tension: PropTypes.number, + toggle: PropTypes.bool, + }; + + static defaultProps = { + color: colors.lightBlueGrey, + friction: 20, + tension: 200, + }; + + componentWillMount() { + this._width = new Value(this.props.startingWidth); + } + + componentWillUpdate(prevProps) { + const { animationNode, friction, tension, toggle } = this.props; + + if ( + !isNil(prevProps.toggle) && + prevProps.toggle !== toggle && + !animationNode + ) { + const clock = new Clock(); + const base = runTiming( + clock, + toggle ? -1 : 1, + toggle ? 1 : -1, + friction, + tension + ); + this._width = interpolate(base, { + inputRange: [-1, 1], + outputRange: [1, 0], + }); + } + } + + static capSize = RoundButtonCapSize; + + render() { + const { + animationNode, + color, + endingWidth, + isAbsolute, + reversed, + startingWidth, + } = this.props; + + let contentScaleX = + (startingWidth + (reversed ? 0 : endingWidth + 5)) / 100; + if (animationNode) { + contentScaleX = add( + multiply(animationNode, endingWidth / 100 - startingWidth / 100), + startingWidth / 100 + ); + } + + let contentTranslateX = reversed ? startingWidth : endingWidth; + if (animationNode) { + contentTranslateX = multiply(divide(sub(1, contentScaleX, 100), 2), -1); + } + + let rightCapTranslateX = + -1 * (100 - (reversed ? startingWidth : endingWidth)) - 11; + if (animationNode) { + rightCapTranslateX = sub(multiply(-100, sub(1, contentScaleX)), 11); + } + + return ( + + + + + + + + ); + } +} diff --git a/src/components/animations/ScaleInAnimation.js b/src/components/animations/ScaleInAnimation.js index d0f0bc63147..c52ce4c1cbd 100644 --- a/src/components/animations/ScaleInAnimation.js +++ b/src/components/animations/ScaleInAnimation.js @@ -1,39 +1,34 @@ import PropTypes from 'prop-types'; import React from 'react'; -import { pure, toClass } from 'recompact'; import Animated from 'react-native-reanimated'; import stylePropType from 'react-style-proptype'; import { position } from '../../styles'; -import { Centered } from '../layout'; +import { interpolate } from './procs'; -const { createAnimatedComponent, interpolate } = Animated; - -const AnimatedCentered = createAnimatedComponent(toClass(Centered)); - -const ScaleInAnimation = ({ - range, - scaleTo, - style, - value, - ...props -}) => ( - ( + ); @@ -52,7 +47,7 @@ ScaleInAnimation.defaultProps = { from: 0, to: 100, }, - scaleTo: 0.420, + scaleTo: 0.42, }; -export default pure(ScaleInAnimation); +export default React.memo(ScaleInAnimation); diff --git a/src/components/animations/SizeToggler.js b/src/components/animations/SizeToggler.js new file mode 100644 index 00000000000..f94fc4574c1 --- /dev/null +++ b/src/components/animations/SizeToggler.js @@ -0,0 +1,115 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import Animated from 'react-native-reanimated'; +import { interpolate } from './procs'; + +const { + add, + block, + Clock, + clockRunning, + cond, + multiply, + set, + spring, + SpringUtils, + startClock, + Value, +} = Animated; + +function runTiming(clock, value, dest, friction, tension) { + const state = { + finished: new Value(1), + position: new Value(value), + time: new Value(0), + velocity: new Value(0), + }; + + const config = Animated.SpringUtils.makeConfigFromOrigamiTensionAndFriction({ + ...SpringUtils.makeDefaultConfig(), + friction, + tension, + }); + + const reset = [ + set(state.finished, 0), + set(state.time, 0), + set(state.velocity, 0), + ]; + + return block([ + cond(state.finished, [...reset, set(config.toValue, dest)]), + cond(clockRunning(clock), 0, startClock(clock)), + spring(clock, state, config), + state.position, + ]); +} + +export default class SizeToggler extends Component { + static propTypes = { + animationNode: PropTypes.any, + children: PropTypes.any, + endingWidth: PropTypes.number, + friction: PropTypes.number, + startingWidth: PropTypes.number, + tension: PropTypes.number, + toggle: PropTypes.bool, + }; + + static defaultProps = { + endingOpacity: 0, + friction: 20, + startingOpacity: 1, + tension: 200, + }; + + componentWillMount() { + const { endingWidth, startingWidth, toggle } = this.props; + + if (!toggle === true) { + this._height = new Value(startingWidth); + } else { + this._height = new Value(endingWidth); + } + } + + componentWillUpdate(prevProps) { + const { + animationNode, + endingWidth, + friction, + startingWidth, + tension, + toggle, + } = this.props; + + if ( + prevProps.toggle !== undefined && + prevProps.toggle !== toggle && + !animationNode + ) { + const clock = new Clock(); + const base = runTiming( + clock, + toggle ? -1 : 1, + toggle ? 1 : -1, + friction, + tension + ); + this._height = interpolate(base, { + inputRange: [-1, 1], + outputRange: [endingWidth, startingWidth], + }); + } + } + + render() { + const { animationNode, children, endingWidth, startingWidth } = this.props; + + const height = animationNode + ? add(multiply(animationNode, endingWidth - startingWidth), startingWidth) + : this._height; + + return {children}; + } +} diff --git a/src/components/animations/SpinAnimation.js b/src/components/animations/SpinAnimation.js index 69a57dad28c..42aa796f3aa 100644 --- a/src/components/animations/SpinAnimation.js +++ b/src/components/animations/SpinAnimation.js @@ -8,15 +8,13 @@ export default class SpinAnimation extends PureComponent { children: PropTypes.node, duration: PropTypes.number, style: stylePropType, - } + }; static defaultProps = { duration: 2000, - } + }; - animatedValue = new Animated.Value(0) - - componentDidMount = () => ( + componentDidMount = () => Animated.loop( Animated.timing(this.animatedValue, { duration: this.props.duration, @@ -24,26 +22,31 @@ export default class SpinAnimation extends PureComponent { isInteraction: false, toValue: 1, useNativeDriver: true, - }), - ).start() - ) + }) + ).start(); + + componentWillUnmount = () => this.animatedValue.stopAnimation(); - componentWillUnmount = () => this.animatedValue.stopAnimation() + animatedValue = new Animated.Value(0); - interpolatedAnimation = () => ( + interpolatedAnimation = () => this.animatedValue.interpolate({ inputRange: [0, 1], outputRange: ['0deg', '360deg'], - }) - ) + }); render = () => { const { children, style } = this.props; return ( - + {children} ); - } + }; } diff --git a/src/components/animations/TouchableScale.js b/src/components/animations/TouchableScale.js new file mode 100644 index 00000000000..f70038bbf86 --- /dev/null +++ b/src/components/animations/TouchableScale.js @@ -0,0 +1,132 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { TouchableWithoutFeedback, Animated } from 'react-native'; +import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; +import stylePropType from 'react-style-proptype'; + +const HapticFeedbackTypes = { + impactHeavy: 'impactHeavy', + impactLight: 'impactLight', + impactMedium: 'impactMedium', + notificationError: 'notificationError', + notificationSuccess: 'notificationSuccess', + notificationWarning: 'notificationWarning', + selection: 'selection', +}; + +export default class TouchableScale extends React.Component { + constructor(...args) { + super(...args); + const props = this.props; + + this.onPressIn = this.onPressIn.bind(this); + this.onPressOut = this.onPressOut.bind(this); + this.scaleAnimation = new Animated.Value(props.defaultScale); + } + + handleHaptic = () => { + const { enableHapticFeedback, hapticType } = this.props; + + if (enableHapticFeedback) { + ReactNativeHapticFeedback.trigger(hapticType); + } + }; + + onPressIn(...args) { + const props = this.props; + const friction = + typeof props.pressInFriction !== 'undefined' + ? props.pressInFriction + : props.friction; + const tension = + typeof props.pressInTension !== 'undefined' + ? props.pressInTension + : props.tension; + + Animated.spring(this.scaleAnimation, { + friction: friction, + tension: tension, + toValue: props.activeScale, + useNativeDriver: props.useNativeDriver, + }).start(); + + if (props.onPressIn) { + props.onPressIn(...args); + } + } + + onPressOut(...args) { + const props = this.props; + const tension = + typeof props.pressOutTension !== 'undefined' + ? props.pressOutTension + : props.tension; + const friction = + typeof props.pressOutFriction !== 'undefined' + ? props.pressOutFriction + : props.friction; + + Animated.spring(this.scaleAnimation, { + friction: friction, + tension: tension, + toValue: props.defaultScale, + useNativeDriver: props.useNativeDriver, + }).start(); + + this.handleHaptic(); + + if (props.onPressOut) { + props.onPressOut(...args); + } + } + + render() { + const props = this.props; + + return ( + + + {props.children} + + + ); + } +} + +TouchableScale.propTypes = { + ...TouchableWithoutFeedback.propTypes, + activeScale: PropTypes.number.isRequired, + defaultScale: PropTypes.number.isRequired, + enableHapticFeedback: PropTypes.bool, + friction: PropTypes.number.isRequired, + hapticType: PropTypes.oneOf(Object.keys(HapticFeedbackTypes)), + pressInFriction: PropTypes.number, + pressInTension: PropTypes.number, + pressOutFriction: PropTypes.number, + pressOutTension: PropTypes.number, + style: stylePropType, + tension: PropTypes.number.isRequired, + useNativeDriver: PropTypes.bool, +}; + +TouchableScale.defaultProps = { + activeScale: 0.9, + defaultScale: 1, + enableHapticFeedback: true, + friction: 3, + hapticType: HapticFeedbackTypes.selection, + tension: 150, + useNativeDriver: true, +}; diff --git a/src/components/animations/index.js b/src/components/animations/index.js index 461d66034e7..cb5ac8291bf 100644 --- a/src/components/animations/index.js +++ b/src/components/animations/index.js @@ -1,5 +1,10 @@ export { default as ButtonPressAnimation } from './ButtonPressAnimation'; -export { default as FadeInAnimation } from './FadeInAnimation'; export { default as FlyInAnimation } from './FlyInAnimation'; +export { contains, interpolate, timing, updateState } from './procs'; +export { default as OpacityToggler } from './OpacityToggler'; +export { default as RotationArrow } from './RotationArrow'; +export { default as RoundButtonSizeToggler } from './RoundButtonSizeToggler'; export { default as ScaleInAnimation } from './ScaleInAnimation'; +export { default as SizeToggler } from './SizeToggler'; export { default as SpinAnimation } from './SpinAnimation'; +export { default as TouchableScale } from './TouchableScale'; diff --git a/src/components/animations/procs/contains.js b/src/components/animations/procs/contains.js new file mode 100644 index 00000000000..475e3d0e037 --- /dev/null +++ b/src/components/animations/procs/contains.js @@ -0,0 +1,9 @@ +import Animated from 'react-native-reanimated'; + +const { eq, or, proc, Value } = Animated; + +const containsProc = proc((acc, value, v) => or(acc, eq(value, v))); + +export default function contains(values, value) { + return values.reduce((acc, v) => containsProc(acc, value, v), new Value(0)); +} diff --git a/src/components/animations/procs/index.js b/src/components/animations/procs/index.js new file mode 100644 index 00000000000..4ad25fffb5e --- /dev/null +++ b/src/components/animations/procs/index.js @@ -0,0 +1,4 @@ +export { default as contains } from './contains'; +export { default as interpolate } from './interpolate'; +export { default as timing } from './timing'; +export { updateState } from './updateState'; diff --git a/src/components/animations/procs/interpolate.js b/src/components/animations/procs/interpolate.js new file mode 100644 index 00000000000..5797bbbee29 --- /dev/null +++ b/src/components/animations/procs/interpolate.js @@ -0,0 +1,79 @@ +import Animated from 'react-native-reanimated'; + +const interpolateTwo = Animated.proc( + (value, extrapolate, input1, input2, output1, output2) => + Animated.interpolate(value, { + extrapolate, + inputRange: [input1, input2], + outputRange: [output1, output2], + }) +); + +const interpolateThree = Animated.proc( + (value, extrapolate, input1, input2, input3, output1, output2, output3) => + Animated.interpolate(value, { + extrapolate, + inputRange: [input1, input2, input3], + outputRange: [output1, output2, output3], + }) +); + +const interpolateFour = Animated.proc( + ( + value, + extrapolate, + input1, + input2, + input3, + input4, + output1, + output2, + output3, + output4 + ) => + Animated.interpolate(value, { + extrapolate, + inputRange: [input1, input2, input3, input4], + outputRange: [output1, output2, output3, output4], + }) +); + +const interpolateFive = Animated.proc( + ( + value, + extrapolate, + input1, + input2, + input3, + input4, + input5, + output1, + output2, + output3, + output4, + output5 + ) => + Animated.interpolate(value, { + extrapolate, + inputRange: [input1, input2, input3, input4, input5], + outputRange: [output1, output2, output3, output4, output5], + }) +); + +export default function interpolate( + value, + { extrapolate = Animated.Extrapolate.EXTEND, inputRange, outputRange } = {} +) { + if (inputRange.length === 2) { + return interpolateTwo(value, extrapolate, ...inputRange, ...outputRange); + } + if (inputRange.length === 3) { + return interpolateThree(value, extrapolate, ...inputRange, ...outputRange); + } + if (inputRange.length === 4) { + return interpolateFour(value, extrapolate, ...inputRange, ...outputRange); + } + if (inputRange.length === 5) { + return interpolateFive(value, extrapolate, ...inputRange, ...outputRange); + } +} diff --git a/src/components/animations/procs/timing.js b/src/components/animations/procs/timing.js new file mode 100644 index 00000000000..37bae3d596f --- /dev/null +++ b/src/components/animations/procs/timing.js @@ -0,0 +1,84 @@ +import Animated, { Easing } from 'react-native-reanimated'; +import { updateState } from './updateState'; + +const { + block, + Clock, + clockRunning, + cond, + set, + startClock, + stopClock, + Value, +} = Animated; + +const timingProc = Animated.proc( + (clock, finished, position, time, frameTime, toValue, duration) => + Animated.timing( + clock, + { + finished, + frameTime, + position, + time, + }, + { + duration, + easing: Easing.linear, + toValue, + } + ) +); + +const runTiming = (clock, state, config) => + timingProc( + clock, + state.finished, + state.position, + state.time, + state.frameTime, + config.toValue, + config.duration + ); + +export default function timing(params) { + const { clock, duration, easing, from, to } = { + clock: new Clock(), + duration: 250, + easing: Easing.linear, + from: 0, + to: 1, + ...params, + }; + + const state = { + finished: new Value(0), + frameTime: new Value(0), + position: new Value(0), + time: new Value(0), + }; + + const config = { + duration, + easing, + toValue: new Value(0), + }; + + return block([ + cond(clockRunning(clock), 0, [ + updateState( + from, + to, + state.finished, + state.position, + state.time, + state.frameTime, + config.toValue + ), + startClock(clock), + ]), + runTiming(clock, state, config), + cond(state.finished, stopClock(clock)), + set(from, state.position), + ]); +} diff --git a/src/components/animations/procs/updateState.js b/src/components/animations/procs/updateState.js new file mode 100644 index 00000000000..845da8bce45 --- /dev/null +++ b/src/components/animations/procs/updateState.js @@ -0,0 +1,12 @@ +import Animated from 'react-native-reanimated'; + +export const updateState = Animated.proc( + (value, dest, finished, position, time, frameTime, toValue) => + Animated.block([ + Animated.set(finished, 0), + Animated.set(time, 0), + Animated.set(position, value), + Animated.set(frameTime, 0), + Animated.set(toValue, dest), + ]) +); diff --git a/src/components/asset-list/AssetList.js b/src/components/asset-list/AssetList.js index a2f1f3a22aa..6b173c9f3a8 100644 --- a/src/components/asset-list/AssetList.js +++ b/src/components/asset-list/AssetList.js @@ -1,60 +1,57 @@ import PropTypes from 'prop-types'; import React from 'react'; -import { compose, onlyUpdateForKeys } from 'recompact'; -import { withIsWalletImporting } from '../../hoc'; -import { safeAreaInsetValues } from '../../utils'; +import isEqual from 'react-fast-compare'; +import { useSafeArea } from 'react-native-safe-area-context'; import { FabWrapper, FloatingActionButton } from '../fab'; import { ListFooter } from '../list'; import EmptyAssetList from './EmptyAssetList'; import RecyclerAssetList from './RecyclerAssetList'; -const FabSizeWithPadding = FloatingActionButton.size + (FabWrapper.bottomPosition * 2); -const PaddingBottom = (safeAreaInsetValues.bottom + FabSizeWithPadding) - ListFooter.height; +const FabSizeWithPadding = + FloatingActionButton.size + FabWrapper.bottomPosition * 2; const AssetList = ({ fetchData, hideHeader, isEmpty, - isImporting, isWalletEthZero, scrollViewTracker, sections, ...props -}) => ( - (isEmpty || isImporting) - ? ( - - ) : ( - - ) -); +}) => { + const insets = useSafeArea(); + + return isEmpty ? ( + + ) : ( + + ); +}; AssetList.propTypes = { fetchData: PropTypes.func.isRequired, hideHeader: PropTypes.bool, isEmpty: PropTypes.bool, - isImporting: PropTypes.bool, isWalletEthZero: PropTypes.bool, scrollViewTracker: PropTypes.object, sections: PropTypes.arrayOf(PropTypes.object), }; -export default compose( - withIsWalletImporting, - onlyUpdateForKeys([ - 'isEmpty', - 'isImporting', - 'isWalletEthZero', - 'sections', - ]), -)(AssetList); +const arePropsEqual = (prev, next) => + prev.isEmpty === next.isEmpty && + prev.isWalletEthZero === next.isWalletEthZero && + prev.sections.length === next.sections.length && + isEqual(prev.sections, next.sections); + +export default React.memo(AssetList, arePropsEqual); diff --git a/src/components/asset-list/AssetListHeader.js b/src/components/asset-list/AssetListHeader.js index a413a3391f9..33cf9b0fe1f 100644 --- a/src/components/asset-list/AssetListHeader.js +++ b/src/components/asset-list/AssetListHeader.js @@ -5,15 +5,10 @@ import Divider from '../Divider'; import { Monospace } from '../text'; import { ListHeader } from '../list'; -const enhance = onlyUpdateForKeys(['showShitcoins', 'title', 'totalValue']); +const enhance = onlyUpdateForKeys(['title', 'totalValue']); -const AssetListHeader = enhance(({ - showShitcoins, - title, - totalValue, - ...props -}) => ( - +const AssetListHeader = enhance(({ title, totalValue, isSticky, ...props }) => ( + {totalValue ? ( {totalValue} @@ -23,11 +18,15 @@ const AssetListHeader = enhance(({ )); AssetListHeader.propTypes = { - showShitcoins: PropTypes.bool, + isSticky: PropTypes.bool, title: PropTypes.string, totalValue: PropTypes.string, }; +AssetListHeader.defaultProps = { + isSticky: false, +}; + AssetListHeader.height = ListHeader.height + Divider.size; export default AssetListHeader; diff --git a/src/components/asset-list/AssetListItemSkeleton.js b/src/components/asset-list/AssetListItemSkeleton.js index 5ff4fd15782..9b8a15012bf 100644 --- a/src/components/asset-list/AssetListItemSkeleton.js +++ b/src/components/asset-list/AssetListItemSkeleton.js @@ -8,6 +8,7 @@ import { withProps } from 'recompact'; import styled from 'styled-components/primitives'; import { colors, padding, position } from '../../styles'; import { deviceUtils } from '../../utils'; +import { interpolate } from '../animations'; import { CoinRow } from '../coin-row'; import { ColumnWithMargins, Row, RowWithMargins } from '../layout'; @@ -15,7 +16,6 @@ const { block, Clock, cond, - interpolate, set, startClock, stopClock, @@ -27,7 +27,8 @@ const AnimatedLinearGradient = Animated.createAnimatedComponent(LinearGradient); const Container = styled.View` height: ${CoinRow.height}; - opacity: ${({ descendingOpacity, index }) => (1 - (0.2 * (descendingOpacity ? index : 0)))}; + opacity: ${({ descendingOpacity, index }) => + 1 - 0.2 * (descendingOpacity ? index : 0)}; width: 100%; `; @@ -54,7 +55,7 @@ const Wrapper = styled(RowWithMargins).attrs({ justify: 'space-between', margin: 11, })` - ${({ index }) => padding((index === 0 ? 15 : 12.5), 19, 12.5, 15)}; + ${({ index }) => padding(index === 0 ? 15 : 12.5, 19, 12.5, 15)}; ${position.size('100%')}; background-color: ${colors.transparent}; `; @@ -64,16 +65,22 @@ export default class AssetListItemSkeleton extends PureComponent { animated: PropTypes.bool, descendingOpacity: PropTypes.bool, index: PropTypes.number, - } + }; static defaultProps = { animated: true, index: 0, - } + }; startShimmerLoop = () => { const clock = new Clock(); + const config = { + duration: new Value(1250), + easing: Easing.linear, + toValue: new Value(1), + }; + const state = { finished: new Value(0), frameTime: new Value(0), @@ -81,12 +88,6 @@ export default class AssetListItemSkeleton extends PureComponent { time: new Value(0), }; - const config = { - duration: new Value(1250), - easing: Easing.linear, - toValue: new Value(1), - }; - return block([ startClock(clock), timing(clock, state, config), @@ -100,9 +101,9 @@ export default class AssetListItemSkeleton extends PureComponent { ]), state.position, ]); - } + }; - animation = this.startShimmerLoop() + animation = this.startShimmerLoop(); renderShimmer = () => { const gradientColors = [ @@ -134,7 +135,7 @@ export default class AssetListItemSkeleton extends PureComponent { /> ); - } + }; render = () => { const { animated, descendingOpacity, index } = this.props; @@ -161,11 +162,14 @@ export default class AssetListItemSkeleton extends PureComponent { return ( - {animated - ? {this.renderShimmer()} - : skeletonElement - } + {animated ? ( + + {this.renderShimmer()} + + ) : ( + skeletonElement + )} ); - } + }; } diff --git a/src/components/asset-list/EmptyAssetList.js b/src/components/asset-list/EmptyAssetList.js index 0c10cf0138e..dc01efa7f54 100644 --- a/src/components/asset-list/EmptyAssetList.js +++ b/src/components/asset-list/EmptyAssetList.js @@ -1,8 +1,8 @@ import lang from 'i18n-js'; +import stylePropType from 'react-style-proptype'; import { times } from 'lodash'; import PropTypes from 'prop-types'; import React from 'react'; -import { withNeverRerender } from '../../hoc'; import { position } from '../../styles'; import AddFundsInterstitial from '../AddFundsInterstitial'; import { FabWrapper } from '../fab'; @@ -12,29 +12,42 @@ import AssetListItemSkeleton from './AssetListItemSkeleton'; const InterstitialOffset = AssetListHeader.height + FabWrapper.bottomPosition; -const renderSkeleton = (index, isWalletEthZero) => ( - -); - -const EmptyAssetList = ({ isWalletEthZero, ...props }) => ( - - +const EmptyAssetList = ({ + hideHeader, + isWalletEthZero, + skeletonCount, + style, + ...props +}) => ( + + {hideHeader && } - {times(5, index => renderSkeleton(index, isWalletEthZero))} + {times(skeletonCount, index => ( + + ))} - {isWalletEthZero && ()} + {isWalletEthZero && ( + + )} ); EmptyAssetList.propTypes = { + hideHeader: PropTypes.bool, isWalletEthZero: PropTypes.bool, + skeletonCount: PropTypes.number, + style: stylePropType, +}; + +EmptyAssetList.defaultProps = { + skeletonCount: 5, }; -export default withNeverRerender(EmptyAssetList); +export default React.memo(EmptyAssetList); diff --git a/src/components/asset-list/RecyclerAssetList.js b/src/components/asset-list/RecyclerAssetList.js index 85ee7be7ae9..c171668d4f4 100644 --- a/src/components/asset-list/RecyclerAssetList.js +++ b/src/components/asset-list/RecyclerAssetList.js @@ -1,59 +1,84 @@ -import { - findIndex, - get, - has, - isNil, -} from 'lodash'; +import { findIndex, get, has, isNil } from 'lodash'; import PropTypes from 'prop-types'; import React, { Component } from 'react'; import { LayoutAnimation, RefreshControl, View } from 'react-native'; import { compose, pure } from 'recompact'; import { + BaseItemAnimator, DataProvider, LayoutProvider, RecyclerListView, } from 'recyclerlistview'; import StickyContainer from 'recyclerlistview/dist/reactnative/core/StickyContainer'; import { - buildAssetHeaderUniqueIdentifier, - buildAssetUniqueIdentifier, -} from '../../helpers/assets'; -import { withFabSelection, withOpenFamilyTabs } from '../../hoc'; + withFabSelection, + withOpenBalances, + withOpenFamilyTabs, + withOpenInvestmentCards, +} from '../../hoc'; import { colors } from '../../styles'; -import { deviceUtils, isNewValueForPath, safeAreaInsetValues } from '../../utils'; -import { CoinRow, CollectiblesSendRow } from '../coin-row'; +import { + deviceUtils, + isNewValueForPath, + safeAreaInsetValues, +} from '../../utils'; +import { CoinDivider, SmallBalancesWrapper } from '../coin-divider'; +import { CoinRow } from '../coin-row'; import { TokenFamilyHeader } from '../token-family'; import { FloatingActionButton } from '../fab'; -import { InvestmentCard, UniswapInvestmentCard } from '../investment-cards'; +import { + InvestmentCard, + UniswapInvestmentCard, + InvestmentCardHeader, +} from '../investment-cards'; import { ListFooter } from '../list'; import { UniqueTokenRow } from '../unique-token'; import AssetListHeader from './AssetListHeader'; +import { TokenFamilyWrapPaddingTop } from '../token-family/TokenFamilyWrap'; /* eslint-disable sort-keys */ export const ViewTypes = { HEADER: 0, COIN_ROW: 1, COIN_ROW_LAST: 2, - UNIQUE_TOKEN_ROW: 3, - UNIQUE_TOKEN_ROW_CLOSED: 4, - UNIQUE_TOKEN_ROW_CLOSED_LAST: 5, - UNISWAP_ROW: 6, - UNISWAP_ROW_LAST: 7, - FOOTER: 10, + COIN_SMALL_BALANCES: 3, + FOOTER: 11, + UNIQUE_TOKEN_ROW: 4, + UNIQUE_TOKEN_ROW_CLOSED: 5, + UNIQUE_TOKEN_ROW_CLOSED_LAST: 6, + UNIQUE_TOKEN_ROW_FIRST: 8, // TODO remove + UNIQUE_TOKEN_ROW_LAST: 9, // TODO remove + UNISWAP_ROW: 7, + UNISWAP_ROW_CLOSED: 9, + UNISWAP_ROW_CLOSED_LAST: 10, + UNISWAP_ROW_LAST: 8, }; /* eslint-enable sort-keys */ const NOOP = () => undefined; -const layoutItemAnimator = { - animateDidMount: NOOP, - animateShift: () => LayoutAnimation.configureNext(LayoutAnimation.create(200, 'easeInEaseOut', 'opacity')), - animateWillMount: NOOP, - animateWillUnmount: NOOP, - animateWillUpdate: NOOP, -}; +class LayoutItemAnimator extends BaseItemAnimator { + animateDidMount = NOOP; + animateShift = () => + LayoutAnimation.configureNext({ + duration: 200, + update: { + initialVelocity: 0, + springDamping: 1, + type: LayoutAnimation.Types.spring, + }, + }); + animateWillMount = NOOP; + animateWillUnmount = NOOP; + animateWillUpdate = NOOP; +} + +const layoutItemAnimator = new LayoutItemAnimator(); + +const reloadHeightOffsetTop = -60; +const reloadHeightOffsetBottom = -62; +let smallBalancedChanged = false; -// eslint-disable-next-line react/prop-types const AssetListHeaderRenderer = pure(data => ); const hasRowChanged = (r1, r2) => { @@ -65,68 +90,95 @@ const hasRowChanged = (r1, r2) => { const isNewTokenFamilyId = isNewValueForPath(r1, r2, 'item.familyId'); const isNewTokenFamilyName = isNewValueForPath(r1, r2, 'item.familyName'); const isNewTokenFamilySize = isNewValueForPath(r1, r2, 'item.childrenAmount'); - const isNewUniswapPercentageOwned = isNewValueForPath(r1, r2, 'item.percentageOwned'); + const isNewUniswapPercentageOwned = isNewValueForPath( + r1, + r2, + 'item.percentageOwned' + ); const isNewUniswapToken = isNewValueForPath(r1, r2, 'item.tokenSymbol'); const isCollectiblesRow = has(r1, 'item.tokens') && has(r2, 'item.tokens'); let isNewAssetBalance = false; if (!isCollectiblesRow) { - isNewAssetBalance = isNewValueForPath(r1, r2, 'item.native.balance.display'); + isNewAssetBalance = isNewValueForPath( + r1, + r2, + 'item.native.balance.display' + ); } - return isNewAsset - || isNewAssetBalance - || isNewShowShitcoinsValue - || isNewTitle - || isNewTokenFamilyId - || isNewTokenFamilyName - || isNewTokenFamilySize - || isNewTotalItems - || isNewTotalValue - || isNewUniswapPercentageOwned - || isNewUniswapToken; + if ( + r1.item && + r2.item && + r1.item.smallBalancesContainer && + r2.item.smallBalancesContainer + ) { + if (r1.item.assets.length !== r2.item.assets.length) { + smallBalancedChanged = true; + } else if (r2.item.assets.length > 0) { + for (let i = 0; i < r2.item.assets.length; i++) { + if (r1.item.assets[i].native) { + if ( + r1.item.assets[i].native.balance.display !== + r2.item.assets[i].native.balance.display + ) { + smallBalancedChanged = true; + } + } + } + } + } + + return ( + isNewAsset || + isNewAssetBalance || + isNewShowShitcoinsValue || + isNewTitle || + isNewTokenFamilyId || + isNewTokenFamilyName || + isNewTokenFamilySize || + isNewTotalItems || + isNewTotalValue || + isNewUniswapPercentageOwned || + isNewUniswapToken + ); }; class RecyclerAssetList extends Component { static propTypes = { + externalScrollView: PropTypes.any, fetchData: PropTypes.func, hideHeader: PropTypes.bool, - openFamilyTabs: PropTypes.array, + openFamilyTabs: PropTypes.object, + openInvestmentCards: PropTypes.object, + openSmallBalances: PropTypes.bool, paddingBottom: PropTypes.number, renderAheadOffset: PropTypes.number, scrollingVelocity: PropTypes.number, scrollViewTracker: PropTypes.object, - sections: PropTypes.arrayOf(PropTypes.shape({ - balances: PropTypes.bool, - collectibles: PropTypes.bool, - data: PropTypes.array.isRequired, - header: PropTypes.shape({ - title: PropTypes.string, - totalItems: PropTypes.number, - totalValue: PropTypes.string, - }), - investments: PropTypes.bool, - perData: PropTypes.object, - renderItem: PropTypes.func.isRequired, - type: PropTypes.string, - })), + sections: PropTypes.arrayOf( + PropTypes.shape({ + balances: PropTypes.bool, + collectibles: PropTypes.bool, + data: PropTypes.array.isRequired, + header: PropTypes.shape({ + title: PropTypes.string, + totalItems: PropTypes.number, + totalValue: PropTypes.string, + }), + investments: PropTypes.bool, + perData: PropTypes.object, + renderItem: PropTypes.func.isRequired, + type: PropTypes.string, + }) + ), }; static defaultProps = { renderAheadOffset: deviceUtils.dimensions.height, }; - rlv = React.createRef(); - - contentSize = 0; - - layoutMeasurement = 0; - - position = 0; - - refresh = false; - constructor(props) { super(props); @@ -134,40 +186,81 @@ class RecyclerAssetList extends Component { dataProvider: new DataProvider(hasRowChanged, this.getStableId), headersIndices: [], isRefreshing: false, + itemsCount: 0, }; this.layoutProvider = new LayoutProvider( index => { - const { openFamilyTabs, sections } = this.props; + const { openFamilyTabs, openInvestmentCards, sections } = this.props; + const { headersIndices } = this.state; if (headersIndices.includes(index)) { return ViewTypes.HEADER; } - if (index === this.state.length - 1) { + if (index === this.state.itemsCount - 1) { return ViewTypes.FOOTER; } - const balancesIndex = findIndex(sections, ({ name }) => name === 'balances'); - const collectiblesIndex = findIndex(sections, ({ name }) => name === 'collectibles'); - const investmentsIndex = findIndex(sections, ({ name }) => name === 'investments'); + const balancesIndex = findIndex( + sections, + ({ name }) => name === 'balances' + ); + const collectiblesIndex = findIndex( + sections, + ({ name }) => name === 'collectibles' + ); + const investmentsIndex = findIndex( + sections, + ({ name }) => name === 'investments' + ); if (balancesIndex > -1) { - const balanceItemsCount = get(sections, `[${balancesIndex}].data.length`, 0); - const lastBalanceIndex = headersIndices[balancesIndex] + balanceItemsCount; + const balanceItemsCount = get( + sections, + `[${balancesIndex}].data.length`, + 0 + ); + const lastBalanceIndex = + headersIndices[balancesIndex] + balanceItemsCount; if (index === lastBalanceIndex) { + if ( + sections[balancesIndex].data[lastBalanceIndex - 1] + .smallBalancesContainer + ) { + return ViewTypes.COIN_SMALL_BALANCES; + } return ViewTypes.COIN_ROW_LAST; } } if (investmentsIndex > -1) { - const investmentItemsCount = get(sections, `[${investmentsIndex}].data.length`, 0); - const lastInvestmentIndex = headersIndices[investmentsIndex] + investmentItemsCount; - - if ((index > headersIndices[investmentsIndex]) && (index <= lastInvestmentIndex)) { + const investmentItemsCount = get( + sections, + `[${investmentsIndex}].data.length`, + 0 + ); + const lastInvestmentIndex = + headersIndices[investmentsIndex] + investmentItemsCount; + + if ( + index > headersIndices[investmentsIndex] && + index <= lastInvestmentIndex + ) { + if ( + !openInvestmentCards[ + sections[investmentsIndex].data[ + index - headersIndices[investmentsIndex] - 1 + ].uniqueId + ] + ) { + return index === lastInvestmentIndex + ? ViewTypes.UNISWAP_ROW_LAST + : ViewTypes.UNISWAP_ROW; + } return index === lastInvestmentIndex - ? ViewTypes.UNISWAP_ROW_LAST - : ViewTypes.UNISWAP_ROW; + ? ViewTypes.UNISWAP_ROW_CLOSED_LAST + : ViewTypes.UNISWAP_ROW_CLOSED; } } @@ -175,17 +268,28 @@ class RecyclerAssetList extends Component { if (index > headersIndices[collectiblesIndex]) { const familyIndex = index - headersIndices[collectiblesIndex] - 1; if (openFamilyTabs[familyIndex]) { - if (get(sections, `[${collectiblesIndex}].data[${familyIndex}].tokens`)) { + if ( + get( + sections, + `[${collectiblesIndex}].data[${familyIndex}].tokens` + ) + ) { return { get: ViewTypes.UNIQUE_TOKEN_ROW, - isLast: index === this.state.length - 2, - size: get(sections, `[${collectiblesIndex}].data[${familyIndex}].tokens`, []).length, + isFirst: index === headersIndices[collectiblesIndex] + 1, + isLast: index === this.state.itemsCount - 2, + rowCount: get( + sections, + `[${collectiblesIndex}].data[${familyIndex}].tokens`, + [] + ).length, }; } } return { get: ViewTypes.UNIQUE_TOKEN_ROW_CLOSED, - isLast: index === this.state.length - 2, + isFirst: index === headersIndices[collectiblesIndex] + 1, + isLast: index === this.state.itemsCount - 2, }; } } @@ -193,7 +297,13 @@ class RecyclerAssetList extends Component { return ViewTypes.COIN_ROW; }, (type, dim) => { - const { hideHeader, paddingBottom } = this.props; + const { + hideHeader, + openSmallBalances, + paddingBottom, + sections, + } = this.props; + const { areSmallCollectibles } = this.state; dim.width = deviceUtils.dimensions.width; @@ -203,28 +313,68 @@ class RecyclerAssetList extends Component { return; } - const fabPositionBottom = type.isLast ? (paddingBottom - (FloatingActionButton.size / 2)) : 0; - const TokenFamilyHeaderHeight = TokenFamilyHeader.height + fabPositionBottom; + const fabPositionBottom = type.isLast + ? paddingBottom - FloatingActionButton.size / 2 + : 0; + const TokenFamilyHeaderHeight = + TokenFamilyHeader.height + fabPositionBottom; + const firstRowExtraTopPadding = type.isFirst ? 4 : 0; if (type.get === ViewTypes.UNIQUE_TOKEN_ROW) { - const extraSpaceForDropShadow = 12; - dim.height = TokenFamilyHeaderHeight + (type.size * UniqueTokenRow.cardSize) + (UniqueTokenRow.cardMargin * (type.size - 1)) + extraSpaceForDropShadow; + const heightOfRows = type.rowCount * UniqueTokenRow.cardSize; + const heightOfRowMargins = + UniqueTokenRow.cardMargin * (type.rowCount - 1); + const extraSpaceForDropShadow = 19; + dim.height = + TokenFamilyHeaderHeight + + heightOfRows + + heightOfRowMargins + + firstRowExtraTopPadding + + extraSpaceForDropShadow; } else if (type.get === ViewTypes.UNIQUE_TOKEN_ROW_CLOSED) { - dim.height = TokenFamilyHeaderHeight; + dim.height = TokenFamilyHeaderHeight + firstRowExtraTopPadding; } else if (type === ViewTypes.COIN_ROW_LAST) { - dim.height = areSmallCollectibles ? CoinRow.height : CoinRow.height + ListFooter.height - 1; + dim.height = areSmallCollectibles + ? CoinRow.height + : CoinRow.height + ListFooter.height + 1; + } else if (type === ViewTypes.COIN_SMALL_BALANCES) { + const balancesIndex = findIndex( + sections, + ({ name }) => name === 'balances' + ); + const size = + sections[balancesIndex].data[ + sections[balancesIndex].data.length - 1 + ].assets.length; + dim.height = openSmallBalances + ? CoinDivider.height + size * CoinRow.height + ListFooter.height + 9 + : CoinDivider.height + ListFooter.height + 16; } else if (type === ViewTypes.COIN_ROW) { dim.height = CoinRow.height; } else if (type === ViewTypes.UNISWAP_ROW_LAST) { - dim.height = UniswapInvestmentCard.height + InvestmentCard.margin.vertical + ListFooter.height + 7; + dim.height = + UniswapInvestmentCard.height + + InvestmentCard.margin.vertical + + ListFooter.height + + 8; } else if (type === ViewTypes.UNISWAP_ROW) { - dim.height = UniswapInvestmentCard.height + InvestmentCard.margin.vertical; + dim.height = + UniswapInvestmentCard.height + InvestmentCard.margin.vertical; + } else if (type === ViewTypes.UNISWAP_ROW_CLOSED_LAST) { + dim.height = + InvestmentCardHeader.height + + InvestmentCard.margin.vertical + + ListFooter.height + + 8; + } else if (type === ViewTypes.UNISWAP_ROW_CLOSED) { + dim.height = + InvestmentCardHeader.height + InvestmentCard.margin.vertical; } else if (type === ViewTypes.HEADER) { dim.height = hideHeader ? 0 : AssetListHeader.height; } else if (type === ViewTypes.FOOTER) { dim.height = 0; } - }, + } ); } @@ -233,47 +383,49 @@ class RecyclerAssetList extends Component { const items = sections.reduce((ctx, section) => { headersIndices.push(ctx.length); return ctx - .concat([{ - isHeader: true, - ...section.header, - }]) - .concat(section.data.map(item => ({ item: { ...item, ...section.perData }, renderItem: section.renderItem }))); + .concat([ + { + isHeader: true, + ...section.header, + }, + ]) + .concat( + section.data.map(item => ({ + item: { ...item, ...section.perData }, + renderItem: section.renderItem, + })) + ); }, []); - items.push({ item: { isLastPlaceholder: true }, renderItem: () => NOOP }); - const areSmallCollectibles = (c => c && get(c, 'type') === 'small')(sections.find(e => e.collectibles)); + items.push({ item: { isLastPlaceholder: true }, renderItem: () => null }); + const areSmallCollectibles = (c => c && get(c, 'type') === 'small')( + sections.find(e => e.collectibles) + ); return { areSmallCollectibles, dataProvider: state.dataProvider.cloneWithRows(items), headersIndices, - length: items.length, + itemsCount: items.length, }; } - shouldComponentUpdate = (nextProps, nextState) => { - if (nextProps.openFamilyTabs !== this.props.openFamilyTabs) { - return true; - } - - if (nextState.isRefreshing !== this.state.isRefreshing) { - return true; - } - - if (this.contentSize - this.layoutMeasurement < this.position && this.position !== 0 && this.position !== 60.5) { - return false; - } - - return true; - } - componentDidMount = () => { this.isCancelled = false; }; - componentDidUpdate(prev) { + componentDidUpdate(prevProps) { + const { + openFamilyTabs, + openInvestmentCards, + openSmallBalances, + scrollingVelocity, + sections, + } = this.props; + let balances = {}; let collectibles = {}; let investments = {}; - this.props.sections.forEach(section => { + + sections.forEach(section => { if (section.balances) { balances = section; } else if (section.collectibles) { @@ -282,51 +434,195 @@ class RecyclerAssetList extends Component { investments = section; } }); - if (this.props.scrollingVelocity === 0) { + + if (scrollingVelocity === 0) { clearInterval(this.interval); } - if (this.props.scrollingVelocity && this.props.scrollingVelocity !== prev.scrollingVelocity) { + + if ( + scrollingVelocity && + scrollingVelocity !== prevProps.scrollingVelocity + ) { clearInterval(this.interval); this.interval = setInterval(() => { - this.rlv.scrollToOffset(0, this.position + this.props.scrollingVelocity * 10); + this.rlv.scrollToOffset(0, this.position + scrollingVelocity * 10); }, 30); } - if (this.props.openFamilyTabs !== prev.openFamilyTabs) { + + if (openFamilyTabs !== prevProps.openFamilyTabs && collectibles.data) { let i = 0; - while (i < this.props.openFamilyTabs.length) { - if (this.props.openFamilyTabs[i] === true && prev.openFamilyTabs[i] === false) { - // TODO no function creation in while loop - setTimeout(() => { - let collectiblesHeight = 0; - for (let j = 0; j < i; j++) { - if (this.props.openFamilyTabs[j] && collectibles.data[j].tokens) { - collectiblesHeight += collectibles.data[j].tokens.length * UniqueTokenRow.cardSize + TokenFamilyHeader.height + UniqueTokenRow.rowPadding * (collectibles.data[j].tokens.length - 1); + while (i < collectibles.data.length) { + if (openFamilyTabs[i] === true && !prevProps.openFamilyTabs[i]) { + let collectiblesHeight = 0; + for (let j = 0; j < i; j++) { + if (openFamilyTabs[j] && collectibles.data[j].tokens) { + collectiblesHeight += + TokenFamilyHeader.height + + collectibles.data[j].tokens.length * UniqueTokenRow.height + + TokenFamilyWrapPaddingTop - + 2; + } else { + collectiblesHeight += TokenFamilyHeader.height; + } + } + let investmentHeight = 0; + if (investments.data) { + for (let k = 0; k < investments.data.length; k++) { + if (!openInvestmentCards[investments.data[k].uniqueId]) { + investmentHeight += + UniswapInvestmentCard.height + InvestmentCard.margin.vertical; } else { - collectiblesHeight += TokenFamilyHeader.height; + investmentHeight += + InvestmentCardHeader.height + InvestmentCard.margin.vertical; } } - const verticalOffset = 17.5; - const deviceDimensions = deviceUtils.dimensions.height - (deviceUtils.isSmallPhone ? 210 : 235); - const sectionBeforeCollectibles = AssetListHeader.height * (this.props.sections.length - 1) + ListFooter.height * (this.props.sections.length - 1) + CoinRow.height * get(balances, 'data.length', 0) + (UniswapInvestmentCard.height + InvestmentCard.margin.vertical) * get(investments, 'data.length', 0) + ListFooter.height; - const sectionsHeight = sectionBeforeCollectibles + collectiblesHeight; - const renderSize = UniqueTokenRow.cardSize * collectibles.data[i].tokens.length + UniqueTokenRow.rowPadding * (collectibles.data[i].tokens.length - 1) - verticalOffset; - - if (renderSize >= deviceDimensions) { - const scrollDistance = sectionsHeight - this.position; - this.rlv.scrollToOffset(0, this.position + scrollDistance - verticalOffset, true); - } else { - const diff = this.position - sectionsHeight + deviceDimensions; - if (renderSize > diff) { - const scrollDistance = deviceDimensions > renderSize ? renderSize - diff : deviceUtils.dimensions.height - (deviceUtils.isSmallPhone ? 250 : 280); - this.rlv.scrollToOffset(0, this.position + scrollDistance, true); + } + let balancesHeight = 0; + if (balances.data) { + balancesHeight += CoinRow.height * (balances.data.length - 1); + if ( + balances.data[balances.data.length - 1].smallBalancesContainer + ) { + balancesHeight += CoinDivider.height + ListFooter.height + 9; + if (openSmallBalances) { + balancesHeight += + CoinRow.height * + balances.data[balances.data.length - 1].assets.length; } + } else { + balancesHeight += CoinDivider.height + ListFooter.height + 16; + } + } + const verticalOffset = 10; + const deviceDimensions = + deviceUtils.dimensions.height - + (deviceUtils.isSmallPhone ? 210 : 235); + const sectionBeforeCollectibles = + AssetListHeader.height * (sections.length - 1) + + ListFooter.height * (sections.length - 1) + + balancesHeight + + investmentHeight; + const sectionsHeight = sectionBeforeCollectibles + collectiblesHeight; + const renderSize = + collectibles.data[i].tokens.length * UniqueTokenRow.height + + TokenFamilyWrapPaddingTop; + + if (renderSize >= deviceDimensions) { + const scrollDistance = sectionsHeight - this.position; + this.scrollToOffset( + this.position + scrollDistance - verticalOffset, + true + ); + } else { + const diff = this.position - sectionsHeight + deviceDimensions; + if (renderSize > diff) { + const scrollDistance = renderSize - diff; + this.scrollToOffset(this.position + scrollDistance, true); } - }, 50); + } break; } i++; } } + + let shouldAutoscrollBack = false; + if (collectibles.data) { + for (let i = 0; i < collectibles.data.length; i++) { + if ( + openFamilyTabs[i] === false && + prevProps.openFamilyTabs[i] === true + ) { + shouldAutoscrollBack = true; + break; + } + } + } + + if (investments.data && !shouldAutoscrollBack) { + for (let i = 0; i < investments.data.length; i++) { + if ( + openInvestmentCards[investments.data[i].uniqueId] === true && + prevProps.openInvestmentCards[investments.data[i].uniqueId] === false + ) { + shouldAutoscrollBack = true; + break; + } + } + } + + if ( + shouldAutoscrollBack || + (openSmallBalances === false && prevProps.openSmallBalances === true) + ) { + let balancesHeight = 0; + if (balances.data) { + balancesHeight += CoinRow.height * (balances.data.length - 1); + if (balances.data[balances.data.length - 1].smallBalancesContainer) { + balancesHeight += CoinDivider.height + ListFooter.height; + if (openSmallBalances) { + balancesHeight += + CoinRow.height * + balances.data[balances.data.length - 1].assets.length; + } + } else { + balancesHeight += CoinRow.height + ListFooter.height; + } + } + + let investmentHeight = 0; + if (investments.data) { + for (let k = 0; k < investments.data.length; k++) { + if (!openInvestmentCards[investments.data[k].uniqueId]) { + investmentHeight += + UniswapInvestmentCard.height + InvestmentCard.margin.vertical; + } else { + investmentHeight += + InvestmentCardHeader.height + InvestmentCard.margin.vertical; + } + } + } + + let collectiblesHeight = 0; + if (collectibles.data) { + collectiblesHeight = + collectibles.data.length > 0 ? AssetListHeader.height : 0; + for (let j = 0; j < collectibles.data.length; j++) { + if (openFamilyTabs[j] && collectibles.data[j].tokens) { + collectiblesHeight += + TokenFamilyHeader.height + + collectibles.data[j].tokens.length * UniqueTokenRow.height + + TokenFamilyWrapPaddingTop - + 2; + } else { + collectiblesHeight += TokenFamilyHeader.height; + } + } + } + const renderSize = + balancesHeight + + investmentHeight + + collectiblesHeight + + ListFooter.height; + const deviceDimensions = + deviceUtils.dimensions.height - (deviceUtils.isSmallPhone ? 240 : 360); + if ( + this.position + deviceDimensions > renderSize && + renderSize > deviceDimensions + ) { + layoutItemAnimator.animateShift = () => + LayoutAnimation.configureNext( + LayoutAnimation.create(310, 'easeInEaseOut', 'opacity') + ); + this.scrollToOffset(renderSize - deviceDimensions, true); + setTimeout(() => { + layoutItemAnimator.animateShift = () => + LayoutAnimation.configureNext( + LayoutAnimation.create(200, 'easeInEaseOut', 'opacity') + ); + }, 300); + } + } } componentWillUnmount = () => { @@ -334,32 +630,73 @@ class RecyclerAssetList extends Component { clearInterval(this.interval); }; - getStableId = (index) => { - const row = get(this.state, `dataProvider._data[${index}]`); - if (get(row, 'item.isLastPlaceholder', false)) { - return 'isLastPlaceholder'; + rlv = React.createRef(); + + contentSize = 0; + + layoutMeasurement = 0; + + position = 0; + + renderList = []; + + scrollToOffset = (position, animated) => { + setTimeout(() => { + this.rlv.scrollToOffset(0, position, animated); + }, 5); + }; + + getStableId = index => { + const { dataProvider } = this.state; + const row = get(dataProvider, `_data[${index}]`); + + if (row.isHeader) { + return `header_${row.title}`; } - return has(row, 'isHeader') - ? buildAssetHeaderUniqueIdentifier(row) - : buildAssetUniqueIdentifier(row.item); + if (row.item && row.item.address) { + return `balance_${row.item.address}`; + } + + if (row.item && row.item.uniqueId) { + return `investment_${row.item.uniqueId}`; + } + + if (row.item && row.item.familyName) { + return `family_${row.item.familyName}`; + } + + if (row.item && row.item.smallBalancesContainer) { + return `balance_${row.item.stableId}`; + } + + if (index === dataProvider._data.length - 1) { + return 'footer'; + } + + return index; }; - handleListRef = (ref) => { this.rlv = ref; } + handleListRef = ref => { + this.rlv = ref; + }; handleRefresh = () => { if (this.state.isRefreshing) return; this.setState({ isRefreshing: true }, () => { - this.props.fetchData().then(() => { - if (!this.isCancelled) { - this.setState({ isRefreshing: false }); - } - }).catch(error => { - if (!this.isCancelled) { - this.setState({ isRefreshing: false }); - } - }); + this.props + .fetchData() + .then(() => { + if (!this.isCancelled) { + this.setState({ isRefreshing: false }); + } + }) + .catch(() => { + if (!this.isCancelled) { + this.setState({ isRefreshing: false }); + } + }); }); }; @@ -376,8 +713,11 @@ class RecyclerAssetList extends Component { this.layoutMeasurement = layoutMeasurement.height; } - if ((contentSize.height - layoutMeasurement.height >= offsetY && offsetY >= 0) - || (offsetY < -60 && offsetY > -62)) { + if ( + (contentSize.height - layoutMeasurement.height >= offsetY && + offsetY >= 0) || + (offsetY < reloadHeightOffsetTop && offsetY > reloadHeightOffsetBottom) + ) { if (this.props.scrollViewTracker) { this.props.scrollViewTracker.setValue(offsetY); } @@ -394,61 +734,94 @@ class RecyclerAssetList extends Component { rowRenderer = (type, data, index) => { if (isNil(data) || isNil(index)) { - return NOOP; + return null; } const { item = {}, renderItem } = data; const { hideHeader, sections } = this.props; if (type === ViewTypes.HEADER) { - return hideHeader ? NOOP : ; + return hideHeader ? null : ; } - const isNotUniqueToken = ( - type === ViewTypes.COIN_ROW - || type === ViewTypes.COIN_ROW_LAST - || type === ViewTypes.UNISWAP_ROW - || type === ViewTypes.UNISWAP_ROW_LAST - || type === ViewTypes.FOOTER - ); + if (type === ViewTypes.COIN_SMALL_BALANCES) { + if ( + this.renderList.length !== item.assets.length || + smallBalancedChanged + ) { + smallBalancedChanged = false; + const renderList = []; + for (let i = 0; i < item.assets.length; i++) { + renderList.push( + renderItem({ + item: { + ...item.assets[i], + isSmall: true, + }, + key: `CoinSmallBalances${i}`, + }) + ); + } + this.renderList = renderList; + } + + return ; + } + + const isNotUniqueToken = + type === ViewTypes.COIN_ROW || + type === ViewTypes.COIN_ROW_LAST || + type === ViewTypes.UNISWAP_ROW || + type === ViewTypes.UNISWAP_ROW_LAST || + type === ViewTypes.UNISWAP_ROW_CLOSED || + type === ViewTypes.UNISWAP_ROW_CLOSED_LAST || + type === ViewTypes.FOOTER; // TODO sections return isNotUniqueToken ? renderItem({ item }) : renderItem({ - childrenAmount: item.childrenAmount, - familyId: item.familyId, - familyImage: item.familyImage, - familyName: item.familyName, - item: item.tokens, - shouldPrioritizeImageLoading: index < get(sections, '[0].data.length', 0) + 9, - uniqueId: item.uniqueId, - }); + childrenAmount: item.childrenAmount, + familyId: item.familyId, + familyImage: item.familyImage, + familyName: item.familyName, + item: item.tokens, + paddingTop: type.isFirst ? 4 : 0, + shouldPrioritizeImageLoading: + index < get(sections, '[0].data.length', 0) + 9, + uniqueId: item.uniqueId, + }); }; render() { - const { hideHeader, renderAheadOffset, ...props } = this.props; + const { + externalScrollView, + fetchData, + hideHeader, + renderAheadOffset, + } = this.props; const { dataProvider, headersIndices } = this.state; return ( size}; position: absolute; - right: ${({ offset }) => (offset * -1)}; - top: ${({ offset }) => (offset * -1)}; + right: ${({ offset }) => offset * -1}; + top: ${({ offset }) => offset * -1}; `; const MultiDigitValue = css` ${padding(2, 5.5, 3)} - transform: translateX(${({ offset }) => (Math.floor(offset / 2))}px); + transform: translateX(${({ offset }) => Math.floor(offset / 2)}px); `; const SingleDigitValue = css` @@ -38,11 +28,8 @@ const SingleDigitValue = css` `; const Circle = styled(Centered)` - ${({ valueLength }) => ( - (valueLength === 1) - ? SingleDigitValue - : MultiDigitValue - )} + ${({ valueLength }) => + valueLength === 1 ? SingleDigitValue : MultiDigitValue} background-color: ${colors.primaryBlue}; border-radius: 15; `; @@ -96,6 +83,6 @@ export default compose( onlyUpdateForKeys(['value']), withProps(({ value }) => ({ valueLength: value.toString().length })), withProps(({ maxLength, value, valueLength }) => ({ - value: (valueLength > maxLength) ? `${'9'.repeat(maxLength)}+` : value, - })), + value: valueLength > maxLength ? `${'9'.repeat(maxLength)}+` : value, + })) )(Badge); diff --git a/src/components/bubble-sheet/BubbleSheet.js b/src/components/bubble-sheet/BubbleSheet.js index 4b66cbe0c7a..22e4ece86f0 100644 --- a/src/components/bubble-sheet/BubbleSheet.js +++ b/src/components/bubble-sheet/BubbleSheet.js @@ -4,7 +4,7 @@ import { Column } from '../layout'; const BubbleSheetBorderRadius = 30; -const BubbleSheet = (props) => ( +const BubbleSheet = props => ( + + + + + + + + + + +); + +const enhanceButton = compose( + setPropTypes({ onPress: PropTypes.func.isRequired }), + withNeverRerender +); + +const AddButton = enhanceButton(({ onPress }) => ( + +)); + +const EditButton = enhanceButton(({ onPress }) => ( + + + +)); + +const AddContactButton = ({ edit, onPress }) => { + const addButtonRef = useRef(); + const editButtonRef = useRef(); + + useEffect(() => { + if (addButtonRef.current) addButtonRef.current.animateNextTransition(); + if (editButtonRef.current) editButtonRef.current.animateNextTransition(); + }, [edit]); + + return ( + + {edit ? ( + + + + ) : ( + + + + )} + + ); +}; + +AddContactButton.propTypes = { + edit: PropTypes.bool, + onPress: PropTypes.func.isRequired, +}; + +export default React.memo(AddContactButton); diff --git a/src/components/buttons/BlockButton.js b/src/components/buttons/BlockButton.js deleted file mode 100644 index ba2b1281871..00000000000 --- a/src/components/buttons/BlockButton.js +++ /dev/null @@ -1,115 +0,0 @@ -import withViewLayoutProps from '@hocs/with-view-layout-props'; -import PropTypes from 'prop-types'; -import React from 'react'; -import RadialGradient from 'react-native-radial-gradient'; -import styled, { css } from 'styled-components/primitives'; -import { componentFromProp } from 'recompact'; -import { - colors, - padding, - position, - shadow, -} from '../../styles'; -import ButtonPressAnimation from '../animations'; -import InnerBorder from '../InnerBorder'; -import { Centered } from '../layout'; -import { Text } from '../text'; -import { Icon } from '../icons'; - -const BlockButtonBorderRadius = 14; -const BlockButtonHeight = 59; - -const containerStyles = css` - border-radius: ${BlockButtonBorderRadius}; - flex-grow: 0; - height: ${BlockButtonHeight}; -`; - -const ContainerElement = componentFromProp('component'); - -const Container = styled(ContainerElement)` - border-radius: ${BlockButtonBorderRadius}; -`; - -const Content = styled(Centered)` - ${containerStyles} - ${padding(15, 15)} - overflow: hidden; -`; - -const Shadow = styled.View` - ${containerStyles} - ${shadow.build(0, 6, 10, colors.purple, 0.14)} - ${shadow.build(0, 1, 18, colors.purple, 0.12)} - ${shadow.build(0, 3, 5, colors.purple, 0.2)} -`; - -const LeftIcon = styled(Icon).attrs({ color: colors.white, size: 32 })` - ${position.size(BlockButtonHeight)} - position: absolute; - left: 15px; -`; - -const RightIcon = styled(Icon).attrs({ color: colors.white, size: 32 })` - ${position.size(BlockButtonHeight)} - position: absolute; - right: 15px; -`; - -const BlockButton = ({ - children, - disabled, - height, - onLayout, - width, - leftIconName, - leftIconProps, - rightIconName, - rightIconProps, - ...props -}) => ( - - - - - - {leftIconName ? : null} - - {children} - - {rightIconName ? : null} - - - -); - -BlockButton.propTypes = { - children: PropTypes.node, - disabled: PropTypes.disabled, - height: PropTypes.number, - leftIconName: PropTypes.string, - leftIconProps: PropTypes.object, - onLayout: PropTypes.func, - rightIconName: PropTypes.string, - rightIconProps: PropTypes.object, - width: PropTypes.number, -}; - -BlockButton.defaultProps = { - component: ButtonPressAnimation, - disabled: false, - leftIconProps: {}, - rightIconProps: {}, -}; - -export default withViewLayoutProps(({ height, width }) => ({ height, width }))(BlockButton); diff --git a/src/components/buttons/Button.js b/src/components/buttons/Button.js index eefa7030c20..1464bb33587 100644 --- a/src/components/buttons/Button.js +++ b/src/components/buttons/Button.js @@ -35,15 +35,12 @@ const Container = styled(Centered)` ${({ showShadow }) => (showShadow ? shadowStyles : '')} ${({ size }) => padding(...ButtonSizeTypes[size].padding)} background-color: ${({ backgroundColor }) => backgroundColor}; - border-radius: ${({ type }) => ((type === 'rounded') ? 14 : 50)}; + border-radius: ${({ type }) => (type === 'rounded' ? 14 : 50)}; flex-grow: 0; `; -const shouldRenderChildrenAsText = (children) => ( - isArray(children) - ? isString(children[0]) - : isString(children) -); +const shouldRenderChildrenAsText = children => + isArray(children) ? isString(children[0]) : isString(children); const Button = ({ backgroundColor, @@ -77,24 +74,23 @@ const Button = ({ style={style} type={type} > - {!shouldRenderChildrenAsText(children) - ? children - : ( - - {children} - - ) - } + {!shouldRenderChildrenAsText(children) ? ( + children + ) : ( + + {children} + + )} {(!onPress || !disabled) && ( )} diff --git a/src/components/buttons/CoolButton.js b/src/components/buttons/CoolButton.js new file mode 100644 index 00000000000..477c87e1984 --- /dev/null +++ b/src/components/buttons/CoolButton.js @@ -0,0 +1,73 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import FastImage from 'react-native-fast-image'; +import { onlyUpdateForKeys, withProps } from 'recompact'; +import CaretImageSource from '../../assets/family-dropdown-arrow.png'; +import { colors, margin, padding, position } from '../../styles'; +import { ButtonPressAnimation } from '../animations'; +import InnerBorder from '../InnerBorder'; +import { Row, RowWithMargins } from '../layout'; +import { ShadowStack } from '../shadow-stack'; +import { Text } from '../text'; + +const CoolLabel = withProps({ + color: 'white', + flex: 1, + size: 'lmedium', + weight: 'semibold', +})(Text); + +const enhance = onlyUpdateForKeys(['children', 'color']); + +const CoolButton = enhance( + ({ borderRadius, children, color, onPress, shadows }) => ( + + + + + {children} + + + + + + ) +); + +CoolButton.propTypes = { + borderRadius: PropTypes.number, + children: PropTypes.node, + color: PropTypes.string, + onPress: PropTypes.func, + shadows: PropTypes.arrayOf(PropTypes.array), +}; + +CoolButton.defaultProps = { + borderRadius: 20, + shadows: [ + [0, 2, 5, colors.dark, 0.15], + [0, 6, 10, colors.dark, 0.14], + [0, 1, 18, colors.dark, 0.08], + ], +}; + +export default CoolButton; diff --git a/src/components/buttons/HoldToAuthorizeButton.js b/src/components/buttons/HoldToAuthorizeButton.js deleted file mode 100644 index ebeedcbce91..00000000000 --- a/src/components/buttons/HoldToAuthorizeButton.js +++ /dev/null @@ -1,252 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { PureComponent } from 'react'; -import { - LongPressGestureHandler, - State, - TapGestureHandler, -} from 'react-native-gesture-handler'; -import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; -import RadialGradient from 'react-native-radial-gradient'; -import Animated, { Easing } from 'react-native-reanimated'; -import { withProps } from 'recompact'; -import styled from 'styled-components/primitives'; -import { colors, padding, position } from '../../styles'; -import { deviceUtils } from '../../utils'; -import { ScaleInAnimation } from '../animations'; -import { BiometryIcon, Icon } from '../icons'; -import InnerBorder from '../InnerBorder'; -import { Centered } from '../layout'; -import { ShadowStack } from '../shadow-stack'; -import { Text } from '../text'; - -const { - cond, - divide, - greaterThan, - multiply, - sub, - timing, - Value, - View, -} = Animated; - -const ButtonBorderRadius = 30; -const ButtonHeight = 59; -const ButtonShadows = { - default: [ - [0, 3, 5, colors.dark, 0.2], - [0, 6, 10, colors.dark, 0.14], - [0, 1, 18, colors.dark, 0.12], - ], - disabled: [ - [0, 2, 6, colors.dark, 0.06], - [0, 3, 9, colors.dark, 0.08], - ], -}; - -const progressDurationMs = 500; // @christian approves - -const Content = styled(Centered)` - ${padding(15)} - border-radius: ${ButtonBorderRadius}; - flex-grow: 0; - height: ${ButtonHeight}; - overflow: hidden; - width: 100%; -`; - -const IconContainer = styled(Centered)` - ${position.size(34)} - left: 19; - margin-bottom: 2; - position: absolute; -`; - -const Title = withProps({ - color: 'white', - size: 'large', - style: { marginBottom: 2 }, - weight: 'semibold', -})(Text); - -const GradientColors = { - default: { - from: colors.primaryBlue, - to: '#006FFF', - }, - disabled: { - from: colors.grey, - to: colors.grey, - }, -}; - -const buildAnimation = (value, options) => { - const { - duration = 150, - isInteraction = false, - toValue, - } = options; - - return timing(value, { - duration, - easing: Easing.inOut(Easing.ease), - isInteraction, - toValue, - useNativeDriver: true, - }); -}; - -const calculateReverseDuration = progess => multiply(divide(progess, 100), progressDurationMs); - -const HoldToAuthorizeButtonIcon = ({ animatedValue, isAuthorizing }) => { - const isSpinnerVisible = greaterThan(animatedValue, 0); - const spinnerIn = sub(22, animatedValue); - const spinnerOut = divide(1, animatedValue); - - return ( - - - - - - - - - ); -}; - -HoldToAuthorizeButtonIcon.propTypes = { - animatedValue: PropTypes.object, - isAuthorizing: PropTypes.bool, -}; - -export default class HoldToAuthorizeButton extends PureComponent { - static propTypes = { - children: PropTypes.any, - disabled: PropTypes.bool, - isAuthorizing: PropTypes.bool, - onLongPress: PropTypes.func.isRequired, - style: PropTypes.object, - } - - static defaultProps = { - disabled: false, - } - - state = { - isAuthorizing: false, - } - - animation = new Value(0) - - progress = new Value(0) - - scale = new Value(1) - - tapHandlerState = 1 - - componentDidUpdate = () => { - if (this.state.isAuthorizing && !this.props.isAuthorizing) { - this.setState({ isAuthorizing: false }); - } - } - - onTapChange = ({ nativeEvent }) => { - const { disabled } = this.props; - - this.tapHandlerState = nativeEvent.state; - - if (nativeEvent.state === State.BEGAN) { - if (disabled) { - ReactNativeHapticFeedback.trigger('notificationWarning'); - buildAnimation(this.scale, { toValue: 0.99 }).start(() => { - buildAnimation(this.scale, { toValue: 1 }).start(); - }); - } else { - buildAnimation(this.scale, { toValue: 0.97 }).start(); - buildAnimation(this.animation, { - duration: progressDurationMs, - toValue: 100, - }).start(); - } - } else if (!disabled && nativeEvent.state === State.END) { - buildAnimation(this.scale, { toValue: 1 }).start(); - buildAnimation(this.animation, { - duration: calculateReverseDuration(this.animation), - isInteraction: true, - toValue: 0, - }).start(); - } - } - - onLongPressChange = ({ nativeEvent }) => { - const { disabled, onLongPress } = this.props; - - if (!disabled && nativeEvent.state === State.ACTIVE) { - ReactNativeHapticFeedback.trigger('notificationSuccess'); - - buildAnimation(this.scale, { - isInteraction: true, - toValue: 1, - }).start(() => this.setState({ isAuthorizing: true })); - - if (onLongPress) { - onLongPress(); - } - } - } - - render() { - const { - children, - disabled, - style, - ...props - } = this.props; - - const theme = disabled ? 'disabled' : 'default'; - - return ( - - - - - - - - - {this.state.isAuthorizing - ? 'Authorizing' - : children - } - - - - - - - - ); - } -} diff --git a/src/components/buttons/LongPressButton.js b/src/components/buttons/LongPressButton.js deleted file mode 100644 index 73a38bff31a..00000000000 --- a/src/components/buttons/LongPressButton.js +++ /dev/null @@ -1,106 +0,0 @@ -import React, { Component } from 'react'; -import { InteractionManager } from 'react-native'; -import Animated, { Easing } from 'react-native-reanimated'; -import { LongPressGestureHandler, State, TapGestureHandler } from 'react-native-gesture-handler'; -import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; -import PropTypes from 'prop-types'; - -const { - timing, - Value, - View, -} = Animated; - -export default class LongPressButton extends Component { - static propTypes = { - children: PropTypes.any, - disabled: PropTypes.bool, - onLongPress: PropTypes.func, - onPress: PropTypes.func, - onRelease: PropTypes.func, - style: PropTypes.object, - }; - - static defaultProps = { - disabled: false, - onLongPress() {}, - onPress() {}, - onRelease() {}, - }; - - constructor(props) { - super(props); - - this.scale = new Value(1); - } - - onTapHandlerStateChange = ({ nativeEvent }) => { - const { disabled, onPress, onRelease } = this.props; - - if (nativeEvent.state === State.BEGAN) { - if (disabled) { - ReactNativeHapticFeedback.trigger('notificationWarning'); - - timing(this.scale, { - duration: 150, - easing: Easing.inOut(Easing.ease), - toValue: 0.975, - }).start(() => { - timing(this.scale, { - duration: 150, - easing: Easing.inOut(Easing.ease), - toValue: 1, - }).start(); - }); - } else { - timing(this.scale, { - duration: 150, - easing: Easing.inOut(Easing.ease), - toValue: 0.875, - }).start(); - - onPress(); - } - } else if (!disabled && nativeEvent.state === State.END) { - timing(this.scale, { - duration: 150, - easing: Easing.inOut(Easing.ease), - toValue: 1, - }).start(); - - InteractionManager.runAfterInteractions(() => { - onRelease(); - }); - } - }; - - onLongPressHandlerStateChange = ({ nativeEvent }) => { - const { disabled, onLongPress } = this.props; - - if (!disabled && nativeEvent.state === State.ACTIVE) { - ReactNativeHapticFeedback.trigger('impactHeavy'); - - timing(this.scale, { - duration: 150, - easing: Easing.inOut(Easing.ease), - toValue: 1, - }).start(() => { - InteractionManager.runAfterInteractions(() => { - onLongPress(); - }); - }); - } - }; - - render() { - const { children, style } = this.props; - - return ( - - - {children} - - - ); - } -} diff --git a/src/components/buttons/PasteAddressButton.js b/src/components/buttons/PasteAddressButton.js index e6f82968234..577fc3726c1 100644 --- a/src/components/buttons/PasteAddressButton.js +++ b/src/components/buttons/PasteAddressButton.js @@ -4,46 +4,52 @@ import { Clipboard } from 'react-native'; import Button from './Button'; import { withAppState } from '../../hoc'; import { colors } from '../../styles'; -import { isValidAddress } from '../../helpers/validators'; +import { checkIsValidAddress } from '../../helpers/validators'; class PasteAddressButton extends PureComponent { static propTypes = { appState: PropTypes.string, onPress: PropTypes.func.isRequired, - } + }; - state = { clipboardContents: null } + state = { clipboardContents: null }; componentDidMount() { this.getClipboardContents(); } componentDidUpdate(prevProps) { - if (prevProps.appState === 'background' && this.props.appState === 'active') { + if ( + prevProps.appState === 'background' && + this.props.appState === 'active' + ) { this.getClipboardContents(); } } - getClipboardContents = async () => Clipboard.getString().then(this.setClipboardContents) + getClipboardContents = async () => + Clipboard.getString().then(this.setClipboardContents); handlePress = () => { if (this.state.clipboardContents) { this.props.onPress(this.state.clipboardContents); } - } + }; - setClipboardContents = async (clipboardContents) => { - if (await isValidAddress(clipboardContents)) { + setClipboardContents = async clipboardContents => { + if (await checkIsValidAddress(clipboardContents)) { this.setState({ clipboardContents }); } - } + }; render() { const { clipboardContents } = this.state; return ( + + + + {contact ? 'Delete Contact' : 'Cancel'} + + + + + + + + ); + } +} + +export default compose( + withAccountData, + withAccountSettings, + withContacts, + onlyUpdateForKeys(['price', 'subtitle']) +)(AddContactState); diff --git a/src/components/expanded-state/FloatingPanel.js b/src/components/expanded-state/FloatingPanel.js index 7baf5e8b901..ecdd8e34d40 100644 --- a/src/components/expanded-state/FloatingPanel.js +++ b/src/components/expanded-state/FloatingPanel.js @@ -12,33 +12,31 @@ export const FloatingPanelPadding = { y: 0, }; -const FloatingPanel = pure(({ - color, - height, - hideShadow, - style, - ...props -}) => ( - ( + -)); + style={hideShadow ? {} : style} + {...props} + /> + ) +); FloatingPanel.propTypes = { color: PropTypes.string, height: PropTypes.number, hideShadow: PropTypes.bool, + overflow: PropTypes.string, + radius: PropTypes.number, style: stylePropType, width: PropTypes.number, }; diff --git a/src/components/expanded-state/FloatingPanels.js b/src/components/expanded-state/FloatingPanels.js index 1557e7a84d1..af3bbf76293 100644 --- a/src/components/expanded-state/FloatingPanels.js +++ b/src/components/expanded-state/FloatingPanels.js @@ -6,12 +6,12 @@ const FloatingPanelsMargin = 20; const FloatingPanels = compose( setDisplayName('FloatingPanels'), - withProps({ + withProps(({ margin = FloatingPanelsMargin, style }) => ({ justify: 'center', - margin: FloatingPanelsMargin, + margin, pointerEvents: 'box-none', - style: position.sizeAsObject('100%'), - }), + style: [position.sizeAsObject('100%'), style], + })) )(ColumnWithMargins); FloatingPanels.margin = FloatingPanelsMargin; diff --git a/src/components/expanded-state/InvestmentExpandedState.js b/src/components/expanded-state/InvestmentExpandedState.js index 46196c51a19..051b9b6376e 100644 --- a/src/components/expanded-state/InvestmentExpandedState.js +++ b/src/components/expanded-state/InvestmentExpandedState.js @@ -9,6 +9,7 @@ const InvestmentExpandedState = ({ asset }) => ( diff --git a/src/components/expanded-state/TokenExpandedState.js b/src/components/expanded-state/TokenExpandedState.js index 54587c73014..c7228e93b11 100644 --- a/src/components/expanded-state/TokenExpandedState.js +++ b/src/components/expanded-state/TokenExpandedState.js @@ -2,35 +2,17 @@ import { get } from 'lodash'; import PropTypes from 'prop-types'; import React from 'react'; import { InteractionManager } from 'react-native'; -import { - compose, - onlyUpdateForKeys, - withHandlers, - withProps, -} from 'recompact'; +import { compose, onlyUpdateForKeys, withHandlers, withProps } from 'recompact'; import { withAccountData, withAccountSettings } from '../../hoc'; import { ethereumUtils } from '../../utils'; import { AssetPanel, AssetPanelAction, AssetPanelHeader } from './asset-panel'; import FloatingPanels from './FloatingPanels'; -const TokenExpandedState = ({ - onPressSend, - price, - subtitle, - title, -}) => ( - +const TokenExpandedState = ({ onPressSend, price, subtitle, title }) => ( + - - + + ); @@ -45,16 +27,7 @@ TokenExpandedState.propTypes = { export default compose( withAccountData, withAccountSettings, - withProps(({ - asset: { - address, - name, - symbol, - ...asset - }, - assets, - nativeCurrencySymbol, - }) => { + withProps(({ asset: { address, name, symbol }, assets }) => { const selectedAsset = ethereumUtils.getAsset(assets, address); return { price: get(selectedAsset, 'native.price.display', null), @@ -71,5 +44,5 @@ export default compose( }); }, }), - onlyUpdateForKeys(['price', 'subtitle']), + onlyUpdateForKeys(['price', 'subtitle']) )(TokenExpandedState); diff --git a/src/components/expanded-state/UniqueTokenExpandedState.js b/src/components/expanded-state/UniqueTokenExpandedState.js index b09844b626d..2362b7da12d 100644 --- a/src/components/expanded-state/UniqueTokenExpandedState.js +++ b/src/components/expanded-state/UniqueTokenExpandedState.js @@ -19,11 +19,7 @@ import { import { Centered } from '../layout'; import { Pager } from '../pager'; import { UniqueTokenAttributes, UniqueTokenImage } from '../unique-token'; -import { - AssetPanel, - AssetPanelAction, - AssetPanelHeader, -} from './asset-panel'; +import { AssetPanel, AssetPanelAction, AssetPanelHeader } from './asset-panel'; import FloatingPanel from './FloatingPanel'; import FloatingPanels from './FloatingPanels'; @@ -34,9 +30,6 @@ const PagerControlsColorVariants = { const UniqueTokenExpandedState = ({ asset, - containerHeight, - containerWidth, - imageDimensions, maxImageHeight, onLayout, onPressSend, @@ -48,18 +41,20 @@ const UniqueTokenExpandedState = ({ subtitle, title, }) => { - const PanelPages = [{ - component: ( - - ), - name: 'UniqueTokenImage', - }]; + const PanelPages = [ + { + component: ( + + ), + name: 'UniqueTokenImage', + }, + ]; if (asset.traits.length) { PanelPages.push({ @@ -69,10 +64,14 @@ const UniqueTokenExpandedState = ({ } return ( - + {!!maxImageHeight && ( - + {/* TODO XXX: THIS FLOATING PANEL SHOULD HAVE HORIZONTAL PADDING IF THE IMAGE IS A PERFECT SQUARE @@ -80,7 +79,10 @@ const UniqueTokenExpandedState = ({ )} - + {asset.isSendable && ( - + ); @@ -139,7 +134,7 @@ const buildPanelDimensions = ({ panelWidth, }) => { const panelHeight = imageDimensions - ? ((panelWidth * imageDimensions.height) / imageDimensions.width) + ? (panelWidth * imageDimensions.height) / imageDimensions.width : panelWidth; const panelDimensions = { panelHeight }; @@ -148,7 +143,7 @@ const buildPanelDimensions = ({ panelDimensions.panelHeight = maxImageHeight; panelDimensions.panelWidth = background ? panelWidth - : ((maxImageHeight * imageDimensions.width) / imageDimensions.height); + : (maxImageHeight * imageDimensions.width) / imageDimensions.height; } return panelDimensions; @@ -159,9 +154,10 @@ export default compose( withViewLayoutProps(({ height: siblingHeight }) => { const { bottom, top } = safeAreaInsetValues; - const viewportPadding = (bottom ? (bottom + top) : (top + top)); + const viewportPadding = bottom ? bottom + top : top + top; const viewportHeight = deviceUtils.dimensions.height - viewportPadding; - const maxImageHeight = viewportHeight - siblingHeight - FloatingPanels.margin; + const maxImageHeight = + viewportHeight - siblingHeight - FloatingPanels.margin; return { maxImageHeight }; }), @@ -192,5 +188,5 @@ export default compose( Linking.openURL(permalink); }, }), - onlyUpdateForPropTypes, + onlyUpdateForPropTypes )(UniqueTokenExpandedState); diff --git a/src/components/expanded-state/asset-panel/AssetPanel.js b/src/components/expanded-state/asset-panel/AssetPanel.js index 080c67f9715..db2cb206b17 100644 --- a/src/components/expanded-state/asset-panel/AssetPanel.js +++ b/src/components/expanded-state/asset-panel/AssetPanel.js @@ -5,9 +5,7 @@ import FloatingPanel from '../FloatingPanel'; const AssetPanel = ({ children, ...props }) => ( - - {children} - + {children} ); diff --git a/src/components/expanded-state/asset-panel/AssetPanelAction.js b/src/components/expanded-state/asset-panel/AssetPanelAction.js index 560e2e1b466..e59887448e3 100644 --- a/src/components/expanded-state/asset-panel/AssetPanelAction.js +++ b/src/components/expanded-state/asset-panel/AssetPanelAction.js @@ -31,17 +31,8 @@ const AssetPanelIconContainer = styled(Centered)` width: 24; `; -const AssetPanelAction = ({ - color, - icon, - label, - onPress, -}) => ( - +const AssetPanelAction = ({ color, icon, label, onPress }) => ( + - + ); diff --git a/src/components/expanded-state/asset-panel/AssetPanelHeader.js b/src/components/expanded-state/asset-panel/AssetPanelHeader.js index 68f3cc93fe3..16ef44eb9ee 100644 --- a/src/components/expanded-state/asset-panel/AssetPanelHeader.js +++ b/src/components/expanded-state/asset-panel/AssetPanelHeader.js @@ -41,12 +41,7 @@ const Title = styled(TruncatedText).attrs(HeadingTextStyles)` padding-right: ${({ paddingRight }) => paddingRight}; `; -const AssetPanelHeader = ({ - price, - priceLabel, - subtitle, - title, -}) => ( +const AssetPanelHeader = ({ price, priceLabel, subtitle, title }) => ( diff --git a/src/components/expanded-state/index.js b/src/components/expanded-state/index.js index 2582acc9818..c8cff3f975e 100644 --- a/src/components/expanded-state/index.js +++ b/src/components/expanded-state/index.js @@ -3,3 +3,4 @@ export { default as FloatingPanels } from './FloatingPanels'; export { default as InvestmentExpandedState } from './InvestmentExpandedState'; export { default as TokenExpandedState } from './TokenExpandedState'; export { default as UniqueTokenExpandedState } from './UniqueTokenExpandedState'; +export { default as AddContactState } from './AddContactState'; diff --git a/src/components/fab/DeleteButton.js b/src/components/fab/DeleteButton.js index cc42a74deae..43b413e3f31 100644 --- a/src/components/fab/DeleteButton.js +++ b/src/components/fab/DeleteButton.js @@ -17,7 +17,9 @@ const DeleteButton = enhance(({ deleteButtonScale }) => ( ...position.centeredAsObject, ...position.sizeAsObject(size), position: 'absolute', - transform: transformOrigin(size / -8, size / -8, { scale: deleteButtonScale }), + transform: transformOrigin(size / -8, size / -8, { + scale: deleteButtonScale, + }), }} > <ShadowStack @@ -25,11 +27,7 @@ const DeleteButton = enhance(({ deleteButtonScale }) => ( backgroundColor={colors.dark} shadows={FloatingActionButton.shadow} > - <Icon - color="white" - name="close" - size={12} - /> + <Icon color="white" name="close" size={12} /> </ShadowStack> </Animated.View> )); diff --git a/src/components/fab/ExchangeFab.js b/src/components/fab/ExchangeFab.js new file mode 100644 index 00000000000..cba952d1555 --- /dev/null +++ b/src/components/fab/ExchangeFab.js @@ -0,0 +1,33 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { withNavigation } from 'react-navigation'; +import { compose, onlyUpdateForKeys, withHandlers } from 'recompact'; +import { withFabSelection } from '../../hoc'; +import { colors } from '../../styles'; +import { Icon } from '../icons'; +import FloatingActionButton from './FloatingActionButton'; + +const ExchangeFab = ({ disabled, onPress, ...props }) => ( + <FloatingActionButton + {...props} + backgroundColor={colors.dodgerBlue} + disabled={disabled} + onPress={onPress} + > + <Icon height={21} marginBottom={2} name="swap" width={26} /> + </FloatingActionButton> +); + +ExchangeFab.propTypes = { + disabled: PropTypes.bool, + onPress: PropTypes.func, +}; + +export default compose( + withFabSelection, + withNavigation, + withHandlers({ + onPress: ({ navigation }) => () => navigation.navigate('ExchangeModal'), + }), + onlyUpdateForKeys(['disabled']) +)(ExchangeFab); diff --git a/src/components/fab/FabWrapper.js b/src/components/fab/FabWrapper.js index 72a9798cf73..1a7674e25c7 100644 --- a/src/components/fab/FabWrapper.js +++ b/src/components/fab/FabWrapper.js @@ -4,16 +4,12 @@ import { onlyUpdateForKeys } from 'recompact'; import { safeAreaInsetValues } from '../../utils'; import { FlexItem, RowWithMargins } from '../layout'; import SendFab from './SendFab'; +import ExchangeFab from './ExchangeFab'; const bottomPosition = 21 + safeAreaInsetValues.bottom; const enhance = onlyUpdateForKeys(['children', 'disabled']); -const FabWrapper = enhance(({ - children, - disabled, - fabs, - ...props -}) => ( +const FabWrapper = enhance(({ children, disabled, fabs, ...props }) => ( <FlexItem> {children} {!disabled && ( @@ -26,9 +22,10 @@ const FabWrapper = enhance(({ `} direction="row-reverse" margin={12} - marginKey="left" > - {fabs.map(fab => createElement(fab, props))} + {fabs.map((fab, id) => + createElement(fab, { key: `fab-${id}`, ...props }) + )} </RowWithMargins> )} </FlexItem> @@ -43,7 +40,7 @@ FabWrapper.propTypes = { }; FabWrapper.defaultProps = { - fabs: [SendFab], + fabs: [ExchangeFab, SendFab], }; FabWrapper.bottomPosition = bottomPosition; diff --git a/src/components/fab/FloatingActionButton.js b/src/components/fab/FloatingActionButton.js index 61f138fd679..2b41b34a90c 100644 --- a/src/components/fab/FloatingActionButton.js +++ b/src/components/fab/FloatingActionButton.js @@ -5,7 +5,7 @@ import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; import { ButtonPressAnimation } from '../animations'; import InnerBorder from '../InnerBorder'; import { borders, colors, position } from '../../styles'; -import { isNewValueForPath } from '../../utils'; +import { isNewValueForObjectPaths } from '../../utils'; import { ShadowStack } from '../shadow-stack'; const FabSize = 56; @@ -17,6 +17,7 @@ const FabShadow = [ export default class FloatingActionButton extends Component { static propTypes = { + backgroundColor: PropTypes.string, children: PropTypes.oneOfType([PropTypes.func, PropTypes.node]), disabled: PropTypes.bool, isFabSelectionValid: PropTypes.bool, @@ -25,39 +26,41 @@ export default class FloatingActionButton extends Component { scaleTo: PropTypes.number, size: PropTypes.number, tapRef: PropTypes.object, - } + }; static defaultProps = { scaleTo: 0.82, size: FabSize, - } + }; - static size = FabSize + shouldComponentUpdate = nextProps => + isNewValueForObjectPaths(this.props, nextProps, [ + 'disabled', + 'isFabSelectionValid', + 'scaleTo', + ]); - static sizeWhileDragging = 74 + static size = FabSize; - static shadow = FabShadow + static sizeWhileDragging = 74; - shouldComponentUpdate = nextProps => ( - isNewValueForPath(this.props, nextProps, 'disabled') - || isNewValueForPath(this.props, nextProps, 'isFabSelectionValid') - || isNewValueForPath(this.props, nextProps, 'scaleTo') - ) + static shadow = FabShadow; - handlePress = (event) => { + handlePress = event => { const { onPress } = this.props; ReactNativeHapticFeedback.trigger('impactLight'); if (onPress) onPress(event); - } + }; - handlePressIn = (event) => { + handlePressIn = event => { const { onPressIn } = this.props; ReactNativeHapticFeedback.trigger('impactLight'); if (onPressIn) onPressIn(event); - } + }; render = () => { const { + backgroundColor, children, disabled, isFabSelectionValid, @@ -84,23 +87,15 @@ export default class FloatingActionButton extends Component { <View {...position.centeredAsObject} {...position.coverAsObject} - backgroundColor={isDisabled ? colors.grey : colors.paleBlue} + backgroundColor={isDisabled ? colors.grey : backgroundColor} disabled={disabled} isFabSelectionValid={isFabSelectionValid} > - {(typeof children === 'function') - ? children({ size }) - : children - } - {!disabled && ( - <InnerBorder - opacity={0.06} - radius={size / 2} - /> - )} + {typeof children === 'function' ? children({ size }) : children} + {!disabled && <InnerBorder opacity={0.06} radius={size / 2} />} </View> </ShadowStack> </ButtonPressAnimation> ); - } + }; } diff --git a/src/components/fab/MovableFabWrapper.js b/src/components/fab/MovableFabWrapper.js index 898ac3d0c99..ea6586a8fb6 100644 --- a/src/components/fab/MovableFabWrapper.js +++ b/src/components/fab/MovableFabWrapper.js @@ -3,11 +3,21 @@ import React, { PureComponent } from 'react'; import { PanGestureHandler, State } from 'react-native-gesture-handler'; import Animated from 'react-native-reanimated'; import { compose, withProps } from 'recompact'; -import { withFabSelection, withOpenFamilyTabs } from '../../hoc'; +import { + withFabSelection, + withOpenBalances, + withOpenFamilyTabs, + withOpenInvestmentCards, +} from '../../hoc'; import { deviceUtils } from '../../utils'; import { CoinRow } from '../coin-row'; -import { InvestmentCard, UniswapInvestmentCard } from '../investment-cards'; import { ListFooter } from '../list'; +import { + InvestmentCard, + InvestmentCardHeader, + UniswapInvestmentCard, +} from '../investment-cards'; +import { CoinDivider } from '../coin-divider'; import { UniqueTokenRow } from '../unique-token'; import DeleteButton from './DeleteButton'; @@ -35,13 +45,7 @@ const { Value, } = Animated; -function runSpring( - clock, - value, - velocity, - dest, - wasRunSpring = false, -) { +function runSpring(clock, value, velocity, dest, wasRunSpring = false) { const state = { finished: new Value(0), position: new Value(0), @@ -68,10 +72,7 @@ function runSpring( startClock(clock), ]), spring(clock, state, config), - cond(state.finished, [ - stopClock(clock), - set(wasRunSpring, 1), - ]), + cond(state.finished, [stopClock(clock), set(wasRunSpring, 1)]), state.position, ]; } @@ -89,9 +90,7 @@ class MovableFabWrapper extends PureComponent { areas: PropTypes.array, children: PropTypes.any, deleteButtonScale: PropTypes.object, - openFamilyTabs: PropTypes.array, scrollViewTracker: PropTypes.object, - sections: PropTypes.array, setActionType: PropTypes.func, setScrollingVelocity: PropTypes.func, tapRef: PropTypes.object, @@ -120,7 +119,8 @@ class MovableFabWrapper extends PureComponent { gestureState = new Animated.Value(0); - isOverDeleteButtonBoundary = position => greaterThan(abs(position), DeleteButton.size * 2); + isOverDeleteButtonBoundary = position => + greaterThan(abs(position), DeleteButton.size * 2); key = 0; @@ -140,31 +140,44 @@ class MovableFabWrapper extends PureComponent { xClockShow = new Clock(); - calculateSelectedIndex = () => cond( - or( - lessThan(this.absoluteY, 109), - this.isOverX, - ), - extraStates.overX, - this.props.areas.reduce((prev, curr, i) => cond( - and( - greaterThan(this.absoluteX, curr.left), - greaterThan(add(this.absoluteY, this.props.scrollViewTracker), curr.top), - lessThan(add(this.absoluteY, this.props.scrollViewTracker), curr.bottom), - lessThan(this.absoluteX, curr.right), - ), i, prev, - ), extraStates.nothing), - ); + calculateSelectedIndex = () => + cond( + or(lessThan(this.absoluteY, 109), this.isOverX), + extraStates.overX, + this.props.areas.reduce( + (prev, curr, i) => + cond( + and( + greaterThan(this.absoluteX, curr.left), + greaterThan( + add(this.absoluteY, this.props.scrollViewTracker), + curr.top + ), + lessThan( + add(this.absoluteY, this.props.scrollViewTracker), + curr.bottom + ), + lessThan(this.absoluteX, curr.right) + ), + i, + prev + ), + extraStates.nothing + ) + ); isOverX = and( greaterThan(this.absoluteY, deviceUtils.dimensions.height - 120), - greaterThan(this.absoluteX, deviceUtils.dimensions.width - 100), + greaterThan(this.absoluteX, deviceUtils.dimensions.width - 100) ); manageUpAndDownScrolling = cond( - and(greaterThan(this.absoluteY, deviceUtils.dimensions.height - 20), not(this.isOverX)), + and( + greaterThan(this.absoluteY, deviceUtils.dimensions.height - 20), + not(this.isOverX) + ), 1, - cond(lessThan(this.absoluteY, 120), 2, 0), + cond(lessThan(this.absoluteY, 120), 2, 0) ); onGestureEvent = event([ @@ -193,12 +206,12 @@ class MovableFabWrapper extends PureComponent { const selectedIndexWithState = cond( eq(this.gestureState, State.ACTIVE), this.selectedIndex, - extraStates.gestureInactive, + extraStates.gestureInactive ); const showDeleteButton = or( this.isOverDeleteButtonBoundary(this.translateX), - this.isOverDeleteButtonBoundary(this.translateY), + this.isOverDeleteButtonBoundary(this.translateY) ); return ( @@ -215,7 +228,7 @@ class MovableFabWrapper extends PureComponent { ], }} > - {(this.props.areas && this.props.areas.length !== 0) && ( + {this.props.areas && this.props.areas.length !== 0 && ( <Animated.Code // Provoke change on reordering key={this.key++} @@ -223,71 +236,114 @@ class MovableFabWrapper extends PureComponent { /> )} <Animated.Code - exec={( - onChange(this.manageUpAndDownScrolling, [ - // eslint-disable-next-line no-nested-ternary - call([this.manageUpAndDownScrolling], ([v]) => this.props.setScrollingVelocity(v === 1 ? 1 : (v === 2 ? -1 : 0))), - ]) - )} + exec={onChange(this.manageUpAndDownScrolling, [ + call([this.manageUpAndDownScrolling], ([v]) => + this.props.setScrollingVelocity(v === 1 ? 1 : v === 2 ? -1 : 0) + ), + ])} /> <Animated.Code - exec={ - block([ + exec={block([ + cond(eq(this.gestureState, State.ACTIVE), [ cond( - eq(this.gestureState, State.ACTIVE), - [ - cond( - showDeleteButton, - set(this.props.deleteButtonScale, runSpring(this.xClockShow, this.props.deleteButtonScale, 0, 1)), - set(this.props.deleteButtonScale, runSpring(this.xClockShow, this.props.deleteButtonScale, 0, DeleteButton.defaultScale)), - ), - stopClock(this.xClockHide), - ], - ), - cond( - and(eq(this.gestureState, State.END), neq(this.props.deleteButtonScale, DeleteButton.defaultScale)), - [ - call([], () => this.props.setScrollingVelocity(0)), - set(this.props.deleteButtonScale, runSpring(this.xClockHide, this.props.deleteButtonScale, 0, DeleteButton.defaultScale)), - stopClock(this.xClockShow), - ], + showDeleteButton, + set( + this.props.deleteButtonScale, + runSpring( + this.xClockShow, + this.props.deleteButtonScale, + 0, + 1 + ) + ), + set( + this.props.deleteButtonScale, + runSpring( + this.xClockShow, + this.props.deleteButtonScale, + 0, + DeleteButton.defaultScale + ) + ) ), - onChange( - selectedIndexWithState, - call([selectedIndexWithState], ([i]) => { - this.props.updateSelectedID(i < 0 ? i : this.props.areas[i].id); - }), + stopClock(this.xClockHide), + ]), + cond( + and( + eq(this.gestureState, State.END), + neq(this.props.deleteButtonScale, DeleteButton.defaultScale) ), - onChange( - this.gestureState, - cond( - eq(this.gestureState, State.END), - [ - set(this.springOffsetX, this.translateX), - set(this.springOffsetY, this.translateY), - set(this.dragX, 0), - set(this.dragY, 0), - ], - cond( - eq(this.gestureState, State.BEGAN), - call([], () => this.props.setActionType(this.props.actionType)), - ), + [ + call([], () => this.props.setScrollingVelocity(0)), + set( + this.props.deleteButtonScale, + runSpring( + this.xClockHide, + this.props.deleteButtonScale, + 0, + DeleteButton.defaultScale + ) ), - ), + stopClock(this.xClockShow), + ] + ), + onChange( + selectedIndexWithState, + call([selectedIndexWithState], ([i]) => { + this.props.updateSelectedID( + i < 0 ? i : this.props.areas[i].id + ); + }) + ), + onChange( + this.gestureState, cond( eq(this.gestureState, State.END), [ - set(this.springOffsetX, runSpring(this.clockX, this.springOffsetX, this.dragVX, 0, this.wasRunSpring)), - set(this.springOffsetY, runSpring(this.clockY, this.springOffsetY, this.dragVY, 0, this.wasRunSpring)), - ], - [ - stopClock(this.clockX), - stopClock(this.clockY), - set(this.wasRunSpring, 0), + set(this.springOffsetX, this.translateX), + set(this.springOffsetY, this.translateY), + set(this.dragX, 0), + set(this.dragY, 0), ], - ), - ]) - } + cond( + eq(this.gestureState, State.BEGAN), + call([], () => + this.props.setActionType(this.props.actionType) + ) + ) + ) + ), + cond( + eq(this.gestureState, State.END), + [ + set( + this.springOffsetX, + runSpring( + this.clockX, + this.springOffsetX, + this.dragVX, + 0, + this.wasRunSpring + ) + ), + set( + this.springOffsetY, + runSpring( + this.clockY, + this.springOffsetY, + this.dragVY, + 0, + this.wasRunSpring + ) + ), + ], + [ + stopClock(this.clockX), + stopClock(this.clockY), + set(this.wasRunSpring, 0), + ] + ), + ])} /> {this.props.children} </Animated.View> @@ -296,10 +352,16 @@ class MovableFabWrapper extends PureComponent { } } -const traverseSectionsToDimensions = ({ sections, openFamilyTabs }) => { +const traverseSectionsToDimensions = ({ + openFamilyTabs, + openInvestmentCards, + openSmallBalances, + sections, +}) => { let balances = false; let collectibles = false; let investments = false; + sections.forEach(section => { if (section.balances) { balances = section; @@ -309,13 +371,14 @@ const traverseSectionsToDimensions = ({ sections, openFamilyTabs }) => { investments = section; } }); + if (sections) { const areas = []; const headerHeight = 54; const familyHeaderHeight = 52; let height = 55 + headerHeight; if (balances) { - for (let i = 0; i < balances.data.length; i++) { + for (let i = 0; i < balances.data.length - 1; i++) { areas.push({ bottom: height + CoinRow.height, id: balances.data[i].uniqueId, @@ -323,13 +386,42 @@ const traverseSectionsToDimensions = ({ sections, openFamilyTabs }) => { right: deviceUtils.dimensions.width, top: height, }); - height += CoinRow.height + (balances.data.length - 1 === i ? ListFooter.height : 0); + height += CoinRow.height; } - height += headerHeight; + areas.push({ + bottom: height + CoinDivider.height, + id: 'smallBalancesHeader', + left: 0, + right: deviceUtils.dimensions.width, + top: height, + }); + height += CoinDivider.height; + if (openSmallBalances) { + const smallBalances = balances.data[balances.data.length - 1].assets; + for (let i = 0; i < smallBalances.length; i++) { + areas.push({ + bottom: height + CoinRow.height, + id: smallBalances[i].uniqueId, + left: 0, + right: deviceUtils.dimensions.width, + top: height, + }); + height += CoinRow.height; + } + } + height += ListFooter.height + headerHeight; } if (investments) { - height += headerHeight; - height += investments.data.length * (UniswapInvestmentCard.height + InvestmentCard.margin.vertical) + ListFooter.height; + height += headerHeight + ListFooter.height; + for (let i = 0; i < investments.data.length; i++) { + if (!openInvestmentCards[investments.data[i].uniqueId]) { + height += + UniswapInvestmentCard.height + InvestmentCard.margin.vertical; + } else { + height += + InvestmentCardHeader.height + InvestmentCard.margin.vertical; + } + } } if (collectibles) { for (let i = 0; i < collectibles.data.length; i++) { @@ -346,13 +438,15 @@ const traverseSectionsToDimensions = ({ sections, openFamilyTabs }) => { for (let k = 0; k < tokens[j].length; k++) { areas.push({ bottom: height + UniqueTokenRow.cardSize, - id: tokens[j][k].isSendable ? tokens[j][k].uniqueId : extraStates.notSendable, + id: tokens[j][k].isSendable + ? tokens[j][k].uniqueId + : extraStates.notSendable, left: k === 0 ? 0 : deviceUtils.dimensions.width / 2, right: deviceUtils.dimensions.width / (k === 0 ? 2 : 1), top: height, }); } - if (openFamilyTabs[i]) { + if (openFamilyTabs[collectibles.data[i].familyName]) { height += UniqueTokenRow.cardSize; if (j > 0) { height += UniqueTokenRow.cardMargin; @@ -361,7 +455,7 @@ const traverseSectionsToDimensions = ({ sections, openFamilyTabs }) => { } } } - return ({ areas }); + return { areas }; } return null; }; @@ -369,5 +463,7 @@ const traverseSectionsToDimensions = ({ sections, openFamilyTabs }) => { export default compose( withFabSelection, withOpenFamilyTabs, - withProps(traverseSectionsToDimensions), + withOpenInvestmentCards, + withOpenBalances, + withProps(traverseSectionsToDimensions) )(MovableFabWrapper); diff --git a/src/components/fab/SendFab.js b/src/components/fab/SendFab.js index 9942b4a760f..0de38ec604c 100644 --- a/src/components/fab/SendFab.js +++ b/src/components/fab/SendFab.js @@ -1,14 +1,10 @@ import PropTypes from 'prop-types'; import React from 'react'; -import Animated from 'react-native-reanimated'; +// import Animated from 'react-native-reanimated'; import { withNavigation } from 'react-navigation'; -import { - compose, - onlyUpdateForKeys, - withHandlers, - withProps, -} from 'recompact'; +import { compose, onlyUpdateForKeys, withHandlers } from 'recompact'; import { withFabSelection } from '../../hoc'; +import { colors } from '../../styles'; import { Icon } from '../icons'; import { Centered } from '../layout'; // import DeleteButton from './DeleteButton'; @@ -18,15 +14,15 @@ import FloatingActionButton from './FloatingActionButton'; const FloatingActionButtonWithDisabled = withFabSelection(FloatingActionButton); const SendFab = ({ - areas, - deleteButtonScale, + //areas, + //deleteButtonScale, disabled, onPress, scaleTo, - scrollViewTracker, - sections, + //scrollViewTracker, + //sections, tapRef, - ...props + //...props }) => ( <Centered flex={0}> {/* @@ -39,19 +35,15 @@ const SendFab = ({ tapRef={tapRef} > */} - <FloatingActionButtonWithDisabled - disabled={disabled} - onPress={onPress} - scaleTo={scaleTo} - tapRef={tapRef} - > - <Icon - height={22} - marginBottom={4} - name="send" - width={23} - /> - </FloatingActionButtonWithDisabled> + <FloatingActionButtonWithDisabled + backgroundColor={colors.paleBlue} + disabled={disabled} + onPress={onPress} + scaleTo={scaleTo} + tapRef={tapRef} + > + <Icon height={22} marginBottom={4} name="send" width={23} /> + </FloatingActionButtonWithDisabled> {/* </MovableFabWrapper> */} @@ -59,14 +51,14 @@ const SendFab = ({ ); SendFab.propTypes = { - areas: PropTypes.array, - children: PropTypes.any, - deleteButtonScale: PropTypes.object, + //areas: PropTypes.array, + //children: PropTypes.any, + //deleteButtonScale: PropTypes.object, disabled: PropTypes.bool, onPress: PropTypes.func, scaleTo: PropTypes.number, - scrollViewTracker: PropTypes.object, - sections: PropTypes.array, + //scrollViewTracker: PropTypes.object, + //sections: PropTypes.array, tapRef: PropTypes.object, }; @@ -76,8 +68,10 @@ SendFab.defaultProps = { export default compose( withNavigation, - withHandlers({ onPress: ({ navigation }) => () => navigation.navigate('SendSheet') }), - onlyUpdateForKeys(['disabled', 'sections']), + withHandlers({ + onPress: ({ navigation }) => () => navigation.navigate('SendSheet'), + }), + onlyUpdateForKeys(['disabled', 'sections']) // withProps({ // deleteButtonScale: new Animated.Value(DeleteButton.defaultScale), // tapRef: React.createRef(), diff --git a/src/components/fields/AddressField.js b/src/components/fields/AddressField.js index aa86c6898fa..7a99260c0b5 100644 --- a/src/components/fields/AddressField.js +++ b/src/components/fields/AddressField.js @@ -1,20 +1,17 @@ import { omit } from 'lodash'; import PropTypes from 'prop-types'; -import React, { PureComponent } from 'react'; +import React from 'react'; import styled from 'styled-components/primitives'; +import { withNavigation } from 'react-navigation'; +import { TouchableWithoutFeedback } from 'react-native-gesture-handler'; +import { Clipboard } from 'react-native'; +import { checkIsValidAddress } from '../../helpers/validators'; +import { isHexString } from '../../handlers/web3'; +import { colors } from '../../styles'; +import { abbreviations, addressUtils, isNewValueForPath } from '../../utils'; import { Input } from '../inputs'; import { Row } from '../layout'; -import { colors } from '../../styles'; import { Label } from '../text'; -import { isValidAddress } from '../../helpers/validators'; -import { isHexString } from '../../handlers/web3'; -import { abbreviations, addressUtils, isNewValueForPath } from '../../utils'; - -const AddressInput = styled(Input).attrs({ family: 'SFMono' })` - flex-grow: 1; - margin-top: 1; - z-index: 1; -`; const Placeholder = styled(Row)` position: absolute; @@ -26,75 +23,158 @@ const PlaceholderText = styled(Label)` opacity: 0.45; `; -const formatValue = value => ( - (isHexString(value) && (value.length === addressUtils.maxLength)) - ? abbreviations.address(value) - : value -); +const formatValue = value => + isHexString(value) && value.length === addressUtils.maxLength + ? abbreviations.address(value, 4, 10) + : value; -export default class AddressField extends PureComponent { - static propTypes = { - address: PropTypes.string, - autoFocus: PropTypes.bool, - onChange: PropTypes.func.isRequired, - } +export default withNavigation( + class AddressField extends React.Component { + static propTypes = { + address: PropTypes.string, + autoFocus: PropTypes.bool, + currentContact: PropTypes.object, + onChange: PropTypes.func.isRequired, + }; - state = { - address: '', - isValid: false, - } + state = { + address: '', + currentContact: false, + inputValue: '', + isValid: false, + }; - componentDidUpdate(prevProps, prevState) { - // Validate 'address' whenever its value changes - if (isNewValueForPath(this.state, prevState, 'address')) { - this.validateAddress(this.state.address); + componentDidMount() { + this.focusListener = this.props.navigation.addListener('refocus', () => + this.inputRef.focus() + ); } + shouldComponentUpdate(nextProps, nextState) { + const isNewAddress = isNewValueForPath(this.props, this.state, 'address'); + const isNewInputValue = isNewValueForPath( + this.state, + nextState, + 'inputValue' + ); + const isNewNickname = isNewValueForPath( + this.props, + nextProps, + 'currentContact.nickname' + ); + const isNewValid = isNewValueForPath(this.state, nextState, 'isValid'); + return isNewAddress || isNewInputValue || isNewNickname || isNewValid; + } + + componentDidUpdate(prevProps) { + const { address, currentContact } = this.props; + + const isNewNickname = isNewValueForPath( + this.props, + prevProps, + 'currentContact.nickname' + ); + const isNewAddress = address !== this.state.address; - // Allow component state to be overwritten by parent component through the - // use of the 'address' prop. Assume that 'address' is valid because redux handles that for us. - if (this.props.address && !this.state.address) { - this.setState({ - address: this.props.address, - isValid: true, - }); + if (isNewAddress || isNewNickname) { + const newState = { + address, + inputValue: currentContact.nickname + ? currentContact.nickname + : address, + isValid: true, + }; + + if (isNewNickname) { + newState.currentContact = currentContact; + } + + // eslint-disable-next-line react/no-did-update-set-state + this.setState(newState); + } } - } - onChange = ({ nativeEvent }) => this.props.onChange(nativeEvent.text) + componentWillUnmount() { + this.focusListener.remove(); + } - onChangeText = address => this.setState({ address }) + inputRef = undefined; - validateAddress = async (inputValue) => { - const isValid = await isValidAddress(inputValue); - return this.setState({ isValid }); - } + handleInputRef = ref => { + this.inputRef = ref; + this.props.inputRef(ref); + }; + + onChange = ({ nativeEvent: { text } }) => { + this.props.onChange(text); + this.validateAddress(text); + this.checkClipboard(this.state.address); + return this.setState({ address: text }); + }; + + onChangeText = inputValue => this.setState({ inputValue }); - render() { - const { autoFocus, ...props } = this.props; - const { address, isValid } = this.state; - - return ( - <Row flex={1}> - <AddressInput - {...props} - {...omit(Label.textProps, 'opacity')} - autoCorrect={false} - autoFocus={autoFocus} - color={isValid ? colors.appleBlue : colors.blueGreyDark} - maxLength={addressUtils.maxLength} - onChange={this.onChange} - onChangeText={this.onChangeText} - selectTextOnFocus={true} - value={formatValue(address)} - /> - {!address && ( - <Placeholder> - <PlaceholderText>ENS or Address (</PlaceholderText> - <PlaceholderText family="SFMono">0x</PlaceholderText> - <PlaceholderText>...)</PlaceholderText> - </Placeholder> - )} - </Row> - ); + validateAddress = async address => { + const isValid = await checkIsValidAddress(address); + return this.setState({ isValid }); + }; + + onBlur = () => { + this.checkClipboard(this.state.address); + if (this.props.onBlur) { + this.props.onBlur(); + } + }; + + checkClipboard = async address => { + const clipboard = await Clipboard.getString(); + if (abbreviations.address(address, 4, 10) === clipboard) { + Clipboard.setString(address); + } + }; + + onPressNickname = () => { + this.inputRef.focus(); + }; + + render() { + const { autoFocus, ...props } = this.props; + const { inputValue, isValid } = this.state; + + return ( + <Row flex={1}> + <Input + {...props} + {...omit(Label.textProps, 'opacity')} + autoCorrect={false} + autoFocus={autoFocus} + color={isValid ? colors.appleBlue : colors.blueGreyDark} + maxLength={addressUtils.maxLength} + onBlur={this.onBlur} + onChange={this.onChange} + onChangeText={this.onChangeText} + ref={this.handleInputRef} + selectTextOnFocus + spellCheck + size="bmedium" + style={{ + flexGrow: 1, + marginTop: 1, + zIndex: 1, + }} + value={formatValue(inputValue)} + weight="semibold" + /> + {!inputValue && ( + <Placeholder> + <TouchableWithoutFeedback onPress={this.onPressNickname}> + <PlaceholderText>ENS or Address (</PlaceholderText> + </TouchableWithoutFeedback> + <PlaceholderText family="SFMono">0x</PlaceholderText> + <PlaceholderText>...)</PlaceholderText> + </Placeholder> + )} + </Row> + ); + } } -} +); diff --git a/src/components/fields/UnderlineField.js b/src/components/fields/UnderlineField.js index 6099f4da84b..08367f05d3e 100644 --- a/src/components/fields/UnderlineField.js +++ b/src/components/fields/UnderlineField.js @@ -3,6 +3,8 @@ import React, { PureComponent } from 'react'; import styled from 'styled-components/primitives'; import { View } from 'react-native'; import Animated, { Easing } from 'react-native-reanimated'; +import { setSelectedInputId } from '../../redux/selectedInput'; +import store from '../../redux/store'; import { colors, position } from '../../styles'; import { Button } from '../buttons'; import { Input } from '../inputs'; @@ -40,11 +42,11 @@ export default class UnderlineField extends PureComponent { onPressButton: PropTypes.func, placeholder: PropTypes.string, value: PropTypes.any, - } + }; static defaultProps = { autoFocus: false, - } + }; constructor(props) { super(props); @@ -55,21 +57,18 @@ export default class UnderlineField extends PureComponent { }; } - animation = new Animated.Value(0) - componentDidUpdate(prevProps) { const { value } = this.props; if (value !== prevProps.value) { + // eslint-disable-next-line react/no-did-update-set-state this.setState({ value }); } } - format = (string) => ( - this.props.format - ? this.props.format(string) - : string - ) + animation = new Animated.Value(0); + + format = string => (this.props.format ? this.props.format(string) : string); onBlur = (...props) => { Animated.timing(this.animation, { @@ -81,9 +80,10 @@ export default class UnderlineField extends PureComponent { this.setState({ isFocused: false }); if (this.props.onBlur) this.props.onBlur(...props); - } + store.dispatch(setSelectedInputId(null)); + }; - onChange = (event) => { + onChange = event => { const { nativeEvent } = event; const value = this.format(nativeEvent.text); @@ -93,7 +93,7 @@ export default class UnderlineField extends PureComponent { if (this.props.onChange) this.props.onChange(String(value)); } - } + }; onFocus = (...props) => { Animated.timing(this.animation, { @@ -105,7 +105,14 @@ export default class UnderlineField extends PureComponent { this.setState({ isFocused: true }); if (this.props.onFocus) this.props.onFocus(...props); - } + if (this.input && this.input.isFocused()) { + store.dispatch(setSelectedInputId(this.input)); + } + }; + + handleRef = ref => { + this.input = ref; + }; render() { const { @@ -138,6 +145,7 @@ export default class UnderlineField extends PureComponent { onChange={this.onChange} onFocus={this.onFocus} placeholder={placeholder} + ref={this.handleRef} size="h2" value={this.format(String(this.props.value || ''))} /> @@ -156,7 +164,9 @@ export default class UnderlineField extends PureComponent { </Row> <UnderlineContainer> <Underline /> - <UnderlineAnimated style={{ transform: [{ scaleX: this.animation }] }} /> + <UnderlineAnimated + style={{ transform: [{ scaleX: this.animation }] }} + /> </UnderlineContainer> </Column> ); diff --git a/src/components/floating-emojis/FloatingEmoji.js b/src/components/floating-emojis/FloatingEmoji.js index 9e7e4717b42..5285abcbda1 100644 --- a/src/components/floating-emojis/FloatingEmoji.js +++ b/src/components/floating-emojis/FloatingEmoji.js @@ -4,14 +4,9 @@ import Animated, { Easing } from 'react-native-reanimated'; import stylePropType from 'react-style-proptype'; import { colors, fonts } from '../../styles'; import { Emoji } from '../text'; +import { interpolate } from '../animations'; -const { - concat, - interpolate, - timing, - Value, - View, -} = Animated; +const { concat, timing, Value } = Animated; export default class FloatingEmoji extends PureComponent { static propTypes = { @@ -23,16 +18,15 @@ export default class FloatingEmoji extends PureComponent { right: PropTypes.string.isRequired, size: PropTypes.string.isRequired, style: stylePropType, - } + top: PropTypes.number, + }; static defaultProps = { distance: 100, duration: 2000, emoji: '+1', right: 0, - } - - position = new Value(0) + }; componentDidMount() { const animationConfig = { @@ -44,15 +38,12 @@ export default class FloatingEmoji extends PureComponent { timing(this.position, animationConfig).start(this.handleAnimationComplete); } - handleAnimationComplete = () => this.props.onComplete(this.props.id) + position = new Value(0); + + handleAnimationComplete = () => this.props.onComplete(this.props.id); render() { - const { - emoji, - right, - size, - style, - } = this.props; + const { emoji, right, size, style, top } = this.props; const distance = Math.ceil(this.props.distance); const negativeHeight = distance * -1; @@ -85,14 +76,14 @@ export default class FloatingEmoji extends PureComponent { }); return ( - <View + <Animated.View style={{ ...style, backgroundColor: colors.transparent, opacity: this.opacityAnimation, position: 'absolute', right, - top: sizeAsNumber * -0.5, + top: top || sizeAsNumber * -0.5, transform: [ { rotate: concat(this.rotateAnimation, 'deg') }, { scale: this.scaleAnimation }, @@ -102,7 +93,7 @@ export default class FloatingEmoji extends PureComponent { }} > <Emoji name={emoji} size={size} /> - </View> + </Animated.View> ); } } diff --git a/src/components/floating-emojis/FloatingEmojis.js b/src/components/floating-emojis/FloatingEmojis.js index f6c7ca69609..d35783ed1f7 100644 --- a/src/components/floating-emojis/FloatingEmojis.js +++ b/src/components/floating-emojis/FloatingEmojis.js @@ -7,13 +7,13 @@ import FloatingEmoji from './FloatingEmoji'; const getRandomNumber = (min, max) => Math.random() * (max - min) + min; -const createEmojiItem = () => { - const right = `${getRandomNumber(0, 80)}%`; +const createEmojiItem = range => { + const right = `${getRandomNumber(...range)}%`; - return ({ + return { id: right, right, - }); + }; }; export default class FloatingEmojis extends PureComponent { @@ -21,55 +21,65 @@ export default class FloatingEmojis extends PureComponent { color: PropTypes.string, count: PropTypes.number, distance: PropTypes.number, + duration: PropTypes.number, emoji: PropTypes.string.isRequired, + range: PropTypes.arrayOf(PropTypes.number), size: PropTypes.string.isRequired, style: stylePropType, - } + top: PropTypes.number, + }; static defaultProps = { count: -1, + range: [0, 80], size: 'h2', - } + }; state = { emojis: [], - } + }; - componentWillUpdate(nextProps) { - const oldCount = this.props.count; - const newCount = nextProps.count; + componentDidUpdate(prevProps) { + const oldCount = prevProps.count; + const newCount = this.props.count; const numEmojis = newCount - oldCount; if (numEmojis <= 0) return; const items = Array(numEmojis).fill(); - const newEmojis = items.map((_, i) => oldCount + i).map(createEmojiItem); + const newEmojis = items.map((_, i) => oldCount + i).map(this.createItem); - this.setState({ emojis: this.state.emojis.concat(newEmojis) }); + // TODO: refactor this component to utilize hooks, so that we can stop + // having to call setState inside componentDidUpdate. + // eslint-disable-next-line react/no-did-update-set-state + this.setState(prevState => ({ + emojis: prevState.emojis.concat(newEmojis), + })); } - removeEmoji = (id) => { - const newEmojis = this.state.emojis.filter(emoji => emoji.id !== id); - this.setState({ emojis: newEmojis }); - } + createItem = () => createEmojiItem(this.props.range); + + removeEmoji = id => { + this.setState(prevState => ({ + emojis: prevState.emojis.filter(emoji => emoji.id !== id), + })); + }; render = () => ( - <View - css={position.cover} - pointerEvents="none" - style={this.props.style} - > + <View css={position.cover} pointerEvents="none" style={this.props.style}> {this.state.emojis.map(({ id, ...item }) => ( <FloatingEmoji {...item} distance={this.props.distance} + duration={this.props.duration} emoji={this.props.emoji} id={id} key={id} onComplete={this.removeEmoji} size={this.props.size} + top={this.props.top} /> ))} </View> - ) + ); } diff --git a/src/components/gas/GasSpeedButton.js b/src/components/gas/GasSpeedButton.js new file mode 100644 index 00000000000..359b3fbe4fc --- /dev/null +++ b/src/components/gas/GasSpeedButton.js @@ -0,0 +1,135 @@ +import AnimateNumber from '@bankify/react-native-animate-number'; +import analytics from '@segment/analytics-react-native'; +import { get } from 'lodash'; +import PropTypes from 'prop-types'; +import React, { PureComponent } from 'react'; +import { LayoutAnimation } from 'react-native'; +import { compose, mapProps, onlyUpdateForKeys, withProps } from 'recompact'; +import { withAccountSettings, withGas } from '../../hoc'; +import { colors, padding } from '../../styles'; +import { gasUtils } from '../../utils'; +import { ButtonPressAnimation } from '../animations'; +import { Column, Row } from '../layout'; +import { Text } from '../text'; +import GasSpeedLabelPager from './GasSpeedLabelPager'; + +const Label = withProps({ + color: colors.alpha(colors.white, 0.4), + size: 'smedium', + weight: 'medium', +})(Text); + +const renderEstimatedTimeText = animatedNumber => ( + <Label>{animatedNumber}</Label> +); + +const renderGasPriceText = animatedNumber => ( + <Text color="white" letterSpacing="tight" size="lmedium" weight="semibold"> + {animatedNumber} + </Text> +); + +class GasSpeedButton extends PureComponent { + static propTypes = { + estimatedTimeUnit: PropTypes.string, + estimatedTimeValue: PropTypes.string, + gasPrices: PropTypes.object, + gasUpdateGasPriceOption: PropTypes.func, + nativeCurrencySymbol: PropTypes.string, + price: PropTypes.string, + selectedGasPriceOption: PropTypes.oneOf(gasUtils.GasSpeedOrder), + }; + + handlePress = () => { + const { + gasPrices, + gasUpdateGasPriceOption, + selectedGasPriceOption, + } = this.props; + + LayoutAnimation.easeInEaseOut(); + + const currentSpeedIndex = gasUtils.GasSpeedOrder.indexOf( + selectedGasPriceOption + ); + const nextSpeedIndex = + (currentSpeedIndex + 1) % gasUtils.GasSpeedOrder.length; + + const nextSpeed = gasUtils.GasSpeedOrder[nextSpeedIndex]; + const nextSpeedGweiValue = get(gasPrices, `[${nextSpeed}].value.display`); + + gasUpdateGasPriceOption(nextSpeed); + analytics.track('Updated Gas Price', { gasPrice: nextSpeedGweiValue }); + }; + + formatAnimatedGasPrice = animatedPrice => { + const formattedPrice = parseFloat(animatedPrice).toFixed(3); + return `${this.props.nativeCurrencySymbol}${formattedPrice}`; + }; + + formatAnimatedEstimatedTime = estimatedTime => { + const time = parseFloat(estimatedTime || 0).toFixed(0); + return `Swaps in ~ ${time} ${this.props.estimatedTimeUnit}`; + }; + + render = () => ( + <ButtonPressAnimation + hapticType="impactHeavy" + onPress={this.handlePress} + scaleTo={0.99999} + width="100%" + > + <Column css={padding(14, 19, 0)} width="100%"> + <Row align="center" justify="space-between"> + <AnimateNumber + formatter={this.formatAnimatedGasPrice} + interval={6} + renderContent={renderGasPriceText} + steps={6} + timing="linear" + value={this.props.price} + /> + <GasSpeedLabelPager label={this.props.selectedGasPriceOption} /> + </Row> + <Row align="center" justify="space-between"> + <Label>Fee</Label> + <AnimateNumber + formatter={this.formatAnimatedEstimatedTime} + interval={1} + renderContent={renderEstimatedTimeText} + steps={6} + timing="linear" + value={this.props.estimatedTimeValue} + /> + </Row> + </Column> + </ButtonPressAnimation> + ); +} + +export default compose( + withAccountSettings, + withGas, + mapProps(({ selectedGasPrice, ...props }) => { + const estimatedTime = get( + selectedGasPrice, + 'estimatedTime.display', + '' + ).split(' '); + + const gasPrice = get(selectedGasPrice, 'txFee.native.value.amount'); + + return { + estimatedTimeUnit: estimatedTime[1] || 'min', + estimatedTimeValue: estimatedTime[0] || 0, + price: isNaN(gasPrice) ? '0.00' : gasPrice, + ...props, + }; + }), + onlyUpdateForKeys([ + 'estimatedTimeUnit', + 'estimatedTimeValue', + 'price', + 'selectedGasPriceOption', + ]) +)(GasSpeedButton); diff --git a/src/components/gas/GasSpeedEmoji.js b/src/components/gas/GasSpeedEmoji.js new file mode 100644 index 00000000000..b482d17693f --- /dev/null +++ b/src/components/gas/GasSpeedEmoji.js @@ -0,0 +1,50 @@ +import { has } from 'lodash'; +import PropTypes from 'prop-types'; +import React from 'react'; +import { View } from 'react-primitives'; +import { onlyUpdateForKeys } from 'recompact'; +import { gasUtils } from '../../utils'; +import { Emoji } from '../text'; +import { GasSpeedLabelPagerItemHeight } from './GasSpeedLabelPagerItem'; + +const EmojiForGasSpeedType = { + [gasUtils.FAST]: { + emoji: 'rocket', // πŸš€οΈ + position: [1, 2], // x: 1, y: 2 + }, + [gasUtils.NORMAL]: { + emoji: 'stopwatch', // ⏱️ + position: [2, 1], // x: 2, y: 1 + }, + [gasUtils.SLOW]: { + emoji: 'snail', // 🐌️ + position: [1, 0], // x: 1, y: 0 + }, +}; + +const GasSpeedEmoji = ({ label }) => { + const gasSpeed = has(EmojiForGasSpeedType, label) + ? EmojiForGasSpeedType[label] + : EmojiForGasSpeedType[gasUtils.NORMAL]; + + return ( + <View height={GasSpeedLabelPagerItemHeight} width={25}> + <Emoji + lineHeight="looser" + name={gasSpeed.emoji} + size="lmedium" + style={{ + left: gasSpeed.position[0], + position: 'absolute', + top: gasSpeed.position[1], + }} + /> + </View> + ); +}; + +GasSpeedEmoji.propTypes = { + label: PropTypes.oneOf(gasUtils.GasSpeedOrder), +}; + +export default onlyUpdateForKeys(['label'])(GasSpeedEmoji); diff --git a/src/components/gas/GasSpeedLabelPager.js b/src/components/gas/GasSpeedLabelPager.js new file mode 100644 index 00000000000..72dfdc84f94 --- /dev/null +++ b/src/components/gas/GasSpeedLabelPager.js @@ -0,0 +1,31 @@ +import PropTypes from 'prop-types'; +import React, { useEffect, useState } from 'react'; +import { gasUtils } from '../../utils'; +import { Row } from '../layout'; +import GasSpeedLabelPagerItem, { + GasSpeedLabelPagerItemHeight, +} from './GasSpeedLabelPagerItem'; + +const GasSpeedLabelPager = ({ label }) => { + const [touched, setTouched] = useState(false); + useEffect(() => setTouched(true), [label]); + + return ( + <Row align="center" height={GasSpeedLabelPagerItemHeight} justify="end"> + {gasUtils.GasSpeedOrder.map(speed => ( + <GasSpeedLabelPagerItem + key={speed} + label={speed} + selected={speed === label} + shouldAnimate={touched} + /> + ))} + </Row> + ); +}; + +GasSpeedLabelPager.propTypes = { + label: PropTypes.oneOf(gasUtils.GasSpeedOrder), +}; + +export default React.memo(GasSpeedLabelPager); diff --git a/src/components/gas/GasSpeedLabelPagerItem.js b/src/components/gas/GasSpeedLabelPagerItem.js new file mode 100644 index 00000000000..d02cf7cfbc1 --- /dev/null +++ b/src/components/gas/GasSpeedLabelPagerItem.js @@ -0,0 +1,122 @@ +import { upperFirst } from 'lodash'; +import PropTypes from 'prop-types'; +import React, { useEffect, useRef } from 'react'; +import Animated, { + Easing, + Transitioning, + Transition, +} from 'react-native-reanimated'; +import { useTimingTransition } from 'react-native-redash'; +import { withProps } from 'recompact'; +import { gasUtils } from '../../utils'; +import { interpolate } from '../animations'; +import { Row } from '../layout'; +import { Text } from '../text'; +import GasSpeedEmoji from './GasSpeedEmoji'; + +const { cond } = Animated; + +const containerStyle = { + bottom: 0, + position: 'absolute', + right: 0, + top: 0, +}; + +export const GasSpeedLabelPagerItemHeight = 28; + +const GasSpeedLabel = withProps({ + color: 'white', + letterSpacing: 'tight', + size: 'lmedium', + weight: 'semibold', +})(Text); + +const distance = 20; +const duration = 150; +const transition = ( + <Transition.Change durationMs={duration} interpolation="easeOut" /> +); + +const GasSpeedLabelPagerItem = ({ label, selected, shouldAnimate }) => { + const ref = useRef(); + + useEffect(() => { + if (shouldAnimate && ref.current) { + ref.current.animateNextTransition(); + } + }, [shouldAnimate]); + + const index = gasUtils.GasSpeedOrder.indexOf(label); + const isFirst = index === 0; + const isLast = index === gasUtils.GasSpeedOrder.length - 1; + + const transitionVal = useTimingTransition( + !selected, + duration + (isFirst ? 50 : 0), + Easing.out(Easing.ease) + ); + + const defaultOpacity = selected ? 1 : 0; + const opacity = cond( + shouldAnimate, + cond( + selected, + // animate in + interpolate(transitionVal, { + inputRange: [0, 1], + outputRange: [1, 0], + }), + // animate out + interpolate(transitionVal, { + inputRange: [0, 0.333, 1], + outputRange: [1, 0.666, 0], + }) + ), + defaultOpacity + ); + + const defaultTranslateX = 0; + const translateX = cond( + shouldAnimate, + cond( + selected, + // animate in + interpolate(transitionVal, { + inputRange: [0, 1], + outputRange: [0, cond(isFirst, distance * -2, distance)], + }), + // animate out + interpolate(transitionVal, { + inputRange: [0, 1], + outputRange: [0, cond(isLast, distance * 2, distance * -2)], + }) + ), + defaultTranslateX + ); + + return ( + <Transitioning.View + ref={ref} + style={containerStyle} + transition={transition} + > + <Animated.View style={{ opacity, transform: [{ translateX }] }}> + <Row align="end" height={GasSpeedLabelPagerItemHeight} justify="end"> + <GasSpeedEmoji label={label} /> + <GasSpeedLabel style={{ marginBottom: 3 }}> + {upperFirst(label)} + </GasSpeedLabel> + </Row> + </Animated.View> + </Transitioning.View> + ); +}; + +GasSpeedLabelPagerItem.propTypes = { + label: PropTypes.oneOf(gasUtils.GasSpeedOrder), + selected: PropTypes.bool, + shouldAnimate: PropTypes.bool, +}; + +export default React.memo(GasSpeedLabelPagerItem); diff --git a/src/components/gas/index.js b/src/components/gas/index.js new file mode 100644 index 00000000000..2bc10623e0e --- /dev/null +++ b/src/components/gas/index.js @@ -0,0 +1,4 @@ +export { default as GasSpeedButton } from './GasSpeedButton'; +export { default as GasSpeedEmoji } from './GasSpeedEmoji'; +export { default as GasSpeedLabelPager } from './GasSpeedLabelPager'; +export { default as GasSpeedLabelPagerItem } from './GasSpeedLabelPagerItem'; diff --git a/src/components/header/BackButton.js b/src/components/header/BackButton.js index e88c0e5eb64..1417ef40f44 100644 --- a/src/components/header/BackButton.js +++ b/src/components/header/BackButton.js @@ -12,21 +12,13 @@ import HeaderButton from './HeaderButton'; const ContainerElement = omitProps('direction')(Flex); const Container = styled(ContainerElement).attrs({ align: 'end' })` height: 100%; - padding-bottom: 4; - padding-left: ${({ direction }) => ((direction === 'left') ? 0 : 20)}; - padding-right: ${({ direction }) => ((direction === 'right') ? 0 : 20)}; + padding-bottom: 2; `; -const BackButton = ({ - color, direction, onPress, ...props -}) => ( +const BackButton = ({ color, direction, onPress, ...props }) => ( <HeaderButton onPress={onPress} transformOrigin={direction}> <Container direction={direction} {...props}> - <Icon - color={color} - direction={direction} - name="caret" - /> + <Icon color={color} direction={direction} name="caret" {...props} /> </Container> </HeaderButton> ); @@ -40,12 +32,12 @@ BackButton.propTypes = { export default compose( withNavigation, withHandlers({ - onPress: ({ navigation, onPress }) => (event) => { + onPress: ({ navigation, onPress }) => event => { if (onPress) { return onPress(event); } return navigation.dispatch(NavigationActions.back()); }, - }), + }) )(BackButton); diff --git a/src/components/header/CameraHeaderButton.js b/src/components/header/CameraHeaderButton.js index 50f68eb7315..f7617d71265 100644 --- a/src/components/header/CameraHeaderButton.js +++ b/src/components/header/CameraHeaderButton.js @@ -41,5 +41,5 @@ export default compose( withHandlers({ onPress: ({ navigation }) => () => navigation.navigate('QRScannerScreen'), }), - onlyUpdateForPropTypes, + onlyUpdateForPropTypes )(CameraHeaderButton); diff --git a/src/components/header/Header.js b/src/components/header/Header.js index 3fbde49e01e..6fd1780a776 100644 --- a/src/components/header/Header.js +++ b/src/components/header/Header.js @@ -1,26 +1,24 @@ import React from 'react'; import { getStatusBarHeight } from 'react-native-iphone-x-helper'; -import styled from 'styled-components/primitives'; import { padding } from '../../styles'; import { Row } from '../layout'; const StatusBarHeight = getStatusBarHeight(true); -const HeaderHeight = 52; +const HeaderHeight = 44; const HeaderHeightWithStatusBar = HeaderHeight + StatusBarHeight; -const Container = styled(Row).attrs({ align: 'end' })` - ${padding(StatusBarHeight, 9, 0)}; - flex-shrink: 0; - height: ${({ excludeStatusBarHeight }) => ( - (excludeStatusBarHeight === true) - ? HeaderHeight - : HeaderHeightWithStatusBar - )}; - width: 100%; - z-index: 1; -`; - -const Header = props => <Container {...props} />; +// eslint-disable-next-line react/display-name +const Header = React.memo(props => ( + <Row + {...props} + align="end" + css={padding(StatusBarHeight, 0, 0)} + flexShrink={0} + height={HeaderHeightWithStatusBar} + width="100%" + zIndex={1} + /> +)); Header.height = HeaderHeight; diff --git a/src/components/header/HeaderButton.js b/src/components/header/HeaderButton.js index 36ae05309bd..ff4a49d3afa 100644 --- a/src/components/header/HeaderButton.js +++ b/src/components/header/HeaderButton.js @@ -2,24 +2,29 @@ import PropTypes from 'prop-types'; import React from 'react'; import { pure } from 'recompact'; import { padding } from '../../styles'; -import { ButtonPressAnimation } from '../animations'; +import { TouchableScale } from '../animations'; import { Flex } from '../layout'; -const HeaderButton = ({ - children, - onPress, - transformOrigin, - ...props -}) => ( - <ButtonPressAnimation onPress={onPress} transformOrigin={transformOrigin}> - <Flex {...props} css={padding(10)}> +const HeaderButton = ({ children, onPress, transformOrigin, ...props }) => ( + <TouchableScale + activeScale={0.8} + hapticType="impactLight" + pressInFriction={50} + pressInTension={400} + pressOutFriction={30} + pressOutTension={300} + onPress={onPress} + transformOrigin={transformOrigin} + useNativeDriver + > + <Flex css={padding(10, 19, 8)} {...props}> {children} </Flex> - </ButtonPressAnimation> + </TouchableScale> ); HeaderButton.propTypes = { - ...ButtonPressAnimation.propTypes, + ...TouchableScale.propTypes, children: PropTypes.node, onPress: PropTypes.func.isRequired, }; diff --git a/src/components/header/ProfileHeaderButton.js b/src/components/header/ProfileHeaderButton.js index f95434133dc..7d49c6cf596 100644 --- a/src/components/header/ProfileHeaderButton.js +++ b/src/components/header/ProfileHeaderButton.js @@ -1,11 +1,6 @@ import PropTypes from 'prop-types'; import React from 'react'; -import { - compose, - pickProps, - onlyUpdateForKeys, - withHandlers, -} from 'recompact'; +import { compose, pickProps, onlyUpdateForKeys, withHandlers } from 'recompact'; import { withRequests } from '../../hoc'; import { Badge } from '../badge'; import { Centered } from '../layout'; @@ -22,11 +17,7 @@ const ProfileHeaderButton = ({ onPress, pendingRequestCount }) => ( <Centered> <Avatar size={34} /> {pendingRequestCount > 0 && ( - <Badge - delay={1500} - value={pendingRequestCount} - zIndex={1} - /> + <Badge delay={1500} value={pendingRequestCount} zIndex={1} /> )} </Centered> </HeaderButton> @@ -39,7 +30,9 @@ ProfileHeaderButton.propTypes = { export default compose( withRequests, - withHandlers({ onPress: ({ navigation }) => () => navigation.navigate('ProfileScreen') }), + withHandlers({ + onPress: ({ navigation }) => () => navigation.navigate('ProfileScreen'), + }), pickProps(Object.keys(ProfileHeaderButton.propTypes)), - onlyUpdateForKeys(['pendingRequestCount']), + onlyUpdateForKeys(['pendingRequestCount']) )(ProfileHeaderButton); diff --git a/src/components/html-entities/EmDash.js b/src/components/html-entities/EmDash.js new file mode 100644 index 00000000000..06dd8a98013 --- /dev/null +++ b/src/components/html-entities/EmDash.js @@ -0,0 +1,8 @@ +import React from 'react'; +import { Text } from 'react-primitives'; + +const unicodeValue = '\u2014'; + +const EmDash = props => <Text {...props}>{unicodeValue}</Text>; +EmDash.unicode = unicodeValue; +export default EmDash; diff --git a/src/components/html-entities/EnDash.js b/src/components/html-entities/EnDash.js new file mode 100644 index 00000000000..c3c27574d0c --- /dev/null +++ b/src/components/html-entities/EnDash.js @@ -0,0 +1,8 @@ +import React from 'react'; +import { Text } from 'react-primitives'; + +const unicodeValue = '\u2013'; + +const EnDash = props => <Text {...props}>{unicodeValue}</Text>; +EnDash.unicode = unicodeValue; +export default EnDash; diff --git a/src/components/html-entities/Nbsp.js b/src/components/html-entities/Nbsp.js index c600157940e..098b4c4be66 100644 --- a/src/components/html-entities/Nbsp.js +++ b/src/components/html-entities/Nbsp.js @@ -1,5 +1,7 @@ import React from 'react'; import { Text } from 'react-primitives'; -const Nbsp = props => <Text {...props}> </Text>; +const unicodeValue = '\xa0'; +const Nbsp = props => <Text {...props}>{unicodeValue}</Text>; +Nbsp.unicode = unicodeValue; export default Nbsp; diff --git a/src/components/html-entities/index.js b/src/components/html-entities/index.js index 5828ecc8b31..50af92eac0e 100644 --- a/src/components/html-entities/index.js +++ b/src/components/html-entities/index.js @@ -1 +1,3 @@ +export { default as EmDash } from './EmDash'; +export { default as EnDash } from './EnDash'; export { default as Nbsp } from './Nbsp'; diff --git a/src/components/icons/BiometryIcon.js b/src/components/icons/BiometryIcon.js index 9f45f362e59..7950d91770d 100644 --- a/src/components/icons/BiometryIcon.js +++ b/src/components/icons/BiometryIcon.js @@ -1,64 +1,41 @@ import PropTypes from 'prop-types'; import React from 'react'; -import TouchID from 'react-native-touch-id'; -import stylePropType from 'react-style-proptype'; -import { - compose, - lifecycle, - omitProps, - onlyUpdateForKeys, - withHandlers, - withProps, - withState, -} from 'recompact'; import { position } from '../../styles'; import { Centered } from '../layout'; import Icon from './Icon'; -const DefaultBiometryType = 'FaceID'; +const BiometryTypeStyles = { + faceid: { + ...position.sizeAsObject(27), + marginBottom: 2, + marginLeft: 4, + }, + passcode: { + height: 25, + marginBottom: 4, + marginLeft: 4, + width: 18, + }, + touchid: { + ...position.sizeAsObject(31), + marginBottom: 1, + }, +}; -const BiometryIcon = ({ - isFaceID, - size, - style, - ...props -}) => ( - <Centered - {...props} - {...position.sizeAsObject(size)} - style={[style, { padding: isFaceID ? 2 : 0 }]} - > - <Icon - {...position.sizeAsObject('100%')} - color="white" - name={isFaceID ? 'faceid' : 'touchid'} - /> - </Centered> -); +const BiometryIcon = ({ biometryType, ...props }) => { + if (!biometryType || biometryType === 'none') return null; + const type = biometryType.toLowerCase(); -BiometryIcon.propTypes = { - isFaceID: PropTypes.bool, - size: PropTypes.number, - style: stylePropType, + return ( + <Centered {...props} {...BiometryTypeStyles[type]} align="start"> + <Icon {...position.sizeAsObject('100%')} color="white" name={type} /> + </Centered> + ); }; -BiometryIcon.defaultProps = { - size: 34, +BiometryIcon.propTypes = { + biometryType: PropTypes.string, }; -export default compose( - withState('biometryType', 'setBiometryType', DefaultBiometryType), - withHandlers({ - setBiometryType: ({ setBiometryType }) => (biometryType) => { - setBiometryType(biometryType || DefaultBiometryType); - }, - }), - lifecycle({ - componentDidMount() { - TouchID.isSupported().then(this.props.setBiometryType); - }, - }), - withProps(({ biometryType }) => ({ isFaceID: biometryType === DefaultBiometryType })), - onlyUpdateForKeys(['biometryType', 'size']), - omitProps('biometryType', 'setBiometryType'), -)(BiometryIcon); +const arePropsEqual = (prev, next) => prev.biometryType === next.biometryType; +export default React.memo(BiometryIcon, arePropsEqual); diff --git a/src/components/icons/Icon.js b/src/components/icons/Icon.js index 5ec537f91dd..cd93193d9d7 100644 --- a/src/components/icons/Icon.js +++ b/src/components/icons/Icon.js @@ -10,6 +10,7 @@ import CaretIcon from './svg/CaretIcon'; import CaretThinIcon from './svg/CaretThinIcon'; import CheckmarkCircledIcon from './svg/CheckmarkCircledIcon'; import CheckmarkIcon from './svg/CheckmarkIcon'; +import ClearInputIcon from './svg/ClearInputIcon'; import ClockIcon from './svg/ClockIcon'; import CloseCircledIcon from './svg/CloseCircledIcon'; import CloseIcon from './svg/CloseIcon'; @@ -22,19 +23,25 @@ import FaceIdIcon from './svg/FaceIdIcon'; import GearIcon from './svg/GearIcon'; import HandleIcon from './svg/HandleIcon'; import InboxIcon from './svg/InboxIcon'; +import LockIcon from './svg/LockIcon'; import OfflineIcon from './svg/OfflineIcon'; +import PasscodeIcon from './svg/PasscodeIcon'; import ProgressIcon from './svg/ProgressIcon'; +import SearchIcon from './svg/SearchIcon'; import SendIcon from './svg/SendIcon'; import SendSmallIcon from './svg/SendSmallIcon'; import ShareIcon from './svg/ShareIcon'; import SignatureIcon from './svg/SignatureIcon'; import SpinnerIcon from './svg/SpinnerIcon'; +import StarIcon from './svg/StarIcon'; +import SwapIcon from './svg/SwapIcon'; import ThreeDotsIcon from './svg/ThreeDotsIcon'; import TouchIdIcon from './svg/TouchIdIcon'; import WalletConnectIcon from './svg/WalletConnectIcon'; import WarningIcon from './svg/WarningIcon'; -const Icon = ({ name, ...props }) => createElement(Icon.IconTypes[name] || Flex, props); +const Icon = ({ name, ...props }) => + createElement(Icon.IconTypes[name] || Flex, props); Icon.IconTypes = { arrow: ArrowIcon, @@ -45,6 +52,7 @@ Icon.IconTypes = { caretThin: CaretThinIcon, checkmark: CheckmarkIcon, checkmarkCircled: CheckmarkCircledIcon, + clearInput: ClearInputIcon, clock: ClockIcon, close: CloseIcon, closeCircled: CloseCircledIcon, @@ -57,13 +65,18 @@ Icon.IconTypes = { gear: GearIcon, handle: HandleIcon, inbox: InboxIcon, + lock: LockIcon, offline: OfflineIcon, + passcode: PasscodeIcon, progress: ProgressIcon, + search: SearchIcon, send: SendIcon, sendSmall: SendSmallIcon, share: ShareIcon, signature: SignatureIcon, spinner: SpinnerIcon, + star: StarIcon, + swap: SwapIcon, threeDots: ThreeDotsIcon, touchid: TouchIdIcon, walletConnect: WalletConnectIcon, diff --git a/src/components/icons/Svg.js b/src/components/icons/Svg.js index d82c9ebad59..95550157e87 100644 --- a/src/components/icons/Svg.js +++ b/src/components/icons/Svg.js @@ -1,10 +1,5 @@ import Animated from 'react-native-reanimated'; -import { - compose, - mapProps, - omitProps, - toClass, -} from 'recompact'; +import { compose, mapProps, omitProps, toClass } from 'recompact'; import SvgPrimitive from 'svgs'; import { reduceArrayToObject } from '../../utils'; @@ -15,7 +10,7 @@ const Svg = compose( mapProps(({ style, ...props }) => ({ ...props, style: reduceArrayToObject(style), - })), + })) )(SvgPrimitive); export const AnimatedSvg = Animated.createAnimatedComponent(toClass(Svg)); diff --git a/src/components/icons/svg/ArrowCircledIcon.js b/src/components/icons/svg/ArrowCircledIcon.js index a27f6f0845b..cd5fdd313dc 100644 --- a/src/components/icons/svg/ArrowCircledIcon.js +++ b/src/components/icons/svg/ArrowCircledIcon.js @@ -5,7 +5,6 @@ import { withRotationForDirection } from '../../../hoc'; import { colors } from '../../../styles'; import Svg from '../Svg'; -/* eslint-disable max-len */ const ArrowCircledIcon = ({ color, ...props }) => ( <Svg height="15" width="14" viewBox="0 0 14 15" {...props}> <Path @@ -15,7 +14,6 @@ const ArrowCircledIcon = ({ color, ...props }) => ( /> </Svg> ); -/* eslint-disable max-len */ ArrowCircledIcon.propTypes = { color: PropTypes.string, diff --git a/src/components/icons/svg/ArrowIcon.js b/src/components/icons/svg/ArrowIcon.js index 79bd829596d..a5df250f714 100644 --- a/src/components/icons/svg/ArrowIcon.js +++ b/src/components/icons/svg/ArrowIcon.js @@ -5,13 +5,7 @@ import { withRotationForDirection } from '../../../hoc'; import { colors } from '../../../styles'; import Svg from '../Svg'; -/* eslint-disable max-len */ -const ArrowIcon = ({ - color, - height, - width, - ...props -}) => ( +const ArrowIcon = ({ color, height, width, ...props }) => ( <Svg height={height} width={width} {...props}> <Path d="M5.614 4.186v1.92a.349.349 0 0 0 .552.278L9.554 3.56a.344.344 0 0 0 0-.562L6.166.174a.349.349 0 0 0-.552.278v1.922H1.41a.77.77 0 0 0-.77.77v.272c0 .425.345.77.77.77h4.204z" @@ -19,7 +13,6 @@ const ArrowIcon = ({ /> </Svg> ); -/* eslint-disable max-len */ ArrowIcon.propTypes = { color: PropTypes.string, diff --git a/src/components/icons/svg/AvatarIcon.js b/src/components/icons/svg/AvatarIcon.js index adefa15d4a4..a20fd7a0985 100644 --- a/src/components/icons/svg/AvatarIcon.js +++ b/src/components/icons/svg/AvatarIcon.js @@ -3,7 +3,6 @@ import React from 'react'; import { Path } from 'svgs'; import Svg from '../Svg'; -/* eslint-disable max-len */ const AvatarIcon = ({ size }) => ( <Svg height={size} width={size} viewBox="0 0 30 30"> <Path @@ -20,7 +19,6 @@ const AvatarIcon = ({ size }) => ( /> </Svg> ); -/* eslint-disable max-len */ AvatarIcon.propTypes = { size: PropTypes.number, diff --git a/src/components/icons/svg/CameraIcon.js b/src/components/icons/svg/CameraIcon.js index b7e6e1589a0..17b4410cfbe 100644 --- a/src/components/icons/svg/CameraIcon.js +++ b/src/components/icons/svg/CameraIcon.js @@ -4,7 +4,6 @@ import { Path } from 'svgs'; import { colors } from '../../../styles'; import Svg from '../Svg'; -/* eslint-disable max-len */ const CameraIcon = ({ color, ...props }) => ( <Svg height="19" width="18" viewBox="0 0 18 19" {...props}> <Path @@ -14,7 +13,6 @@ const CameraIcon = ({ color, ...props }) => ( /> </Svg> ); -/* eslint-disable max-len */ CameraIcon.propTypes = { color: PropTypes.string, diff --git a/src/components/icons/svg/CaretIcon.js b/src/components/icons/svg/CaretIcon.js index 1996a97e7eb..5faf394638b 100644 --- a/src/components/icons/svg/CaretIcon.js +++ b/src/components/icons/svg/CaretIcon.js @@ -3,37 +3,32 @@ import React from 'react'; import { Path } from 'svgs'; import { withRotationForDirection } from '../../../hoc'; import { colors } from '../../../styles'; +import { directionPropType } from '../../../utils'; import Svg from '../Svg'; -/* eslint-disable max-len */ -const CaretIcon = ({ - color, - direction, - size, - ...props -}) => ( +const CaretIcon = ({ color, size, ...props }) => ( <Svg {...props} - height={size ? size * 1.9 : '19'} - width={size || '10'} - viewBox="0 0 10 19" + height={size ? (size * 20) / 9 : '20'} + width={size || '9'} + viewBox="0 0 9 20" > <Path - d="M.329 16.877L7.039 9.5.328 2.123A1.24 1.24 0 0 1 .467.313a1.4 1.4 0 0 1 1.905.131l7.168 7.88a1.73 1.73 0 0 1 0 2.352l-7.168 7.88a1.4 1.4 0 0 1-1.905.131 1.24 1.24 0 0 1-.138-1.81z" + d="M2.24494815,0.705401289 L8.30260563,8.06112823 C9.23008934,9.18735845 9.23008934,10.8127123 8.30260563,11.9389425 L2.24494815,19.2946694 C1.80608387,19.827576 1.01830791,19.9038124 0.485401289,19.4649481 C-0.0475053327,19.0260839 -0.123741716,18.2383079 0.31512256,17.7054013 L6.37278004,10.3496743 C6.5400312,10.1465836 6.5400312,9.85348706 6.37278004,9.65039637 L0.31512256,2.29466942 C-0.123741716,1.7617628 -0.0475053327,0.973986837 0.485401289,0.53512256 C1.01830791,0.0962582838 1.80608387,0.172494667 2.24494815,0.705401289 Z" fill={color} fillRule="nonzero" /> </Svg> ); -/* eslint-disable max-len */ CaretIcon.propTypes = { color: PropTypes.string, - size: PropTypes.number, + direction: directionPropType, + size: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), }; CaretIcon.defaultProps = { - color: colors.black, + color: colors.dark, }; export default withRotationForDirection(CaretIcon); diff --git a/src/components/icons/svg/CaretThinIcon.js b/src/components/icons/svg/CaretThinIcon.js index 71983dd9784..d07628a698f 100644 --- a/src/components/icons/svg/CaretThinIcon.js +++ b/src/components/icons/svg/CaretThinIcon.js @@ -5,14 +5,8 @@ import { withRotationForDirection } from '../../../hoc'; import { colors } from '../../../styles'; import Svg from '../Svg'; -/* eslint-disable max-len */ const CaretThinIcon = ({ color, ...props }) => ( - <Svg - height="14" - viewBox="0 0 7 14" - width="7" - {...props} - > + <Svg height="14" viewBox="0 0 7 14" width="7" {...props}> <Path d="M.317 12.203a.875.875 0 1 0 1.366 1.094l4.15-5.188a1.375 1.375 0 0 0 0-1.718l-4.15-5.188A.875.875 0 1 0 .317 2.297L4.279 7.25.317 12.203z" fill={color} @@ -20,7 +14,6 @@ const CaretThinIcon = ({ color, ...props }) => ( /> </Svg> ); -/* eslint-enable max-len */ CaretThinIcon.propTypes = { color: PropTypes.string, diff --git a/src/components/icons/svg/CheckmarkCircledIcon.js b/src/components/icons/svg/CheckmarkCircledIcon.js index 657f720c1ea..384eb33bba5 100644 --- a/src/components/icons/svg/CheckmarkCircledIcon.js +++ b/src/components/icons/svg/CheckmarkCircledIcon.js @@ -4,7 +4,6 @@ import { Path } from 'svgs'; import { colors } from '../../../styles'; import Svg from '../Svg'; -/* eslint-disable max-len */ const CheckmarkCircledIcon = ({ color, ...props }) => ( <Svg height="20" width="21" viewBox="0 0 20 21" {...props}> <Path @@ -14,7 +13,6 @@ const CheckmarkCircledIcon = ({ color, ...props }) => ( /> </Svg> ); -/* eslint-enable max-len */ CheckmarkCircledIcon.propTypes = { color: PropTypes.string, diff --git a/src/components/icons/svg/CheckmarkIcon.js b/src/components/icons/svg/CheckmarkIcon.js index 0ff79030bb0..28e874ea704 100644 --- a/src/components/icons/svg/CheckmarkIcon.js +++ b/src/components/icons/svg/CheckmarkIcon.js @@ -4,7 +4,6 @@ import { Path } from 'svgs'; import { colors } from '../../../styles'; import Svg from '../Svg'; -/* eslint-disable max-len */ const CheckmarkIcon = ({ color, ...props }) => ( <Svg height="11" width="10" viewBox="0 0 11 10" {...props}> <Path @@ -14,7 +13,6 @@ const CheckmarkIcon = ({ color, ...props }) => ( /> </Svg> ); -/* eslint-disable max-len */ CheckmarkIcon.propTypes = { color: PropTypes.string, diff --git a/src/components/icons/svg/ClearInputIcon.js b/src/components/icons/svg/ClearInputIcon.js new file mode 100644 index 00000000000..43d63ae04cc --- /dev/null +++ b/src/components/icons/svg/ClearInputIcon.js @@ -0,0 +1,27 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { Path } from 'svgs'; +import { colors } from '../../../styles'; +import Svg from '../Svg'; + +const ClearInputIcon = ({ color, size, ...props }) => ( + <Svg height={size} width={size} viewBox="0 0 20 20" {...props}> + <Path + d="M9.99 0C15.464 0 20 4.524 20 10.005 20 15.476 15.474 20 10 20S0 15.476 0 10.005C0 4.524 4.516 0 9.99 0zm3.366 5.742a.842.842 0 00-.648.27L9.99 8.71 7.292 6.022a.868.868 0 00-.648-.27.914.914 0 00-.928.918c0 .242.106.474.28.638l2.689 2.697-2.689 2.706a.87.87 0 00-.28.638c0 .513.416.928.928.928a.927.927 0 00.667-.27l2.68-2.688 2.698 2.688a.91.91 0 00.657.27.922.922 0 00.929-.928.962.962 0 00-.271-.657l-2.698-2.687 2.698-2.707a.83.83 0 00.28-.638.914.914 0 00-.928-.918z" + fill={color} + fillRule="nonzero" + /> + </Svg> +); + +ClearInputIcon.propTypes = { + color: PropTypes.string, + size: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), +}; + +ClearInputIcon.defaultProps = { + color: colors.black, + size: 20, +}; + +export default ClearInputIcon; diff --git a/src/components/icons/svg/ClockIcon.js b/src/components/icons/svg/ClockIcon.js index 65a0b576398..350551a7fce 100644 --- a/src/components/icons/svg/ClockIcon.js +++ b/src/components/icons/svg/ClockIcon.js @@ -4,17 +4,10 @@ import { Circle, G, Path } from 'svgs'; import { colors } from '../../../styles'; import Svg from '../Svg'; -/* eslint-disable max-len */ const ClockIcon = ({ color, ...props }) => ( <Svg viewBox="0 0 30 30" {...props}> <G fill="none" fillRule="nonzero"> - <Circle - cx="15" - cy="15" - r="13.875" - stroke={color} - strokeWidth="2.25" - /> + <Circle cx="15" cy="15" r="13.875" stroke={color} strokeWidth="2.25" /> <Path d="M15.3 14.726l5.16 2.98c.232.133.302.206.36.3a.545.545 0 0 1 .083.31c-.003.11-.028.208-.161.44l-.356.616c-.134.232-.207.302-.3.36a.545.545 0 0 1-.31.084c-.111-.004-.21-.028-.44-.162l-5.722-3.303a1.122 1.122 0 0 1-.564-.976V8.769c0-.267.028-.364.08-.462a.545.545 0 0 1 .227-.227c.098-.052.195-.08.462-.08h.712c.267 0 .364.028.462.08a.545.545 0 0 1 .227.227c.052.098.08.195.08.462v5.957z" fill={color} @@ -22,7 +15,6 @@ const ClockIcon = ({ color, ...props }) => ( </G> </Svg> ); -/* eslint-disable max-len */ ClockIcon.propTypes = { color: PropTypes.string, diff --git a/src/components/icons/svg/CloseCircledIcon.js b/src/components/icons/svg/CloseCircledIcon.js index 37a3cfcf99a..998ff2c5caa 100644 --- a/src/components/icons/svg/CloseCircledIcon.js +++ b/src/components/icons/svg/CloseCircledIcon.js @@ -4,7 +4,6 @@ import { Path } from 'svgs'; import { colors } from '../../../styles'; import Svg from '../Svg'; -/* eslint-disable max-len */ const CloseCircledIcon = ({ color, ...props }) => ( <Svg height="12" width="12" viewBox="0 0 12 12" {...props}> <Path @@ -14,7 +13,6 @@ const CloseCircledIcon = ({ color, ...props }) => ( /> </Svg> ); -/* eslint-disable max-len */ CloseCircledIcon.propTypes = { color: PropTypes.string, diff --git a/src/components/icons/svg/CloseIcon.js b/src/components/icons/svg/CloseIcon.js index 414b592d616..97a50289729 100644 --- a/src/components/icons/svg/CloseIcon.js +++ b/src/components/icons/svg/CloseIcon.js @@ -4,7 +4,6 @@ import { Path } from 'svgs'; import { colors } from '../../../styles'; import Svg from '../Svg'; -/* eslint-disable max-len */ const CloseIcon = ({ color, size, ...props }) => ( <Svg height={size} width={size} viewBox="0 0 12 12" {...props}> <Path @@ -14,7 +13,6 @@ const CloseIcon = ({ color, size, ...props }) => ( /> </Svg> ); -/* eslint-disable max-len */ CloseIcon.propTypes = { color: PropTypes.string, diff --git a/src/components/icons/svg/CompassIcon.js b/src/components/icons/svg/CompassIcon.js index fa407d5f754..6efe441835d 100644 --- a/src/components/icons/svg/CompassIcon.js +++ b/src/components/icons/svg/CompassIcon.js @@ -3,7 +3,6 @@ import React from 'react'; import Svg, { Path } from 'svgs'; import { colors } from '../../../styles'; -/* eslint-disable max-len */ const CompassIcon = ({ color, size, ...props }) => ( <Svg height={size || 24} width={size || 24} viewBox="0 0 24 24" {...props}> <Path @@ -13,7 +12,6 @@ const CompassIcon = ({ color, size, ...props }) => ( /> </Svg> ); -/* eslint-disable max-len */ CompassIcon.propTypes = { color: PropTypes.string, diff --git a/src/components/icons/svg/CopyIcon.js b/src/components/icons/svg/CopyIcon.js index f5c3a6f85da..807843bb193 100644 --- a/src/components/icons/svg/CopyIcon.js +++ b/src/components/icons/svg/CopyIcon.js @@ -4,7 +4,6 @@ import { Path } from 'svgs'; import { colors } from '../../../styles'; import Svg from '../Svg'; -/* eslint-disable max-len */ const CopyIcon = ({ color, ...props }) => ( <Svg height="16" width="17" viewBox="0 0 16 17" {...props}> <Path @@ -14,7 +13,6 @@ const CopyIcon = ({ color, ...props }) => ( /> </Svg> ); -/* eslint-disable max-len */ CopyIcon.propTypes = { color: PropTypes.string, diff --git a/src/components/icons/svg/CrosshairIcon.js b/src/components/icons/svg/CrosshairIcon.js index f1801377852..1242fcd516c 100644 --- a/src/components/icons/svg/CrosshairIcon.js +++ b/src/components/icons/svg/CrosshairIcon.js @@ -4,7 +4,6 @@ import { Path } from 'svgs'; import { colors } from '../../../styles'; import Svg from '../Svg'; -/* eslint-disable max-len */ const CrosshairIcon = ({ color, ...props }) => ( <Svg viewBox="0 0 259 259" {...props}> <Path @@ -17,7 +16,6 @@ const CrosshairIcon = ({ color, ...props }) => ( /> </Svg> ); -/* eslint-disable max-len */ CrosshairIcon.propTypes = { color: PropTypes.string, diff --git a/src/components/icons/svg/DotIcon.js b/src/components/icons/svg/DotIcon.js index 32f577353c7..ad35c4c65f4 100644 --- a/src/components/icons/svg/DotIcon.js +++ b/src/components/icons/svg/DotIcon.js @@ -6,12 +6,7 @@ import Svg from '../Svg'; const DotIcon = ({ color, ...props }) => ( <Svg height="7" width="7" viewBox="0 0 7 7" {...props}> - <Circle - cx="3.5" - cy="3.5" - r="3.5" - fill={color} - /> + <Circle cx="3.5" cy="3.5" r="3.5" fill={color} /> </Svg> ); diff --git a/src/components/icons/svg/FaceIdIcon.js b/src/components/icons/svg/FaceIdIcon.js index 5b94652a0a1..e8856c266b5 100644 --- a/src/components/icons/svg/FaceIdIcon.js +++ b/src/components/icons/svg/FaceIdIcon.js @@ -3,17 +3,16 @@ import React from 'react'; import Svg, { Path } from 'svgs'; import { colors } from '../../../styles'; -/* eslint-disable max-len */ const FaceIdIcon = ({ color, ...props }) => ( - <Svg viewBox="0 0 32 32" {...props}> + <Svg viewBox="0 0 27 27" {...props}> <Path - d="M31.1821561,23 C31.6282528,23 32,23.3448276 32,23.7586207 L32,26.9310345 C32,29.7241379 29.5464684,32 26.535316,32 L22.8178439,32 C22.3717472,32 22,31.6551724 22,31.2413793 C22,30.8275862 22.3717472,30.4827586 22.8178439,30.4827586 L26.535316,30.4827586 C28.6542751,30.4827586 30.3643123,28.8965517 30.3643123,26.9310345 L30.3643123,23.7586207 C30.3643123,23.3448276 30.7360595,23 31.1821561,23 Z M26.535316,0 C29.5464684,0 32,2.39130435 32,5.32608696 L32,9.20289855 C32,9.63768116 31.6282528,10 31.1821561,10 C30.7360595,10 30.3643123,9.63768116 30.3643123,9.20289855 L30.3643123,5.32608696 C30.3643123,3.26086957 28.6542751,1.5942029 26.535316,1.5942029 L22.8178439,1.5942029 C22.3717472,1.5942029 22,1.23188406 22,0.797101449 C22,0.362318841 22.3717472,0 22.8178439,0 L26.535316,0 Z M23,16 C22.4642857,16 22,15.5275591 22,14.8976378 L22,12.1023622 C22,11.511811 22.4285714,11 23,11 C23.5714286,11 24,11.4724409 24,12.1023622 L24,14.9370079 C23.9642857,15.5275591 23.5357143,16 23,16 Z M20.7038627,22.2529274 C21.0128755,21.9156909 21.4935622,21.9156909 21.7682403,22.2529274 C22.0772532,22.5901639 22.0772532,23.1147541 21.7682403,23.4145199 C20.2575107,25.1007026 18.2317597,26 16.1373391,26 L15.8626609,26 C13.7682403,26 11.776824,25.1007026 10.2317597,23.4145199 C9.92274678,23.0772834 9.92274678,22.5526932 10.2317597,22.2529274 C10.5407725,21.9156909 11.0214592,21.9156909 11.2961373,22.2529274 C12.5321888,23.6018735 14.1459227,24.3512881 15.8626609,24.3512881 L16.1373391,24.3512881 C17.8197425,24.3512881 19.4678112,23.6018735 20.7038627,22.2529274 Z M13.8148148,20 C13.3703704,20 13,19.6456693 13,19.2204724 C13,18.7952756 13.3703704,18.4409449 13.8148148,18.4409449 L14,18.4409449 C14.7407407,18.4409449 15.3703704,17.8740157 15.3703704,17.1299213 L15.3703704,11.7795276 C15.3703704,11.3543307 15.7407407,11 16.1851852,11 C16.6296296,11 17,11.3543307 17,11.7795276 L17,17.1653543 C17,18.7244094 15.6666667,20 14,20 L13.8148148,20 Z M9,11 C9.53571429,11 10,11.4724409 10,12.1023622 L10,14.9370079 C10,15.5275591 9.57142857,16 9,16 C8.46428571,16 8,15.5275591 8,14.8976378 L8,12.1023622 C8,11.511811 8.42857143,11 9,11 Z M0.817843866,10 C0.371747212,10 0,9.63768116 0,9.20289855 L0,5.32608696 C0,2.39130435 2.4535316,0 5.46468401,0 L9.18215613,0 C9.62825279,0 10,0.362318841 10,0.797101449 C10,1.23188406 9.62825279,1.5942029 9.18215613,1.5942029 L5.46468401,1.5942029 C3.34572491,1.5942029 1.63568773,3.26086957 1.63568773,5.32608696 L1.63568773,9.20289855 C1.63568773,9.63768116 1.26394052,10 0.817843866,10 Z M9.18215613,30.4827586 C9.62825279,30.4827586 10,30.8275862 10,31.2413793 C10,31.6551724 9.66542751,32 9.18215613,32 L5.46468401,32 C2.4535316,32 0,29.7241379 0,26.9310345 L0,23.7586207 C0,23.3448276 0.371747212,23 0.817843866,23 C1.26394052,23 1.63568773,23.3448276 1.63568773,23.7586207 L1.63568773,26.9310345 C1.63568773,28.8965517 3.34572491,30.4827586 5.46468401,30.4827586 L9.18215613,30.4827586 Z" + clipRule="evenodd" + d="M0 8.152c0 .78.426 1.206 1.191 1.206.765 0 1.177-.427 1.177-1.207V4.68c0-1.53.823-2.31 2.294-2.31H8.22c.764 0 1.19-.427 1.19-1.192C9.412.427 8.986 0 8.222 0H4.618C1.558 0 0 1.516 0 4.547v3.605zm24.632 0c0 .78.427 1.206 1.177 1.206.78 0 1.191-.427 1.191-1.207V4.548C27 1.516 25.47 0 22.382 0h-3.588c-.78 0-1.206.427-1.206 1.177 0 .765.427 1.192 1.206 1.192h3.559c1.441 0 2.28.78 2.28 2.31v3.473zM11.265 15.14c0-.427.338-.75.78-.75h.484c.192 0 .368-.104.368-.369v-4.62c0-.485.309-.78.78-.78.47 0 .764.295.764.78v4.488c0 1.383-.735 2.075-2.059 2.075h-.132c-.691 0-.985-.354-.985-.824zM8.25 8.65c-.574 0-.985.413-.985.987v1.957c0 .603.411 1 .985 1 .603 0 1-.397 1-1V9.638c0-.574-.397-.986-1-.986zm9.25.987c0-.574.397-.986 1-.986.573 0 .97.412.97.986v1.957c0 .603-.396 1-.97 1-.603 0-1-.397-1-1V9.638zm-8.765 8.754c1.177 1.207 2.883 1.943 4.588 1.943 1.692 0 3.383-.736 4.589-1.943a.948.948 0 00.206-.588.742.742 0 00-.765-.765c-.28 0-.427.132-.632.338-.81.883-2.133 1.413-3.398 1.413-1.279 0-2.558-.56-3.397-1.413-.205-.206-.367-.338-.647-.338-.455 0-.779.323-.779.765 0 .25.103.427.235.588zM4.618 27C1.558 27 0 25.485 0 22.439v-3.59c0-.78.412-1.207 1.191-1.207.75 0 1.177.427 1.177 1.207v3.472c0 1.53.823 2.31 2.294 2.31H8.22c.764 0 1.19.427 1.19 1.192 0 .75-.426 1.177-1.19 1.177H4.618zm12.97-1.177c0 .75.427 1.177 1.206 1.177h3.588C25.471 27 27 25.47 27 22.439v-3.59c0-.78-.427-1.207-1.191-1.207-.765 0-1.177.427-1.177 1.207v3.472c0 1.53-.838 2.31-2.28 2.31h-3.558c-.78 0-1.206.427-1.206 1.192z" fill={color} fillRule="evenodd" /> </Svg> ); -/* eslint-disable max-len */ FaceIdIcon.propTypes = { color: PropTypes.string, diff --git a/src/components/icons/svg/GearIcon.js b/src/components/icons/svg/GearIcon.js index 41aa8586aab..470cd977f19 100644 --- a/src/components/icons/svg/GearIcon.js +++ b/src/components/icons/svg/GearIcon.js @@ -4,7 +4,6 @@ import { Path } from 'svgs'; import { colors } from '../../../styles'; import Svg from '../Svg'; -/* eslint-disable max-len */ const GearIcon = ({ color, ...props }) => ( <Svg height="24" width="24" viewBox="0 0 24 24" {...props}> <Path @@ -14,14 +13,13 @@ const GearIcon = ({ color, ...props }) => ( /> </Svg> ); -/* eslint-disable max-len */ GearIcon.propTypes = { color: PropTypes.string, }; GearIcon.defaultProps = { - color: colors.black, + color: colors.dark, }; export default GearIcon; diff --git a/src/components/icons/svg/HandleIcon.js b/src/components/icons/svg/HandleIcon.js index 7e8010faea7..e6eba50027c 100644 --- a/src/components/icons/svg/HandleIcon.js +++ b/src/components/icons/svg/HandleIcon.js @@ -4,7 +4,6 @@ import { Path } from 'svgs'; import { colors } from '../../../styles'; import Svg from '../Svg'; -/* eslint-disable max-len */ const HandleIcon = ({ color, ...props }) => ( <Svg height="11" width="37" viewBox="0 0 37 11" {...props}> <Path @@ -14,7 +13,6 @@ const HandleIcon = ({ color, ...props }) => ( /> </Svg> ); -/* eslint-disable max-len */ HandleIcon.propTypes = { color: PropTypes.string, diff --git a/src/components/icons/svg/InboxIcon.js b/src/components/icons/svg/InboxIcon.js index ff2cccd9fe1..ae31bc69fbb 100644 --- a/src/components/icons/svg/InboxIcon.js +++ b/src/components/icons/svg/InboxIcon.js @@ -3,7 +3,6 @@ import React from 'react'; import Svg, { Path } from 'svgs'; import { colors } from '../../../styles'; -/* eslint-disable max-len */ const InboxIcon = ({ color, ...props }) => ( <Svg height="17" width="16" viewBox="0 0 16 17" {...props}> <Path @@ -13,7 +12,6 @@ const InboxIcon = ({ color, ...props }) => ( /> </Svg> ); -/* eslint-disable max-len */ InboxIcon.propTypes = { color: PropTypes.string, diff --git a/src/components/icons/svg/LockIcon.js b/src/components/icons/svg/LockIcon.js new file mode 100644 index 00000000000..c814e2d5a01 --- /dev/null +++ b/src/components/icons/svg/LockIcon.js @@ -0,0 +1,25 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { Path } from 'svgs'; +import { colors } from '../../../styles'; +import Svg from '../Svg'; + +const LockIcon = ({ color, ...props }) => ( + <Svg height="14" width="10" {...props}> + <Path + d="M4.602 0c1.854 0 3.6 1.301 3.6 4.043v1.65c.672.102.996.553.996 1.385v4.92c0 .977-.438 1.42-1.34 1.42H1.34c-.895 0-1.339-.443-1.339-1.42V7.083c0-.832.33-1.27.997-1.377V4.043C.997 1.301 2.749 0 4.602 0zm0 1.377c-1.187 0-2.17.864-2.17 2.559v1.739l4.34-.007V3.936c0-1.695-.99-2.559-2.17-2.559z" + fill={color} + fillRule="nonzero" + /> + </Svg> +); + +LockIcon.propTypes = { + color: PropTypes.string, +}; + +LockIcon.defaultProps = { + color: colors.black, +}; + +export default LockIcon; diff --git a/src/components/icons/svg/OfflineIcon.js b/src/components/icons/svg/OfflineIcon.js index 3d37cb8dece..fa6d9a9ac4d 100644 --- a/src/components/icons/svg/OfflineIcon.js +++ b/src/components/icons/svg/OfflineIcon.js @@ -4,7 +4,6 @@ import { Path } from 'svgs'; import { colors } from '../../../styles'; import Svg from '../Svg'; -/* eslint-disable max-len */ const OfflineIcon = ({ color, ...props }) => ( <Svg width="19" height="15" viewBox="0 0 15 19" {...props}> <Path @@ -14,7 +13,6 @@ const OfflineIcon = ({ color, ...props }) => ( /> </Svg> ); -/* eslint-disable max-len */ OfflineIcon.propTypes = { color: PropTypes.string, diff --git a/src/components/icons/svg/PasscodeIcon.js b/src/components/icons/svg/PasscodeIcon.js new file mode 100644 index 00000000000..879f179b4df --- /dev/null +++ b/src/components/icons/svg/PasscodeIcon.js @@ -0,0 +1,37 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import Svg, { Defs, G, LinearGradient, Path, Stop } from 'svgs'; +import { colors } from '../../../styles'; + +const PasscodeIcon = ({ color, ...props }) => ( + <Svg viewBox="0 0 18 24" {...props}> + <Defs> + <LinearGradient id="gradient" x1="50%" x2="50%" y1="0%" y2="100%"> + <Stop offset="0%" stopColor={color} /> + <Stop offset="34.274%" stopColor={color} /> + <Stop offset="66.193%" stopColor={color} stopOpacity=".84" /> + <Stop offset="100%" stopColor={color} stopOpacity=".64" /> + </LinearGradient> + </Defs> + <G fill-rule="nonzero" fill="none"> + <Path + d="M8.998 0c3.494 0 6.818 2.404 6.818 7.396v4.195c.98.096-3.564.11-13.636.04V7.395C2.18 2.404 5.504 0 8.998 0zm0 2.418c-2.351 0-4.296 1.681-4.296 4.742v3.36l8.592-.014V7.16c0-3.06-1.958-4.742-4.296-4.742z" + fill="url(#gradient)" + /> + <Path + d="M13.193 9c1.671 0 2.277.174 2.889.5.61.328 1.09.807 1.417 1.418.327.612.501 1.218.501 2.89v5.385c0 1.671-.174 2.277-.5 2.889a3.407 3.407 0 01-1.418 1.417c-.612.327-1.218.501-2.89.501H4.808c-1.671 0-2.277-.174-2.889-.5a3.407 3.407 0 01-1.417-1.418C.174 21.47 0 20.864 0 19.192v-5.385c0-1.671.174-2.277.5-2.889a3.407 3.407 0 011.418-1.417C2.53 9.174 3.136 9 4.808 9h8.385zm-4.18 3.102c-.506 0-.878.347-.812.919l.166 2.277-1.921-1.333a.844.844 0 00-.547-.19c-.422 0-.795.339-.795.827 0 .331.174.588.53.745l2.103 1.035-2.103 1.052c-.34.157-.53.406-.53.737 0 .48.373.836.795.836.207 0 .381-.066.538-.19l1.93-1.333-.174 2.219c-.05.521.265.902.82.902.546 0 .844-.364.794-.902l-.165-2.22 1.912 1.342c.158.124.34.199.555.199.414 0 .787-.356.787-.837 0-.33-.19-.596-.53-.745l-2.112-1.06 2.112-1.043c.34-.157.53-.414.53-.745 0-.489-.373-.828-.787-.828a.916.916 0 00-.555.19l-1.929 1.342.174-2.286c.058-.58-.29-.91-.787-.91z" + fill={color} + /> + </G> + </Svg> +); + +PasscodeIcon.propTypes = { + color: PropTypes.string, +}; + +PasscodeIcon.defaultProps = { + color: colors.white, +}; + +export default PasscodeIcon; diff --git a/src/components/icons/svg/ProgressIcon.js b/src/components/icons/svg/ProgressIcon.js index 04e1f6d8b39..6c0b0ea6593 100644 --- a/src/components/icons/svg/ProgressIcon.js +++ b/src/components/icons/svg/ProgressIcon.js @@ -1,7 +1,6 @@ import PropTypes from 'prop-types'; import React from 'react'; import Animated from 'react-native-reanimated'; -import { pure } from 'recompact'; import { G, Path } from 'svgs'; import { colors, position } from '../../../styles'; import { Centered } from '../../layout'; @@ -18,15 +17,22 @@ const { max, min, multiply, + proc, sin, sub, } = Animated; + const AnimatedPath = createAnimatedComponent(Path); -const convertProgress = progress => divide(multiply(360, min(100, max(0, progress))), 100); +const convertProgress = proc(progress => + divide(multiply(360, min(100, max(0, progress))), 100) +); function polarToCartesian(center, radius, angleInDegrees) { - const angleInRadians = divide(multiply(sub(angleInDegrees, 90), Math.PI), 180); + const angleInRadians = divide( + multiply(sub(angleInDegrees, 90), Math.PI), + 180 + ); return { x: concat(add(center, multiply(radius, cos(angleInRadians)))), @@ -40,8 +46,17 @@ function circlePath(center, radius, startAngle, endAngle) { const largeArcFlag = cond(lessOrEq(sub(endAngle, startAngle), 180), 0, 1); const path = [ - 'M', start.x, start.y, - 'A', radius, radius, 0, largeArcFlag, 0, end.x, end.y, + 'M', + start.x, + start.y, + 'A', + radius, + radius, + 0, + largeArcFlag, + 0, + end.x, + end.y, ]; const pathWithSpaces = path.reduce((arr, p) => [...arr, p, ' '], []); @@ -58,13 +73,10 @@ const ProgressIcon = ({ }) => { const radius = size / 2; const center = radius + 2; - const viewBoxSize = size + (strokeWidth * 2); + const viewBoxSize = size + strokeWidth * 2; return ( - <Centered - {...props} - {...position.sizeAsObject(size)} - > + <Centered {...props} {...position.sizeAsObject(size)}> <AnimatedSvg {...position.sizeAsObject(size)} viewBox={`0 0 ${viewBoxSize} ${viewBoxSize}`} @@ -106,4 +118,4 @@ ProgressIcon.defaultProps = { strokeWidth: 2, }; -export default pure(ProgressIcon); +export default React.memo(ProgressIcon); diff --git a/src/components/icons/svg/SearchIcon.js b/src/components/icons/svg/SearchIcon.js new file mode 100644 index 00000000000..a70e63c8245 --- /dev/null +++ b/src/components/icons/svg/SearchIcon.js @@ -0,0 +1,25 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { Path } from 'svgs'; +import { colors } from '../../../styles'; +import Svg from '../Svg'; + +const SearchIcon = ({ color, ...props }) => ( + <Svg height="18" width="18" viewBox="0 0 18 18" {...props}> + <Path + d="M7.455 0a7.444 7.444 0 0 1 5.982 11.888l4.024 3.404a1.538 1.538 0 1 1-2.169 2.168l-3.404-4.023A7.45 7.45 0 1 1 7.455 0zm0 13.34a5.885 5.885 0 1 0 0-11.77 5.885 5.885 0 0 0 0 11.77z" + fill={color} + fillRule="nonzero" + /> + </Svg> +); + +SearchIcon.propTypes = { + color: PropTypes.string, +}; + +SearchIcon.defaultProps = { + color: colors.black, +}; + +export default SearchIcon; diff --git a/src/components/icons/svg/SendIcon.js b/src/components/icons/svg/SendIcon.js index c0a24f59225..b98e613309c 100644 --- a/src/components/icons/svg/SendIcon.js +++ b/src/components/icons/svg/SendIcon.js @@ -3,7 +3,6 @@ import React from 'react'; import Svg, { Path } from 'svgs'; import { colors } from '../../../styles'; -/* eslint-disable max-len */ const SendIcon = ({ color, ...props }) => ( <Svg viewBox="0 0 23 22" {...props}> <Path @@ -13,7 +12,6 @@ const SendIcon = ({ color, ...props }) => ( /> </Svg> ); -/* eslint-disable max-len */ SendIcon.propTypes = { color: PropTypes.string, diff --git a/src/components/icons/svg/SendSmallIcon.js b/src/components/icons/svg/SendSmallIcon.js index 453c9a0c8c2..7bef82bb19c 100644 --- a/src/components/icons/svg/SendSmallIcon.js +++ b/src/components/icons/svg/SendSmallIcon.js @@ -4,7 +4,6 @@ import { Path } from 'svgs'; import { colors } from '../../../styles'; import Svg from '../Svg'; -/* eslint-disable max-len */ const SendSmallIcon = ({ color, ...props }) => ( <Svg height="10" width="10" viewBox="0 0 10 10" {...props}> <Path @@ -14,7 +13,6 @@ const SendSmallIcon = ({ color, ...props }) => ( /> </Svg> ); -/* eslint-disable max-len */ SendSmallIcon.propTypes = { color: PropTypes.string, diff --git a/src/components/icons/svg/ShareIcon.js b/src/components/icons/svg/ShareIcon.js index 0caaca65fbb..998f57a8a37 100644 --- a/src/components/icons/svg/ShareIcon.js +++ b/src/components/icons/svg/ShareIcon.js @@ -4,7 +4,6 @@ import { Path } from 'svgs'; import { colors } from '../../../styles'; import Svg from '../Svg'; -/* eslint-disable max-len */ const ShareIcon = ({ color, ...props }) => ( <Svg height="26" width="18" viewBox="0 0 18 26" {...props}> <Path @@ -14,7 +13,6 @@ const ShareIcon = ({ color, ...props }) => ( /> </Svg> ); -/* eslint-disable max-len */ ShareIcon.propTypes = { color: PropTypes.string, diff --git a/src/components/icons/svg/SignatureIcon.js b/src/components/icons/svg/SignatureIcon.js index 4fb6adc90c6..d3a5703c0c3 100644 --- a/src/components/icons/svg/SignatureIcon.js +++ b/src/components/icons/svg/SignatureIcon.js @@ -4,7 +4,6 @@ import { Path } from 'svgs'; import { colors } from '../../../styles'; import Svg from '../Svg'; -/* eslint-disable max-len */ const SignatureIcon = ({ color, ...props }) => ( <Svg height="10" width="10" viewBox="0 0 10 10" {...props}> <Path @@ -14,7 +13,6 @@ const SignatureIcon = ({ color, ...props }) => ( /> </Svg> ); -/* eslint-disable max-len */ SignatureIcon.propTypes = { color: PropTypes.string, diff --git a/src/components/icons/svg/SpinnerIcon.js b/src/components/icons/svg/SpinnerIcon.js index e5478a48930..1d0a6d12476 100644 --- a/src/components/icons/svg/SpinnerIcon.js +++ b/src/components/icons/svg/SpinnerIcon.js @@ -5,7 +5,7 @@ import { colors } from '../../../styles'; import { SpinAnimation } from '../../animations'; import Svg from '../Svg'; -const SpinnerIcon = ({ color, size, ...props }) => ( +const SpinnerIcon = ({ color, size }) => ( <SpinAnimation> <Svg height={size} width={size}> <Path diff --git a/src/components/icons/svg/StarIcon.js b/src/components/icons/svg/StarIcon.js new file mode 100644 index 00000000000..52b5d9bc7f3 --- /dev/null +++ b/src/components/icons/svg/StarIcon.js @@ -0,0 +1,19 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import Svg, { Path } from 'svgs'; + +const StarIcon = ({ color, ...props }) => ( + <Svg height="18" width="19" viewBox="0 0 18 19" {...props}> + <Path + d="M9.411 15.009l-4.618 2.835c-.81.487-1.782-.243-1.54-1.134l1.216-5.266L.337 7.879C-.31 7.312.013 6.178.985 6.097l5.348-.486L8.439.668c.405-.89 1.54-.89 1.945 0l2.106 4.943 5.347.486c.891.08 1.297 1.215.567 1.782l-4.05 3.565 1.215 5.266c.162.891-.73 1.62-1.54 1.134L9.411 15.01z" + fill={color} + fillRule="evenodd" + /> + </Svg> +); + +StarIcon.propTypes = { + color: PropTypes.string, +}; + +export default StarIcon; diff --git a/src/components/icons/svg/SwapIcon.js b/src/components/icons/svg/SwapIcon.js new file mode 100644 index 00000000000..b5e50b6c23c --- /dev/null +++ b/src/components/icons/svg/SwapIcon.js @@ -0,0 +1,24 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import Svg, { Path } from 'svgs'; +import { colors } from '../../../styles'; + +const SwapIcon = ({ color, ...props }) => ( + <Svg height="21" width="26" viewBox="0 0 26 21" {...props}> + <Path + d="M7.015 15.812c.825 0 1.18.863.673 1.498l-2.336 2.996c-.61.787-1.371.787-1.98 0L1.034 17.31c-.508-.635-.152-1.498.673-1.498h1.524V6.291c0-3.682 2.26-6.018 5.433-6.018 3.161 0 5.472 2.336 5.472 6.018v8.696c0 2.209 1.37 3.567 3.199 3.567 1.84 0 3.174-1.384 3.174-3.567V5.275h-1.524c-.825 0-1.18-.85-.685-1.498L20.637.78c.622-.775 1.37-.775 1.993 0l2.336 2.996c.508.647.152 1.498-.673 1.498H22.77v9.534c0 3.682-2.26 6.018-5.434 6.018-3.161 0-5.472-2.336-5.472-6.018V6.113c0-2.222-1.37-3.58-3.199-3.58-1.84 0-3.174 1.384-3.174 3.58v9.7h1.524z" + fill={color} + fillRule="nonzero" + /> + </Svg> +); + +SwapIcon.propTypes = { + color: PropTypes.string, +}; + +SwapIcon.defaultProps = { + color: colors.white, +}; + +export default SwapIcon; diff --git a/src/components/icons/svg/ThreeDotsIcon.js b/src/components/icons/svg/ThreeDotsIcon.js index 693beec14c7..7b45c6c8737 100644 --- a/src/components/icons/svg/ThreeDotsIcon.js +++ b/src/components/icons/svg/ThreeDotsIcon.js @@ -7,9 +7,9 @@ import Svg from '../Svg'; const ThreeDotsIcon = ({ color, ...props }) => ( <Svg height="5" width="23" viewBox="0 0 23 5" {...props}> <G fill={color} fillRule="evenodd"> - <Circle cx="2.5" cy="2.5" r="2.5"/> - <Circle cx="11.5" cy="2.5" r="2.5"/> - <Circle cx="20.5" cy="2.5" r="2.5"/> + <Circle cx="2.5" cy="2.5" r="2.5" /> + <Circle cx="11.5" cy="2.5" r="2.5" /> + <Circle cx="20.5" cy="2.5" r="2.5" /> </G> </Svg> ); diff --git a/src/components/icons/svg/TouchIdIcon.js b/src/components/icons/svg/TouchIdIcon.js index 00d3f68eda7..d79b77557d0 100644 --- a/src/components/icons/svg/TouchIdIcon.js +++ b/src/components/icons/svg/TouchIdIcon.js @@ -3,7 +3,6 @@ import React from 'react'; import Svg, { Path } from 'svgs'; import { colors } from '../../../styles'; -/* eslint-disable max-len */ const TouchIdIcon = ({ color, size, ...props }) => ( <Svg height={size} width={size} viewBox="0 0 34 34" {...props}> <Path @@ -13,7 +12,6 @@ const TouchIdIcon = ({ color, size, ...props }) => ( /> </Svg> ); -/* eslint-disable max-len */ TouchIdIcon.propTypes = { color: PropTypes.string, diff --git a/src/components/icons/svg/WalletConnectIcon.js b/src/components/icons/svg/WalletConnectIcon.js index 5007f796312..e2b1b52def0 100644 --- a/src/components/icons/svg/WalletConnectIcon.js +++ b/src/components/icons/svg/WalletConnectIcon.js @@ -4,7 +4,6 @@ import { Path } from 'svgs'; import { colors } from '../../../styles'; import Svg from '../Svg'; -/* eslint-disable max-len */ const WalletConnectIcon = ({ color, ...props }) => ( <Svg height="19" width="31" viewBox="0 0 31 19" {...props}> <Path @@ -14,7 +13,6 @@ const WalletConnectIcon = ({ color, ...props }) => ( /> </Svg> ); -/* eslint-disable max-len */ WalletConnectIcon.propTypes = { color: PropTypes.string, diff --git a/src/components/icons/svg/WarningIcon.js b/src/components/icons/svg/WarningIcon.js index e948336c008..06868247cfe 100644 --- a/src/components/icons/svg/WarningIcon.js +++ b/src/components/icons/svg/WarningIcon.js @@ -4,17 +4,15 @@ import { Path } from 'svgs'; import { colors } from '../../../styles'; import Svg from '../Svg'; -/* eslint-disable max-len */ const WarningIcon = ({ color, ...props }) => ( - <Svg height="16" width="16" viewBox="0 0 16 16" {...props}> + <Svg height="14" width="15" viewBox="0 0 14 15" {...props}> <Path - d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm-.003-3.333a1.014 1.014 0 1 0 0-2.028 1.014 1.014 0 0 0 0 2.028zM8.673 3.2H7.327a.342.342 0 0 0-.345.356l.31 5.748a.342.342 0 0 0 .345.32h.726a.343.343 0 0 0 .346-.32l.309-5.748a.342.342 0 0 0-.345-.356z" + d="M7.504 0c.637 0 1.274.322 1.625.952l5.62 10.06c.172.3.251.616.251.93 0 1.032-.752 1.89-1.883 1.89H1.89c-1.138 0-1.89-.858-1.89-1.89 0-.314.079-.63.25-.923L5.872.952C6.215.322 6.866 0 7.504 0zm0 9.866c-.53 0-.924.337-.924.845 0 .501.4.845.924.845.522 0 .923-.336.923-.845 0-.508-.4-.845-.923-.845zm-.008-5.649c-.5 0-.852.337-.83.816l.107 3.093c.022.459.28.71.73.71.444 0 .702-.244.724-.717l.114-3.078c.022-.48-.343-.824-.845-.824z" fill={color} - fillRule="evenodd" + fillRule="nonzero" /> </Svg> ); -/* eslint-disable max-len */ WarningIcon.propTypes = { color: PropTypes.string, diff --git a/src/components/inputs/ClearInputDecorator.js b/src/components/inputs/ClearInputDecorator.js new file mode 100644 index 00000000000..d132e7a859d --- /dev/null +++ b/src/components/inputs/ClearInputDecorator.js @@ -0,0 +1,89 @@ +import PropTypes from 'prop-types'; +import React, { useRef } from 'react'; +import { Transition, Transitioning } from 'react-native-reanimated'; +import styled from 'styled-components/primitives'; +import { colors } from '../../styles'; +import { ButtonPressAnimation } from '../animations'; +import { Icon } from '../icons'; +import { Centered } from '../layout'; + +const Container = styled.View` + bottom: 0; + flex: 0; + position: absolute; + right: 0; + top: 0; +`; + +const duration = 100; +const transition = ( + <Transition.Sequence> + <Transition.Together> + <Transition.Out + durationMs={duration * 0.666} + interpolation="easeIn" + type="fade" + /> + <Transition.Out + durationMs={duration * 0.42} + interpolation="easeIn" + type="scale" + /> + </Transition.Together> + <Transition.Change durationMs={duration} interpolation="easeInOut" /> + <Transition.Together> + <Transition.In + durationMs={duration} + interpolation="easeOut" + type="fade" + /> + <Transition.In + durationMs={duration * 0.5} + interpolation="easeOut" + type="scale" + /> + </Transition.Together> + </Transition.Sequence> +); + +const ClearInputDecorator = ({ inputHeight, isVisible, onPress }) => { + const ref = useRef(); + + if (ref.current) { + ref.current.animateNextTransition(); + } + + const paddingLeft = inputHeight / 2; + const paddingRight = inputHeight / 4; + + return ( + <Container height={inputHeight} width={paddingLeft * 2 + paddingRight}> + {isVisible && ( + <Transitioning.View ref={ref} transition={transition}> + <ButtonPressAnimation + exclusive + onPressStart={onPress} + scaleTo={0.69} + style={{ paddingLeft, paddingRight }} + > + <Centered height={inputHeight} width={paddingLeft}> + <Icon + color={colors.blueGreyDark} + name="clearInput" + opacity={0.3} + /> + </Centered> + </ButtonPressAnimation> + </Transitioning.View> + )} + </Container> + ); +}; + +ClearInputDecorator.propTypes = { + inputHeight: PropTypes.number, + isVisible: PropTypes.bool, + onPress: PropTypes.func, +}; + +export default React.memo(ClearInputDecorator); diff --git a/src/components/inputs/Input.js b/src/components/inputs/Input.js index 333ab528294..971567d6b74 100644 --- a/src/components/inputs/Input.js +++ b/src/components/inputs/Input.js @@ -1,52 +1,57 @@ import PropTypes from 'prop-types'; -import React from 'react'; +import React, { PureComponent } from 'react'; import { TextInput } from 'react-native'; import { buildTextStyles, colors } from '../../styles'; -const Input = ({ - allowFontScaling, - autoCapitalize, - autoCorrect, - keyboardType, - placeholderTextColor, - spellCheck, - ...props -}) => ( - <TextInput - {...props} - allowFontScaling={allowFontScaling} - autoCapitalize={autoCapitalize} - autoCorrect={autoCorrect} - css={buildTextStyles} - keyboardType={keyboardType} - placeholderTextColor={placeholderTextColor} - spellCheck={spellCheck} - /> -); - -Input.propTypes = { - allowFontScaling: PropTypes.bool, - autoCapitalize: PropTypes.string, - autoCorrect: PropTypes.bool, - keyboardType: PropTypes.oneOf([ - 'decimal-pad', - 'default', - 'email-address', - 'name-phone-pad', - 'number-pad', - 'numeric', - 'phone-pad', - ]), - placeholderTextColor: PropTypes.string, - spellCheck: PropTypes.bool, -}; - -Input.defaultProps = { - allowFontScaling: false, - autoCapitalize: 'none', - autoCorrect: false, - placeholderTextColor: colors.placeholder, - spellCheck: true, -}; - -export default Input; +export default class Input extends PureComponent { + static propTypes = { + allowFontScaling: PropTypes.bool, + autoCapitalize: PropTypes.string, + autoCorrect: PropTypes.bool, + keyboardType: PropTypes.string, + placeholderTextColor: PropTypes.string, + spellCheck: PropTypes.bool, + }; + + static defaultProps = { + allowFontScaling: false, + autoCapitalize: 'none', + autoCorrect: false, + placeholderTextColor: colors.placeholder, + spellCheck: true, + }; + + clear = () => this.ref.current.clear(); + + focus = event => this.ref.current.focus(event); + + isFocused = () => this.ref.current.isFocused(); + + ref = React.createRef(); + + render = () => { + const { + allowFontScaling, + autoCapitalize, + autoCorrect, + keyboardType, + placeholderTextColor, + spellCheck, + ...props + } = this.props; + + return ( + <TextInput + {...props} + allowFontScaling={allowFontScaling} + autoCapitalize={autoCapitalize} + autoCorrect={autoCorrect} + css={buildTextStyles} + keyboardType={keyboardType} + placeholderTextColor={placeholderTextColor} + ref={this.ref} + spellCheck={spellCheck} + /> + ); + }; +} diff --git a/src/components/inputs/MultiLineInput.js b/src/components/inputs/MultiLineInput.js index ffa1fd6ee14..b8093f5bdf6 100644 --- a/src/components/inputs/MultiLineInput.js +++ b/src/components/inputs/MultiLineInput.js @@ -6,5 +6,5 @@ export default compose( withProps({ lineHeight: 'loosest', multiline: true, - }), + }) )(Input); diff --git a/src/components/inputs/index.js b/src/components/inputs/index.js index c96a28a6d85..a808b7086a4 100644 --- a/src/components/inputs/index.js +++ b/src/components/inputs/index.js @@ -1,2 +1,3 @@ +export { default as ClearInputDecorator } from './ClearInputDecorator'; export { default as Input } from './Input'; export { default as MultiLineInput } from './MultiLineInput'; diff --git a/src/components/investment-cards/InvestmentCard.js b/src/components/investment-cards/InvestmentCard.js index ef264aa7b58..29d2ebcc830 100644 --- a/src/components/investment-cards/InvestmentCard.js +++ b/src/components/investment-cards/InvestmentCard.js @@ -1,82 +1,132 @@ import PropTypes from 'prop-types'; import React from 'react'; import LinearGradient from 'react-native-linear-gradient'; -import { pure } from 'recompact'; -import { colors, margin, position } from '../../styles'; -import { deviceUtils } from '../../utils'; +import { View } from 'react-native'; +import { compose, withHandlers } from 'recompact'; +import { withOpenInvestmentCards } from '../../hoc'; +import { colors, position } from '../../styles'; import InnerBorder from '../InnerBorder'; import { Column } from '../layout'; -import { ShadowStack } from '../shadow-stack'; +import { ButtonPressAnimation, SizeToggler } from '../animations'; import InvestmentCardHeader from './InvestmentCardHeader'; +import UniswapInvestmentCard from './UniswapInvestmentCard'; +import InvestmentCardWrap from './InvestmentCard'; + +const InvestmentCardBorderRadius = 18; const InvestmentCardMargin = { horizontal: 19, vertical: 15, }; -const InvestmentCard = pure(({ - children, - collapsed, - containerHeight, - gradientColors, - headerProps, - height, - onLayout, - shadows, - ...props -}) => ( - <ShadowStack - backgroundColor={gradientColors[0]} - borderRadius={18} - css={margin(InvestmentCardMargin.vertical, InvestmentCardMargin.horizontal)} - height={collapsed ? InvestmentCardHeader.height : height} - shadows={shadows} - width={deviceUtils.dimensions.width - (InvestmentCardMargin.horizontal * 2)} - {...props} - > - <Column - css={` - background-color: ${gradientColors[0]}; - border-radius: 18; - overflow: hidden; - width: 100%; - `} - onLayout={onLayout} +const enhance = compose( + withOpenInvestmentCards, + withHandlers({ + onPress: ({ + openInvestmentCards, + setOpenInvestmentCards, + uniqueId, + }) => () => { + setOpenInvestmentCards({ + index: uniqueId, + state: !openInvestmentCards[uniqueId], + }); + }, + }) +); + +const InvestmentCard = enhance( + ({ + children, + collapsed, + containerHeight, + gradientColors, + headerProps, + isExpandedState, + onLayout, + onPress, + openInvestmentCards, + uniqueId, + }) => ( + <View + style={ + headerProps.isCollapsible && { + height: + UniswapInvestmentCard.height + + 2 * InvestmentCardWrap.margin.vertical + + 20, + } + } > - <LinearGradient - colors={gradientColors} - end={{ x: 1, y: 0.5 }} - pointerEvents="none" - start={{ x: 0, y: 0.5 }} - style={position.coverAsObject} - /> - <InvestmentCardHeader - {...headerProps} - collapsed={collapsed} - /> - {collapsed ? null : children} - <InnerBorder radius={18} /> - </Column> - </ShadowStack> -)); + <View + paddingHorizontal={ + isExpandedState ? 0 : InvestmentCardMargin.horizontal + } + paddingVertical={InvestmentCardMargin.vertical} + style={{ + shadowColor: colors.dark, + shadowOffset: { height: 2, width: 0 }, + shadowOpacity: 0.08, + shadowRadius: 3, + }} + > + <SizeToggler + endingWidth={InvestmentCardHeader.height} + startingWidth={containerHeight} + toggle={openInvestmentCards[uniqueId]} + > + <View borderRadius={InvestmentCardBorderRadius} overflow="hidden"> + <Column + {...position.sizeAsObject('100%')} + backgroundColor={gradientColors[0]} + borderRadius={InvestmentCardBorderRadius} + justify="start" + onLayout={onLayout} + > + <LinearGradient + colors={gradientColors} + end={{ x: 1, y: 0.5 }} + pointerEvents="none" + start={{ x: 0, y: 0.5 }} + style={position.coverAsObject} + /> + <ButtonPressAnimation + disabled={!headerProps.isCollapsible} + onPress={onPress} + scaleTo={0.98} + > + <InvestmentCardHeader {...headerProps} collapsed={collapsed} /> + </ButtonPressAnimation> + {children} + <InnerBorder + opacity={0.04} + radius={InvestmentCardBorderRadius} + width={0.5} + /> + </Column> + </View> + </SizeToggler> + </View> + </View> + ) +); InvestmentCard.propTypes = { children: PropTypes.node, collapsed: PropTypes.bool, + containerHeight: PropTypes.number, gradientColors: PropTypes.arrayOf(PropTypes.string).isRequired, headerProps: PropTypes.shape(InvestmentCardHeader.propTypes), - height: PropTypes.number.isRequired, + isExpandedState: PropTypes.bool, onLayout: PropTypes.func, - shadows: PropTypes.arrayOf(PropTypes.array), + onPress: PropTypes.func, + openInvestmentCards: PropTypes.bool, + uniqueId: PropTypes.string, }; InvestmentCard.defaultProps = { + containerHeight: InvestmentCardHeader.height, gradientColors: ['#F7FAFC', '#E0E6EC'], - height: InvestmentCardHeader.height, - shadows: [ - [0, 1, 3, colors.dark, 0.08], - [0, 4, 6, colors.dark, 0.04], - ], }; InvestmentCard.margin = InvestmentCardMargin; diff --git a/src/components/investment-cards/InvestmentCardHeader.js b/src/components/investment-cards/InvestmentCardHeader.js index 27a273782b2..7fe0a395940 100644 --- a/src/components/investment-cards/InvestmentCardHeader.js +++ b/src/components/investment-cards/InvestmentCardHeader.js @@ -1,93 +1,58 @@ import PropTypes from 'prop-types'; import React from 'react'; -import { onlyUpdateForKeys } from 'recompact'; -import styled from 'styled-components/primitives'; -import { colors, padding, position } from '../../styles'; -import { Icon } from '../icons'; -import { - Centered, - Column, - Row, - RowWithMargins, -} from '../layout'; +import FastImage from 'react-native-fast-image'; +import { View } from 'react-primitives'; +import { pure } from 'recompact'; +import Caret from '../../assets/family-dropdown-arrow.png'; +import { colors } from '../../styles'; +import { Column, Row, RowWithMargins } from '../layout'; import { Emoji, Monospace, Text } from '../text'; +import { RotationArrow } from '../animations'; -const HeaderHeight = 48; +const height = 48; -const Container = styled(Row).attrs({ - align: 'center', - justify: 'space-between', -})` - ${padding(0, 15)}; - height: ${HeaderHeight}; -`; - -const enhance = onlyUpdateForKeys(['collapsed', 'title', 'value']); - -const InvestmentCardHeader = enhance(({ - collapsed, - color, - emoji, - isCollapsible, - title, - titleColor, - value, -}) => ( - <Container> - <Row align="center"> - <Column - align="start" - justify="center" - width={24} - > - <Emoji - name={emoji} - lineHeight="none" - size="smedium" - /> - </Column> - <Text - color={titleColor || color} - letterSpacing="tight" - size="lmedium" - weight="medium" - > - {title} - </Text> +const InvestmentCardHeader = pure( + ({ collapsed, color, emoji, isCollapsible, title, titleColor, value }) => ( + <Row + align="center" + height={height} + justify="space-between" + paddingHorizontal={15} + > + <Row align="center"> + <Column align="start" justify="center" width={24}> + <Emoji name={emoji} lineHeight="none" size="smedium" /> + </Column> + <Text + color={titleColor || color} + letterSpacing="tight" + size="lmedium" + weight="medium" + > + {title} + </Text> + </Row> + <RowWithMargins align="center" margin={1}> + <Monospace color={color} size="lmedium" weight="medium"> + {value} + </Monospace> + {isCollapsible && ( + <View paddingLeft={10}> + <RotationArrow isOpen={!collapsed} endingPosition={90}> + <FastImage + source={Caret} + style={{ + height: 13.5, + width: 6.5, + }} + /> + </RotationArrow> + </View> + )} + </RowWithMargins> </Row> - <RowWithMargins align="center" margin={1}> - <Monospace - color={color} - size="lmedium" - weight="medium" - > - {value} - </Monospace> - {isCollapsible && ( - <Centered justify="end" style={position.sizeAsObject(19)}> - <Centered - flex={0} - justify="end" - style={{ - ...position.sizeAsObject(13), - paddingBottom: collapsed ? 1 : 0, - paddingTop: collapsed ? 0 : 2, - position: 'absolute', - right: 0, - }} - > - <Icon - color={color} - direction={collapsed ? 'right' : 'down'} - name="caretThin" - width={13} - /> - </Centered> - </Centered> - )} - </RowWithMargins> - </Container> -)); + ) +); InvestmentCardHeader.propTypes = { collapsed: PropTypes.bool, @@ -104,6 +69,6 @@ InvestmentCardHeader.defaultProps = { isCollapsible: false, }; -InvestmentCardHeader.height = HeaderHeight; +InvestmentCardHeader.height = height; export default InvestmentCardHeader; diff --git a/src/components/investment-cards/InvestmentCardPill.js b/src/components/investment-cards/InvestmentCardPill.js index 032858df782..ed95ae52c4f 100644 --- a/src/components/investment-cards/InvestmentCardPill.js +++ b/src/components/investment-cards/InvestmentCardPill.js @@ -12,14 +12,10 @@ const Pill = styled(Centered)` border-radius: 9.5; `; -const InvestmentCardPill = ({ - hideIcon, - reverse, - symbol, - value, -}) => { +const InvestmentCardPill = ({ hideIcon, reverse, symbol, value }) => { const icon = hideIcon ? null : ( <CoinIcon + key={`CoinIcon-${symbol}`} showShadow={false} size={18} symbol={symbol} @@ -27,12 +23,8 @@ const InvestmentCardPill = ({ ); const label = ( - <Pill> - <Text - letterSpacing="loose" - size="smaller" - weight="semibold" - > + <Pill key={`Pill-${symbol}`}> + <Text letterSpacing="loose" size="smaller" weight="semibold"> {`${value} ${symbol}`} </Text> </Pill> @@ -40,11 +32,8 @@ const InvestmentCardPill = ({ const children = [icon, label]; return ( - <RowWithMargins margin={5}> - {reverse - ? children.reverse() - : children - } + <RowWithMargins margin={5} key={`RowWithMargins-${symbol}`}> + {reverse ? children.reverse() : children} </RowWithMargins> ); }; diff --git a/src/components/investment-cards/UniswapInvestmentCard.js b/src/components/investment-cards/UniswapInvestmentCard.js index 03d991afe18..3d2d46cfb0e 100644 --- a/src/components/investment-cards/UniswapInvestmentCard.js +++ b/src/components/investment-cards/UniswapInvestmentCard.js @@ -1,14 +1,9 @@ import { floor } from 'lodash'; import PropTypes from 'prop-types'; import React from 'react'; -import { - compose, - pure, - withHandlers, - withProps, -} from 'recompact'; +import { compose, pure, withHandlers, withProps } from 'recompact'; import { convertAmountToNativeDisplay } from '../../helpers/utilities'; -import { withAccountSettings } from '../../hoc'; +import { withAccountSettings, withOpenInvestmentCards } from '../../hoc'; import { colors, padding } from '../../styles'; import { ButtonPressAnimation } from '../animations'; import Divider from '../Divider'; @@ -34,35 +29,39 @@ const enhance = compose( onPress(item); } }, - }), + }) ); -const UniswapInvestmentCard = enhance(({ - item: { - ethBalance, - tokenBalance, - tokenName, - tokenSymbol, - totalBalanceAmount, - totalNativeDisplay, - }, - onPress, - onPressContainer, - nativeCurrency, - ...props -}) => ( - <ButtonPressAnimation - disabled={!onPress} - onPress={onPressContainer} - scaleTo={0.96} - > +const UniswapInvestmentCard = enhance( + ({ + isCollapsible, + item: { + ethBalance, + tokenBalance, + tokenName, + tokenSymbol, + totalBalanceAmount, + totalNativeDisplay, + uniqueId, + }, + nativeCurrency, + onPress, + onPressContainer, + openInvestmentCards, + ...props + }) => ( <InvestmentCard {...props} flex={0} gradientColors={['#ECF1F5', '#E4E9F0']} + collapsed={openInvestmentCards[uniqueId]} + uniqueId={uniqueId} + containerHeight={UniswapInvestmentCard.height} + isExpandedState={!onPress} headerProps={{ color: colors.dark, emoji: 'unicorn_face', + isCollapsible, title: 'Uniswap', titleColor: '#D040FF', value: floor(parseFloat(totalBalanceAmount), 4) @@ -75,26 +74,29 @@ const UniswapInvestmentCard = enhance(({ backgroundColor={colors.transparent} color={colors.alpha(colors.blueGreyDark, 0.02)} /> - <ColumnWithMargins css={padding(8, 15, 15)} margin={6}> - <Row align="center" justify="space-between"> - <AssetLabel>Ethereum</AssetLabel> - <AssetLabel>{tokenName}</AssetLabel> - </Row> - <Row align="center" justify="space-between"> - <InvestmentCardPill - symbol="ETH" - value={ethBalance} - /> - <InvestmentCardPill - reverse - symbol={tokenSymbol} - value={tokenBalance} - /> - </Row> - </ColumnWithMargins> + <ButtonPressAnimation + disabled={!onPress} + onPress={onPressContainer} + scaleTo={0.96} + > + <ColumnWithMargins css={padding(8, 15, 15)} margin={6}> + <Row align="center" justify="space-between"> + <AssetLabel>Ethereum</AssetLabel> + <AssetLabel>{tokenName}</AssetLabel> + </Row> + <Row align="center" justify="space-between"> + <InvestmentCardPill symbol="ETH" value={ethBalance} /> + <InvestmentCardPill + reverse + symbol={tokenSymbol} + value={tokenBalance} + /> + </Row> + </ColumnWithMargins> + </ButtonPressAnimation> </InvestmentCard> - </ButtonPressAnimation> -)); + ) +); UniswapInvestmentCard.propTypes = { item: PropTypes.object, @@ -105,4 +107,4 @@ UniswapInvestmentCard.propTypes = { UniswapInvestmentCard.height = UniswapInvestmentCardHeight; -export default UniswapInvestmentCard; +export default withOpenInvestmentCards(UniswapInvestmentCard); diff --git a/src/components/layout/Centered.js b/src/components/layout/Centered.js index 2b3b45152f0..f36cc903bd7 100644 --- a/src/components/layout/Centered.js +++ b/src/components/layout/Centered.js @@ -3,5 +3,5 @@ import Flex from './Flex'; export default compose( setDisplayName('Centered'), - withProps({ align: 'center', justify: 'center' }), + withProps({ align: 'center', justify: 'center' }) )(Flex); diff --git a/src/components/layout/Column.js b/src/components/layout/Column.js index 165d76c79a2..d290a3334ab 100644 --- a/src/components/layout/Column.js +++ b/src/components/layout/Column.js @@ -3,5 +3,5 @@ import Flex from './Flex'; export default compose( setDisplayName('Column'), - withProps({ direction: 'column' }), + withProps({ direction: 'column' }) )(Flex); diff --git a/src/components/layout/ColumnWithDividers.js b/src/components/layout/ColumnWithDividers.js index 8349d827b30..f6df3f75d1c 100644 --- a/src/components/layout/ColumnWithDividers.js +++ b/src/components/layout/ColumnWithDividers.js @@ -9,5 +9,5 @@ export default compose( horizontal: true, ...dividerProps, }, - })), + })) )(LayoutWithDividers); diff --git a/src/components/layout/ColumnWithMargins.js b/src/components/layout/ColumnWithMargins.js index 7d3b5c4f14e..003504a9c2f 100644 --- a/src/components/layout/ColumnWithMargins.js +++ b/src/components/layout/ColumnWithMargins.js @@ -1,9 +1,4 @@ -import { - compose, - defaultProps, - setDisplayName, - withProps, -} from 'recompact'; +import { compose, defaultProps, setDisplayName, withProps } from 'recompact'; import LayoutWithMargins from './LayoutWithMargins'; export default compose( @@ -12,5 +7,5 @@ export default compose( withProps({ direction: 'column', marginKey: 'marginBottom', - }), + }) )(LayoutWithMargins); diff --git a/src/components/layout/Flex.js b/src/components/layout/Flex.js index 69a6a642b1f..9f849ce3bd9 100644 --- a/src/components/layout/Flex.js +++ b/src/components/layout/Flex.js @@ -4,18 +4,25 @@ import { View } from 'react-primitives'; import { componentFromProp } from 'recompact'; import styled from 'styled-components/primitives'; -export const getFlexStyleKeysFromShorthand = style => ( - (style === 'end' || style === 'start') - ? `flex-${style}` - : style -); +export const getFlexStyleKeysFromShorthand = style => + style === 'end' || style === 'start' ? `flex-${style}` : style; -const FlexPropBlacklist = ['align', 'direction', 'flex', 'justify', 'self', 'wrap']; -const FlexElement = omitProps(...FlexPropBlacklist)(componentFromProp('component')); +const FlexPropBlacklist = [ + 'align', + 'direction', + 'flex', + 'justify', + 'self', + 'wrap', +]; +const FlexElement = omitProps(...FlexPropBlacklist)( + componentFromProp('component') +); const Flex = styled(FlexElement)` - ${({ self }) => (self ? `align-self: ${getFlexStyleKeysFromShorthand(self)};` : null)} - ${({ flex }) => (flex ? `flex: ${flex};` : null)} + ${({ self }) => + self ? `align-self: ${getFlexStyleKeysFromShorthand(self)};` : ''} + ${({ flex }) => (flex ? `flex: ${flex};` : '')} align-items: ${({ align }) => getFlexStyleKeysFromShorthand(align)}; flex-direction: ${({ direction }) => direction}; flex-wrap: ${({ wrap }) => (wrap ? 'wrap' : 'nowrap')}; @@ -26,10 +33,21 @@ Flex.displayName = 'Flex'; Flex.propTypes = { align: PropTypes.oneOf(['baseline', 'center', 'end', 'start', 'stretch']), - component: PropTypes.func, - direction: PropTypes.oneOf(['column', 'column-reverse', 'row', 'row-reverse']), + component: PropTypes.oneOfType([PropTypes.func, PropTypes.object]), + direction: PropTypes.oneOf([ + 'column', + 'column-reverse', + 'row', + 'row-reverse', + ]), flex: PropTypes.number, - justify: PropTypes.oneOf(['center', 'end', 'space-around', 'space-between', 'start']), + justify: PropTypes.oneOf([ + 'center', + 'end', + 'space-around', + 'space-between', + 'start', + ]), self: PropTypes.oneOf(['center', 'end', 'start', 'stretch']), wrap: PropTypes.bool, }; diff --git a/src/components/layout/FlexItem.js b/src/components/layout/FlexItem.js index 2febbc028fd..eb55b28b671 100644 --- a/src/components/layout/FlexItem.js +++ b/src/components/layout/FlexItem.js @@ -4,20 +4,20 @@ import React from 'react'; import { View } from 'react-primitives'; import stylePropType from 'react-style-proptype'; -const FlexItem = ({ - flex, - grow, - shrink, - style, - ...props -}) => ( +const FlexItem = ({ flex, grow, shrink, style, ...props }) => ( <View {...props} - style={[{ - flex: (isUndefined(flex) && isUndefined(grow) && isUndefined(shrink)) ? 1 : flex, - flexGrow: grow, - flexShrink: shrink, - }, style]} + style={[ + { + flex: + isUndefined(flex) && isUndefined(grow) && isUndefined(shrink) + ? 1 + : flex, + flexGrow: grow, + flexShrink: shrink, + }, + style, + ]} /> ); @@ -25,7 +25,7 @@ FlexItem.propTypes = { flex: PropTypes.number, grow: PropTypes.number, shrink: PropTypes.number, - style: stylePropType, + style: PropTypes.oneOfType([PropTypes.arrayOf(stylePropType), stylePropType]), }; export default FlexItem; diff --git a/src/components/layout/KeyboardFixedOpenLayout.js b/src/components/layout/KeyboardFixedOpenLayout.js new file mode 100644 index 00000000000..202e8f45713 --- /dev/null +++ b/src/components/layout/KeyboardFixedOpenLayout.js @@ -0,0 +1,90 @@ +import PropTypes from 'prop-types'; +import React, { useCallback, useEffect, useRef, useState } from 'react'; +import { Keyboard, KeyboardAvoidingView } from 'react-native'; +import { Transition, Transitioning } from 'react-native-reanimated'; +import styled from 'styled-components/primitives'; +import { withKeyboardHeight } from '../../hoc'; +import { padding, position } from '../../styles'; +import { deviceUtils, safeAreaInsetValues } from '../../utils'; +import Centered from './Centered'; +import { setKeyboardHeight as storeKeyboardHeight } from '../../handlers/localstorage/globalSettings'; +import { calculateKeyboardHeight } from '../../helpers/keyboardHeight'; + +const deviceHeight = deviceUtils.dimensions.height; + +const FallbackKeyboardHeight = calculateKeyboardHeight(deviceHeight); + +const containerStyle = { + left: 0, + position: 'absolute', + right: 0, + top: 0, +}; + +const InnerWrapper = styled(Centered)` + ${padding(safeAreaInsetValues.top, 0, 10)}; + ${position.size('100%')}; +`; + +const transition = ( + <Transition.Change durationMs={150} interpolation="easeOut" /> +); + +const KeyboardFixedOpenLayout = ({ + keyboardHeight, + setKeyboardHeight, + ...props +}) => { + const ref = useRef(); + const [didMeasure, setDidMeasure] = useState(false); + const resolvedKeyboardHeight = keyboardHeight || FallbackKeyboardHeight; + + const handleKeyboardWillShow = useCallback( + async ({ endCoordinates: { height } }) => { + if (height !== keyboardHeight) { + const newHeight = Math.floor(height); + setDidMeasure(true); + storeKeyboardHeight(newHeight); + setKeyboardHeight(newHeight); + } + }, + [keyboardHeight, setDidMeasure, setKeyboardHeight] + ); + + useEffect(() => { + let listener = undefined; + + if (!didMeasure) { + listener = Keyboard.addListener( + 'keyboardWillShow', + handleKeyboardWillShow + ); + } + + return () => { + if (listener) { + listener.remove(); + } + }; + }, [didMeasure, handleKeyboardWillShow]); + + return ( + <Transitioning.View + ref={ref} + height={deviceHeight - resolvedKeyboardHeight} + style={containerStyle} + transition={transition} + > + <KeyboardAvoidingView behavior="height" enabled={!keyboardHeight}> + <InnerWrapper {...props} /> + </KeyboardAvoidingView> + </Transitioning.View> + ); +}; + +KeyboardFixedOpenLayout.propTypes = { + keyboardHeight: PropTypes.number, + setKeyboardHeight: PropTypes.func, +}; + +export default withKeyboardHeight(KeyboardFixedOpenLayout); diff --git a/src/components/layout/LayoutWithDividers.js b/src/components/layout/LayoutWithDividers.js index a3400218d3a..5d2ade383ea 100644 --- a/src/components/layout/LayoutWithDividers.js +++ b/src/components/layout/LayoutWithDividers.js @@ -1,10 +1,5 @@ import PropTypes from 'prop-types'; -import React, { - Children, - cloneElement, - createElement, - Fragment, -} from 'react'; +import React, { Children, cloneElement, createElement, Fragment } from 'react'; import Flex from './Flex'; import Divider from '../Divider'; @@ -18,10 +13,9 @@ const LayoutWithDividers = ({ {Children.toArray(children).map((child, index, array) => ( <Fragment key={index}> {cloneElement(child)} - {(index < array.length - 1) + {index < array.length - 1 ? createElement(dividerRenderer, dividerProps) - : null - } + : null} </Fragment> ))} </Flex> diff --git a/src/components/layout/LayoutWithMargins.js b/src/components/layout/LayoutWithMargins.js index 24c243f1f93..1481975f477 100644 --- a/src/components/layout/LayoutWithMargins.js +++ b/src/components/layout/LayoutWithMargins.js @@ -3,20 +3,16 @@ import PropTypes from 'prop-types'; import React, { Children, cloneElement } from 'react'; import Flex from './Flex'; -const LayoutWithMargins = ({ - children, - margin, - marginKey, - ...props -}) => ( +const LayoutWithMargins = ({ children, margin, marginKey, ...props }) => ( <Flex {...props}> - {Children.toArray(children).map((child, index, array) => ( + {Children.toArray(children).map((child, index, array) => cloneElement(child, { style: { ...get(child, 'props.style', {}), - [marginKey]: (index < array.length - 1) ? margin : 0, + [marginKey]: index < array.length - 1 ? margin : 0, }, - })))} + }) + )} </Flex> ); diff --git a/src/components/layout/Page.js b/src/components/layout/Page.js index d6394620f1a..aaf2e631b6e 100644 --- a/src/components/layout/Page.js +++ b/src/components/layout/Page.js @@ -17,12 +17,7 @@ const SafeArea = styled.View` padding-top: ${({ topInset }) => topInset}; `; -const Page = ({ - safeAreaInset, - showBottomInset, - showTopInset, - ...props -}) => ( +const Page = ({ safeAreaInset, showBottomInset, showTopInset, ...props }) => ( <SafeArea {...props} bottomInset={showBottomInset ? safeAreaInset.bottom : 0} diff --git a/src/components/layout/Row.js b/src/components/layout/Row.js index c71003b3519..de8b90af663 100644 --- a/src/components/layout/Row.js +++ b/src/components/layout/Row.js @@ -3,5 +3,5 @@ import Flex from './Flex'; export default compose( setDisplayName('Row'), - withProps({ direction: 'row' }), + withProps({ direction: 'row' }) )(Flex); diff --git a/src/components/layout/RowWithDividers.js b/src/components/layout/RowWithDividers.js index 1f1740fe1ec..9e41dff77f5 100644 --- a/src/components/layout/RowWithDividers.js +++ b/src/components/layout/RowWithDividers.js @@ -9,5 +9,5 @@ export default compose( horizontal: false, ...dividerProps, }, - })), + })) )(LayoutWithDividers); diff --git a/src/components/layout/RowWithMargins.js b/src/components/layout/RowWithMargins.js index 476b5717cf7..957e437e77a 100644 --- a/src/components/layout/RowWithMargins.js +++ b/src/components/layout/RowWithMargins.js @@ -1,9 +1,4 @@ -import { - compose, - defaultProps, - setDisplayName, - withProps, -} from 'recompact'; +import { compose, defaultProps, setDisplayName, withProps } from 'recompact'; import LayoutWithMargins from './LayoutWithMargins'; export default compose( @@ -12,5 +7,5 @@ export default compose( margin: 19, marginKey: 'marginRight', }), - withProps({ direction: 'row' }), + withProps({ direction: 'row' }) )(LayoutWithMargins); diff --git a/src/components/layout/index.js b/src/components/layout/index.js index 8e6ffb4819a..01407a14db7 100644 --- a/src/components/layout/index.js +++ b/src/components/layout/index.js @@ -4,6 +4,7 @@ export { default as ColumnWithDividers } from './ColumnWithDividers'; export { default as ColumnWithMargins } from './ColumnWithMargins'; export { default as Flex } from './Flex'; export { default as FlexItem } from './FlexItem'; +export { default as KeyboardFixedOpenLayout } from './KeyboardFixedOpenLayout'; export { default as LayoutWithDividers } from './LayoutWithDividers'; export { default as LayoutWithMargins } from './LayoutWithMargins'; export { default as Page } from './Page'; diff --git a/src/components/list/List.js b/src/components/list/List.js index 970ac4905f9..bcd70f9bb1e 100644 --- a/src/components/list/List.js +++ b/src/components/list/List.js @@ -10,12 +10,7 @@ const getListItemLayout = (data, index) => ({ offset: ListItem.height * index, }); -const List = ({ - getItemLayout, - items, - renderItem, - ...props -}) => ( +const List = ({ getItemLayout, items, renderItem, ...props }) => ( <FlatList data={items} getItemLayout={getItemLayout} @@ -29,9 +24,11 @@ const List = ({ List.propTypes = { getItemLayout: PropTypes.func.isRequired, - items: PropTypes.arrayOf(PropTypes.shape({ - key: PropTypes.string.isRequired, - })).isRequired, + items: PropTypes.arrayOf( + PropTypes.shape({ + key: PropTypes.string.isRequired, + }) + ).isRequired, renderItem: PropTypes.func.isRequired, }; diff --git a/src/components/list/ListHeader.js b/src/components/list/ListHeader.js index 943428bc680..800cc94aa4b 100644 --- a/src/components/list/ListHeader.js +++ b/src/components/list/ListHeader.js @@ -1,43 +1,61 @@ import PropTypes from 'prop-types'; import React, { createElement, Fragment } from 'react'; +import { View } from 'react-native'; import { pure } from 'recompact'; -import styled from 'styled-components/primitives'; -import { colors, padding } from '../../styles'; +import { colors, padding, position } from '../../styles'; +import LinearGradient from 'react-native-linear-gradient'; import { Row } from '../layout'; import { H1 } from '../text'; import ContextMenu from '../ContextMenu'; import Divider from '../Divider'; +import { deviceUtils } from '../../utils'; -const ListHeaderHeight = 42; +const height = 42; -const Header = styled(Row).attrs({ - align: 'center', - justify: 'space-between', -})` - ${padding(0, 19, 3, 19)} - background-color: ${colors.white}; - height: ${ListHeaderHeight}; - width: 100%; -`; - -const ListHeader = pure(({ - children, - contextMenuOptions, - showDivider, - title, - titleRenderer, -}) => ( - <Fragment> - <Header> - <Row align="center"> - {createElement(titleRenderer, { children: title })} - {contextMenuOptions && (<ContextMenu {...contextMenuOptions} />)} +const ListHeader = pure( + ({ + children, + contextMenuOptions, + isSticky, + showDivider, + title, + titleRenderer, + }) => ( + <Fragment> + <LinearGradient + colors={['#ffffffff', '#ffffff80', '#ffffff00']} + end={{ x: 0, y: 0 }} + pointerEvents="none" + start={{ x: 0, y: 0.5 }} + style={[position.coverAsObject]} + /> + <Row + align="center" + backgroundColor={isSticky ? colors.white : colors.transparent} + css={padding(0, 19, 3, 19)} + height={height} + justify="space-between" + width="100%" + > + <Row align="center"> + {createElement(titleRenderer, { children: title })} + {contextMenuOptions && <ContextMenu {...contextMenuOptions} />} + </Row> + {children} </Row> - {children} - </Header> - {showDivider && <Divider />} - </Fragment> -)); + {showDivider && <Divider />} + {!isSticky && title !== 'Balances' && ( + <View + style={{ + backgroundColor: colors.white, + height: deviceUtils.dimensions.height, + width: deviceUtils.dimensions.width, + }} + /> + )} + </Fragment> + ) +); ListHeader.propTypes = { children: PropTypes.node, @@ -52,6 +70,6 @@ ListHeader.defaultProps = { titleRenderer: H1, }; -ListHeader.height = ListHeaderHeight; +ListHeader.height = height; export default ListHeader; diff --git a/src/components/list/ListItem.js b/src/components/list/ListItem.js index 1d4b0bc6b54..29f7aa1ac62 100644 --- a/src/components/list/ListItem.js +++ b/src/components/list/ListItem.js @@ -5,21 +5,17 @@ import { compose, onlyUpdateForKeys, withHandlers } from 'recompact'; import { fonts, padding, position } from '../../styles'; import { ButtonPressAnimation } from '../animations'; import { Icon } from '../icons'; -import { - Centered, - FlexItem, - Row, - RowWithMargins, -} from '../layout'; +import { Centered, FlexItem, Row, RowWithMargins } from '../layout'; import { TruncatedText } from '../text'; const ListItemHeight = 54; -const renderIcon = icon => ( - isString(icon) - ? <Icon name={icon} style={position.sizeAsObject('100%')} /> - : icon -); +const renderIcon = icon => + isString(icon) ? ( + <Icon name={icon} style={position.sizeAsObject('100%')} /> + ) : ( + icon + ); const propTypes = { activeOpacity: PropTypes.number, @@ -38,49 +34,43 @@ const enhance = compose( onPress(value); } }, - }), + }) ); -const ListItem = enhance(({ - activeOpacity, - children, - icon, - iconMargin, - label, - onPress, - ...props -}) => ( - <ButtonPressAnimation - activeOpacity={activeOpacity} - enableHapticFeedback={false} - onPress={onPress} - scaleTo={1} - > - <Row - align="center" - css={padding(0, 16, 2)} - height={ListItemHeight} - justify="space-between" - {...props} +const ListItem = enhance( + ({ activeOpacity, children, icon, iconMargin, label, onPress, ...props }) => ( + <ButtonPressAnimation + activeOpacity={activeOpacity} + enableHapticFeedback={false} + onPress={onPress} + scaleTo={0.99} > - <RowWithMargins align="center" flex={1} margin={iconMargin}> - {icon && <Centered>{renderIcon(icon)}</Centered>} - <TruncatedText - flex={1} - paddingRight={fonts.size.bmedium} - size="bmedium" - > - {label} - </TruncatedText> - </RowWithMargins> - {children && ( - <Centered component={FlexItem} shrink={0}> - {children} - </Centered> - )} - </Row> - </ButtonPressAnimation> -)); + <Row + align="center" + css={padding(0, 16, 2)} + height={ListItemHeight} + justify="space-between" + {...props} + > + <RowWithMargins align="center" flex={1} margin={iconMargin}> + {icon && <Centered>{renderIcon(icon)}</Centered>} + <TruncatedText + flex={1} + paddingRight={fonts.size.bmedium} + size="bmedium" + > + {label} + </TruncatedText> + </RowWithMargins> + {children && ( + <Centered component={FlexItem} shrink={0}> + {children} + </Centered> + )} + </Row> + </ButtonPressAnimation> + ) +); ListItem.propTypes = propTypes; diff --git a/src/components/list/ListItemArrowGroup.js b/src/components/list/ListItemArrowGroup.js index 79a8182d816..0bef62d4be6 100644 --- a/src/components/list/ListItemArrowGroup.js +++ b/src/components/list/ListItemArrowGroup.js @@ -14,15 +14,14 @@ const ListItemArrowGroup = ({ children }) => ( margin={6} opacity={0.6} > - {typeof children === 'string' - ? <Text color="blueGreyDark" size="bmedium">{children}</Text> - : children - } - <Icon - color={colors.blueGreyDark} - name="caretThin" - style={{ width: 11 }} - /> + {typeof children === 'string' ? ( + <Text color="blueGreyDark" size="bmedium"> + {children} + </Text> + ) : ( + children + )} + <Icon color={colors.blueGreyDark} name="caretThin" style={{ width: 11 }} /> </RowWithMargins> ); diff --git a/src/components/modal/LoadingOverlay.js b/src/components/modal/LoadingOverlay.js index aacaf4dd933..7569a21c87c 100644 --- a/src/components/modal/LoadingOverlay.js +++ b/src/components/modal/LoadingOverlay.js @@ -1,19 +1,18 @@ import { BlurView } from '@react-native-community/blur'; import PropTypes from 'prop-types'; import React from 'react'; -import { pure } from 'recompact'; import styled from 'styled-components/primitives'; -import { colors, padding } from '../../styles'; +import { colors, padding, position } from '../../styles'; import ActivityIndicator from '../ActivityIndicator'; -import { FadeInAnimation } from '../animations'; import { Centered } from '../layout'; import { Text } from '../text'; import TouchableBackdrop from '../TouchableBackdrop'; const Overlay = styled(Centered)` - ${padding(19, 19, 22)} + ${padding(19, 19, 22)}; background-color: ${colors.alpha(colors.blueGreyDark, 0.15)}; border-radius: 20; + overflow: hidden; `; const Title = styled(Text).attrs({ @@ -25,30 +24,31 @@ const Title = styled(Text).attrs({ margin-left: 8; `; -const LoadingOverlay = ({ title }) => ( - <Centered - activeOpacity={1} - component={TouchableBackdrop} - disabled={true} +const LoadingOverlay = ({ title, ...props }) => ( + <TouchableBackdrop + {...props} + {...position.sizeAsObject('100%')} + disabled zIndex={999} > - <FadeInAnimation - isInteraction - > - <Overlay + <Overlay> + <Centered zIndex={2}> + <ActivityIndicator /> + {title && <Title>{title}} + + - - {title && ({title})} - - - + zIndex={1} + /> + + ); LoadingOverlay.propTypes = { title: PropTypes.string, }; -export default pure(LoadingOverlay); +const neverRerender = () => true; +export default React.memo(LoadingOverlay, neverRerender); diff --git a/src/components/modal/Modal.js b/src/components/modal/Modal.js index a26a8130b4d..1bd4bea0751 100644 --- a/src/components/modal/Modal.js +++ b/src/components/modal/Modal.js @@ -2,25 +2,16 @@ import PropTypes from 'prop-types'; import React from 'react'; import { StatusBar } from 'react-native'; import styled from 'styled-components'; -import { colors, padding } from '../../styles'; +import { colors } from '../../styles'; import { deviceUtils } from '../../utils'; import { Centered, Column } from '../layout'; import TouchableBackdrop from '../TouchableBackdrop'; -const Container = styled(Centered)` - ${padding(15)}; - height: 100%; -`; - const ModalElement = styled(Column)` background-color: ${colors.white}; - border-radius: 12; + border-radius: ${({ radius }) => radius || 12}; flex-shrink: 0; height: ${({ height }) => height}; - shadow-color: ${colors.dark}; - shadow-offset: 0px 10px; - shadow-opacity: 0.6; - shadow-radius: 50; width: 100%; `; @@ -28,26 +19,32 @@ const Modal = ({ height, onCloseModal, statusBarStyle, + containerPadding, ...props }) => ( - + - - + + ); Modal.propTypes = { - height: PropTypes.number.isRequired, - onCloseModal: PropTypes.func.isRequired, + containerPadding: PropTypes.number.isRequired, + height: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, + onCloseModal: PropTypes.func, statusBarStyle: PropTypes.oneOf(['default', 'light-content', 'dark-content']), }; Modal.defaultProps = { + containerPadding: 15, height: deviceUtils.dimensions.height - 230, + onCloseModal: () => null, statusBarStyle: 'light-content', }; diff --git a/src/components/modal/ModalFooterButton.js b/src/components/modal/ModalFooterButton.js index 59861d2495c..ac3c69f4d79 100644 --- a/src/components/modal/ModalFooterButton.js +++ b/src/components/modal/ModalFooterButton.js @@ -27,16 +27,9 @@ const IconContainer = styled(Centered)` const ModalFooterButton = ({ icon, label, onPress }) => ( - + - + {label} diff --git a/src/components/modal/ModalFooterButtonsRow.js b/src/components/modal/ModalFooterButtonsRow.js index f69bdc80026..19425cfed31 100644 --- a/src/components/modal/ModalFooterButtonsRow.js +++ b/src/components/modal/ModalFooterButtonsRow.js @@ -15,7 +15,7 @@ const ModalFooterButtonsRow = ({ children, ...props }) => ( {Children.map(children, (child, index) => ( {child} - {(index < children.length - 1) && } + {index < children.length - 1 && } ))} diff --git a/src/components/modal/ModalHeader.js b/src/components/modal/ModalHeader.js index b9ec2576c80..8b0ab077b8b 100644 --- a/src/components/modal/ModalHeader.js +++ b/src/components/modal/ModalHeader.js @@ -6,7 +6,7 @@ import { Centered, Row } from '../layout'; import { TruncatedText } from '../text'; import ModalHeaderButton from './ModalHeaderButton'; -const ModalHeaderHeight = 50; +export const ModalHeaderHeight = 50; const Container = styled(Row).attrs({ align: 'center', @@ -22,13 +22,14 @@ const Container = styled(Row).attrs({ const TitleContainer = styled(Centered)` ${position.cover}; - zIndex: 0; + z-index: 0; `; const ModalHeader = ({ onPressBack, onPressClose, showBackButton, + showDoneButton, title, ...props }) => ( @@ -43,19 +44,19 @@ const ModalHeader = ({ )} {title} - + {showDoneButton && ( + + )} ); @@ -63,9 +64,14 @@ ModalHeader.propTypes = { onPressBack: PropTypes.func, onPressClose: PropTypes.func, showBackButton: PropTypes.bool, + showDoneButton: PropTypes.bool, title: PropTypes.string, }; +ModalHeader.defaultProps = { + showDoneButton: true, +}; + ModalHeader.height = ModalHeaderHeight; export default ModalHeader; diff --git a/src/components/modal/ModalHeaderButton.js b/src/components/modal/ModalHeaderButton.js index 2366c12eb71..4bf32385240 100644 --- a/src/components/modal/ModalHeaderButton.js +++ b/src/components/modal/ModalHeaderButton.js @@ -26,15 +26,10 @@ const Text = styled(UnstyledText).attrs({ margin-left: ${({ showBackArrow }) => (showBackArrow ? 4 : 0)}; `; -const ModalHeaderButton = ({ - label, - showBackArrow, - side, - ...props -}) => ( +const ModalHeaderButton = ({ label, showBackArrow, side, ...props }) => ( @@ -46,9 +41,7 @@ const ModalHeaderButton = ({ name="caret" /> )} - - {label} - + {label} ); diff --git a/src/components/pager/AnimatedPager.js b/src/components/pager/AnimatedPager.js index d0610dbfa9c..f274ab9b27b 100644 --- a/src/components/pager/AnimatedPager.js +++ b/src/components/pager/AnimatedPager.js @@ -24,36 +24,36 @@ export default class AnimatedPager extends Component { children: PropTypes.node, isOpen: PropTypes.bool.isRequired, width: PropTypes.number, - } + }; static defaultProps = { width: deviceUtils.dimensions.width - 31, - } - - translateValues = { - page1: new Animated.Value(0), - page2: new Animated.Value(this.props.width), - } + }; - componentDidUpdate = () => this.onAnimatePages(this.props.isOpen) + componentDidUpdate = () => this.onAnimatePages(this.props.isOpen); componentWillUnmount() { this.translateValues.page1.stopAnimation(); this.translateValues.page2.stopAnimation(); } - onAnimatePages = (isOpen) => { + translateValues = { + page1: new Animated.Value(0), + page2: new Animated.Value(this.props.width), + }; + + onAnimatePages = isOpen => { const { width } = this.props; const { page1, page2 } = this.translateValues; - const page1TargetValue = isOpen ? (width * -1) : 0; + const page1TargetValue = isOpen ? width * -1 : 0; const page2TargetValue = isOpen ? 0 : width; return Animated.parallel([ Animated.timing(page1, buildPagerAnimation(page1TargetValue)).start(), Animated.timing(page2, buildPagerAnimation(page2TargetValue)).start(), ]); - } + }; render = () => { const { children, ...props } = this.props; @@ -69,5 +69,5 @@ export default class AnimatedPager extends Component { ); - } + }; } diff --git a/src/components/pager/AnimatedPagerItem.js b/src/components/pager/AnimatedPagerItem.js index 4f01c3afa5d..e3e1c229e47 100644 --- a/src/components/pager/AnimatedPagerItem.js +++ b/src/components/pager/AnimatedPagerItem.js @@ -16,9 +16,7 @@ const AnimatedPagerItem = ({ children, translateX, ...props }) => ( {...props} style={[styles.item, { transform: [{ translateX }] }]} > - - {children} - + {children} ); diff --git a/src/components/pager/Pager.js b/src/components/pager/Pager.js index e0232e3ea94..e7c6fa8dd13 100644 --- a/src/components/pager/Pager.js +++ b/src/components/pager/Pager.js @@ -24,14 +24,13 @@ const getItemLayout = (data, index) => { }; }; -const keyExtractor = ({ name }, index) => (`${name}_${index}`); +const keyExtractor = ({ name }, index) => `${name}_${index}`; const renderItem = props => ; const Pager = ({ controlsProps, currentIndex, - dimensions, onScroll, onScrollEndDrag, pages, @@ -86,7 +85,9 @@ export default compose( scrollEnabled: pages.length > 1, })), withHandlers({ - onScroll: ({ currentIndex, dimensions, setCurrentIndex }) => ({ nativeEvent }) => { + onScroll: ({ currentIndex, dimensions, setCurrentIndex }) => ({ + nativeEvent, + }) => { const currentOffsetX = get(nativeEvent, 'contentOffset.x', 0); const startOffsetX = currentIndex * dimensions.width; @@ -112,5 +113,5 @@ export default compose( return setCurrentIndex(currentScreenIndex < 0 ? 0 : currentScreenIndex); }, }), - onlyUpdateForKeys(['currentIndex']), + onlyUpdateForKeys(['currentIndex']) )(Pager); diff --git a/src/components/pager/PagerControls.js b/src/components/pager/PagerControls.js index ee6cfd53af2..922a8d373b6 100644 --- a/src/components/pager/PagerControls.js +++ b/src/components/pager/PagerControls.js @@ -18,27 +18,23 @@ const Container = styled(Centered)` const enhance = onlyUpdateForKeys(['selectedIndex']); -const PagerControls = enhance(({ - color, - length, - selectedIndex, - size, - ...props -}) => ( - - {times(length, index => ( - - ))} - -)); +const PagerControls = enhance( + ({ color, length, selectedIndex, size, ...props }) => ( + + {times(length, index => ( + + ))} + + ) +); PagerControls.propTypes = { color: PropTypes.string, diff --git a/src/components/pager/PagerItem.js b/src/components/pager/PagerItem.js index 60a70e657bf..18ab1227d09 100644 --- a/src/components/pager/PagerItem.js +++ b/src/components/pager/PagerItem.js @@ -11,9 +11,7 @@ export const pagerPagePropType = PropTypes.shape({ }); const PagerItem = ({ item: { component, dimensions } }) => ( - - {cloneElement(component, { dimensions })} - + {cloneElement(component, { dimensions })} ); PagerItem.propTypes = { diff --git a/src/components/profile/ProfileAction.js b/src/components/profile/ProfileAction.js index ac357b5f04e..674058429ef 100644 --- a/src/components/profile/ProfileAction.js +++ b/src/components/profile/ProfileAction.js @@ -16,13 +16,7 @@ const Container = styled(RowWithMargins).attrs({ background-color: ${colors.white}; `; -const ProfileAction = ({ - icon, - iconSize, - onPress, - text, - ...props -}) => ( +const ProfileAction = ({ icon, iconSize, onPress, text, ...props }) => ( - + {text} diff --git a/src/components/profile/ProfileMasthead.js b/src/components/profile/ProfileMasthead.js index cd332bed18f..e077dd74374 100644 --- a/src/components/profile/ProfileMasthead.js +++ b/src/components/profile/ProfileMasthead.js @@ -2,12 +2,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import { Clipboard } from 'react-native'; import FastImage from 'react-native-fast-image'; -import { - compose, - onlyUpdateForKeys, - withHandlers, - withState, -} from 'recompact'; +import { compose, onlyUpdateForKeys, withHandlers, withState } from 'recompact'; import styled from 'styled-components/primitives'; import AvatarImageSource from '../../assets/avatar.png'; import { borders, margin } from '../../styles'; @@ -33,7 +28,6 @@ const AddressAbbreviation = styled(TruncatedAddress).attrs({ const Container = styled(Centered).attrs({ direction: 'column' })` margin-bottom: 24; padding-bottom: 32; - padding-top: 3; `; const ProfileMasthead = ({ @@ -60,7 +54,7 @@ const ProfileMasthead = ({ icon="copy" onPress={onPressCopy} scaleTo={0.82} - text="Copy" + text="Copy Address" /> - {showBottomDivider && } + {showBottomDivider && ( + + )} ); @@ -99,7 +95,8 @@ export default compose( setEmojiCount(emojiCount + 1); Clipboard.setString(accountAddress); }, - onPressReceive: ({ navigation }) => () => navigation.navigate('ReceiveModal'), + onPressReceive: ({ navigation }) => () => + navigation.navigate('ReceiveModal'), }), - onlyUpdateForKeys(['accountAddress', 'emojiCount', 'showBottomDivider']), + onlyUpdateForKeys(['accountAddress', 'emojiCount', 'showBottomDivider']) )(ProfileMasthead); diff --git a/src/components/qrcode-scanner/QRCodeScanner.js b/src/components/qrcode-scanner/QRCodeScanner.js index 59b46bdb663..bd126c2dbb0 100644 --- a/src/components/qrcode-scanner/QRCodeScanner.js +++ b/src/components/qrcode-scanner/QRCodeScanner.js @@ -1,88 +1,115 @@ import PropTypes from 'prop-types'; -import React, { PureComponent } from 'react'; -import DeviceInfo from 'react-native-device-info'; +import React, { useEffect, useRef, useState } from 'react'; import FastImage from 'react-native-fast-image'; -import stylePropType from 'react-style-proptype'; -import styled from 'styled-components/primitives'; +import { Transition, Transitioning } from 'react-native-reanimated'; import SimulatorFakeCameraImageSource from '../../assets/simulator-fake-camera-image.jpg'; +import { usePrevious } from '../../hooks'; import { colors, position } from '../../styles'; +import { isNewValueForObjectPaths } from '../../utils'; import { Centered } from '../layout'; import { ErrorText } from '../text'; import QRCodeScannerCamera from './QRCodeScannerCamera'; import QRCodeScannerCrosshair from './QRCodeScannerCrosshair'; -const Container = styled(Centered).attrs({ direction: 'column' })` - ${position.cover}; - background-color: ${colors.black}; -`; +const transition = ( + +); -export default class QRCodeScanner extends PureComponent { - static propTypes = { - contentStyles: stylePropType, - enableCamera: PropTypes.bool, - enableScanning: PropTypes.bool, - isCameraAuthorized: PropTypes.bool, - onCameraReady: PropTypes.func, - onSuccess: PropTypes.func, - showCrosshairText: PropTypes.bool, - } - - state = { - error: null, - isInitialized: false, - } - - handleCameraReady = () => this.setState({ isInitialized: true }) +const QRCodeScanner = ({ + contentPositionBottom, + contentPositionTop, + enableCamera, + enableScanning, + isCameraAuthorized, + isEmulator, + onSuccess, + showCrosshairText, +}) => { + const ref = useRef(); + const [error, setError] = useState(null); + const [isInitialized, setInitialized] = useState(false); - handleMountError = () => this.setState({ error: 'mounting' }) - - renderCamera = () => { - if (DeviceInfo.isEmulator()) { - return ( - - ); + const prevContentPositionBottom = usePrevious(contentPositionBottom); + useEffect(() => { + if (ref.current && contentPositionBottom !== prevContentPositionBottom) { + ref.current.animateNextTransition(); } + }, [contentPositionBottom, prevContentPositionBottom]); - return this.props.enableCamera ? ( + let cameraRenderer = null; + if (isEmulator) { + cameraRenderer = ( + + ); + } else if (enableCamera) { + cameraRenderer = ( setInitialized(true)} + onMountError={() => setError('mounting')} + onSuccess={onSuccess} /> - ) : null; + ); } - render = () => { - const { contentStyles, isCameraAuthorized, showCrosshairText } = this.props; - const { error, isInitialized } = this.state; + const showErrorMessage = error && !isInitialized; + const showCrosshair = !error && !showErrorMessage; - const showErrorMessage = error && !isInitialized; - const showCrosshair = !error && !showErrorMessage; - - return ( - - {this.renderCamera()} - {isCameraAuthorized && ( - + return ( + + {cameraRenderer} + {isCameraAuthorized && ( + + {showErrorMessage && ( - + )} {showCrosshair && ( )} - )} - - ); - } -} + + )} + + ); +}; + +QRCodeScanner.propTypes = { + contentPositionBottom: PropTypes.node, + contentPositionTop: PropTypes.node, + enableCamera: PropTypes.bool, + enableScanning: PropTypes.bool, + isCameraAuthorized: PropTypes.bool, + isEmulator: PropTypes.bool, + onSuccess: PropTypes.func, + showCrosshairText: PropTypes.bool, +}; + +const arePropsEqual = (prev, next) => + !isNewValueForObjectPaths(prev, next, [ + 'contentPositionBottom', + 'enableCamera', + 'enableScanning', + 'isCameraAuthorized', + 'showCrosshairText', + ]); + +export default React.memo(QRCodeScanner, arePropsEqual); diff --git a/src/components/qrcode-scanner/QRCodeScannerCamera.js b/src/components/qrcode-scanner/QRCodeScannerCamera.js index 2630524cbab..a9a8ea096d7 100644 --- a/src/components/qrcode-scanner/QRCodeScannerCamera.js +++ b/src/components/qrcode-scanner/QRCodeScannerCamera.js @@ -4,7 +4,6 @@ import PropTypes from 'prop-types'; import React, { PureComponent } from 'react'; import { InteractionManager, StyleSheet } from 'react-native'; import ReactNativeQRCodeScanner from 'react-native-qrcode-scanner'; -import stylePropType from 'react-style-proptype'; import { position } from '../../styles'; import { deviceUtils } from '../../utils'; import QRCodeScannerNeedsAuthorization from './QRCodeScannerNeedsAuthorization'; @@ -22,22 +21,20 @@ const styles = StyleSheet.create({ class QRCodeScannerCamera extends PureComponent { static propTypes = { - contentStyles: stylePropType, enableScanning: PropTypes.bool, onCameraReady: PropTypes.func, onMountError: PropTypes.func, onSuccess: PropTypes.func, - scannerRef: PropTypes.func, setSafeTimeout: PropTypes.func, - } + }; state = { showAuthorizationView: false, - } + }; componentDidMount = () => { this.props.setSafeTimeout(this.handleShowAuthorizationView, 500); - } + }; componentDidUpdate = () => { const { enableScanning } = this.props; @@ -45,7 +42,8 @@ class QRCodeScannerCamera extends PureComponent { if (!this.scannerRef) return; InteractionManager.runAfterInteractions(() => { - const isScannerEnabled = this.scannerRef && !this.scannerRef.state.disablingByUser; + const isScannerEnabled = + this.scannerRef && !this.scannerRef.state.disablingByUser; if (enableScanning && !isScannerEnabled) { this.handleEnableScanner(); @@ -53,31 +51,33 @@ class QRCodeScannerCamera extends PureComponent { this.handleDisableScanner(); } }); - } + }; handleDisableScanner = () => { if (this.scannerRef && isFunction(this.scannerRef.disable)) { console.log('πŸ“ πŸš« Disabling QR Code Scanner'); this.scannerRef.disable(); } - } + }; handleEnableScanner = () => { if (this.scannerRef && isFunction(this.scannerRef.enable)) { console.log('πŸ“ βœ… Enabling QR Code Scanner'); this.scannerRef.enable(); } - } + }; - handleScannerRef = (ref) => { this.scannerRef = ref; } + handleScannerRef = ref => { + this.scannerRef = ref; + }; - handleShowAuthorizationView = () => this.setState({ showAuthorizationView: true }) + handleShowAuthorizationView = () => + this.setState({ showAuthorizationView: true }); - renderAuthorizationView = () => ( - this.state.showAuthorizationView - ? - : null - ) + renderAuthorizationView = () => + this.state.showAuthorizationView ? ( + + ) : null; render = () => ( - ) + ); } export default withSafeTimeout(QRCodeScannerCamera); diff --git a/src/components/qrcode-scanner/QRCodeScannerCrosshair.js b/src/components/qrcode-scanner/QRCodeScannerCrosshair.js index d2469ca46d6..26e64010103 100644 --- a/src/components/qrcode-scanner/QRCodeScannerCrosshair.js +++ b/src/components/qrcode-scanner/QRCodeScannerCrosshair.js @@ -15,10 +15,7 @@ const Container = styled(Centered)` const QRCodeScannerCrosshair = ({ showText, text }) => ( - + {showText ? ( ( `} justify="center" > - - - In order to use WalletConnect, you must first give Rainbow - permission to access your camera. + + + In order to use WalletConnect, you must first give Rainbow permission to + access your camera. diff --git a/src/components/send/index.js b/src/components/send/index.js index 8e3fcf91a0d..89c34394065 100644 --- a/src/components/send/index.js +++ b/src/components/send/index.js @@ -1,7 +1,10 @@ export { default as SendAssetForm } from './SendAssetForm'; +export { default as SendAssetFormCollectible } from './SendAssetFormCollectible'; +export { default as SendAssetFormField } from './SendAssetFormField'; +export { default as SendAssetFormToken } from './SendAssetFormToken'; export { default as SendAssetList } from './SendAssetList'; export { default as SendButton } from './SendButton'; +export { default as SendContactList } from './SendContactList'; export { default as SendEmptyState } from './SendEmptyState'; export { default as SendHeader } from './SendHeader'; export { default as SendTransactionSpeed } from './SendTransactionSpeed'; -export { default as SendAssetFormField } from './SendAssetFormField'; diff --git a/src/components/settings-menu/BackupSection.js b/src/components/settings-menu/BackupSection.js index 02d68eccb7d..3ca6f5f8b75 100644 --- a/src/components/settings-menu/BackupSection.js +++ b/src/components/settings-menu/BackupSection.js @@ -6,12 +6,7 @@ import { compose, withHandlers, withState } from 'recompact'; import styled from 'styled-components'; import SeedPhraseImageSource from '../../assets/seed-phrase-icon.png'; import { loadSeedPhrase as loadSeedPhraseFromKeychain } from '../../model/wallet'; -import { - colors, - padding, - position, - shadow, -} from '../../styles'; +import { colors, padding, position, shadow } from '../../styles'; import { Button } from '../buttons'; import { Centered, Column } from '../layout'; import { Br, Monospace, Text } from '../text'; @@ -21,7 +16,7 @@ const Content = styled(Centered)` margin-bottom: 34; margin-top: 6; max-width: 265; - padding-top: ${({ seedPhrase }) => (seedPhrase ? 34 : 0)} + padding-top: ${({ seedPhrase }) => (seedPhrase ? 34 : 0)}; `; const ToggleSeedPhraseButton = styled(Button)` @@ -30,64 +25,48 @@ const ToggleSeedPhraseButton = styled(Button)` width: 235; `; -const BackupSection = ({ - hideSeedPhrase, - navigation, - seedPhrase, - toggleSeedPhrase, -}) => ( +const BackupSection = ({ navigation, seedPhrase, toggleSeedPhrase }) => ( - + Your Private Key - {seedPhrase - ? ( - - - {seedPhrase} - - - ) : ( - + - If you lose access to your device, the only way to restore your - funds is with your private key. -
-
- Please store it in a safe place. -
- ) - } + {seedPhrase} +
+ + ) : ( + + If you lose access to your device, the only way to restore your funds + is with your private key. +
+
+ Please store it in a safe place. +
+ )} - {seedPhrase ? 'Hide' : 'Show'} Seed Phrase + {seedPhrase ? 'Hide' : 'Show'} Private Key ); BackupSection.propTypes = { - hideSeedPhrase: PropTypes.func.isRequired, navigation: PropTypes.object, seedPhrase: PropTypes.string, toggleSeedPhrase: PropTypes.func.isRequired, @@ -95,12 +74,14 @@ BackupSection.propTypes = { export default compose( withState('seedPhrase', 'setSeedPhrase', null), - withHandlers({ hideSeedPhrase: ({ setSeedPhrase }) => () => setSeedPhrase(null) }), + withHandlers({ + hideSeedPhrase: ({ setSeedPhrase }) => () => setSeedPhrase(null), + }), withHandlers({ toggleSeedPhrase: ({ hideSeedPhrase, seedPhrase, setSeedPhrase }) => () => { if (!seedPhrase) { loadSeedPhraseFromKeychain() - .then((keychainValue) => { + .then(keychainValue => { setSeedPhrase(keychainValue); analytics.track('Viewed backup seed phrase text'); }) @@ -109,5 +90,5 @@ export default compose( hideSeedPhrase(); } }, - }), + }) )(BackupSection); diff --git a/src/components/settings-menu/CurrencySection.js b/src/components/settings-menu/CurrencySection.js index 9629c7f1fdb..ecc9d7a1b98 100644 --- a/src/components/settings-menu/CurrencySection.js +++ b/src/components/settings-menu/CurrencySection.js @@ -9,32 +9,23 @@ import { RadioList, RadioListItem } from '../radio-list'; import supportedNativeCurrencies from '../../references/native-currencies.json'; import { Emoji } from '../text'; -const currencyListItems = Object.values(supportedNativeCurrencies).map(({ currency, ...item }) => ({ - ...item, - currency, - key: currency, - value: currency, -})); +const currencyListItems = Object.values(supportedNativeCurrencies).map( + ({ currency, ...item }) => ({ + ...item, + currency, + key: currency, + value: currency, + }) +); const renderCurrencyIcon = (currency, emojiName) => { if (!currency) return null; if (!isNil(emojiName)) return ; - return ( - - ); + return ; }; -const CurrencyListItem = ({ - currency, - emojiName, - label, - ...item -}) => ( +const CurrencyListItem = ({ currency, emojiName, label, ...item }) => ( (currency) => { + onSelectCurrency: ({ settingsChangeNativeCurrency }) => currency => { settingsChangeNativeCurrency(currency); analytics.track('Changed native currency', { currency }); }, }), - onlyUpdateForKeys(['nativeCurrency']), + onlyUpdateForKeys(['nativeCurrency']) )(CurrencySection); diff --git a/src/components/settings-menu/LanguageSection.js b/src/components/settings-menu/LanguageSection.js index c3ac4a24623..121a9199b07 100644 --- a/src/components/settings-menu/LanguageSection.js +++ b/src/components/settings-menu/LanguageSection.js @@ -9,7 +9,9 @@ import { RadioList, RadioListItem } from '../radio-list'; // Only show languages that have 'wallet' translations available. const hasWalletTranslations = language => get(language, 'translation.wallet'); -const languagesWithWalletTranslations = keys(pickBy(resources, hasWalletTranslations)); +const languagesWithWalletTranslations = keys( + pickBy(resources, hasWalletTranslations) +); const languageListItems = languagesWithWalletTranslations.map(code => ({ code, @@ -18,13 +20,8 @@ const languageListItems = languagesWithWalletTranslations.map(code => ({ value: code, })); -// eslint-disable-next-line react/prop-types const renderLanguageListItem = ({ code, language, ...item }) => ( - + ); const LanguageSection = ({ language, onSelectLanguage }) => ( @@ -45,10 +42,10 @@ LanguageSection.propTypes = { export default compose( withAccountSettings, withHandlers({ - onSelectLanguage: ({ settingsChangeLanguage }) => (language) => { + onSelectLanguage: ({ settingsChangeLanguage }) => language => { settingsChangeLanguage(language); analytics.track('Changed language', { language }); }, }), - onlyUpdateForKeys(['language']), + onlyUpdateForKeys(['language']) )(LanguageSection); diff --git a/src/components/settings-menu/SettingsSection.js b/src/components/settings-menu/SettingsSection.js index 23fda7a9b1f..ef1a0927265 100644 --- a/src/components/settings-menu/SettingsSection.js +++ b/src/components/settings-menu/SettingsSection.js @@ -1,7 +1,8 @@ +import { upperFirst } from 'lodash'; import PropTypes from 'prop-types'; import React from 'react'; import { InteractionManager, Linking, ScrollView } from 'react-native'; -import DeviceInfo from 'react-native-device-info'; +import { isEmulatorSync } from 'react-native-device-info'; import FastImage from 'react-native-fast-image'; import * as StoreReview from 'react-native-store-review'; import { compose, onlyUpdateForKeys, withHandlers } from 'recompact'; @@ -12,15 +13,14 @@ import LanguageIcon from '../../assets/language-icon.png'; import NetworkIcon from '../../assets/network-icon.png'; // import SecurityIcon from '../../assets/security-icon.png'; import { - getAppStoreReviewRequestCount, - setAppStoreReviewRequestCount, -} from '../../handlers/commonStorage'; + getAppStoreReviewCount, + saveAppStoreReviewCount, +} from '../../handlers/localstorage/globalSettings'; import { withAccountSettings, withSendFeedback } from '../../hoc'; import { supportedLanguages } from '../../languages'; -import { colors, position } from '../../styles'; +import { position } from '../../styles'; import AppVersionStamp from '../AppVersionStamp'; -import { Icon } from '../icons'; -import { Centered, Column, ColumnWithDividers } from '../layout'; +import { Column, ColumnWithDividers } from '../layout'; import { ListFooter, ListItem, @@ -30,7 +30,8 @@ import { import { Emoji } from '../text'; const SettingsExternalURLs = { - review: 'itms-apps://itunes.apple.com/us/app/appName/id1457119021?mt=8&action=write-review', + review: + 'itms-apps://itunes.apple.com/us/app/appName/id1457119021?mt=8&action=write-review', twitterDeepLink: 'twitter://user?screen_name=rainbowdotme', twitterWebUrl: 'https://twitter.com/rainbowdotme', }; @@ -55,8 +56,6 @@ const SettingsSection = ({ onPressReview, onPressTwitter, onSendFeedback, - // onPressSecurity, - ...props }) => ( - - {network || ''} - + {upperFirst(network) || ''} } onPress={onPressCurrency} label="Currency" > - - {nativeCurrency || ''} - + {nativeCurrency || ''} } @@ -127,7 +122,7 @@ const SettingsSection = ({ } - label="Import Wallet" + label="Replace Wallet" onPress={onPressImportSeedPhrase} /> - + @@ -184,25 +174,26 @@ export default compose( withHandlers({ onPressReview: ({ onCloseModal }) => async () => { const maxRequestCount = 2; - const count = await getAppStoreReviewRequestCount(); - const shouldDeeplinkToAppStore = (count >= maxRequestCount) || !StoreReview.isAvailable; + const count = await getAppStoreReviewCount(); + const shouldDeeplinkToAppStore = + count >= maxRequestCount || !StoreReview.isAvailable; - if (shouldDeeplinkToAppStore && !DeviceInfo.isEmulator()) { + if (shouldDeeplinkToAppStore && !isEmulatorSync()) { Linking.openURL(SettingsExternalURLs.review); } else { onCloseModal(); InteractionManager.runAfterInteractions(StoreReview.requestReview); } - return setAppStoreReviewRequestCount(count + 1); + return saveAppStoreReviewCount(count + 1); }, onPressTwitter: () => async () => { - Linking.canOpenURL(SettingsExternalURLs.twitterDeepLink).then((supported) => ( + Linking.canOpenURL(SettingsExternalURLs.twitterDeepLink).then(supported => supported ? Linking.openURL(SettingsExternalURLs.twitterDeepLink) : Linking.openURL(SettingsExternalURLs.twitterWebUrl) - )); + ); }, }), - onlyUpdateForKeys(['language', 'nativeCurrency']), + onlyUpdateForKeys(['language', 'nativeCurrency']) )(SettingsSection); diff --git a/src/components/shadow-stack/ShadowStack.js b/src/components/shadow-stack/ShadowStack.js index 8f95c2a7cc7..08532a045ab 100644 --- a/src/components/shadow-stack/ShadowStack.js +++ b/src/components/shadow-stack/ShadowStack.js @@ -8,18 +8,16 @@ import ShadowItem from './ShadowItem'; const ChildrenWrapper = styled.View` ${position.cover}; - background-color: ${({ backgroundColor }) => backgroundColor || colors.transparent}; + background-color: ${colors.transparent}; border-radius: ${({ borderRadius }) => borderRadius}; overflow: hidden; - justify-content: center; - align-items: center; `; const ShadowStackContainer = styled.View` - background-color: ${({ backgroundColor }) => backgroundColor || colors.transparent}; + ${({ height }) => (height ? `height: ${height};` : '')} + ${({ width }) => (width ? `width: ${width};` : '')} + background-color: ${colors.transparent}; border-radius: ${({ borderRadius }) => borderRadius}; - height: ${({ height }) => height}; - width: ${({ width }) => width}; z-index: 1; `; @@ -27,18 +25,20 @@ const ShadowItemPropBlacklist = ['children', 'shadowProps', 'shadows', 'style']; export default class ShadowStack extends PureComponent { static propTypes = { - borderRadius: PropTypes.number.isRequired, + borderRadius: PropTypes.number, children: PropTypes.node, - height: PropTypes.number.isRequired, + childrenWrapperStyle: stylePropType, + height: PropTypes.number, shadowProps: PropTypes.object, shadows: PropTypes.arrayOf(PropTypes.array).isRequired, style: stylePropType, - width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, - } + width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), + }; static defaultProps = { + borderRadius: 0, shadows: [], - } + }; renderItem = (shadow, index) => ( - ) + ); render = () => { const { children, + childrenWrapperStyle, shadows, style, ...props @@ -61,10 +62,13 @@ export default class ShadowStack extends PureComponent { return ( {shadows.map(this.renderItem)} - + {children} ); - } + }; } diff --git a/src/components/sheet/SheetHandle.js b/src/components/sheet/SheetHandle.js new file mode 100644 index 00000000000..7c9c6160d5f --- /dev/null +++ b/src/components/sheet/SheetHandle.js @@ -0,0 +1,11 @@ +import styled from 'styled-components/primitives'; +import { withNeverRerender } from '../../hoc'; + +const SheetHandle = styled.View` + background-color: #d9dadb; + border-radius: 3; + height: 5px; + width: 46px; +`; + +export default withNeverRerender(SheetHandle); diff --git a/src/components/sheet/index.js b/src/components/sheet/index.js new file mode 100644 index 00000000000..8743bca745b --- /dev/null +++ b/src/components/sheet/index.js @@ -0,0 +1 @@ +export { default as SheetHandle } from './SheetHandle'; diff --git a/src/components/text/ErrorText.js b/src/components/text/ErrorText.js index 01de9cfe855..949f1328c2c 100644 --- a/src/components/text/ErrorText.js +++ b/src/components/text/ErrorText.js @@ -1,21 +1,18 @@ import PropTypes from 'prop-types'; import React from 'react'; -import styled from 'styled-components/primitives'; -import Icon from '../icons/Icon'; -import { Row } from '../layout'; +import { withNeverRerender } from '../../hoc'; +import { colors } from '../../styles'; +import { Icon } from '../icons'; +import { RowWithMargins } from '../layout'; import Monospace from './Monospace'; -import { colors, fonts } from '../../styles'; - -const Text = styled(Monospace).attrs({ size: 'lmedium', weight: 'medium' })` - line-height: ${fonts.lineHeight.looser}; - margin-left: ${fonts.size.micro}; -`; const ErrorText = ({ color, error }) => ( - + - {error} - + + {error} + + ); ErrorText.propTypes = { @@ -27,4 +24,4 @@ ErrorText.defaultProps = { color: colors.red, }; -export default ErrorText; +export default withNeverRerender(ErrorText); diff --git a/src/components/text/H1.js b/src/components/text/H1.js index e29a5aabbb3..0d288aef0b7 100644 --- a/src/components/text/H1.js +++ b/src/components/text/H1.js @@ -1,4 +1,8 @@ import { withProps } from 'recompact'; import Text from './Text'; -export default withProps({ letterSpacing: 'tighter', size: 'blarge', weight: 'bold' })(Text); +export default withProps({ + letterSpacing: 'tighter', + size: 'blarge', + weight: 'bold', +})(Text); diff --git a/src/components/text/Label.js b/src/components/text/Label.js index 043527678a6..99737137573 100644 --- a/src/components/text/Label.js +++ b/src/components/text/Label.js @@ -9,12 +9,7 @@ const textProps = { weight: 'semibold', }; -const Label = props => ( - -); +const Label = props => ; Label.textProps = textProps; diff --git a/src/components/text/PlaceholderText.js b/src/components/text/PlaceholderText.js new file mode 100644 index 00000000000..c1f69abc048 --- /dev/null +++ b/src/components/text/PlaceholderText.js @@ -0,0 +1,28 @@ +import React from 'react'; +import { colors } from '../../styles'; +import { Text } from '.'; + +class PlaceholderText extends React.Component { + state = { + text: ' ', + }; + + updateValue = text => { + this.setState({ text }); + }; + + render() { + return ( + + {this.state.text} + + ); + } +} + +export default PlaceholderText; diff --git a/src/components/text/TruncatedAddress.js b/src/components/text/TruncatedAddress.js index 690ccc7ae66..4a7dcee8c02 100644 --- a/src/components/text/TruncatedAddress.js +++ b/src/components/text/TruncatedAddress.js @@ -1,31 +1,46 @@ import PropTypes from 'prop-types'; import React from 'react'; +import { isENSAddressFormat } from '../../helpers/validators'; import { abbreviations } from '../../utils'; -import Monospace from './Monospace'; +import Text from './Text'; const TruncatedAddress = ({ address, firstSectionLength, + monospace, truncationLength, ...props -}) => ( - - {address - ? abbreviations.address(address, truncationLength, firstSectionLength) - : 'Error displaying address' - } - -); +}) => { + let text = 'Error displaying address'; + + if (address) { + text = isENSAddressFormat(address) + ? address + : abbreviations.address(address, truncationLength, firstSectionLength); + } + + return ( + + {text} + + ); +}; TruncatedAddress.propTypes = { address: PropTypes.string, firstSectionLength: PropTypes.number, + monospace: PropTypes.bool, truncationLength: PropTypes.number, }; +TruncatedAddress.defaultProps = { + monospace: true, +}; + export default TruncatedAddress; diff --git a/src/components/text/TruncatedText.js b/src/components/text/TruncatedText.js index 42c3627968c..619f970cf32 100644 --- a/src/components/text/TruncatedText.js +++ b/src/components/text/TruncatedText.js @@ -3,7 +3,8 @@ import { pure } from 'recompact'; import { createElement } from 'react'; import Text from './Text'; -const TruncatedText = ({ component, ...props }) => createElement(component, props); +const TruncatedText = ({ component, ...props }) => + createElement(component, props); TruncatedText.propTypes = { component: PropTypes.func, diff --git a/src/components/token-family/TokenFamilyHeader.js b/src/components/token-family/TokenFamilyHeader.js index b0c2889584d..9dcede98f28 100644 --- a/src/components/token-family/TokenFamilyHeader.js +++ b/src/components/token-family/TokenFamilyHeader.js @@ -5,24 +5,23 @@ import FastImage from 'react-native-fast-image'; import Animated, { Easing } from 'react-native-reanimated'; import { toRad } from 'react-native-redash'; import { toClass, withProps } from 'recompact'; -import styled from 'styled-components/primitives'; import CaretImageSource from '../../assets/family-dropdown-arrow.png'; -import { borders, colors, padding } from '../../styles'; +import { borders, colors } from '../../styles'; import { initials, isNewValueForPath } from '../../utils'; -import { ButtonPressAnimation } from '../animations'; +import { ButtonPressAnimation, interpolate } from '../animations'; import Highlight from '../Highlight'; import ImageWithCachedDimensions from '../ImageWithCachedDimensions'; import { Row, RowWithMargins } from '../layout'; import { ShadowStack } from '../shadow-stack'; import { TruncatedText, Monospace } from '../text'; -const { interpolate, timing, Value } = Animated; +const { timing, Value } = Animated; const AnimatedMonospace = Animated.createAnimatedComponent(toClass(Monospace)); const AnimatedFastImage = Animated.createAnimatedComponent(FastImage); const TokenFamilyHeaderAnimationDuration = 200; -const TokenFamilyHeaderHeight = 54; +const TokenFamilyHeaderHeight = 50; const FamilyIcon = withProps(({ familyImage }) => ({ id: familyImage, @@ -38,29 +37,26 @@ export default class TokenFamilyHeader extends PureComponent { isCoinRow: PropTypes.bool, isOpen: PropTypes.bool, onHeaderPress: PropTypes.func, - } + }; + + componentDidUpdate = prevProps => { + if (isNewValueForPath(this.props, prevProps, 'isOpen')) { + this.runTiming(); + } + }; static animationDuration = TokenFamilyHeaderAnimationDuration; static height = TokenFamilyHeaderHeight; - animation = new Value(0) + animation = new Value(this.props.isOpen ? 1 : 0); - componentDidMount = () => this.runTiming() - - componentDidUpdate = (prevProps) => { - if (isNewValueForPath(this.props, prevProps, 'isOpen')) { - this.runTiming(); - } - } - - runTiming = () => ( + runTiming = () => timing(this.animation, { duration: TokenFamilyHeaderAnimationDuration, - easing: Easing.bezier(0.25, 0.46, 0.45, 0.94), + easing: Easing.bezier(0.25, 0.1, 0.25, 1), toValue: this.props.isOpen ? 1 : 0, - }).start() - ) + }).start(); renderFamilyIcon = () => { const { familyImage, familyName, isCoinRow } = this.props; @@ -75,66 +71,74 @@ export default class TokenFamilyHeader extends PureComponent { [0, 1, 3, colors.dark, 0.08], ]} > - {familyImage - ? - : - } + {familyImage ? ( + + ) : ( + + )} ); - } + }; render = () => ( - + - + {this.renderFamilyIcon()} {this.props.familyName} + + + + {this.props.childrenAmount} + - - {this.props.childrenAmount} - - ) + ); } diff --git a/src/components/token-family/TokenFamilyWrap.js b/src/components/token-family/TokenFamilyWrap.js index 4a6a16596c0..2b0cf63471e 100644 --- a/src/components/token-family/TokenFamilyWrap.js +++ b/src/components/token-family/TokenFamilyWrap.js @@ -15,26 +15,28 @@ import { import { createSelector } from 'reselect'; import { withOpenFamilyTabs, withFabSendAction } from '../../hoc'; import { colors } from '../../styles'; -import { FadeInAnimation } from '../animations'; import { UniqueTokenRow } from '../unique-token'; import TokenFamilyHeader from './TokenFamilyHeader'; +export const TokenFamilyWrapPaddingTop = 6; + const EnhancedUniqueTokenRow = compose( withNavigation, withHandlers({ - onPress: ({ assetType, navigation }) => (item) => { + onPress: ({ assetType, navigation }) => item => { navigation.navigate('ExpandedAssetScreen', { asset: item, type: assetType, }); }, - onPressSend: ({ navigation }) => (asset) => { + onPressSend: ({ navigation }) => asset => { navigation.navigate('SendSheet', { asset }); }, - }), + }) )(UniqueTokenRow); -const getHeight = (openFamilyTab) => (openFamilyTab ? UniqueTokenRow.height + 100 : 100); +const getHeight = openFamilyTab => + openFamilyTab ? UniqueTokenRow.height + 100 : 100; const TokenFamilyWrap = ({ areChildrenVisible, @@ -45,10 +47,15 @@ const TokenFamilyWrap = ({ highlight, isFamilyOpen, item, + paddingTop, onPressFamilyHeader, renderCollectibleItem, }) => ( - + {areChildrenVisible && ( - {times(item.length, renderCollectibleItem)} - + )} ); @@ -71,14 +78,14 @@ const TokenFamilyWrap = ({ TokenFamilyWrap.propTypes = { areChildrenVisible: PropTypes.bool, childrenAmount: PropTypes.number, - familyId: PropTypes.string, + familyId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), familyImage: PropTypes.string, familyName: PropTypes.string, highlight: PropTypes.bool, isFamilyOpen: PropTypes.bool, - isOpen: PropTypes.bool, item: PropTypes.array, onPressFamilyHeader: PropTypes.func, + paddingTop: PropTypes.number, renderCollectibleItem: PropTypes.func, }; @@ -93,7 +100,7 @@ const isFamilyOpenSelector = (familyId, openFamilyTabs) => ({ const withFamilyOpenStateProps = createSelector( [familyIdSelector, openFamilyTabsSelector], - isFamilyOpenSelector, + isFamilyOpenSelector ); export default compose( @@ -108,33 +115,40 @@ export default compose( setAreChildrenVisible(false); } }, - onPressFamilyHeader: ({ familyId, isFamilyOpen, setOpenFamilyTabs }) => () => ( + onPressFamilyHeader: ({ + familyId, + isFamilyOpen, + setOpenFamilyTabs, + }) => () => setOpenFamilyTabs({ index: familyId, state: !isFamilyOpen, - }) - ), + }), onShowChildren: ({ areChildrenVisible, setAreChildrenVisible }) => () => { if (!areChildrenVisible) { setAreChildrenVisible(true); } }, - /* eslint-disable react/display-name */ - renderCollectibleItem: ({ familyId, item }) => (index) => ( + renderCollectibleItem: ({ familyId, item }) => index => ( ), - /* eslint-enable react/display-name */ }), lifecycle({ + componentDidMount() { + this.props.onShowChildren(); + }, componentDidUpdate() { if (!this.props.isFamilyOpen) { this.props.onHideChildren(); } else if (!this.props.areChildrenVisible) { - this.props.setSafeTimeout(this.props.onShowChildren, TokenFamilyHeader.animationDuration); + this.props.setSafeTimeout( + this.props.onShowChildren, + TokenFamilyHeader.animationDuration + ); } }, }), @@ -142,7 +156,8 @@ export default compose( 'areChildrenVisible', 'childrenAmount', 'highlight', + 'paddingTop', 'isFamilyOpen', 'uniqueId', - ]), + ]) )(TokenFamilyWrap); diff --git a/src/components/transaction/TransactionSheet.js b/src/components/transaction/TransactionSheet.js index 0cef3d20144..2252825a0ca 100644 --- a/src/components/transaction/TransactionSheet.js +++ b/src/components/transaction/TransactionSheet.js @@ -7,7 +7,7 @@ import Divider from '../Divider'; import { Column } from '../layout'; const Container = styled(Column).attrs({ justify: 'end' })` - ${borders.buildRadius('top', 15)} + ${borders.buildRadius('top', 20)} background-color: ${colors.white}; flex-grow: 0; padding-bottom: ${safeAreaInsetValues.bottom}; @@ -25,12 +25,10 @@ const TransactionSheet = ({ children, sendButton, ...props }) => ( {Children.map(children, (child, index) => ( {child} - {(index < children.length - 1) && } + {index < children.length - 1 && } ))} - - {sendButton} - + {sendButton}
); diff --git a/src/components/transaction/sections/DefaultTransactionConfirmationSection.js b/src/components/transaction/sections/DefaultTransactionConfirmationSection.js index becd9f5933b..10e7645459c 100644 --- a/src/components/transaction/sections/DefaultTransactionConfirmationSection.js +++ b/src/components/transaction/sections/DefaultTransactionConfirmationSection.js @@ -23,7 +23,7 @@ const DefaultTransactionConfirmationSection = ({ truncationLength={15} /> - {!!(value) && ( + {!!value && ( )} - {!!(data) && ( + {!!data && ( @@ -54,5 +54,5 @@ export default compose( ...props, ...asset, })), - pure, + pure )(DefaultTransactionConfirmationSection); diff --git a/src/components/transaction/sections/TransactionConfirmationSection.js b/src/components/transaction/sections/TransactionConfirmationSection.js index f7cf88fbeff..76087eddf09 100644 --- a/src/components/transaction/sections/TransactionConfirmationSection.js +++ b/src/components/transaction/sections/TransactionConfirmationSection.js @@ -44,13 +44,7 @@ const TokenSymbol = styled(Amount)` `; const TransactionConfirmationSection = ({ - asset: { - address, - amount, - name, - nativeAmountDisplay, - symbol, - }, + asset: { address, amount, name, nativeAmountDisplay, symbol }, sendButton, }) => ( @@ -63,7 +57,12 @@ const TransactionConfirmationSection = ({ /> - + @@ -72,7 +71,10 @@ const TransactionConfirmationSection = ({ {amount} - {symbol} + + + {symbol} + {nativeAmountDisplay} diff --git a/src/components/unique-token/UniqueTokenAttributes.js b/src/components/unique-token/UniqueTokenAttributes.js index cfdfb121d64..8a9feac6cda 100644 --- a/src/components/unique-token/UniqueTokenAttributes.js +++ b/src/components/unique-token/UniqueTokenAttributes.js @@ -1,5 +1,4 @@ import PropTypes from 'prop-types'; -import styled from 'styled-components/primitives'; import React from 'react'; import { ScrollView } from 'react-native-gesture-handler'; import { @@ -11,31 +10,18 @@ import { withState, } from 'recompact'; import { sortList } from '../../helpers/sortList'; -import { colors, margin, padding } from '../../styles'; -import { dimensionsPropType } from '../../utils'; +import { colors, margin, padding, position } from '../../styles'; import { Centered, FlexItem } from '../layout'; import { PagerControls } from '../pager'; import Tag from '../Tag'; const AttributesPadding = 15; -const scrollInsetBottom = AttributesPadding + (PagerControls.padding * 4); +const scrollInsetBottom = AttributesPadding + PagerControls.padding * 4; -const Wrapper = styled(Centered).attrs({ wrap: true })` - ${padding(0, AttributesPadding * 1.125)} - flex-grow: 1; -`; - -/* eslint-disable camelcase */ -const AttributeItem = ({ trait_type: type, value }) => ( +const AttributeItem = ({ trait_type: type, value }) => type ? ( - - ) : null -); + + ) : null; AttributeItem.propTypes = { trait_type: PropTypes.string.isRequired, @@ -51,24 +37,21 @@ const UniqueTokenAttributes = ({ }) => ( - + {traits.map(AttributeItem)} - + ); UniqueTokenAttributes.propTypes = { background: PropTypes.string, - dimensions: dimensionsPropType, onListLayout: PropTypes.func, onScroll: PropTypes.func, - traits: PropTypes.arrayOf(PropTypes.shape({ - trait_type: PropTypes.string.isRequired, - value: PropTypes.node.isRequired, - })), + traits: PropTypes.arrayOf( + PropTypes.shape({ + trait_type: PropTypes.string.isRequired, + value: PropTypes.node.isRequired, + }) + ), willListOverflow: PropTypes.bool, }; UniqueTokenAttributes.padding = AttributesPadding; const enhance = compose( - onlyUpdateForKeys(['traits', 'willListOverflow']), withState('willListOverflow', 'setWillListOverflow', false), withProps(({ traits }) => ({ // Sort traits alphabetically by "trait_type" traits: sortList(traits, 'trait_type', 'asc'), })), withHandlers({ - onListLayout: ({ dimensions, setWillListOverflow }) => ({ nativeEvent: { layout } }) => { + onListLayout: ({ dimensions, setWillListOverflow }) => ({ + nativeEvent: { layout }, + }) => { setWillListOverflow(layout.height > dimensions.height); }, onScroll: () => event => event.stopPropagation(), }), + onlyUpdateForKeys(['traits', 'willListOverflow']) ); -/* eslint-enable camelcase */ export default hoistStatics(enhance)(UniqueTokenAttributes); diff --git a/src/components/unique-token/UniqueTokenCard.js b/src/components/unique-token/UniqueTokenCard.js index 0dbfaeb7166..2afc76ef640 100644 --- a/src/components/unique-token/UniqueTokenCard.js +++ b/src/components/unique-token/UniqueTokenCard.js @@ -1,37 +1,27 @@ import PropTypes from 'prop-types'; import React from 'react'; +import { View } from 'react-native'; import stylePropType from 'react-style-proptype'; -import { - compose, - onlyUpdateForKeys, - withHandlers, - withProps, -} from 'recompact'; +import { compose, onlyUpdateForKeys, withHandlers, withProps } from 'recompact'; import { withFabSendAction } from '../../hoc'; -import { colors, position } from '../../styles'; +import { colors } from '../../styles'; import { ButtonPressAnimation } from '../animations'; import Highlight from '../Highlight'; import InnerBorder from '../InnerBorder'; -import { Centered } from '../layout'; -import { ShadowStack } from '../shadow-stack'; import UniqueTokenImage from './UniqueTokenImage'; const UniqueTokenCardBorderRadius = 18; const UniqueTokenCard = ({ + borderEnabled, disabled, height, - item: { - background, - image_preview_url, - ...item - }, + item: { background, image_preview_url, ...item }, onPress, onPressSend, - size, highlight, resizeMode, - shadows, + shadowStyle, style, width, ...props @@ -43,69 +33,66 @@ const UniqueTokenCard = ({ onPress={onPress} onPressSend={onPressSend} scaleTo={0.94} + style={{ + shadowColor: colors.dark, + shadowOffset: { height: 2, width: 0 }, + shadowOpacity: 0.08, + shadowRadius: 3, + ...shadowStyle, + }} > - - - + + {borderEnabled && ( - - - + )} + +
); }; UniqueTokenCard.propTypes = { + borderEnabled: PropTypes.bool, disabled: PropTypes.bool, height: PropTypes.number, highlight: PropTypes.bool, item: PropTypes.shape({ background: PropTypes.string, - // eslint-disable-next-line camelcase image_preview_url: PropTypes.string, }), onPress: PropTypes.func, onPressSend: PropTypes.func, resizeMode: UniqueTokenImage.propTypes.resizeMode, - shadows: PropTypes.array, + shadowStyle: stylePropType, size: PropTypes.number, style: stylePropType, width: PropTypes.number, }; UniqueTokenCard.defaultProps = { - shadows: [ - [0, 1, 3, colors.dark, 0.06], - [0, 4, 6, colors.dark, 0.04], - ], + borderEnabled: true, }; - export default compose( withHandlers({ onPress: ({ item, onPress }) => () => { @@ -121,5 +108,5 @@ export default compose( }), withProps(({ item: { uniqueId } }) => ({ uniqueId })), withFabSendAction, - onlyUpdateForKeys(['height', 'style', 'uniqueId', 'width', 'highlight']), + onlyUpdateForKeys(['height', 'style', 'uniqueId', 'width', 'highlight']) )(UniqueTokenCard); diff --git a/src/components/unique-token/UniqueTokenImage.js b/src/components/unique-token/UniqueTokenImage.js index 34a4e1d9d7e..94be806695f 100644 --- a/src/components/unique-token/UniqueTokenImage.js +++ b/src/components/unique-token/UniqueTokenImage.js @@ -19,49 +19,56 @@ const FallbackTextColorVariants = { light: colors.white, }; -const getFallbackTextColor = bg => colors.getTextColorForBackground(bg, FallbackTextColorVariants); +const getFallbackTextColor = bg => + colors.getTextColorForBackground(bg, FallbackTextColorVariants); const enhance = compose( withState('error', 'handleErrorState', null), - withHandlers({ onError: ({ handleErrorState }) => error => handleErrorState(error) }), + withHandlers({ + onError: ({ handleErrorState }) => error => handleErrorState(error), + }), withProps(({ backgroundColor, item }) => ({ fallbackTextColor: getFallbackTextColor(backgroundColor), name: buildUniqueTokenName(item), })), - onlyUpdateForKeys(['error', 'imageUrl']), + onlyUpdateForKeys(['error', 'imageUrl']) ); -const UniqueTokenImage = enhance(({ - backgroundColor, - borderRadius, - error, - fallbackTextColor, - imageUrl, - name, - onError, - resizeMode, -}) => ( - - {(imageUrl && !error) ? ( - - ) : ( - - {name} - - )} - -)); +const UniqueTokenImage = enhance( + ({ + backgroundColor, + error, + fallbackTextColor, + imageUrl, + name, + onError, + resizeMode, + }) => ( + + {imageUrl && !error ? ( + + ) : ( + + {name} + + )} + + ) +); UniqueTokenImage.propTypes = { backgroundColor: PropTypes.string, diff --git a/src/components/unique-token/UniqueTokenRow.js b/src/components/unique-token/UniqueTokenRow.js index c98c2acfe03..5e491eaf1e3 100644 --- a/src/components/unique-token/UniqueTokenRow.js +++ b/src/components/unique-token/UniqueTokenRow.js @@ -8,15 +8,14 @@ import UniqueTokenCard from './UniqueTokenCard'; const CardMargin = 15; const RowPadding = 19; -const CardSize = (deviceUtils.dimensions.width - (RowPadding * 2) - CardMargin) / 2; +const CardSize = + (deviceUtils.dimensions.width - RowPadding * 2 - CardMargin) / 2; -const enhance = shouldUpdate((...props) => isNewValueForPath(...props, 'item.uniqueId')); +const enhance = shouldUpdate((...props) => + isNewValueForPath(...props, 'item.uniqueId') +); -const UniqueTokenRow = enhance(({ - item, - onPress, - onPressSend, -}) => ( +const UniqueTokenRow = enhance(({ item, onPress, onPressSend }) => ( = 1) ? CardMargin : 0 }} + style={{ marginLeft: itemIndex >= 1 ? CardMargin : 0 }} /> ))} diff --git a/src/components/walletconnect-list/WalletConnectExplainerItem.js b/src/components/walletconnect-list/WalletConnectExplainerItem.js index aeb12bb0d10..a002b1526b8 100644 --- a/src/components/walletconnect-list/WalletConnectExplainerItem.js +++ b/src/components/walletconnect-list/WalletConnectExplainerItem.js @@ -5,27 +5,14 @@ import { colors, padding } from '../../styles'; import { Column, FlexItem, Row } from '../layout'; import { Emoji, Text, TruncatedText } from '../text'; -const WalletConnectExplainerItem = ({ - children, - content, - emoji, - title, -}) => ( - +const WalletConnectExplainerItem = ({ children, content, emoji, title }) => ( + - + {title} diff --git a/src/components/walletconnect-list/WalletConnectLearnMoreButton.js b/src/components/walletconnect-list/WalletConnectLearnMoreButton.js index 8defca391b5..7675be10b62 100644 --- a/src/components/walletconnect-list/WalletConnectLearnMoreButton.js +++ b/src/components/walletconnect-list/WalletConnectLearnMoreButton.js @@ -38,9 +38,12 @@ WalletConnectLearnMoreButton.propTypes = { onPressLearnMore: PropTypes.func, }; -const openWalletConnectWebsite = () => Linking.openURL('https://walletconnect.org/'); +const openWalletConnectWebsite = () => + Linking.openURL('https://walletconnect.org/'); export default compose( pure, - withHandlers({ onPressLearnMore: () => debounce(openWalletConnectWebsite, 200) }), + withHandlers({ + onPressLearnMore: () => debounce(openWalletConnectWebsite, 200), + }) )(WalletConnectLearnMoreButton); diff --git a/src/components/walletconnect-list/WalletConnectList.js b/src/components/walletconnect-list/WalletConnectList.js index 4f27d71f657..7d6f055f074 100644 --- a/src/components/walletconnect-list/WalletConnectList.js +++ b/src/components/walletconnect-list/WalletConnectList.js @@ -17,7 +17,6 @@ const scrollIndicatorInsets = { const keyExtractor = ({ expires }) => expires; -// eslint-disable-next-line react/prop-types const renderItem = ({ item }) => ; const WalletConnectList = ({ items, onLayout, ...props }) => ( diff --git a/src/components/walletconnect-list/WalletConnectListItem.js b/src/components/walletconnect-list/WalletConnectListItem.js index 08a1cd2b526..01bc621ac91 100644 --- a/src/components/walletconnect-list/WalletConnectListItem.js +++ b/src/components/walletconnect-list/WalletConnectListItem.js @@ -6,18 +6,13 @@ import { compose, withHandlers } from 'recompact'; import { RequestVendorLogoIcon } from '../coin-icon'; import ContextMenu from '../ContextMenu'; import { withWalletConnectConnections } from '../../hoc'; -import { - Centered, - ColumnWithMargins, - FlexItem, - Row, -} from '../layout'; +import { Centered, ColumnWithMargins, FlexItem, Row } from '../layout'; import { padding } from '../../styles'; import { TruncatedText } from '../text'; const ContainerPadding = 15; const VendorLogoIconSize = 50; -const WalletConnectListItemHeight = VendorLogoIconSize + (ContainerPadding * 2); +const WalletConnectListItemHeight = VendorLogoIconSize + ContainerPadding * 2; const enhance = compose( withWalletConnectConnections, @@ -26,7 +21,7 @@ const enhance = compose( dappName, dappUrl, walletConnectDisconnectAllByDappName, - }) => (buttonIndex) => { + }) => buttonIndex => { if (buttonIndex === 0) { walletConnectDisconnectAllByDappName(dappName); analytics.track('Manually disconnected from WalletConnect connection', { @@ -35,51 +30,41 @@ const enhance = compose( }); } }, - }), + }) ); -const WalletConnectListItem = enhance(({ - dappName, - dappIcon, - dappUrl, - onPressActionSheet, -}) => ( - - - - ( + + - - {dappName || 'Unknown connection'} - - + + + + {dappName || 'Unknown connection'} + + + + + + - - - - -)); + ) +); WalletConnectListItem.propTypes = { dappIcon: PropTypes.string.isRequired, diff --git a/src/handlers/__tests__/web3.test.js b/src/handlers/__tests__/web3.test.js index 118e4d874a0..421e712f53a 100644 --- a/src/handlers/__tests__/web3.test.js +++ b/src/handlers/__tests__/web3.test.js @@ -1,29 +1,24 @@ -import { ethers } from 'ethers'; -import { - isHexString, - isValidMnemonic, - mnemonicToSeed, -} from '../web3'; +import { isHexString, isValidMnemonic } from '../web3'; -test('isHexString', () => { +it('isHexString', () => { const address = '0x1492004547FF0eFd778CC2c14E794B26B4701105'; const result = isHexString(address); expect(result).toBeTruthy(); }); -test('isHexStringFalse', () => { +it('isHexStringFalse', () => { const address = '1492004547FF0eFd778CC2c14E794B26B4701105'; const result = isHexString(address); expect(result).toBeFalsy(); }); -test('isHexStringFalse', () => { +it('isHexStringFalse2', () => { const address = '1492004547FF0eFd778CC2c14E794B26B470110'; const result = isHexString(address); expect(result).toBeFalsy(); }); -test('isValidMnemonic', () => { +it('isValidMnemonic', () => { const seed = 'blah'; const result = isValidMnemonic(seed); expect(result).toBeFalsy(); diff --git a/src/handlers/commonStorage.js b/src/handlers/commonStorage.js deleted file mode 100644 index c70a1c6f992..00000000000 --- a/src/handlers/commonStorage.js +++ /dev/null @@ -1,474 +0,0 @@ -import { differenceInMinutes } from 'date-fns'; -import { omit, pickBy } from 'lodash'; - -const defaultVersion = '0.1.0'; -const transactionsVersion = '0.2.0'; -const uniqueTokensVersion = '0.2.0'; -const assetsVersion = '0.2.0'; - -/** - * @desc save to storage - * @param {String} [key=''] - * @param {Object} [data={}] - * @param {String} [version=defaultVersion] - */ -export const saveLocal = async ( - key = '', - data = {}, - version = defaultVersion, -) => { - try { - data.storageVersion = version; - await storage.save({ - data, - expires: null, - key, - }); - } catch (error) { - console.log('Storage: error saving to local for key', key); - } -}; - -/** - * @desc get from storage - * @param {String} [key=''] - * @return {Object} - */ -export const getLocal = async (key = '', version = defaultVersion) => { - try { - const result = await storage.load({ - autoSync: false, - key, - syncInBackground: false, - }); - if (result && result.storageVersion === version) { - return result; - } - if (result) { - removeLocal(key); - return null; - } - return null; - } catch (error) { - console.log('Storage: error getting from local for key', key); - return null; - } -}; - -/** - * @desc get from storage - * @param {String} [key=''] - * @return {Object} - */ -export const removeLocal = (key = '') => { - try { - storage.remove({ key }); - } catch (error) { - console.log('Storage: error removing local with key', key); - } -}; - -const getAssetsKey = (accountAddress, network) => `assets-${accountAddress.toLowerCase()}-${network.toLowerCase()}`; -const getIsWalletEmptyKey = (accountAddress, network) => `iswalletempty-${accountAddress.toLowerCase()}-${network.toLowerCase()}`; -const getRequestsKey = (accountAddress, network) => `requests-${accountAddress.toLowerCase()}-${network.toLowerCase()}`; -const getTransactionsKey = (accountAddress, network) => `transactions-${accountAddress.toLowerCase()}-${network.toLowerCase()}`; -const getUniqueTokensKey = (accountAddress, network) => `uniquetokens-${accountAddress.toLowerCase()}-${network.toLowerCase()}`; -const getUniswapKey = (accountAddress, network) => `uniswap-${accountAddress.toLowerCase()}-${network.toLowerCase()}`; -const getUniswapLiquidityKey = (accountAddress, network) => `uniswapliquidity-${accountAddress.toLowerCase()}-${network.toLowerCase()}`; - -/** - * @desc get Uniswap liquidity tokens - * @param {String} [address] - * @param {String} [network] - * @return {Object} - */ -export const getUniswapLiquidityTokens = async (accountAddress, network) => { - const uniswap = await getLocal(getUniswapLiquidityKey(accountAddress, network)); - return uniswap ? uniswap.data : []; -}; - -/** - * @desc save Uniswap liquidity tokens - * @param {String} [address] - * @param {String} [network] - */ -export const saveUniswapLiquidityTokens = async (accountAddress, uniswap, network) => { - await saveLocal( - getUniswapLiquidityKey(accountAddress, network), - { data: uniswap }, - ); -}; - -/** - * @desc remove Uniswap liquidity tokens - * @param {String} [address] - * @param {String} [network] - * @return {Object} - */ -export const removeUniswapLiquidityTokens = (accountAddress, network) => { - const key = getUniswapLiquidityKey(accountAddress, network); - removeLocal(key); -}; - -/** - * @desc get Uniswap - * @param {String} [address] - * @param {String} [network] - * @return {Object} - */ -export const getUniswap = async (accountAddress, network) => { - const uniswap = await getLocal(getUniswapKey(accountAddress, network)); - return uniswap ? uniswap.data : {}; -}; - -/** - * @desc save Uniswap - * @param {String} [address] - * @param {String} [network] - */ -export const saveUniswap = async (accountAddress, uniswap, network) => { - await saveLocal( - getUniswapKey(accountAddress, network), - { data: uniswap }, - ); -}; - -/** - * @desc remove Uniswap - * @param {String} [address] - * @param {String} [network] - * @return {Object} - */ -export const removeUniswap = (accountAddress, network) => { - const key = getUniswapKey(accountAddress, network); - removeLocal(key); -}; - -/** - * @desc get assets - * @param {String} [address] - * @param {String} [network] - * @return {Object} - */ -export const getAssets = async (accountAddress, network) => { - const assets = await getLocal(getAssetsKey(accountAddress, network), assetsVersion); - return assets ? assets.data : []; -}; - -/** - * @desc save assets - * @param {String} [address] - * @param {String} [network] - */ -export const saveAssets = async (accountAddress, assets, network) => { - await saveLocal( - getAssetsKey(accountAddress, network), - { data: assets }, - assetsVersion, - ); -}; - -/** - * @desc remove assets - * @param {String} [address] - * @param {String} [network] - * @return {Object} - */ -export const removeAssets = (accountAddress, network) => { - const key = getAssetsKey(accountAddress, network); - removeLocal(key, assetsVersion); -}; - -/** - * @desc get transactions - * @param {String} [address] - * @param {String} [network] - * @return {Object} - */ -export const getLocalTransactions = async (accountAddress, network) => { - const transactions = await getLocal(getTransactionsKey(accountAddress, network), transactionsVersion); - return transactions ? transactions.data : []; -}; - -/** - * @desc save transactions - * @param {String} [address] - * @param {Array} [transactions] - * @param {String} [network] - */ -export const saveLocalTransactions = async (accountAddress, transactions, network) => { - await saveLocal( - getTransactionsKey(accountAddress, network), - { data: transactions }, - transactionsVersion, - ); -}; - -/** - * @desc remove transactions - * @param {String} [address] - * @param {String} [network] - * @return {Object} - */ -export const removeLocalTransactions = (accountAddress, network) => { - const key = getTransactionsKey(accountAddress, network); - removeLocal(key, transactionsVersion); -}; - -/** - * @desc get is wallet empty - * @param {String} [address] - * @param {String} [network] - * @return {Boolean} - */ -export const getIsWalletEmpty = async (accountAddress, network) => await getLocal(getIsWalletEmptyKey(accountAddress, network)); - -/** - * @desc save is wallet empty - * @param {String} [address] - * @param {Boolean} [isWalletEmpty] - * @param {String} [network] - */ -export const saveIsWalletEmpty = async (accountAddress, isWalletEmpty, network) => { - await saveLocal( - getIsWalletEmptyKey(accountAddress, network), - isWalletEmpty, - ); -}; - -/** - * @desc remove is wallet empty - * @param {String} [address] - * @param {String} [network] - * @return {Object} - */ -export const removeIsWalletEmpty = (accountAddress, network) => { - const key = getIsWalletEmptyKey(accountAddress, network); - removeLocal(key); -}; - -/** - * @desc get unique tokens - * @param {String} [address] - * @param {String} [network] - * @return {Object} - */ -export const getUniqueTokens = async (accountAddress, network) => { - const uniqueTokens = await getLocal(getUniqueTokensKey(accountAddress, network), uniqueTokensVersion); - return uniqueTokens ? uniqueTokens.data : []; -}; - -/** - * @desc save unique tokens - * @param {String} [address] - * @param {Array} [uniqueTokens] - * @param {String} [network] - */ -export const saveUniqueTokens = async (accountAddress, uniqueTokens, network) => { - await saveLocal( - getUniqueTokensKey(accountAddress, network), - { data: uniqueTokens }, - uniqueTokensVersion, - ); -}; - -/** - * @desc remove unique tokens - * @param {String} [address] - * @param {String} [network] - * @return {Object} - */ -export const removeUniqueTokens = (accountAddress, network) => { - const key = getUniqueTokensKey(accountAddress, network); - removeLocal(key, uniqueTokensVersion); -}; - -/** - * @desc get native currency - * @return {Object} - */ -export const getNativeCurrency = async () => { - const nativeCurrency = await getLocal('nativeCurrency'); - const currency = nativeCurrency ? nativeCurrency.data : 'USD'; - if (currency === 'GBP') { - await saveNativeCurrency('USD'); - return 'USD'; - } - return currency; -}; - -/** - * @desc save native currency - * @param {String} [currency] - */ -export const saveNativeCurrency = async nativeCurrency => { - await saveLocal( - 'nativeCurrency', - { data: nativeCurrency }, - ); -}; - -/** - * @desc get all wallet connect sessions - * @return {Object} - */ -export const getAllValidWalletConnectSessions = async () => { - const allSessions = await getAllWalletConnectSessions(); - return pickBy(allSessions, value => value.connected); -}; - -/** - * @desc get all wallet connect sessions - * @return {Object} - */ -export const getAllWalletConnectSessions = async () => { - const allSessions = await getLocal( - 'walletconnect', - ); - return allSessions || {}; -}; - -/** - * @desc save wallet connect session - * @param {String} [peerId] - * @param {Object} [session] - */ -export const saveWalletConnectSession = async (peerId, session) => { - const allSessions = await getAllValidWalletConnectSessions(); - allSessions[peerId] = session; - await saveLocal('walletconnect', allSessions); -}; - -/** - * @desc remove wallet connect session - * @param {String} [peerId] - */ -export const removeWalletConnectSession = async (peerId) => { - const allSessions = await getAllWalletConnectSessions(); - const session = allSessions ? allSessions[peerId] : null; - const resultingSessions = omit(allSessions, [peerId]); - await saveLocal('walletconnect', resultingSessions); - return session; -}; - -/** - * @desc remove wallet connect sessions - * @param {String} [sessionId] - */ -export const removeWalletConnectSessions = async (sessionIds) => { - const allSessions = await getAllWalletConnectSessions(); - const resultingSessions = omit(allSessions, sessionIds); - await saveLocal('walletconnect', resultingSessions); -}; - -/** - * @desc remove all wallet connect sessions - * @param {String} [sessionId] - */ -export const removeWalletConnect = () => { - removeLocal('walletconnect'); -}; - -/** - * @desc get language - * @return {Object} - */ -export const getLanguage = async () => { - const language = await getLocal('language'); - return language ? language.data : 'en'; -}; - -/** - * @desc save language - * @param {String} [language] - */ -export const saveLanguage = async language => { - await saveLocal('language', { data: language }); -}; - -/** - * @desc get show shitcoins setting - * @return {True|False} - */ -export const getShowShitcoinsSetting = async () => { - const showShitcoins = await getLocal('showShitcoins'); - return showShitcoins ? showShitcoins.data : null; -}; - -/** - * @desc update show shitcoins setting - * @param {Boolean} [updatedSetting] - * @return {Void} - */ -export const updateShowShitcoinsSetting = async (updatedSetting) => { - await saveLocal('showShitcoins', { data: updatedSetting }); -}; - -const isRequestStillValid = (request) => { - const createdAt = request.displayDetails.timestampInMs; - return (differenceInMinutes(Date.now(), createdAt) < 60); -}; - -/** - * @desc get account local requests - * @param {String} [address] - * @return {Object} - */ -export const getLocalRequests = async (accountAddress, network) => { - const requestsData = await getLocal(getRequestsKey(accountAddress, network)); - const requests = requestsData ? requestsData.data : {}; - const openRequests = pickBy(requests, isRequestStillValid); - await saveLocalRequests(accountAddress, network, openRequests); - return openRequests; -}; - -/** - * @desc save local incoming requests - * @param {String} [address] - * @param {String} [network] - * @return {Void} - */ -export const saveLocalRequests = async (accountAddress, network, requests) => { - await saveLocal( - getRequestsKey(accountAddress, network), - { data: requests }, - ); -}; - -/** - * @desc remove request - * @param {String} [address] - * @param {String} [network] - * @param {String} [requestId] - * @return {Void} - */ -export const removeLocalRequest = async (address, network, requestId) => { - const requests = await getLocalRequests(address, network); - const updatedRequests = { ...requests }; - delete updatedRequests[requestId]; - await saveLocalRequests(address, network, updatedRequests); -}; - -/** - * @desc remove all requests - * @param {String} [address] - * @param {String} [network] - * @param {String} [requestId] - * @return {Void} - */ -export const removeLocalRequests = async (address, network) => { - const requestsKey = getRequestsKey(address, network); - await removeLocal(requestsKey); -}; - -// apple restricts number of times developers are allowed to throw -// the in-app AppStore Review interface. -// see here for more: https://github.com/oblador/react-native-store-review -export const getAppStoreReviewRequestCount = async () => { - const count = await getLocal('appStoreReviewRequestCount'); - return count ? count.data : 0; -}; - -export const setAppStoreReviewRequestCount = async (newCount) => { - await saveLocal('appStoreReviewRequestCount', { data: newCount }); -}; diff --git a/src/handlers/api.js b/src/handlers/gasPrices.js similarity index 100% rename from src/handlers/api.js rename to src/handlers/gasPrices.js diff --git a/src/handlers/localstorage/accountLocal.js b/src/handlers/localstorage/accountLocal.js new file mode 100644 index 00000000000..9eb0f7f70af --- /dev/null +++ b/src/handlers/localstorage/accountLocal.js @@ -0,0 +1,256 @@ +import { + getAccountLocal, + getKey, + getLocal, + removeAccountLocal, + saveAccountLocal, + saveLocal, +} from './common'; + +const transactionsVersion = '0.2.1'; +const uniqueTokensVersion = '0.2.0'; +const assetsVersion = '0.2.0'; + +const ASSETS = 'assets'; +const OPEN_FAMILIES = 'openFamilies'; +const OPEN_INVESTMENT_CARDS = 'openInvestmentCards'; +const SMALL_BALANCE_TOGGLE = 'smallBalanceToggle'; +const TRANSACTIONS = 'transactions'; +const UNIQUE_TOKENS = 'uniquetokens'; +const WALLET_EMPTY = 'iswalletempty'; + +/** + * @desc get assets + * @param {String} [address] + * @param {String} [network] + * @return {Object} + */ +export const getAssets = (accountAddress, network) => + getAccountLocal(ASSETS, accountAddress, network, [], assetsVersion); + +/** + * @desc save assets + * @param {String} [address] + * @param {Array} [assets] + * @param {String} [network] + */ +export const saveAssets = (assets, accountAddress, network) => + saveAccountLocal(ASSETS, assets, accountAddress, network, assetsVersion); + +/** + * @desc remove assets + * @param {String} [address] + * @param {String} [network] + * @return {Object} + */ +export const removeAssets = (accountAddress, network) => + removeAccountLocal(ASSETS, accountAddress, network); + +/** + * @desc get transactions + * @param {String} [address] + * @param {String} [network] + * @return {Object} + */ +export const getLocalTransactions = (accountAddress, network) => + getAccountLocal( + TRANSACTIONS, + accountAddress, + network, + [], + transactionsVersion + ); + +/** + * @desc save transactions + * @param {String} [address] + * @param {Array} [transactions] + * @param {String} [network] + */ +export const saveLocalTransactions = (transactions, accountAddress, network) => + saveAccountLocal( + TRANSACTIONS, + transactions, + accountAddress, + network, + transactionsVersion + ); + +/** + * @desc remove transactions + * @param {String} [address] + * @param {String} [network] + * @return {Object} + */ +export const removeLocalTransactions = (accountAddress, network) => + removeAccountLocal(TRANSACTIONS, accountAddress, network); + +/** + * @desc get is wallet empty + * @param {String} [address] + * @param {String} [network] + * @return {Boolean} + */ +export const getIsWalletEmpty = async (accountAddress, network) => + await getLocal(getKey(WALLET_EMPTY, accountAddress, network)); + +/** + * @desc save is wallet empty + * @param {String} [address] + * @param {Boolean} [isWalletEmpty] + * @param {String} [network] + */ +export const saveIsWalletEmpty = async ( + accountAddress, + isWalletEmpty, + network +) => { + await saveLocal(getKey(WALLET_EMPTY, accountAddress, network), isWalletEmpty); +}; + +/** + * @desc remove is wallet empty + * @param {String} [address] + * @param {String} [network] + * @return {Object} + */ +export const removeIsWalletEmpty = (accountAddress, network) => + removeAccountLocal(WALLET_EMPTY, accountAddress, network); + +/** + * @desc get unique tokens + * @param {String} [address] + * @param {String} [network] + * @return {Object} + */ +export const getUniqueTokens = (accountAddress, network) => + getAccountLocal( + UNIQUE_TOKENS, + accountAddress, + network, + [], + uniqueTokensVersion + ); + +/** + * @desc save unique tokens + * @param {String} [address] + * @param {Array} [uniqueTokens] + * @param {String} [network] + */ +export const saveUniqueTokens = (uniqueTokens, accountAddress, network) => + saveAccountLocal( + UNIQUE_TOKENS, + uniqueTokens, + accountAddress, + network, + uniqueTokensVersion + ); + +/** + * @desc remove unique tokens + * @param {String} [address] + * @param {String} [network] + * @return {Object} + */ +export const removeUniqueTokens = (accountAddress, network) => + removeAccountLocal(UNIQUE_TOKENS, accountAddress, network); + +/** + * @desc get open small balances + * @param {String} [address] + * @param {String} [network] + * @return {Object} + */ +export const getSmallBalanceToggle = (accountAddress, network) => + getAccountLocal(SMALL_BALANCE_TOGGLE, accountAddress, network, false); + +/** + * @desc save small balance toggle + * @param {String} [address] + * @param {Boolean} [small balance toggle] + * @param {String} [network] + */ +export const saveSmallBalanceToggle = ( + openSmallBalances, + accountAddress, + network +) => + saveAccountLocal( + SMALL_BALANCE_TOGGLE, + openSmallBalances, + accountAddress, + network + ); + +/** + * @desc remove small balance toggle + * @param {String} [address] + * @param {String} [network] + * @return {Object} + */ +export const removeSmallBalanceToggle = (accountAddress, network) => + removeAccountLocal(SMALL_BALANCE_TOGGLE, accountAddress, network); + +/** + * @desc get open investment cards + * @param {String} [address] + * @param {String} [network] + * @return {Object} + */ +export const getOpenInvestmentCards = (accountAddress, network) => + getAccountLocal(OPEN_INVESTMENT_CARDS, accountAddress, network, {}); + +/** + * @desc save open investment cards + * @param {String} [address] + * @param {Object} [open investment cards] + * @param {String} [network] + */ +export const saveOpenInvestmentCards = ( + openInvestmentCards, + accountAddress, + network +) => + saveAccountLocal( + OPEN_INVESTMENT_CARDS, + openInvestmentCards, + accountAddress, + network + ); + +/** + * @desc remove open investment cards + * @param {String} [address] + * @param {String} [network] + * @return {Object} + */ +export const removeOpenInvestmentCards = (accountAddress, network) => + removeAccountLocal(OPEN_INVESTMENT_CARDS, accountAddress, network); + +/** + * @desc get open families + * @param {String} [address] + * @param {String} [network] + * @return {Object} + */ +export const getOpenFamilies = (accountAddress, network) => + getAccountLocal(OPEN_FAMILIES, accountAddress, network, {}); + +/** + * @desc save open families + * @param {String} [address] + * @param {Object} [open families] + * @param {String} [network] + */ +export const saveOpenFamilies = (openFamilies, accountAddress, network) => + saveAccountLocal(OPEN_FAMILIES, openFamilies, accountAddress, network); + +/** + * @desc remove open families + * @param {String} [address] + * @param {String} [network] + * @return {Object} + */ +export const removeOpenFamilies = (accountAddress, network) => + removeAccountLocal(OPEN_FAMILIES, accountAddress, network); diff --git a/src/handlers/localstorage/common.js b/src/handlers/localstorage/common.js new file mode 100644 index 00000000000..536121d2d9b --- /dev/null +++ b/src/handlers/localstorage/common.js @@ -0,0 +1,122 @@ +/*global storage*/ +import { map, toLower } from 'lodash'; + +const defaultVersion = '0.1.0'; + +export const getKey = (prefix, accountAddress, network) => + `${prefix}-${toLower(accountAddress)}-${toLower(network)}`; + +/** + * @desc save to storage + * @param {String} [key=''] + * @param {Object} [data={}] + * @param {String} [version=defaultVersion] + */ +export const saveLocal = async ( + key = '', + data = {}, + version = defaultVersion +) => { + try { + data.storageVersion = version; + await storage.save({ + data, + expires: null, + key, + }); + } catch (error) { + console.log('Storage: error saving to local for key', key); + } +}; + +/** + * @desc get from storage + * @param {String} [key=''] + * @return {Object} + */ +export const getLocal = async (key = '', version = defaultVersion) => { + try { + const result = await storage.load({ + autoSync: false, + key, + syncInBackground: false, + }); + if (result && result.storageVersion === version) { + return result; + } + if (result) { + removeLocal(key); + return null; + } + return null; + } catch (error) { + console.log('Storage: error getting from local for key', key); + return null; + } +}; + +/** + * @desc get from storage + * @param {String} [key=''] + * @return {Object} + */ +export const removeLocal = (key = '') => { + try { + storage.remove({ key }); + } catch (error) { + console.log('Storage: error removing local with key', key); + } +}; + +export const removeMultiLocal = async keys => { + try { + await storage.multiRemove(keys); + } catch (error) { + console.log('Storage: error removing multiple keys', keys); + } +}; + +export const getGlobal = async ( + key, + emptyState = [], + version = defaultVersion +) => { + const result = await getLocal(key, version); + return result ? result.data : emptyState; +}; + +export const saveGlobal = (key, data, version = defaultVersion) => + saveLocal(key, { data }, version); + +export const getAccountLocal = async ( + prefix, + accountAddress, + network, + emptyState = [], + version = defaultVersion +) => { + const key = getKey(prefix, accountAddress, network); + const result = await getLocal(key, version); + return result ? result.data : emptyState; +}; + +export const saveAccountLocal = ( + prefix, + data, + accountAddress, + network, + version = defaultVersion +) => saveLocal(getKey(prefix, accountAddress, network), { data }, version); + +export const removeAccountLocal = (prefix, accountAddress, network) => { + const key = getKey(prefix, accountAddress, network); + removeLocal(key); +}; + +export const getAccountLocalKeys = (prefixes, accountAddress, network) => + map(prefixes, prefix => getKey(prefix, accountAddress, network)); + +export const removeAccountLocalMulti = (prefixes, accountAddress, network) => { + const keys = getAccountLocalKeys(prefixes, accountAddress, network); + removeMultiLocal(keys); +}; diff --git a/src/handlers/localstorage/contacts.js b/src/handlers/localstorage/contacts.js new file mode 100644 index 00000000000..63fe9ef8282 --- /dev/null +++ b/src/handlers/localstorage/contacts.js @@ -0,0 +1,17 @@ +import { getGlobal, saveGlobal } from './common'; + +const LOCAL_CONTACTS = 'localContacts'; + +const contactsVersion = '0.2.1'; + +/** + * @desc get contacts + * @return {Object} + */ +export const getContacts = () => getGlobal(LOCAL_CONTACTS, [], contactsVersion); + +/** + * @desc save contacts + */ +export const saveContacts = contacts => + saveGlobal(LOCAL_CONTACTS, contacts, contactsVersion); diff --git a/src/handlers/localstorage/globalSettings.js b/src/handlers/localstorage/globalSettings.js new file mode 100644 index 00000000000..c9ba82441ad --- /dev/null +++ b/src/handlers/localstorage/globalSettings.js @@ -0,0 +1,24 @@ +import { getGlobal, saveGlobal } from './common'; + +const APPSTORE_REVIEW_COUNT = 'appStoreReviewRequestCount'; +const KEYBOARD_HEIGHT = 'keyboardHeight'; +const LANGUAGE = 'language'; +const NATIVE_CURRENCY = 'nativeCurrency'; + +export const getAppStoreReviewCount = () => getGlobal(APPSTORE_REVIEW_COUNT, 0); + +export const saveAppStoreReviewCount = reviewCount => + saveGlobal(APPSTORE_REVIEW_COUNT, reviewCount); + +export const getLanguage = () => getGlobal(LANGUAGE, 'en'); + +export const saveLanguage = language => saveGlobal(LANGUAGE, language); + +export const getKeyboardHeight = () => getGlobal(KEYBOARD_HEIGHT, null); + +export const setKeyboardHeight = height => saveGlobal(KEYBOARD_HEIGHT, height); + +export const getNativeCurrency = () => getGlobal(NATIVE_CURRENCY, 'USD'); + +export const saveNativeCurrency = nativeCurrency => + saveGlobal(NATIVE_CURRENCY, nativeCurrency); diff --git a/src/handlers/localstorage/uniswap.js b/src/handlers/localstorage/uniswap.js new file mode 100644 index 00000000000..b79fd9d284f --- /dev/null +++ b/src/handlers/localstorage/uniswap.js @@ -0,0 +1,74 @@ +import { forEach } from 'lodash'; +import { DefaultUniswapFavorites } from '../../references'; +import { + getAccountLocal, + getGlobal, + saveAccountLocal, + saveGlobal, + removeAccountLocal, +} from './common'; + +const ASSETS = 'uniswapassets'; +const ALLOWANCES = 'uniswapallowances'; +const LIQUIDITY = 'uniswapliquidity'; +const LIQUIDITY_INFO = 'uniswap'; +const PENDING_APPROVALS = 'uniswappendingapprovals'; +const UNISWAP_FAVORITES = 'uniswapFavorites'; + +const uniswapAccountLocalKeys = [ + ASSETS, + ALLOWANCES, + LIQUIDITY, + LIQUIDITY_INFO, + PENDING_APPROVALS, +]; + +export const getUniswapFavorites = () => + getGlobal(UNISWAP_FAVORITES, DefaultUniswapFavorites); + +export const saveUniswapFavorites = favorites => + saveGlobal(UNISWAP_FAVORITES, favorites); + +export const getUniswapLiquidityInfo = (accountAddress, network) => + getAccountLocal(LIQUIDITY_INFO, accountAddress, network, {}); + +export const saveLiquidityInfo = (liquidityInfo, accountAddress, network) => + saveAccountLocal(LIQUIDITY_INFO, liquidityInfo, accountAddress, network); + +export const getLiquidity = (accountAddress, network) => + getAccountLocal(LIQUIDITY, accountAddress, network); + +export const saveLiquidity = (liquidity, accountAddress, network) => + saveAccountLocal(LIQUIDITY, liquidity, accountAddress, network); + +export const getAllowances = (accountAddress, network) => + getAccountLocal(ALLOWANCES, accountAddress, network, {}); + +export const saveAllowances = (allowances, accountAddress, network) => + saveAccountLocal(ALLOWANCES, allowances, accountAddress, network); + +export const getUniswapAssets = (accountAddress, network) => + getAccountLocal(ASSETS, accountAddress, network, {}); + +export const saveUniswapAssets = (assets, accountAddress, network) => + saveAccountLocal(ASSETS, assets, accountAddress, network); + +export const getUniswapPendingApprovals = (accountAddress, network) => + getAccountLocal(PENDING_APPROVALS, accountAddress, network, {}); + +export const saveUniswapPendingApprovals = ( + pendingApprovals, + accountAddress, + network +) => + saveAccountLocal( + PENDING_APPROVALS, + pendingApprovals, + accountAddress, + network + ); + +export const removeUniswapStorage = (accountAddress, network) => + forEach(uniswapAccountLocalKeys, key => + removeAccountLocal(key, accountAddress, network) + ); diff --git a/src/handlers/localstorage/walletconnect.js b/src/handlers/localstorage/walletconnect.js new file mode 100644 index 00000000000..36c2189495a --- /dev/null +++ b/src/handlers/localstorage/walletconnect.js @@ -0,0 +1,130 @@ +import { differenceInMinutes } from 'date-fns'; +import { omit, pickBy } from 'lodash'; +import { + getAccountLocal, + removeAccountLocal, + saveAccountLocal, +} from './common'; + +const REQUESTS = 'requests'; +const WALLETCONNECT = 'walletconnect'; + +/** + * @desc get all wallet connect sessions + * @return {Object} + */ +export const getAllValidWalletConnectSessions = async ( + accountAddress, + network +) => { + const allSessions = await getAllWalletConnectSessions( + accountAddress, + network + ); + return pickBy(allSessions, value => value.connected); +}; + +/** + * @desc get all wallet connect sessions + * @return {Object} + */ +const getAllWalletConnectSessions = (accountAddress, network) => + getAccountLocal(WALLETCONNECT, accountAddress, network, {}); + +/** + * @desc save wallet connect session + * @param {String} [peerId] + * @param {Object} [session] + */ +export const saveWalletConnectSession = async ( + peerId, + session, + accountAddress, + network +) => { + const allSessions = await getAllValidWalletConnectSessions( + accountAddress, + network + ); + allSessions[peerId] = session; + await saveAccountLocal(WALLETCONNECT, allSessions, accountAddress, network); +}; + +/** + * @desc remove wallet connect sessions + * @param {String} [sessionId] + */ +export const removeWalletConnectSessions = async ( + sessionIds, + accountAddress, + network +) => { + const allSessions = await getAllWalletConnectSessions( + accountAddress, + network + ); + const resultingSessions = omit(allSessions, sessionIds); + await saveAccountLocal( + WALLETCONNECT, + resultingSessions, + accountAddress, + network + ); +}; + +/** + * @desc remove all wallet connect sessions + * @param {String} [sessionId] + */ +export const removeWalletConnect = (accountAddress, network) => + removeAccountLocal(WALLETCONNECT, accountAddress, network); + +const isRequestStillValid = request => { + const createdAt = request.displayDetails.timestampInMs; + return differenceInMinutes(Date.now(), createdAt) < 60; +}; + +/** + * @desc get account local requests + * @param {String} [address] + * @return {Object} + */ +export const getLocalRequests = async (accountAddress, network) => { + const requests = getAccountLocal(REQUESTS, accountAddress, network, {}); + const openRequests = pickBy(requests, isRequestStillValid); + await saveLocalRequests(openRequests, accountAddress, network); + return openRequests; +}; + +/** + * @desc save local incoming requests + * @param {String} [address] + * @param {String} [network] + * @return {Void} + */ +export const saveLocalRequests = async (requests, accountAddress, network) => + saveAccountLocal(REQUESTS, requests, accountAddress, network); + +/** + * @desc remove request + * @param {String} [address] + * @param {String} [network] + * @param {String} [requestId] + * @return {Void} + */ +export const removeLocalRequest = async (address, network, requestId) => { + const requests = await getLocalRequests(address, network); + const updatedRequests = { ...requests }; + delete updatedRequests[requestId]; + await saveLocalRequests(updatedRequests, address, network); +}; + +/** + * @desc remove all requests + * @param {String} [address] + * @param {String} [network] + * @param {String} [requestId] + * @return {Void} + */ +export const removeLocalRequests = async (accountAddress, network) => + removeAccountLocal(REQUESTS, accountAddress, network); diff --git a/src/handlers/tokenOverrides.js b/src/handlers/tokenOverrides.js new file mode 100644 index 00000000000..285da0347ad --- /dev/null +++ b/src/handlers/tokenOverrides.js @@ -0,0 +1,30 @@ +import axios from 'axios'; +import { get, mapKeys, toLower } from 'lodash'; + +/** + * Configuration for api + * @type axios instance + */ +const tokenOverridesEndpoint = axios.create({ + baseURL: + 'https://raw.githubusercontent.com/rainbow-me/asset-overrides/master/token-overrides.json', + headers: { + Accept: 'application/json', + }, + timeout: 20000, // 20 secs +}); + +/** + * @desc get token overrides + * @return {Promise} + */ +export const apiGetTokenOverrides = async () => { + try { + const data = await tokenOverridesEndpoint.get(); + const overrides = get(data, 'data') || {}; + return mapKeys(overrides, (value, address) => toLower(address)); + } catch (error) { + console.log('Error getting token overrides', error); + throw error; + } +}; diff --git a/src/handlers/uniswap.js b/src/handlers/uniswap.js index f45eab3bb76..c34f82edc77 100644 --- a/src/handlers/uniswap.js +++ b/src/handlers/uniswap.js @@ -1,21 +1,205 @@ +import { getExecutionDetails, getTokenReserves } from '@uniswap/sdk'; +import axios from 'axios'; import contractMap from 'eth-contract-metadata'; import { ethers } from 'ethers'; -import { get, map, zipObject } from 'lodash'; +import { get, map, mapKeys, mapValues, toLower, zipObject } from 'lodash'; import { convertRawAmountToDecimalFormat, divide, fromWei, multiply, } from '../helpers/utilities'; +import { loadWallet } from '../model/wallet'; import exchangeABI from '../references/uniswap-exchange-abi.json'; import erc20ABI from '../references/erc20-abi.json'; -import { web3Provider } from './web3'; +import { toHex, web3Provider } from './web3'; -export default async function getUniswapLiquidityInfo(accountAddress, exchangeContracts) { - const promises = map(exchangeContracts, async (exchangeAddress) => { +const uniswapPairsEndpoint = axios.create({ + baseURL: + 'https://raw.githubusercontent.com/rainbow-me/asset-overrides/master/uniswap-pairs.json', + headers: { + Accept: 'application/json', + }, + timeout: 20000, // 20 secs +}); + +export const getUniswapPairs = async tokenOverrides => { + try { + const data = await uniswapPairsEndpoint.get(); + const pairs = get(data, 'data') || {}; + const loweredPairs = mapKeys(pairs, (_, key) => toLower(key)); + return mapValues(loweredPairs, (value, key) => ({ + ...value, + ...tokenOverrides[key], + })); + } catch (error) { + console.log('Error getting uniswap pairs', error); + throw error; + } +}; + +const convertArgsForEthers = methodArguments => + methodArguments.map(arg => + typeof arg === 'object' ? ethers.utils.bigNumberify(arg.toFixed()) : arg + ); + +const convertValueForEthers = value => { + const valueBigNumber = ethers.utils.bigNumberify(value.toString()); + return ethers.utils.hexlify(valueBigNumber); +}; + +export const getReserve = async tokenAddress => + !tokenAddress || tokenAddress === 'eth' + ? Promise.resolve(null) + : getTokenReserves(toLower(tokenAddress)); + +const getGasLimit = async ( + accountAddress, + exchange, + methodName, + updatedMethodArgs, + value +) => { + const params = { from: accountAddress, value }; + switch (methodName) { + case 'ethToTokenSwapInput': + return exchange.estimate.ethToTokenSwapInput( + ...updatedMethodArgs, + params + ); + case 'ethToTokenSwapOutput': + return exchange.estimate.ethToTokenSwapOutput( + ...updatedMethodArgs, + params + ); + case 'tokenToEthSwapInput': + return exchange.estimate.tokenToEthSwapInput( + ...updatedMethodArgs, + params + ); + case 'tokenToEthSwapOutput': + return exchange.estimate.tokenToEthSwapOutput( + ...updatedMethodArgs, + params + ); + case 'tokenToTokenSwapInput': + return exchange.estimate.tokenToTokenSwapInput( + ...updatedMethodArgs, + params + ); + case 'tokenToTokenSwapOutput': + return exchange.estimate.tokenToTokenSwapOutput( + ...updatedMethodArgs, + params + ); + default: + return null; + } +}; + +export const estimateSwapGasLimit = async (accountAddress, tradeDetails) => { + try { + const { + exchange, + methodName, + updatedMethodArgs, + value, + } = getContractExecutionDetails(tradeDetails, web3Provider); + const gasLimit = await getGasLimit( + accountAddress, + exchange, + methodName, + updatedMethodArgs, + value + ); + return gasLimit ? gasLimit.toString() : null; + } catch (error) { + return null; + } +}; + +export const getContractExecutionDetails = (tradeDetails, providerOrSigner) => { + const executionDetails = getExecutionDetails(tradeDetails); + const { + exchangeAddress, + methodArguments, + methodName, + value: rawValue, + } = executionDetails; + const exchange = new ethers.Contract( + exchangeAddress, + exchangeABI, + providerOrSigner + ); + const updatedMethodArgs = convertArgsForEthers(methodArguments); + const value = convertValueForEthers(rawValue); + return { + exchange, + methodName, + updatedMethodArgs, + value, + }; +}; + +export const executeSwap = async (tradeDetails, gasLimit, gasPrice) => { + const wallet = await loadWallet(); + if (!wallet) return null; + const { + exchange, + methodName, + updatedMethodArgs, + value, + } = getContractExecutionDetails(tradeDetails, wallet); + const transactionParams = { + gasLimit: gasLimit ? toHex(gasLimit) : undefined, + gasPrice: gasPrice ? toHex(gasPrice) : undefined, + value, + }; + switch (methodName) { + case 'ethToTokenSwapInput': + return exchange.ethToTokenSwapInput( + ...updatedMethodArgs, + transactionParams + ); + case 'ethToTokenSwapOutput': + return exchange.ethToTokenSwapOutput( + ...updatedMethodArgs, + transactionParams + ); + case 'tokenToEthSwapInput': + return exchange.tokenToEthSwapInput( + ...updatedMethodArgs, + transactionParams + ); + case 'tokenToEthSwapOutput': + return exchange.tokenToEthSwapOutput( + ...updatedMethodArgs, + transactionParams + ); + case 'tokenToTokenSwapInput': + return exchange.tokenToTokenSwapInput( + ...updatedMethodArgs, + transactionParams + ); + case 'tokenToTokenSwapOutput': + return exchange.tokenToTokenSwapOutput( + ...updatedMethodArgs, + transactionParams + ); + default: + return null; + } +}; + +export const getLiquidityInfo = async (accountAddress, exchangeContracts) => { + const promises = map(exchangeContracts, async exchangeAddress => { try { const ethReserveCall = web3Provider.getBalance(exchangeAddress); - const exchange = new ethers.Contract(exchangeAddress, exchangeABI, web3Provider); + const exchange = new ethers.Contract( + exchangeAddress, + exchangeABI, + web3Provider + ); const tokenAddressCall = exchange.tokenAddress(); const balanceCall = exchange.balanceOf(accountAddress); const totalSupplyCall = exchange.totalSupply(); @@ -32,11 +216,18 @@ export default async function getUniswapLiquidityInfo(accountAddress, exchangeCo totalSupplyCall, ]); - const tokenContract = new ethers.Contract(tokenAddress, erc20ABI, web3Provider); + const tokenContract = new ethers.Contract( + tokenAddress, + erc20ABI, + web3Provider + ); const tokenReserveCall = tokenContract.balanceOf(exchangeAddress); const tokenDecimalsCall = tokenContract.decimals(); - const [reserve, decimals] = await Promise.all([tokenReserveCall, tokenDecimalsCall]); + const [reserve, decimals] = await Promise.all([ + tokenReserveCall, + tokenDecimalsCall, + ]); let name = ''; try { @@ -44,7 +235,12 @@ export default async function getUniswapLiquidityInfo(accountAddress, exchangeCo } catch (error) { name = get(contractMap, `[${tokenAddress}].name`, ''); if (!name) { - console.log('error getting name for token: ', tokenAddress, ' Error = ', error); + console.log( + 'error getting name for token: ', + tokenAddress, + ' Error = ', + error + ); } } @@ -53,11 +249,21 @@ export default async function getUniswapLiquidityInfo(accountAddress, exchangeCo symbol = await tokenContract.symbol().catch(); } catch (error) { if (!symbol) { - console.log('error getting symbol for token: ', tokenAddress, ' Error = ', error); + console.log( + 'error getting symbol for token: ', + tokenAddress, + ' Error = ', + error + ); } } - const ethBalance = fromWei(divide(multiply(ethReserve, balance), totalSupply)); - const tokenBalance = convertRawAmountToDecimalFormat(divide(multiply(reserve, balance), totalSupply), decimals); + const ethBalance = fromWei( + divide(multiply(ethReserve, balance), totalSupply) + ); + const tokenBalance = convertRawAmountToDecimalFormat( + divide(multiply(reserve, balance), totalSupply), + decimals + ); return { balance, @@ -81,4 +287,4 @@ export default async function getUniswapLiquidityInfo(accountAddress, exchangeCo const results = await Promise.all(promises); return zipObject(exchangeContracts, results); -} +}; diff --git a/src/handlers/web3.js b/src/handlers/web3.js index 2b3c8c6e48e..2fed1b85df8 100644 --- a/src/handlers/web3.js +++ b/src/handlers/web3.js @@ -1,9 +1,5 @@ import { ethers } from 'ethers'; -import { - get, - replace, - startsWith, -} from 'lodash'; +import { get, replace, startsWith } from 'lodash'; import { REACT_APP_INFURA_PROJECT_ID } from 'react-native-dotenv'; import { ethereumUtils } from '../utils'; import { @@ -19,17 +15,22 @@ const infuraUrl = `https://network.infura.io/v3/${REACT_APP_INFURA_PROJECT_ID}`; /** * @desc web3 http instance */ -export let web3Provider = new ethers.providers.JsonRpcProvider(replace(infuraUrl, 'network', 'mainnet')); +export let web3Provider = new ethers.providers.JsonRpcProvider( + replace(infuraUrl, 'network', 'mainnet') +); /** * @desc set a different web3 provider * @param {String} network */ export const web3SetHttpProvider = network => { - web3Provider = new ethers.providers.JsonRpcProvider(replace(infuraUrl, 'network', network)); + web3Provider = new ethers.providers.JsonRpcProvider( + replace(infuraUrl, 'network', network) + ); }; -export const sendRpcCall = async (payload) => web3Provider.send(payload.method, payload.params); +export const sendRpcCall = async payload => + web3Provider.send(payload.method, payload.params); /** * @desc check if hex string @@ -44,23 +45,26 @@ export const isHexStringIgnorePrefix = value => { return isHexString(updatedValue); }; -export const addHexPrefix = value => (startsWith(value, '0x')) ? value : '0x' + value; +export const addHexPrefix = value => + startsWith(value, '0x') ? value : `0x${value}`; -export const mnemonicToSeed = value => ethers.utils.HDNode.mnemonicToSeed(value); +export const mnemonicToSeed = value => + ethers.utils.HDNode.mnemonicToSeed(value); /** * @desc is valid mnemonic * @param {String} value * @return {Boolean} */ -export const isValidMnemonic = value => ethers.utils.HDNode.isValidMnemonic(value); +export const isValidMnemonic = value => + ethers.utils.HDNode.isValidMnemonic(value); /** * @desc convert to checksum address * @param {String} address * @return {String} checksum address */ -export const toChecksumAddress = async (address) => { +export const toChecksumAddress = async address => { try { return await ethers.utils.getAddress(address); } catch (error) { @@ -73,15 +77,16 @@ export const toChecksumAddress = async (address) => { * @param {String|Number} value * @return {String} hex value */ -export const toHex = value => ethers.utils.hexlify(ethers.utils.bigNumberify(value)); +export const toHex = value => + ethers.utils.hexlify(ethers.utils.bigNumberify(value)); /** * @desc has ETH balance * @param {String} address * @return {Boolean} */ -export const hasEthBalance = async (address) => { - const weiBalance = await web3Provider.getBalance(address, "pending"); +export const hasEthBalance = async address => { + const weiBalance = await web3Provider.getBalance(address, 'pending'); return weiBalance > 0; }; @@ -90,12 +95,12 @@ export const hasEthBalance = async (address) => { * @param {String} address * @return {Number} gas limit */ -export const estimateGas = async (estimateGasData) => { +export const estimateGas = async estimateGasData => { try { const gasLimit = await web3Provider.estimateGas(estimateGasData); return gasLimit.toNumber(); } catch (error) { - return 21000; + return null; } }; @@ -123,30 +128,29 @@ export const toWei = ether => { * @param {String} address * @return {Promise} */ -export const getTransactionCount = address => web3Provider.getTransactionCount(address, 'pending'); +export const getTransactionCount = address => + web3Provider.getTransactionCount(address, 'pending'); /** * @desc get transaction details * @param {Object} transaction { from, to, data, value, gasPrice, gasLimit } * @return {Object} */ -export const getTxDetails = async (transaction) => { +export const getTxDetails = async transaction => { const { from, to } = transaction; const data = transaction.data ? transaction.data : '0x'; const value = transaction.amount ? toWei(transaction.amount) : '0x00'; - const estimateGasData = { - data, - from, - to, - value, - }; - const _gasLimit = transaction.gasLimit || (await estimateGas(estimateGasData)); - const _gasPrice = transaction.gasPrice || (await getGasPrice()); + const gasLimit = transaction.gasLimit + ? toHex(transaction.gasLimit) + : undefined; + const gasPrice = transaction.gasPrice + ? toHex(transaction.gasPrice) + : undefined; const nonce = await getTransactionCount(from); const tx = { data, - gasLimit: toHex(_gasLimit), - gasPrice: toHex(_gasPrice), + gasLimit, + gasPrice, nonce: toHex(nonce), to, value: toHex(value), @@ -154,7 +158,7 @@ export const getTxDetails = async (transaction) => { return tx; }; -export const resolveNameOrAddress = async (nameOrAddress) => { +export const resolveNameOrAddress = async nameOrAddress => { if (!isHexString(nameOrAddress)) { return web3Provider.resolveName(nameOrAddress); } @@ -166,7 +170,7 @@ export const resolveNameOrAddress = async (nameOrAddress) => { * @param {Object} transaction { asset, from, to, gasPrice } * @return {Object} */ -export const getTransferNftTransaction = async (transaction) => { +export const getTransferNftTransaction = async transaction => { const recipient = await resolveNameOrAddress(transaction.to); const { from } = transaction; const contractAddress = get(transaction, 'asset.asset_contract.address'); @@ -185,8 +189,11 @@ export const getTransferNftTransaction = async (transaction) => { * @param {Object} transaction { asset, from, to, amount, gasPrice } * @return {Object} */ -export const getTransferTokenTransaction = async (transaction) => { - const value = convertAmountToRawAmount(transaction.amount, transaction.asset.decimals); +export const getTransferTokenTransaction = async transaction => { + const value = convertAmountToRawAmount( + transaction.amount, + transaction.asset.decimals + ); const recipient = await resolveNameOrAddress(transaction.to); const data = getDataForTokenTransfer(value, recipient); return { @@ -203,17 +210,18 @@ export const getTransferTokenTransaction = async (transaction) => { * @param {Object} transaction { asset, from, to, amount, gasPrice } * @return {Promise} */ -export const createSignableTransaction = async (transaction) => { +export const createSignableTransaction = async transaction => { if (get(transaction, 'asset.address') === 'eth') { return getTxDetails(transaction); } const isNft = get(transaction, 'asset.isNft', false); - const result = isNft ? await getTransferNftTransaction(transaction) + const result = isNft + ? await getTransferNftTransaction(transaction) : await getTransferTokenTransaction(transaction); return getTxDetails(result); }; -const estimateAssetBalancePortion = (asset) => { +const estimateAssetBalancePortion = asset => { if (!asset.isNft) { const assetBalance = get(asset, 'balance.amount'); const decimals = get(asset, 'decimals'); @@ -263,9 +271,10 @@ export const estimateGasLimit = async ({ recipient, amount, }) => { - const _amount = amount && Number(amount) - ? convertAmountToRawAmount(amount, asset.decimals) - : estimateAssetBalancePortion(asset); + const _amount = + amount && Number(amount) + ? convertAmountToRawAmount(amount, asset.decimals) + : estimateAssetBalancePortion(asset); const value = _amount.toString(); let _recipient = await resolveNameOrAddress(recipient); _recipient = _recipient || '0x737e583620f4ac1842d4e354789ca0c5e0651fbb'; diff --git a/src/helpers/__tests__/utilities.test.js b/src/helpers/__tests__/utilities.test.js new file mode 100644 index 00000000000..65580ae3e37 --- /dev/null +++ b/src/helpers/__tests__/utilities.test.js @@ -0,0 +1,132 @@ +import { + convertAmountFromNativeValue, + convertBipsToPercentage, + handleSignificantDecimals, + updatePrecisionToDisplay, +} from '../utilities'; + +it('convertAmountFromNativeValue', () => { + const result = convertAmountFromNativeValue('1', '40.00505', 5); + expect(result).toBe('0.02499'); +}); + +it('convertAmountFromNativeValue with trailing zeros', () => { + const result = convertAmountFromNativeValue('1', '1', 5); + expect(result).toBe('1'); +}); + +it('handleSignificantDecimals greater than 1, decimals 2', () => { + const result = handleSignificantDecimals('5.123', 2); + expect(result).toBe('5.12'); +}); + +it('handleSignificantDecimals greater than 1, decimals 18', () => { + const result = handleSignificantDecimals('5.1234', 18); + expect(result).toBe('5.123'); +}); + +it('handleSignificantDecimals greater than 1, decimals 18, long trail', () => { + const result = handleSignificantDecimals('5.00001234', 18); + expect(result).toBe('5.00'); +}); + +it('handleSignificantDecimals less than 1 and few decimals', () => { + const result = handleSignificantDecimals('0.012344', 2); + expect(result).toBe('0.0123'); +}); + +it('handleSignificantDecimals less than 1 and many decimals', () => { + const result = handleSignificantDecimals('0.00000000123', 18); + expect(result).toBe('0.00'); +}); + +it('convertBipsToPercentage, 2 decimal places', () => { + const result = convertBipsToPercentage('1', 2); + expect(result).toBe('0.01'); +}); + +it('convertBipsToPercentage, 1 decimal place', () => { + const result = convertBipsToPercentage('1', 1); + expect(result).toBe('0.0'); +}); + +it('convertBipsToPercentage, 10 bips to 1 decimal', () => { + const result = convertBipsToPercentage('10', 1); + expect(result).toBe('0.1'); +}); + +it('convertBipsToPercentage', () => { + const result = convertBipsToPercentage('12.34567', 2); + expect(result).toBe('0.12'); +}); + +it('updatePrecisionToDisplay1', () => { + const result = updatePrecisionToDisplay('0.00000000123', '0.1234987234'); + expect(result).toBe('0.000000001'); +}); + +it('updatePrecisionToDisplay1RoundUp', () => { + const result = updatePrecisionToDisplay( + '0.00000000123', + '0.1234987234', + true + ); + expect(result).toBe('0.000000002'); +}); + +it('updatePrecisionToDisplay2', () => { + const result = updatePrecisionToDisplay( + '0.17987196800000002', + '0.1234987234' + ); + expect(result).toBe('0.179'); +}); + +it('updatePrecisionToDisplay2RoundUp', () => { + const result = updatePrecisionToDisplay( + '0.17987196800000002', + '0.1234987234', + true + ); + expect(result).toBe('0.18'); +}); + +it('updatePrecisionToDisplay3', () => { + const result = updatePrecisionToDisplay('0.123456789', '3.001'); + expect(result).toBe('0.123'); +}); + +it('updatePrecisionToDisplay3RoundUp', () => { + const result = updatePrecisionToDisplay('0.123456789', '3.001', true); + expect(result).toBe('0.124'); +}); + +it('updatePrecisionToDisplay4', () => { + const result = updatePrecisionToDisplay('0.123456789', '32.0412'); + expect(result).toBe('0.1234'); +}); + +it('updatePrecisionToDisplay4RoundUp', () => { + const result = updatePrecisionToDisplay('0.123456789', '32.0412', true); + expect(result).toBe('0.1235'); +}); + +it('updatePrecisionToDisplay5', () => { + const result = updatePrecisionToDisplay('0.123456789', '132.0051'); + expect(result).toBe('0.12345'); +}); + +it('updatePrecisionToDisplay5RoundUp', () => { + const result = updatePrecisionToDisplay('0.123456789', '132.0051', true); + expect(result).toBe('0.12346'); +}); + +it('updatePrecisionToDisplay6', () => { + const result = updatePrecisionToDisplay('0.123456789', '1320.0112'); + expect(result).toBe('0.123456'); +}); + +it('updatePrecisionToDisplay6RoundUp', () => { + const result = updatePrecisionToDisplay('0.123456789', '1320.0112', true); + expect(result).toBe('0.123457'); +}); diff --git a/src/helpers/assets.js b/src/helpers/assets.js index b260188a473..0c00e717b9b 100644 --- a/src/helpers/assets.js +++ b/src/helpers/assets.js @@ -1,20 +1,12 @@ -import { - compact, - get, - groupBy, - sortBy, -} from 'lodash'; -import { pushOpenFamilyTab } from '../redux/openFamilyTabs'; -import store from '../redux/store'; +import { compact, get, groupBy, sortBy } from 'lodash'; export const buildAssetHeaderUniqueIdentifier = ({ - showShitcoins, title, totalItems, totalValue, -}) => (compact([showShitcoins, title, totalItems, totalValue]).join('_')); +}) => compact([title, totalItems, totalValue]).join('_'); -export const buildAssetUniqueIdentifier = (item) => { +export const buildAssetUniqueIdentifier = item => { const balance = get(item, 'balance.amount', ''); const nativePrice = get(item, 'native.price.display', ''); const uniqueId = get(item, 'uniqueId'); @@ -22,7 +14,32 @@ export const buildAssetUniqueIdentifier = (item) => { return compact([balance, nativePrice, uniqueId]).join('_'); }; -export const buildUniqueTokenList = (uniqueTokens) => { +export const buildCoinsList = assets => { + const newAssets = []; + const smallBalances = { + assets: [], + smallBalancesContainer: true, + }; + for (let i = 0; i < assets.length; i++) { + if ( + (assets[i].native && assets[i].native.balance.amount > 1) || + assets[i].address === 'eth' || + assets.length < 4 + ) { + newAssets.push(assets[i]); + } else { + smallBalances.assets.push(assets[i]); + } + } + + if (smallBalances.assets.length > 0) { + newAssets.push(smallBalances); + return newAssets; + } + return newAssets; +}; + +export const buildUniqueTokenList = uniqueTokens => { let rows = []; const grouped = groupBy(uniqueTokens, token => token.asset_contract.name); @@ -42,15 +59,12 @@ export const buildUniqueTokenList = (uniqueTokens) => { childrenAmount: grouped[families[i]].length, familyImage: get(tokensRow, '[0][0].familyImage', null), familyName: families[i], + stableId: tokensRow[0].map(({ uniqueId }) => uniqueId).join('__'), tokens, uniqueId: tokensRow[0].map(({ uniqueId }) => uniqueId).join('__'), }); } - while (rows.length > store.getState().openFamilyTabs.openFamilyTabs.length) { - store.dispatch(pushOpenFamilyTab()); - } - rows = sortBy(rows, ['familyName']); rows.forEach((row, i) => { row.familyId = i; @@ -59,8 +73,5 @@ export const buildUniqueTokenList = (uniqueTokens) => { return rows; }; -/* eslint-disable camelcase */ -export const buildUniqueTokenName = ({ asset_contract, id, name }) => ( - name || `${asset_contract.name} #${id}` -); -/* eslint-enable camelcase */ +export const buildUniqueTokenName = ({ asset_contract, id, name }) => + name || `${asset_contract.name} #${id}`; diff --git a/src/helpers/buildWalletSections.js b/src/helpers/buildWalletSections.js index d168eb0c1a9..7edb5bc60cc 100644 --- a/src/helpers/buildWalletSections.js +++ b/src/helpers/buildWalletSections.js @@ -1,12 +1,5 @@ import lang from 'i18n-js'; -import { - compact, - findIndex, - flattenDeep, - get, - groupBy, - property, -} from 'lodash'; +import { compact, flattenDeep, get, groupBy, property } from 'lodash'; import React from 'react'; import FastImage from 'react-native-fast-image'; import { withNavigation } from 'react-navigation'; @@ -16,7 +9,7 @@ import { AssetListItemSkeleton } from '../components/asset-list'; import { BalanceCoinRow } from '../components/coin-row'; import { UniswapInvestmentCard } from '../components/investment-cards'; import { TokenFamilyWrap } from '../components/token-family'; -import { buildUniqueTokenList } from './assets'; +import { buildUniqueTokenList, buildCoinsList } from './assets'; const allAssetsSelector = state => state.allAssets; const allAssetsCountSelector = state => state.allAssetsCount; @@ -26,10 +19,7 @@ const isBalancesSectionEmptySelector = state => state.isBalancesSectionEmpty; const isWalletEthZeroSelector = state => state.isWalletEthZero; const languageSelector = state => state.language; const nativeCurrencySelector = state => state.nativeCurrency; -const onToggleShowShitcoinsSelector = state => state.onToggleShowShitcoins; const setIsWalletEmptySelector = state => state.setIsWalletEmpty; -const shitcoinsCountSelector = state => state.shitcoinsCount; -const showShitcoinsSelector = state => state.showShitcoins; const uniqueTokensSelector = state => state.uniqueTokens; const uniswapSelector = state => state.uniswap; const uniswapTotalSelector = state => state.uniswapTotal; @@ -37,74 +27,45 @@ const uniswapTotalSelector = state => state.uniswapTotal; const enhanceRenderItem = compose( withNavigation, withHandlers({ - onPress: ({ assetType, navigation }) => (item) => { + onPress: ({ assetType, navigation }) => item => { navigation.navigate('ExpandedAssetScreen', { asset: item, type: assetType, }); }, - onPressSend: ({ navigation }) => (asset) => { + onPressSend: ({ navigation }) => asset => { navigation.navigate('SendSheet', { asset }); }, - }), + }) ); const TokenItem = enhanceRenderItem(BalanceCoinRow); const UniswapCardItem = enhanceRenderItem(UniswapInvestmentCard); const balancesSkeletonRenderItem = item => ( - + ); const balancesRenderItem = item => ; -const tokenFamilyItem = item => ; -const uniswapRenderItem = item => ; - -const filterWalletSections = sections => ( - sections.filter(({ data, header }) => ( - data - ? get(header, 'totalItems') - : true - )) +const tokenFamilyItem = item => ( + +); +const uniswapRenderItem = item => ( + ); +const filterWalletSections = sections => + sections.filter(({ data, header }) => + data ? get(header, 'totalItems') : true + ); + const buildWalletSections = ( balanceSection, - language, - nativeCurrency, - onToggleShowShitcoins, setIsWalletEmpty, - shitcoinsCount, - showShitcoins, uniqueTokenFamiliesSection, - uniswapSection, + uniswapSection ) => { - const sections = [ - balanceSection, - uniswapSection, - uniqueTokenFamiliesSection, - ]; - - if (shitcoinsCount) { - // 99 is an arbitrarily high number used to disable the 'destructiveButton' option - const destructiveButtonIndex = showShitcoins ? 0 : 99; + const sections = [balanceSection, uniswapSection, uniqueTokenFamiliesSection]; - const index = findIndex(sections, (section) => section.balances === true); - if (index > -1) { - sections[index].header.contextMenuOptions = { - cancelButtonIndex: 1, - destructiveButtonIndex, - onPressActionSheet: onToggleShowShitcoins, - options: [ - `${lang.t(`account.${showShitcoins ? 'hide' : 'show'}`)} ${lang.t('wallet.assets.no_price')}`, - lang.t('wallet.action.cancel'), - ], - }; - } - } const filteredSections = filterWalletSections(sections); const isEmpty = !filteredSections.length; setIsWalletEmpty(isEmpty); @@ -119,7 +80,7 @@ const withUniswapSection = ( language, nativeCurrency, uniswap, - uniswapTotal, + uniswapTotal ) => ({ data: uniswap, header: { @@ -141,10 +102,10 @@ const withBalanceSection = ( isWalletEthZero, language, nativeCurrency, - showShitcoins, + showShitcoins ) => { - let balanceSectionData = showShitcoins ? allAssets : assets; - const isLoadingBalances = (!isWalletEthZero && isBalancesSectionEmpty); + let balanceSectionData = buildCoinsList(allAssets); + const isLoadingBalances = !isWalletEthZero && isBalancesSectionEmpty; if (isLoadingBalances) { balanceSectionData = [{ item: { uniqueId: 'skeleton0' } }]; } @@ -182,23 +143,22 @@ const buildImagesToPreloadArray = (family, index, families) => { if (rowIndex <= largeFamilyThreshold) { priority = FastImage.priority.high; } else if (isJumboFamily) { - const isMedium = (rowIndex > largeFamilyThreshold) && (rowIndex <= jumboFamilyThreshold); + const isMedium = + rowIndex > largeFamilyThreshold && rowIndex <= jumboFamilyThreshold; priority = FastImage.priority[isMedium ? 'normal' : 'low']; } else { priority = FastImage.priority.normal; } } - /* eslint-disable camelcase */ const images = token.map(({ image_preview_url, uniqueId }) => { if (!image_preview_url) return null; - return ({ + return { id: uniqueId, priority, uri: image_preview_url, - }); + }; }); - /* eslint-enable camelcase */ return images.length ? images : null; }); @@ -214,14 +174,12 @@ const sortImagesToPreload = images => { ]; }; -const withUniqueTokenFamiliesSection = ( - language, - uniqueTokens, - data, -) => { +const withUniqueTokenFamiliesSection = (language, uniqueTokens, data) => { // TODO preload elsewhere? if (!isPreloadComplete) { - const imagesToPreload = sortImagesToPreload(data.map(buildImagesToPreloadArray)); + const imagesToPreload = sortImagesToPreload( + data.map(buildImagesToPreloadArray) + ); isPreloadComplete = !!imagesToPreload.length; FastImage.preload(imagesToPreload); } @@ -242,7 +200,7 @@ const withUniqueTokenFamiliesSection = ( const uniqueTokenDataSelector = createSelector( [uniqueTokensSelector], - buildUniqueTokenList, + buildUniqueTokenList ); const balanceSectionSelector = createSelector( @@ -255,9 +213,8 @@ const balanceSectionSelector = createSelector( isWalletEthZeroSelector, languageSelector, nativeCurrencySelector, - showShitcoinsSelector, ], - withBalanceSection, + withBalanceSection ); const uniswapSectionSelector = createSelector( @@ -267,29 +224,20 @@ const uniswapSectionSelector = createSelector( uniswapSelector, uniswapTotalSelector, ], - withUniswapSection, + withUniswapSection ); const uniqueTokenFamiliesSelector = createSelector( - [ - languageSelector, - uniqueTokensSelector, - uniqueTokenDataSelector, - ], - withUniqueTokenFamiliesSection, + [languageSelector, uniqueTokensSelector, uniqueTokenDataSelector], + withUniqueTokenFamiliesSection ); export default createSelector( [ balanceSectionSelector, - languageSelector, - nativeCurrencySelector, - onToggleShowShitcoinsSelector, setIsWalletEmptySelector, - shitcoinsCountSelector, - showShitcoinsSelector, uniqueTokenFamiliesSelector, uniswapSectionSelector, ], - buildWalletSections, + buildWalletSections ); diff --git a/src/helpers/emojiHandler.js b/src/helpers/emojiHandler.js new file mode 100644 index 00000000000..9cf4e9a55df --- /dev/null +++ b/src/helpers/emojiHandler.js @@ -0,0 +1,13 @@ +import GraphemeSplitter from 'grapheme-splitter'; + +const regex = /(?:[\u2700-\u27bf]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff]|[\u0023-\u0039]\ufe0f?\u20e3|\u3299|\u3297|\u303d|\u3030|\u24c2|\ud83c[\udd70-\udd71]|\ud83c[\udd7e-\udd7f]|\ud83c\udd8e|\ud83c[\udd91-\udd9a]|\ud83c[\udde6-\uddff]|\ud83c[\ude01-\ude02]|\ud83c\ude1a|\ud83c\ude2f|\ud83c[\ude32-\ude3a]|\ud83c[\ude50-\ude51]|\u203c|\u2049|[\u25aa-\u25ab]|\u25b6|\u25c0|[\u25fb-\u25fe]|\u00a9|\u00ae|\u2122|\u2139|\ud83c\udc04|[\u2600-\u26FF]|\u2b05|\u2b06|\u2b07|\u2b1b|\u2b1c|\u2b50|\u2b55|\u231a|\u231b|\u2328|\u23cf|[\u23e9-\u23f3]|[\u23f8-\u23fa]|\ud83c\udccf|\u2934|\u2935|[\u2190-\u21ff])/g; + +export const removeFirstEmojiFromString = string => { + const grapheme = new GraphemeSplitter().splitGraphemes(string); + const first = grapheme[0]; + + if (first.search(regex) > -1) { + grapheme.splice(0, 2); + } + return grapheme; +}; diff --git a/src/helpers/keyboardHeight.js b/src/helpers/keyboardHeight.js new file mode 100644 index 00000000000..a088322e5b0 --- /dev/null +++ b/src/helpers/keyboardHeight.js @@ -0,0 +1,23 @@ +export const calculateKeyboardHeight = screenHeight => { + let keyboardHeight = 0; + switch (screenHeight) { + case 568: + keyboardHeight = 216; + break; + case 667: + keyboardHeight = 216; + break; + case 736: + keyboardHeight = 226; + break; + case 812: + keyboardHeight = 291; + break; + case 896: + keyboardHeight = 301; + break; + default: + keyboardHeight = Math.floor(screenHeight * 0.333); + } + return keyboardHeight; +}; diff --git a/src/helpers/sortList.js b/src/helpers/sortList.js index bc254c4f72c..9c35f30db16 100644 --- a/src/helpers/sortList.js +++ b/src/helpers/sortList.js @@ -1,6 +1,12 @@ -import { get, isFunction, isString } from 'lodash'; +import { get, isFunction, isString, toLower } from 'lodash'; -export const sortList = (array = [], sortByKey, direction, defaultValue, formatter) => ( +export const sortList = ( + array = [], + sortByKey, + direction, + defaultValue, + formatter +) => array.slice(0).sort((a, b) => { const isAscending = direction === 'asc'; @@ -18,13 +24,12 @@ export const sortList = (array = [], sortByKey, direction, defaultValue, formatt } if (isString(itemA) && isString(itemB)) { - itemA = itemA.toLowerCase(); - itemB = itemB.toLowerCase(); + itemA = toLower(itemA); + itemB = toLower(itemB); } if (itemA < itemB) return isAscending ? -1 : 1; if (itemA > itemB) return isAscending ? 1 : -1; return 0; - }) -); + }); diff --git a/src/helpers/time.js b/src/helpers/time.js index 7e0df496306..f0318306f39 100644 --- a/src/helpers/time.js +++ b/src/helpers/time.js @@ -1,193 +1,59 @@ -import { - convertStringToNumber, - divide, - formatFixedDecimals, - floorDivide, - greaterThanOrEqual, - mod, - multiply, -} from './utilities'; -import timeUnits from '../references/time-units.json'; +import { findKey, isObjectLike, isString, omitBy, pick } from 'lodash'; +import parseMilliseconds from 'parse-ms'; import lang from '../languages'; +import { convertStringToNumber } from './utilities'; -/** - * @desc get local time & date string - * @param {Number} [timestamp=null] - * @return {String} - */ -export const getLocalTimeDate = (timestamp = null) => { - timestamp = Number(timestamp) || Date.now(); - const date = new Date(timestamp); - return `${date.toLocaleDateString()} ${date.toLocaleTimeString()}`; +const MinimalTimeUnitWhitelist = ['days', 'hours', 'minutes', 'seconds']; + +const buildLocalizedTimeUnitString = ({ plural, short, unit }) => { + const length = short ? 'short' : 'long'; + const plurality = plural ? 'plural' : 'singular'; + + return lang.t(`time.${unit}.${length}.${plurality}`); +}; + +const getHighestResolutionUnit = timeUnitValues => { + const highestResolutionUnit = findKey(timeUnitValues) || 'seconds'; + return { + unit: highestResolutionUnit, + value: timeUnitValues[highestResolutionUnit] || 0, + }; }; +const isZero = number => number === 0; + /** * @desc get time string for minimal unit * @param {String} [value=''] - * @param {String} [unit='ms'] - * @param {Boolean} [short=false] + * @param {Boolean} [short=true] + * @param {Boolean} [plural=false] * @return {String} */ -export const getTimeString = (value = '', unit = 'ms', short = false) => { - if (!value) return null; - let _value = convertStringToNumber(value); - let _unit = ''; - let _unitShort = ''; - if (_value) { - if (unit === 'miliseconds' || unit === 'ms') { - if (_value === 1) { - _unit = lang.t('time.milisecond'); - _unitShort = lang.t('time.ms'); - } else if ( - _value >= timeUnits.ms.second - && _value < timeUnits.ms.minute - ) { - _value = formatFixedDecimals(divide(_value, timeUnits.ms.second), 2); - if (_value === 1) { - _unit = lang.t('time.second'); - _unitShort = lang.t('time.sec'); - } else { - _unit = lang.t('time.seconds'); - _unitShort = lang.t('time.secs'); - } - } else if (_value >= timeUnits.ms.minute && _value < timeUnits.ms.hour) { - _value = formatFixedDecimals(divide(_value, timeUnits.ms.minute), 2); - if (_value === 1) { - _unit = lang.t('time.minute'); - _unitShort = lang.t('time.min'); - } else { - _unit = lang.t('time.minutes'); - _unitShort = lang.t('time.mins'); - } - } else if (_value >= timeUnits.ms.hour && _value < timeUnits.ms.day) { - _value = formatFixedDecimals(divide(_value, timeUnits.ms.hour), 2); - if (_value === 1) { - _unit = lang.t('time.hour'); - _unitShort = lang.t('time.hr'); - } else { - _unit = lang.t('time.hours'); - _unitShort = lang.t('time.hrs'); - } - } else if (_value >= timeUnits.ms.day) { - _value = formatFixedDecimals(divide(_value, timeUnits.ms.day), 2); - if (_value === 1) { - _unit = lang.t('time.day'); - _unitShort = lang.t('time.day'); - } else { - _unit = lang.t('time.days'); - _unitShort = lang.t('time.days'); - } - } else { - _unit = lang.t('time.miliseconds'); - _unitShort = lang.t('time.ms'); - } - } else if (unit === 'seconds' || unit === 'secs') { - if (_value === 1) { - _unit = lang.t('time.second'); - _unitShort = lang.t('time.sec'); - } else if (_value < 1) { - _value = formatFixedDecimals(multiply(_value, timeUnits.ms.second)); - if (_value === 1) { - _unit = lang.t('time.milisecond'); - _unitShort = lang.t('time.ms'); - } else { - _unit = lang.t('time.miliseconds'); - _unitShort = lang.t('time.ms'); - } - } else if ( - _value >= timeUnits.secs.minute - && _value < timeUnits.secs.hour - ) { - _value = formatFixedDecimals(divide(_value, timeUnits.secs.minute), 2); - if (_value === 1) { - _unit = lang.t('time.minute'); - _unitShort = lang.t('time.min'); - } else { - _unit = lang.t('time.minutes'); - _unitShort = lang.t('time.mins'); - } - } else if (_value >= timeUnits.secs.hour && _value < timeUnits.secs.day) { - _value = formatFixedDecimals(divide(_value, timeUnits.secs.hour), 2); - if (_value === 1) { - _unit = lang.t('time.hour'); - _unitShort = lang.t('time.hr'); - } else { - _unit = lang.t('time.hours'); - _unitShort = lang.t('time.hrs'); - } - } else if (_value >= timeUnits.secs.day) { - _value = formatFixedDecimals(divide(_value, timeUnits.secs.day), 2); - if (_value === 1) { - _unit = lang.t('time.day'); - _unitShort = lang.t('time.day'); - } else { - _unit = lang.t('time.days'); - _unitShort = lang.t('time.days'); - } - } else { - _unit = lang.t('time.seconds'); - _unitShort = lang.t('time.secs'); - } - } else if (unit === 'minutes' || unit === 'mins') { - if (_value === 1) { - _unit = lang.t('time.minute'); - _unitShort = lang.t('time.min'); - } else if (_value < 1) { - _value = formatFixedDecimals(multiply(_value, timeUnits.secs.minute)); - if (_value === 1) { - _unit = lang.t('time.second'); - _unitShort = lang.t('time.sec'); - } else { - _unit = lang.t('time.seconds'); - _unitShort = lang.t('time.secs'); - } - } else if (_value > timeUnits.mins.hour && _value < timeUnits.mins.day) { - _value = formatFixedDecimals(divide(_value, timeUnits.mins.hour), 2); - if (_value === 1) { - _unit = lang.t('time.hour'); - _unitShort = lang.t('time.hr'); - } else { - _unit = lang.t('time.hours'); - _unitShort = lang.t('time.hrs'); - } - } else if (_value >= timeUnits.mins.day) { - _value = formatFixedDecimals(divide(_value, timeUnits.mins.day), 2); - if (_value === 1) { - _unit = lang.t('time.day'); - _unitShort = lang.t('time.day'); - } else { - _unit = lang.t('time.days'); - _unitShort = lang.t('time.days'); - } - } else { - _unit = lang.t('time.minutes'); - _unitShort = lang.t('time.mins'); - } - } - } - if (short) { - return `${_value} ${_unitShort}`; - } - return `${_value} ${_unit}`; -}; +export const getMinimalTimeUnitStringForMs = ( + value = 0, + short = true, + plural +) => { + const ms = + isObjectLike(value) || isString(value) + ? convertStringToNumber(value) + : value; -/** - * @desc get countdown (hrs:mins:secs) - * @param {Number} [miliseconds] - * @return {String} - */ -export const getCountdown = miliseconds => { - let remaining = miliseconds; - let slots = [timeUnits.ms.hour, timeUnits.ms.minute, timeUnits.ms.second]; - slots = slots.map(pack => { - const result = floorDivide(remaining, pack); - remaining = mod(remaining, pack); - if (greaterThanOrEqual(result, 1)) { - return result.length < 2 ? `0${result}` : result; - } - return null; + const parsedMs = omitBy( + pick(parseMilliseconds(Number(ms)), MinimalTimeUnitWhitelist), + isZero + ); + + const { + unit: highestResolutionUnit, + value: highestResolutionValue, + } = getHighestResolutionUnit(parsedMs); + + const label = buildLocalizedTimeUnitString({ + plural, + short, + unit: highestResolutionUnit, }); - return `${slots[0] ? `${slots[0]}:` : ''}${ - slots[1] ? `${slots[1]}:` : '00:' - }${slots[1] ? slots[2] || '00' : slots[2]}`; + + return `${highestResolutionValue} ${label}`; }; diff --git a/src/helpers/transactionStatusTypes.js b/src/helpers/transactionStatusTypes.js index 07e5e9db2cf..f9164f3afea 100644 --- a/src/helpers/transactionStatusTypes.js +++ b/src/helpers/transactionStatusTypes.js @@ -5,4 +5,5 @@ export default { self: 'self', sending: 'sending', sent: 'sent', + unknown: 'unknown status', }; diff --git a/src/helpers/transactions.js b/src/helpers/transactions.js index 144c1f65960..31edb274db8 100644 --- a/src/helpers/transactions.js +++ b/src/helpers/transactions.js @@ -5,47 +5,22 @@ import { isToday, isYesterday, } from 'date-fns'; -import { get, groupBy, isEmpty } from 'lodash'; +import { get, groupBy, isEmpty, map, toLower } from 'lodash'; import { createSelector } from 'reselect'; -import TransactionStatusTypes from './transactionStatusTypes'; -import { isLowerCaseMatch } from '../utils'; +import TransactionStatusTypes from '../helpers/transactionStatusTypes'; const accountAddressSelector = state => state.accountAddress; -const nativeCurrencySelector = state => state.nativeCurrency; +const contactsSelector = state => state.contacts; const requestsSelector = state => state.requests; const transactionsSelector = state => state.transactions; -export const buildTransactionUniqueIdentifier = ({ hash, displayDetails }) => ( - hash || get(displayDetails, 'timestampInMs') -); - -export const getTransactionStatus = ({ - accountAddress, - from, - pending, - status, - to, -}) => { - const isFromAccount = isLowerCaseMatch(from, accountAddress); - const isToAccount = isLowerCaseMatch(to, accountAddress); - - if (pending && isFromAccount) return TransactionStatusTypes.sending; - if (pending && isToAccount) return TransactionStatusTypes.receiving; - - if (status === 'failed') return TransactionStatusTypes.failed; - - if (isFromAccount && isToAccount) return TransactionStatusTypes.self; - - if (isFromAccount) return TransactionStatusTypes.sent; - if (isToAccount) return TransactionStatusTypes.received; +export const buildTransactionUniqueIdentifier = ({ hash, displayDetails }) => + hash || get(displayDetails, 'timestampInMs'); - return undefined; -}; - -const groupTransactionByDate = ({ pending, mined_at: time }) => { +const groupTransactionByDate = ({ pending, minedAt }) => { if (pending) return 'Pending'; - const timestamp = new Date(parseInt(time, 10) * 1000); + const timestamp = new Date(parseInt(minedAt, 10) * 1000); if (isToday(timestamp)) return 'Today'; if (isYesterday(timestamp)) return 'Yesterday'; @@ -54,34 +29,32 @@ const groupTransactionByDate = ({ pending, mined_at: time }) => { return format(timestamp, `MMMM${isThisYear(timestamp) ? '' : ' YYYY'}`); }; -const normalizeTransactions = ({ accountAddress, nativeCurrency, transactions }) => ( - transactions.map(({ - asset, - ...tx - }) => ({ - ...tx, - name: get(asset, 'name', ''), - status: getTransactionStatus({ accountAddress, ...tx }), - symbol: get(asset, 'symbol', ''), - })) -); +const addContactInfo = contacts => txn => { + const { from, to, status } = txn; + const isSent = status === TransactionStatusTypes.sent; + const contactAddress = isSent ? to : from; + const contact = get(contacts, `${[toLower(contactAddress)]}`, null); + return { + ...txn, + contact, + }; +}; const buildTransactionsSections = ( accountAddress, - nativeCurrency, + contacts, requests, - transactions, + transactions ) => { let sectionedTransactions = []; - if (!isEmpty(transactions)) { - const normalizedTransactions = normalizeTransactions({ - accountAddress, - nativeCurrency, - transactions, - }); + const transactionsWithContacts = map(transactions, addContactInfo(contacts)); - const transactionsByDate = groupBy(normalizedTransactions, groupTransactionByDate); + if (!isEmpty(transactionsWithContacts)) { + const transactionsByDate = groupBy( + transactionsWithContacts, + groupTransactionByDate + ); sectionedTransactions = Object.keys(transactionsByDate).map(section => ({ data: transactionsByDate[section], @@ -91,26 +64,25 @@ const buildTransactionsSections = ( let requestsToApprove = []; if (!isEmpty(requests)) { - requestsToApprove = [{ - data: requests, - title: 'Requests', - }]; + requestsToApprove = [ + { + data: requests, + title: 'Requests', + }, + ]; } return { - sections: [ - ...requestsToApprove, - ...sectionedTransactions, - ], + sections: [...requestsToApprove, ...sectionedTransactions], }; }; export const buildTransactionsSectionsSelector = createSelector( [ accountAddressSelector, - nativeCurrencySelector, + contactsSelector, requestsSelector, transactionsSelector, ], - buildTransactionsSections, + buildTransactionsSections ); diff --git a/src/helpers/utilities.js b/src/helpers/utilities.js index 8f1e6846368..7c257e8a731 100644 --- a/src/helpers/utilities.js +++ b/src/helpers/utilities.js @@ -8,9 +8,10 @@ import supportedNativeCurrencies from '../references/native-currencies.json'; * @param {Number} numberTwo * @return {String} */ -export const subtract = (numberOne, numberTwo) => BigNumber(`${numberOne}`) - .minus(BigNumber(`${numberTwo}`)) - .toFixed(); +export const subtract = (numberOne, numberTwo) => + BigNumber(`${numberOne}`) + .minus(BigNumber(`${numberTwo}`)) + .toFixed(); /** * @desc convert amount to raw amount @@ -18,7 +19,10 @@ export const subtract = (numberOne, numberTwo) => BigNumber(`${numberOne}`) * @param {Number} decimals * @return {String} */ -export const convertAmountToRawAmount = (value, decimals) => BigNumber(value).times(BigNumber(10).pow(decimals)).toFixed(); +export const convertAmountToRawAmount = (value, decimals) => + BigNumber(value) + .times(BigNumber(10).pow(decimals)) + .toFixed(); /** * @desc convert from number to string @@ -27,14 +31,14 @@ export const convertAmountToRawAmount = (value, decimals) => BigNumber(value).ti */ export const convertNumberToString = value => BigNumber(`${value}`).toFixed(); - /** * @desc compares if numberOne is greater than numberTwo * @param {Number} numberOne * @param {Number} numberTwo * @return {String} */ -export const greaterThan = (numberOne, numberTwo) => BigNumber(`${numberOne}`).comparedTo(BigNumber(`${numberTwo}`)) === 1; +export const greaterThan = (numberOne, numberTwo) => + BigNumber(`${numberOne}`).comparedTo(BigNumber(`${numberTwo}`)) === 1; /** * @desc format fixed number of decimals @@ -55,10 +59,10 @@ export const formatFixedDecimals = (value, decimals) => { * @param {Number} numberTwo * @return {String} */ -export const mod = (numberOne, numberTwo) => BigNumber(`${numberOne}`) - .mod(BigNumber(`${numberTwo}`)) - .toFixed(); - +export const mod = (numberOne, numberTwo) => + BigNumber(`${numberOne}`) + .mod(BigNumber(`${numberTwo}`)) + .toFixed(); /** * @desc compares if numberOne is greater than or equal to numberTwo @@ -66,18 +70,18 @@ export const mod = (numberOne, numberTwo) => BigNumber(`${numberOne}`) * @param {Number} numberTwo * @return {String} */ -export const greaterThanOrEqual = (numberOne, numberTwo) => BigNumber(`${numberOne}`).comparedTo(BigNumber(`${numberTwo}`)) >= 0; - - +export const greaterThanOrEqual = (numberOne, numberTwo) => + BigNumber(`${numberOne}`).comparedTo(BigNumber(`${numberTwo}`)) >= 0; /** * @desc real floor divides two numbers * @param {Number} numberOne * @param {Number} numberTwo * @return {String} */ -export const floorDivide = (numberOne, numberTwo) => BigNumber(`${numberOne}`) - .dividedToIntegerBy(BigNumber(`${numberTwo}`)) - .toFixed(); +export const floorDivide = (numberOne, numberTwo) => + BigNumber(`${numberOne}`) + .dividedToIntegerBy(BigNumber(`${numberTwo}`)) + .toFixed(); /** * @desc count value's number of decimals places @@ -86,6 +90,37 @@ export const floorDivide = (numberOne, numberTwo) => BigNumber(`${numberOne}`) */ export const countDecimalPlaces = value => BigNumber(`${value}`).dp(); +/** + * @desc update the amount to display precision + * equivalent to ~0.01 of the native price + * or use most significant decimal + * if the updated precision amounts to zero + * @param {String} amount + * @param {String} nativePrice + * @param {Boolean} use rounding up mode + * @return {String} updated amount + */ +export const updatePrecisionToDisplay = ( + amount, + nativePrice, + roundUp = false +) => { + const roundingMode = roundUp ? BigNumber.ROUND_UP : BigNumber.ROUND_DOWN; + const bnAmount = BigNumber(`${amount}`); + const significantDigitsOfNativePriceInteger = BigNumber(`${nativePrice}`) + .decimalPlaces(0, BigNumber.ROUND_DOWN) + .sd(true); + const truncatedPrecision = BigNumber(significantDigitsOfNativePriceInteger) + .plus(2, 10) + .toNumber(); + const truncatedAmount = bnAmount.decimalPlaces( + truncatedPrecision, + BigNumber.ROUND_DOWN + ); + return truncatedAmount.isZero() + ? BigNumber(bnAmount.toPrecision(1, roundingMode)).toFixed() + : bnAmount.decimalPlaces(truncatedPrecision, roundingMode).toFixed(); +}; /** * @desc format inputOne value to signficant decimals given inputTwo @@ -96,7 +131,8 @@ export const countDecimalPlaces = value => BigNumber(`${value}`).dp(); // TODO revisit logic, at least rename so it is not native amount dp export const formatInputDecimals = (inputOne, inputTwo) => { const _nativeAmountDecimalPlaces = countDecimalPlaces(inputTwo); - const decimals = _nativeAmountDecimalPlaces > 8 ? _nativeAmountDecimalPlaces : 8; + const decimals = + _nativeAmountDecimalPlaces > 8 ? _nativeAmountDecimalPlaces : 8; const result = BigNumber(formatFixedDecimals(inputOne, decimals)) .toFormat() .replace(/,/g, ''); @@ -123,9 +159,10 @@ export const convertStringToHex = string => BigNumber(`${string}`).toString(16); * @param {Number} numberTwo * @return {String} */ -export const add = (numberOne, numberTwo) => BigNumber(`${numberOne}`) - .plus(BigNumber(`${numberTwo}`)) - .toFixed(); +export const add = (numberOne, numberTwo) => + BigNumber(`${numberOne}`) + .plus(BigNumber(`${numberTwo}`)) + .toFixed(); /** * @desc multiplies two numbers @@ -133,9 +170,10 @@ export const add = (numberOne, numberTwo) => BigNumber(`${numberOne}`) * @param {Number} numberTwo * @return {String} */ -export const multiply = (numberOne, numberTwo) => BigNumber(`${numberOne}`) - .times(BigNumber(`${numberTwo}`)) - .toFixed(); +export const multiply = (numberOne, numberTwo) => + BigNumber(`${numberOne}`) + .times(BigNumber(`${numberTwo}`)) + .toFixed(); /** * @desc divides two numbers @@ -143,9 +181,10 @@ export const multiply = (numberOne, numberTwo) => BigNumber(`${numberOne}`) * @param {Number} numberTwo * @return {String} */ -export const divide = (numberOne, numberTwo) => BigNumber(`${numberOne}`) - .dividedBy(BigNumber(`${numberTwo}`)) - .toFixed(); +export const divide = (numberOne, numberTwo) => + BigNumber(`${numberOne}`) + .dividedBy(BigNumber(`${numberTwo}`)) + .toFixed(); /** * @desc convert to asset amount units from native price value units @@ -154,27 +193,12 @@ export const divide = (numberOne, numberTwo) => BigNumber(`${numberOne}`) * @param {Number} priceUnit * @return {String} */ -export const convertAmountFromNativeValue = ( - value, - asset, - priceUnit, -) => BigNumber(value) - .dividedBy(BigNumber(priceUnit)) - .toFixed(); - -/** - * @desc handle signficant decimals in display format - * @param {String|Number} value - * @param {Number} decimals - * @param {Number} buffer - * @return {String} - */ -export const handleSignificantDecimals = (value, decimals, buffer) => { - const result = significantDecimals(value, decimals, buffer); - return BigNumber(`${result}`).dp() <= 2 - ? BigNumber(`${result}`).toFormat(2) - : BigNumber(`${result}`).toFormat(); -}; +export const convertAmountFromNativeValue = (value, priceUnit, decimals = 18) => + BigNumber( + BigNumber(value) + .dividedBy(BigNumber(priceUnit)) + .toFixed(decimals, BigNumber.ROUND_DOWN) + ).toFixed(); /** * @desc convert from string to number @@ -189,7 +213,8 @@ export const convertStringToNumber = value => BigNumber(`${value}`).toNumber(); * @param {Number} numberTwo * @return {String} */ -export const smallerThan = (numberOne, numberTwo) => BigNumber(`${numberOne}`).comparedTo(BigNumber(`${numberTwo}`)) === -1; +export const smallerThan = (numberOne, numberTwo) => + BigNumber(`${numberOne}`).comparedTo(BigNumber(`${numberTwo}`)) === -1; /** * @desc handle signficant decimals @@ -198,26 +223,31 @@ export const smallerThan = (numberOne, numberTwo) => BigNumber(`${numberOne}`).c * @param {Number} buffer * @return {String} */ -export const significantDecimals = (value, decimals, buffer) => { - if (!BigNumber(`${decimals}`).isInteger() - || (buffer && !BigNumber(`${buffer}`).isInteger())) { +export const handleSignificantDecimals = (value, decimals, buffer) => { + if ( + !BigNumber(`${decimals}`).isInteger() || + (buffer && !BigNumber(`${buffer}`).isInteger()) + ) { return null; } buffer = buffer ? convertStringToNumber(buffer) : 3; decimals = convertStringToNumber(decimals); if (smallerThan(BigNumber(`${value}`).abs(), 1)) { - decimals = BigNumber(`${value}`) - .toFixed() - .slice(2) - .slice('') - .search(/[^0]/g) + buffer; + decimals = + BigNumber(`${value}`) + .toFixed() + .slice(2) + .slice('') + .search(/[^0]/g) + buffer; decimals = decimals < 8 ? decimals : 8; } else { decimals = decimals < buffer ? decimals : buffer; } let result = BigNumber(`${value}`).toFixed(decimals); result = BigNumber(`${result}`).toFixed(); - return result; + return BigNumber(`${result}`).dp() <= 2 + ? BigNumber(`${result}`).toFormat(2) + : BigNumber(`${result}`).toFormat(); }; /** @@ -227,10 +257,8 @@ export const significantDecimals = (value, decimals, buffer) => { * @param {Object} nativePrices * @return {BigNumber} */ -export const convertAmountToNativeAmount = ( - amount, - priceUnit, -) => multiply(amount, priceUnit); +export const convertAmountToNativeAmount = (amount, priceUnit) => + multiply(amount, priceUnit); /** * @desc convert from amount to display formatted string @@ -242,13 +270,13 @@ export const convertAmountAndPriceToNativeDisplay = ( amount, priceUnit, nativeCurrency, - buffer, + buffer ) => { const nativeBalanceRaw = convertAmountToNativeAmount(amount, priceUnit); const nativeDisplay = convertAmountToNativeDisplay( nativeBalanceRaw, nativeCurrency, - buffer, + buffer ); return { amount: nativeBalanceRaw, @@ -267,17 +295,17 @@ export const convertRawAmountToNativeDisplay = ( assetDecimals, priceUnit, nativeCurrency, - buffer, + buffer ) => { const assetBalance = convertRawAmountToDecimalFormat( rawAmount, - assetDecimals, + assetDecimals ); return convertAmountAndPriceToNativeDisplay( assetBalance, priceUnit, nativeCurrency, - buffer, + buffer ); }; @@ -290,10 +318,7 @@ export const convertRawAmountToNativeDisplay = ( */ export const convertRawAmountToBalance = (value, asset, buffer) => { const decimals = get(asset, 'decimals', 18); - const assetBalance = convertRawAmountToDecimalFormat( - value, - decimals, - ); + const assetBalance = convertRawAmountToDecimalFormat(value, decimals); return { amount: assetBalance, @@ -314,18 +339,32 @@ export const convertAmountToBalanceDisplay = (value, asset, buffer) => { return `${display} ${asset.symbol}`; }; - /** * @desc convert from amount to display formatted string * @param {BigNumber} value * @param {Number} buffer * @return {String} */ -export const convertAmountToPercentageDisplay = (value, buffer) => { - const display = handleSignificantDecimals(value, 2, buffer); +export const convertAmountToPercentageDisplay = ( + value, + decimals = 2, + buffer +) => { + const display = handleSignificantDecimals(value, decimals, buffer); return `${display}%`; }; +/** + * @desc convert from bips amount to percentage format + * @param {BigNumber} value in bips + * @param {Number} decimals + * @return {String} + */ +export const convertBipsToPercentage = (value, decimals = 2) => + BigNumber(`${value}`) + .shiftedBy(-2) + .toFixed(decimals); + /** * @desc convert from amount value to display formatted string * @param {BigNumber} value @@ -348,52 +387,9 @@ export const convertAmountToNativeDisplay = (value, nativeCurrency, buffer) => { * @param {Number} decimals * @return {String} */ -export const convertRawAmountToDecimalFormat = (value, decimals = 18) => BigNumber(`${value}`) - .dividedBy(BigNumber(10).pow(decimals)) - .toFixed(); - -export const fromWei = (number) => convertRawAmountToDecimalFormat(number, 18); +export const convertRawAmountToDecimalFormat = (value, decimals = 18) => + BigNumber(`${value}`) + .dividedBy(BigNumber(10).pow(decimals)) + .toFixed(); -/** - * @desc ellipse text to max maxLength - * @param {String} [text = ''] - * @param {Number} [maxLength = 9999] - * @return {Intercom} - */ -export const ellipseText = (text = '', maxLength = 9999) => { - if (text.length <= maxLength) return text; - const _maxLength = maxLength - 3; - let ellipse = false; - let currentLength = 0; - const result = `${text - .split(' ') - .filter(word => { - currentLength += word.length; - if (ellipse || currentLength >= _maxLength) { - ellipse = true; - return false; - } - return true; - }) - .join(' ')}...`; - return result; -}; - -/** - * @desc ellipse text to max maxLength - * @param {String} [text = ''] - * @param {Number} [maxLength = 9999] - * @return {Intercom} - */ -export const ellipseAddress = (text = '') => { - const addressArr = text.split(''); - const firstFour = text.split('', 4).join(''); - const lastFour = addressArr - .reverse() - .join('') - .split('', 4) - .reverse() - .join(''); - const result = `${firstFour}...${lastFour}`; - return result; -}; +export const fromWei = number => convertRawAmountToDecimalFormat(number, 18); diff --git a/src/helpers/validators.js b/src/helpers/validators.js index 11ed9d05c0d..05bf0144343 100644 --- a/src/helpers/validators.js +++ b/src/helpers/validators.js @@ -11,18 +11,19 @@ import { * @param {String} email * @return {Boolean} */ -export const isValidEmail = email => !!email.match( - /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/, -); +export const isValidEmail = email => + !!email.match( + /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ + ); -export const isENSAddressFormat = (address) => address.match(/.+\..+/g); +export const isENSAddressFormat = address => address.match(/.+\..+/g); /** * @desc validate ethereum address * @param {String} address or ENS * @return {Boolean} */ -export const isValidAddress = async (address) => { +export const checkIsValidAddress = async address => { if (isENSAddressFormat(address)) { try { const resolvedAddress = await web3Provider.resolveName(address); @@ -33,9 +34,12 @@ export const isValidAddress = async (address) => { } if (!isHexString(address)) return false; if (!/^(0x)?[0-9a-f]{40}$/i.test(address)) return false; - if (/^(0x)?[0-9a-f]{40}$/.test(address) - || /^(0x)?[0-9A-F]{40}$/.test(address)) return true; - return address === await toChecksumAddress(address); + if ( + /^(0x)?[0-9a-f]{40}$/.test(address) || + /^(0x)?[0-9A-F]{40}$/.test(address) + ) + return true; + return address === (await toChecksumAddress(address)); }; /** @@ -43,7 +47,7 @@ export const isValidAddress = async (address) => { * @param {String} seed phrase mnemonic * @return {Boolean} */ -const isValidSeedPhrase = (seedPhrase) => { +const isValidSeedPhrase = seedPhrase => { const phrases = seedPhrase.split(' ').filter(word => !!word).length; return phrases >= 12 && isValidMnemonic(seedPhrase); }; @@ -53,4 +57,5 @@ const isValidSeedPhrase = (seedPhrase) => { * @param {String} seed phrase mnemonic or private key * @return {Boolean} */ -export const isValidSeed = (seed) => isHexStringIgnorePrefix(seed) || isValidSeedPhrase(seed); +export const isValidSeed = seed => + isHexStringIgnorePrefix(seed) || isValidSeedPhrase(seed); diff --git a/src/hoc/__tests__/withUniswapLiquidity.test.js b/src/hoc/__tests__/withUniswapLiquidityTokenInfo.test.js similarity index 79% rename from src/hoc/__tests__/withUniswapLiquidity.test.js rename to src/hoc/__tests__/withUniswapLiquidityTokenInfo.test.js index 4b0a10a090b..2598921b69f 100644 --- a/src/hoc/__tests__/withUniswapLiquidity.test.js +++ b/src/hoc/__tests__/withUniswapLiquidityTokenInfo.test.js @@ -1,6 +1,6 @@ -import { transformPool } from '../withUniswapLiquidity'; +import { transformPool } from '../withUniswapLiquidityTokenInfo'; -test('transformPool', async () => { +it('transformPool', async () => { const pool = { balance: '1', ethBalance: '1.12', diff --git a/src/hoc/assetSelectors.js b/src/hoc/assetSelectors.js index 00fd7961d3b..e0fbf7c0864 100644 --- a/src/hoc/assetSelectors.js +++ b/src/hoc/assetSelectors.js @@ -1,11 +1,4 @@ -import { - get, - groupBy, - isEmpty, - isNil, - map, - toNumber, -} from 'lodash'; +import { get, groupBy, isEmpty, isNil, map, toNumber } from 'lodash'; import { createSelector } from 'reselect'; import { sortList } from '../helpers/sortList'; import { @@ -34,7 +27,13 @@ const sortAssetsByNativeAmount = (originalAssets, nativeCurrency) => { noValue = EMPTY_ARRAY, } = groupAssetsByMarketValue(assetsNativePrices); - const sortedAssets = sortList(hasValue, 'native.balance.amount', 'desc', 0, toNumber); + const sortedAssets = sortList( + hasValue, + 'native.balance.amount', + 'desc', + 0, + toNumber + ); const sortedShitcoins = sortList(noValue, 'name', 'asc'); const allAssets = sortedAssets.concat(sortedShitcoins); @@ -50,14 +49,10 @@ const sortAssetsByNativeAmount = (originalAssets, nativeCurrency) => { }; }; -const groupAssetsByMarketValue = assets => groupBy(assets, ({ native }) => ( - isNil(native) ? 'noValue' : 'hasValue' -)); +const groupAssetsByMarketValue = assets => + groupBy(assets, ({ native }) => (isNil(native) ? 'noValue' : 'hasValue')); -const parseAssetsNative = ( - assets, - nativeCurrency, -) => { +const parseAssetsNative = (assets, nativeCurrency) => { let assetsNative = assets; assetsNative = map(assets, asset => { const assetNativePrice = get(asset, 'price'); @@ -69,16 +64,17 @@ const parseAssetsNative = ( const nativeDisplay = convertAmountAndPriceToNativeDisplay( get(asset, 'balance.amount', 0), priceUnit, - nativeCurrency, + nativeCurrency ); return { ...asset, native: { balance: nativeDisplay, - change: - isLowerCaseMatch(get(asset, 'symbol'), nativeCurrency) - ? 'β€”β€”β€”' - : convertAmountToPercentageDisplay(assetNativePrice.relative_change_24h), + change: isLowerCaseMatch(get(asset, 'symbol'), nativeCurrency) + ? 'β€”β€”β€”' + : convertAmountToPercentageDisplay( + assetNativePrice.relative_change_24h + ), price: { amount: priceUnit, display: convertAmountToNativeDisplay(priceUnit, nativeCurrency), @@ -87,17 +83,18 @@ const parseAssetsNative = ( }; }); const totalAmount = assetsNative.reduce( - (total, asset) => add( - total, - get(asset, 'native.balance.amount', 0), - ), 0, + (total, asset) => add(total, get(asset, 'native.balance.amount', 0)), + 0 + ); + const totalDisplay = convertAmountToNativeDisplay( + totalAmount, + nativeCurrency ); - const totalDisplay = convertAmountToNativeDisplay(totalAmount, nativeCurrency); const total = { amount: totalAmount, display: totalDisplay }; return { assetsNativePrices: assetsNative, total }; }; export const sortAssetsByNativeAmountSelector = createSelector( [assetsSelector, nativeCurrencySelector], - sortAssetsByNativeAmount, + sortAssetsByNativeAmount ); diff --git a/src/hoc/index.js b/src/hoc/index.js index 897406e5151..1235ba1c52c 100644 --- a/src/hoc/index.js +++ b/src/hoc/index.js @@ -4,28 +4,38 @@ export { default as withAccountSettings } from './withAccountSettings'; export { default as withAccountTransactions } from './withAccountTransactions'; export { default as withActionSheetManager } from './withActionSheetManager'; export { default as withAppState } from './withAppState'; -export { default as withBlurTransitionProps } from './withBlurTransitionProps'; +export { default as withBlockedHorizontalSwipe } from './withBlockedHorizontalSwipe'; +export { default as withContacts } from './withContacts'; export { default as withDataInit } from './withDataInit'; +export { default as withDeepLink } from './withDeepLink'; export { default as withFabSelection } from './withFabSelection'; export { default as withFabSendAction } from './withFabSendAction'; +export { default as withGas } from './withGas'; export { default as withHideSplashScreen } from './withHideSplashScreen'; export { default as withImageDimensionsCache } from './withImageDimensionsCache'; export { default as withIsWalletEmpty } from './withIsWalletEmpty'; export { default as withIsWalletEthZero } from './withIsWalletEthZero'; -export { default as withIsWalletImporting } from './withIsWalletImporting'; +export { default as withKeyboardHeight } from './withKeyboardHeight'; export { default as withMessageSigningScreen } from './withMessageSigningScreen'; -export { default as withNetInfo } from './withNetInfo'; export { default as withNeverRerender } from './withNeverRerender'; export { default as withOpenFamilyTabs } from './withOpenFamilyTabs'; +export { default as withOpenInvestmentCards } from './withOpenInvestmentCards'; +export { default as withOpenBalances } from './withOpenBalances'; export { default as withRequests } from './withRequests'; export { default as withRotationForDirection } from './withRotationForDirection'; export { default as withSafeAreaViewInsetValues } from './withSafeAreaViewInsetValues'; +export { default as withSelectedInput } from './withSelectedInput'; export { default as withSendFeedback } from './withSendFeedback'; export { default as withStatusBarStyle } from './withStatusBarStyle'; export { default as withTransactionConfirmationScreen } from './withTransactionConfirmationScreen'; export { default as withTransitionProps } from './withTransitionProps'; export { default as withUniqueTokens } from './withUniqueTokens'; -export { default as withUniswapLiquidity, readableUniswapSelector } from './withUniswapLiquidity'; +export { default as withUniswapAllowances } from './withUniswapAllowances'; +export { default as withUniswapAssets } from './withUniswapAssets'; +export { + default as withUniswapLiquidityTokenInfo, + readableUniswapSelector, +} from './withUniswapLiquidityTokenInfo'; export { default as withWalletConnectConfirmationModal } from './withWalletConnectConfirmationModal'; export { default as withWalletConnectConnections } from './withWalletConnectConnections'; export { default as withWalletConnectOnSessionRequest } from './withWalletConnectOnSessionRequest'; diff --git a/src/hoc/uniqueTokenSelectors.js b/src/hoc/uniqueTokenSelectors.js index c390a500cf2..0bc4f4d2204 100644 --- a/src/hoc/uniqueTokenSelectors.js +++ b/src/hoc/uniqueTokenSelectors.js @@ -3,11 +3,11 @@ import { createSelector } from 'reselect'; const uniqueTokensSelector = state => state.uniqueTokens; -const sendableUniqueTokens = (uniqueTokens) => ({ +const sendableUniqueTokens = uniqueTokens => ({ sendableUniqueTokens: filter(uniqueTokens, ['isSendable', true]), }); export const sendableUniqueTokensSelector = createSelector( [uniqueTokensSelector], - sendableUniqueTokens, + sendableUniqueTokens ); diff --git a/src/hoc/withAccountAddress.js b/src/hoc/withAccountAddress.js index f430622c1f1..1b018d3f3c2 100644 --- a/src/hoc/withAccountAddress.js +++ b/src/hoc/withAccountAddress.js @@ -1,18 +1,22 @@ +import { toLower } from 'lodash'; import { connect } from 'react-redux'; import { compose, withProps } from 'recompose'; import { createSelector } from 'reselect'; import { settingsUpdateAccountAddress } from '../redux/settings'; -const mapStateToProps = ({ settings: { accountAddress } }) => ({ accountAddress }); +const mapStateToProps = ({ settings: { accountAddress } }) => ({ + accountAddress, +}); const accountAddressSelector = state => state.accountAddress; const lowerAccountAddressSelector = createSelector( [accountAddressSelector], - (accountAddress) => ({ accountAddress: accountAddress.toLowerCase() }), + accountAddress => ({ accountAddress: toLower(accountAddress) }) ); -export default Component => compose( - connect(mapStateToProps, { settingsUpdateAccountAddress }), - withProps(lowerAccountAddressSelector), -)(Component); +export default Component => + compose( + connect(mapStateToProps, { settingsUpdateAccountAddress }), + withProps(lowerAccountAddressSelector) + )(Component); diff --git a/src/hoc/withAccountData.js b/src/hoc/withAccountData.js index 0f0ce5d169d..1b1c0af2ab5 100644 --- a/src/hoc/withAccountData.js +++ b/src/hoc/withAccountData.js @@ -10,9 +10,7 @@ const mapStateToProps = ({ nativeCurrency, }); -const sortAssets = (state) => sortAssetsByNativeAmountSelector(state); +const sortAssets = state => sortAssetsByNativeAmountSelector(state); -export default Component => compose( - connect(mapStateToProps), - withProps(sortAssets), -)(Component); +export default Component => + compose(connect(mapStateToProps), withProps(sortAssets))(Component); diff --git a/src/hoc/withAccountSettings.js b/src/hoc/withAccountSettings.js index f32bee86906..d95c22d7f33 100644 --- a/src/hoc/withAccountSettings.js +++ b/src/hoc/withAccountSettings.js @@ -9,19 +9,13 @@ import { } from '../redux/settings'; const mapStateToProps = ({ - settings: { - language, - nativeCurrency, - }, -}) => ({ - language, - nativeCurrency, -}); + settings: { accountAddress, chainId, language, nativeCurrency, network }, +}) => ({ accountAddress, chainId, language, nativeCurrency, network }); const languageSelector = state => state.language; const nativeCurrencySelector = state => state.nativeCurrency; -const withLanguage = (language) => { +const withLanguage = language => { if (language !== lang.locale) { lang.locale = language; } @@ -33,21 +27,19 @@ const withNativeCurrencySymbol = nativeCurrency => ({ nativeCurrencySymbol: supportedNativeCurrencies[nativeCurrency].symbol, }); -const withLanguageSelector = createSelector( - [languageSelector], - withLanguage, -); +const withLanguageSelector = createSelector([languageSelector], withLanguage); const withNativeCurrencySelector = createSelector( [nativeCurrencySelector], - withNativeCurrencySymbol, + withNativeCurrencySymbol ); -export default Component => compose( - connect(mapStateToProps, { - settingsChangeLanguage, - settingsChangeNativeCurrency, - }), - withProps(withLanguageSelector), - withProps(withNativeCurrencySelector), -)(Component); +export default Component => + compose( + connect(mapStateToProps, { + settingsChangeLanguage, + settingsChangeNativeCurrency, + }), + withProps(withLanguageSelector), + withProps(withNativeCurrencySelector) + )(Component); diff --git a/src/hoc/withAccountTransactions.js b/src/hoc/withAccountTransactions.js index e5970bda3bb..e545ad35a95 100644 --- a/src/hoc/withAccountTransactions.js +++ b/src/hoc/withAccountTransactions.js @@ -4,18 +4,17 @@ import { createSelector } from 'reselect'; const transactionsSelector = state => state.transactions; -const mapStateToProps = ({ - data: { transactions }, -}) => ({ +const mapStateToProps = ({ data: { transactions } }) => ({ transactions, }); const transactionsCountSelector = createSelector( [transactionsSelector], - (transactions) => ({ transactionsCount: transactions.length }), + transactions => ({ transactionsCount: transactions.length }) ); -export default Component => compose( - connect(mapStateToProps), - withProps(transactionsCountSelector), -)(Component); +export default Component => + compose( + connect(mapStateToProps), + withProps(transactionsCountSelector) + )(Component); diff --git a/src/hoc/withActionSheetManager.js b/src/hoc/withActionSheetManager.js index 488d8bd8df6..1c67c847dc5 100644 --- a/src/hoc/withActionSheetManager.js +++ b/src/hoc/withActionSheetManager.js @@ -1,6 +1,9 @@ import { connect } from 'react-redux'; import { setIsActionSheetOpen } from '../redux/actionSheetManager'; -const mapStateToProps = ({ actionSheetManager: { isActionSheetOpen } }) => ({ isActionSheetOpen }); +const mapStateToProps = ({ actionSheetManager: { isActionSheetOpen } }) => ({ + isActionSheetOpen, +}); -export default Component => connect(mapStateToProps, { setIsActionSheetOpen })(Component); +export default Component => + connect(mapStateToProps, { setIsActionSheetOpen })(Component); diff --git a/src/hoc/withAppState.js b/src/hoc/withAppState.js index b5e68941ac1..8495867aa61 100644 --- a/src/hoc/withAppState.js +++ b/src/hoc/withAppState.js @@ -1,16 +1,18 @@ import { Component, createElement } from 'react'; import { AppState } from 'react-native'; -export default ComponentToWrap => ( +export default ComponentToWrap => class AppStateWrapper extends Component { - state = { appState: AppState.currentState } + state = { appState: AppState.currentState }; - componentDidMount = () => AppState.addEventListener('change', this.handleChange) + componentDidMount = () => + AppState.addEventListener('change', this.handleChange); - componentWillUnmount = () => AppState.removeEventListener('change', this.handleChange) + componentWillUnmount = () => + AppState.removeEventListener('change', this.handleChange); - handleChange = appState => this.setState({ appState }) + handleChange = appState => this.setState({ appState }); - render = () => createElement(ComponentToWrap, { ...this.props, ...this.state }) - } -); + render = () => + createElement(ComponentToWrap, { ...this.props, ...this.state }); + }; diff --git a/src/hoc/withBlockedHorizontalSwipe.js b/src/hoc/withBlockedHorizontalSwipe.js new file mode 100644 index 00000000000..9087fa8a6db --- /dev/null +++ b/src/hoc/withBlockedHorizontalSwipe.js @@ -0,0 +1,14 @@ +import { PanGestureHandler } from 'react-native-gesture-handler'; +import React from 'react'; +import { Animated } from 'react-native'; +import { setDisplayName } from 'recompact'; +// Adding extra PanGestureHandler allows for capturing gesture +// before it got delivered to navigator +export default InnerComponent => + setDisplayName('HorizontalGestureBlocker')(props => ( + + + + + + )); diff --git a/src/hoc/withBlurTransitionProps.js b/src/hoc/withBlurTransitionProps.js deleted file mode 100644 index 3071fd1be1f..00000000000 --- a/src/hoc/withBlurTransitionProps.js +++ /dev/null @@ -1,29 +0,0 @@ -import { compose, withProps } from 'recompact'; -import { createSelector } from 'reselect'; -import withTransitionProps from './withTransitionProps'; - -const blurOpacityInterpolation = { - inputRange: [0, 0.01, 1], - outputRange: [0, 1, 1], -}; - -const transitionPropsSelector = state => state.transitionProps; - -const withBlurTransitionProps = ({ effect, isTransitioning, position }) => { - const blurOpacity = position.interpolate(blurOpacityInterpolation); - - return { - blurOpacity, - showBlur: (effect === 'expanded') && (isTransitioning || blurOpacity.__getValue() > 0), - }; -}; - -const withBlurTransitionPropsSelector = createSelector( - [transitionPropsSelector], - withBlurTransitionProps, -); - -export default Component => compose( - withTransitionProps, - withProps(withBlurTransitionPropsSelector), -)(Component); diff --git a/src/hoc/withContacts.js b/src/hoc/withContacts.js new file mode 100644 index 00000000000..3741713b630 --- /dev/null +++ b/src/hoc/withContacts.js @@ -0,0 +1,29 @@ +import { sortBy, values } from 'lodash'; +import { connect } from 'react-redux'; +import { compose, withProps } from 'recompact'; +import { createSelector } from 'reselect'; +import { contactsAddOrUpdate, removeContact } from '../redux/contacts'; + +const contactsSelector = state => state.contacts; + +const withSortedContacts = contacts => ({ + sortedContacts: sortBy(values(contacts), 'name'), +}); + +const withSortedContactsSelector = createSelector( + [contactsSelector], + withSortedContacts +); + +const mapStateToProps = ({ contacts: { contacts } }) => ({ + contacts, +}); + +export default Component => + compose( + connect(mapStateToProps, { + contactsAddOrUpdate, + removeContact, + }), + withProps(withSortedContactsSelector) + )(Component); diff --git a/src/hoc/withDataInit.js b/src/hoc/withDataInit.js index 54672c92d0a..87956cd9d55 100644 --- a/src/hoc/withDataInit.js +++ b/src/hoc/withDataInit.js @@ -1,23 +1,28 @@ +import { captureException } from '@sentry/react-native'; import delay from 'delay'; import { isNil } from 'lodash'; import { Alert } from 'react-native'; import { connect } from 'react-redux'; import { compose, withHandlers } from 'recompact'; -import { getIsWalletEmpty } from '../handlers/commonStorage'; +import { getIsWalletEmpty } from '../handlers/localstorage/accountLocal'; import { hasEthBalance } from '../handlers/web3'; +import { walletInit } from '../model/wallet'; import { dataClearState, dataLoadState, - dataInit, + dataTokenOverridesInit, } from '../redux/data'; -import { clearIsWalletEmpty, loadIsWalletEmpty } from '../redux/isWalletEmpty'; +import { explorerClearState, explorerInit } from '../redux/explorer'; +import { gasClearState, gasPricesInit } from '../redux/gas'; +import { clearIsWalletEmpty } from '../redux/isWalletEmpty'; import { setIsWalletEthZero } from '../redux/isWalletEthZero'; import { nonceClearState } from '../redux/nonce'; -import { clearOpenFamilyTab } from '../redux/openFamilyTabs'; +import { contactsLoadState } from '../redux/contacts'; import { - requestsLoadState, - requestsClearState, -} from '../redux/requests'; + clearOpenStateSettings, + openStateSettingsLoadState, +} from '../redux/openStateSettings'; +import { requestsLoadState, requestsClearState } from '../redux/requests'; import { settingsLoadState, settingsUpdateAccountAddress, @@ -25,6 +30,7 @@ import { import { uniswapLoadState, uniswapClearState, + uniswapPairsInit, uniswapUpdateState, } from '../redux/uniswap'; import { @@ -32,132 +38,175 @@ import { uniqueTokensLoadState, uniqueTokensRefreshState, } from '../redux/uniqueTokens'; -import { walletInit } from '../model/wallet'; import { walletConnectLoadState, walletConnectClearState, } from '../redux/walletconnect'; +import { + web3ListenerClearState, + web3ListenerInit, +} from '../redux/web3listener'; +import { promiseUtils, sentryUtils } from '../utils'; import withHideSplashScreen from './withHideSplashScreen'; -const PromiseAllWithFails = async (promises) => ( - Promise.all(promises.map(promise => ( - (promise && promise.catch) - ? promise.catch(error => error) - : promise - )))); - -export default Component => compose( - connect(null, { - clearIsWalletEmpty, - clearOpenFamilyTab, - dataClearState, - dataInit, - dataLoadState, - nonceClearState, - requestsClearState, - requestsLoadState, - setIsWalletEthZero, - settingsLoadState, - settingsUpdateAccountAddress, - uniqueTokensClearState, - uniqueTokensLoadState, - uniqueTokensRefreshState, - uniswapClearState, - uniswapLoadState, - uniswapUpdateState, - walletConnectClearState, - walletConnectLoadState, - }), - withHideSplashScreen, - withHandlers({ - checkEthBalance: (ownProps) => async (walletAddress) => { - try { - const ethBalance = await hasEthBalance(walletAddress); - ownProps.setIsWalletEthZero(!ethBalance); - } catch (error) { - console.log('Error: Checking eth balance', error); - } - }, - clearAccountData: (ownProps) => async () => { - const p1 = ownProps.dataClearState(); - const p2 = ownProps.clearIsWalletEmpty(); - const p3 = ownProps.uniqueTokensClearState(); - const p4 = ownProps.clearOpenFamilyTab(); - const p5 = ownProps.walletConnectClearState(); - const p6 = ownProps.nonceClearState(); - const p7 = ownProps.requestsClearState(); - const p8 = ownProps.uniswapClearState(); - return PromiseAllWithFails([p1, p2, p3, p4, p5, p6, p7, p8]); - }, - initializeAccountData: (ownProps) => async () => { - try { - ownProps.dataInit(); - await ownProps.uniqueTokensRefreshState(); - } catch (error) { - // TODO - } - }, - loadAccountData: (ownProps) => async () => { - const p1 = ownProps.settingsLoadState(); - const p2 = ownProps.dataLoadState(); - const p3 = ownProps.uniqueTokensLoadState(); - const p4 = ownProps.walletConnectLoadState(); - const p5 = ownProps.uniswapLoadState(); - const p6 = ownProps.requestsLoadState(); - return PromiseAllWithFails([p1, p2, p3, p4, p5, p6]); - }, - refreshAccountData: (ownProps) => async () => { - try { - const getUniswap = ownProps.uniswapUpdateState(); - const getUniqueTokens = ownProps.uniqueTokensRefreshState(); - - return Promise.all([ - delay(1250), // minimum duration we want the "Pull to Refresh" animation to last - getUniswap, - getUniqueTokens, +export default Component => + compose( + connect(null, { + clearIsWalletEmpty, + clearOpenStateSettings, + contactsLoadState, + dataClearState, + dataLoadState, + dataTokenOverridesInit, + explorerClearState, + explorerInit, + gasClearState, + gasPricesInit, + nonceClearState, + openStateSettingsLoadState, + requestsClearState, + requestsLoadState, + setIsWalletEthZero, + settingsLoadState, + settingsUpdateAccountAddress, + uniqueTokensClearState, + uniqueTokensLoadState, + uniqueTokensRefreshState, + uniswapClearState, + uniswapLoadState, + uniswapPairsInit, + uniswapUpdateState, + walletConnectClearState, + walletConnectLoadState, + web3ListenerInit, + }), + withHideSplashScreen, + withHandlers({ + checkEthBalance: ownProps => async walletAddress => { + try { + const ethBalance = await hasEthBalance(walletAddress); + ownProps.setIsWalletEthZero(!ethBalance); + } catch (error) { + console.log('Error: Checking eth balance', error); + } + }, + clearAccountData: ownProps => async () => { + web3ListenerClearState(); + const p0 = ownProps.explorerClearState(); + const p1 = ownProps.dataClearState(); + const p2 = ownProps.clearIsWalletEmpty(); + const p3 = ownProps.uniqueTokensClearState(); + const p4 = ownProps.clearOpenStateSettings(); + const p5 = ownProps.walletConnectClearState(); + const p6 = ownProps.nonceClearState(); + const p7 = ownProps.requestsClearState(); + const p8 = ownProps.uniswapClearState(); + const p9 = ownProps.gasClearState(); + return promiseUtils.PromiseAllWithFails([ + p0, + p1, + p2, + p3, + p4, + p5, + p6, + p7, + p8, + p9, ]); - } catch (error) { - console.log('Error refreshing data', error); - throw error; - } - }, - }), - withHandlers({ - initializeWallet: (ownProps) => async (seedPhrase) => { - try { - const { isImported, isNew, walletAddress } = await walletInit(seedPhrase); - if (isNil(walletAddress)) { - Alert.alert('Import failed due to an invalid seed phrase. Please try again.'); - return null; + }, + initializeAccountData: ownProps => async () => { + try { + // await ownProps.dataTokenOverridesInit(); + sentryUtils.addInfoBreadcrumb('Initialize account data'); + ownProps.explorerInit(); + ownProps.uniswapPairsInit(); + ownProps.gasPricesInit(); + ownProps.web3ListenerInit(); + await ownProps.uniqueTokensRefreshState(); + } catch (error) { + // TODO error state + console.log('Error initializing account data: ', error); + captureException(error); } - if (isImported) { - await ownProps.clearAccountData(); + }, + loadAccountData: ownProps => async () => { + sentryUtils.addInfoBreadcrumb('Load wallet data'); + await ownProps.openStateSettingsLoadState(); + const p1 = ownProps.settingsLoadState(); + const p2 = ownProps.dataLoadState(); + const p3 = ownProps.uniqueTokensLoadState(); + const p4 = ownProps.walletConnectLoadState(); + const p5 = ownProps.uniswapLoadState(); + const p6 = ownProps.requestsLoadState(); + const p7 = ownProps.contactsLoadState(); + return promiseUtils.PromiseAllWithFails([p1, p2, p3, p4, p5, p6, p7]); + }, + refreshAccountData: ownProps => async () => { + try { + const getUniswap = ownProps.uniswapUpdateState(); + const getUniqueTokens = ownProps.uniqueTokensRefreshState(); + + return Promise.all([ + delay(1250), // minimum duration we want the "Pull to Refresh" animation to last + getUniswap, + getUniqueTokens, + ]); + } catch (error) { + console.log('Error refreshing data', error); + captureException(error); + throw error; } - ownProps.settingsUpdateAccountAddress(walletAddress, 'RAINBOWWALLET'); - if (isNew) { - ownProps.setIsWalletEthZero(true); - } else if (isImported) { - await ownProps.checkEthBalance(walletAddress); - } else { - const isWalletEmpty = await getIsWalletEmpty(walletAddress, 'mainnet'); - if (isNil(isWalletEmpty)) { + }, + }), + withHandlers({ + initializeWallet: ownProps => async seedPhrase => { + try { + sentryUtils.addInfoBreadcrumb('Start wallet setup'); + const { isImported, isNew, walletAddress } = await walletInit( + seedPhrase + ); + if (isNil(walletAddress)) { + Alert.alert( + 'Import failed due to an invalid private key. Please try again.' + ); + return null; + } + if (isImported) { + await ownProps.clearAccountData(); + } + ownProps.settingsUpdateAccountAddress(walletAddress); + if (isNew) { + ownProps.setIsWalletEthZero(true); + } else if (isImported) { await ownProps.checkEthBalance(walletAddress); } else { - ownProps.setIsWalletEthZero(isWalletEmpty); + const isWalletEmpty = await getIsWalletEmpty( + walletAddress, + 'mainnet' + ); + if (isNil(isWalletEmpty)) { + ownProps.checkEthBalance(walletAddress); + } else { + ownProps.setIsWalletEthZero(isWalletEmpty); + } } + if (!(isImported || isNew)) { + await ownProps.loadAccountData(); + } + ownProps.onHideSplashScreen(); + sentryUtils.addInfoBreadcrumb('Hide splash screen'); + ownProps.initializeAccountData(); + return walletAddress; + } catch (error) { + // TODO specify error states more granular + ownProps.onHideSplashScreen(); + captureException(error); + Alert.alert( + 'Import failed due to an invalid private key. Please try again.' + ); + return null; } - if (!(isImported || isNew)) { - await ownProps.loadAccountData(); - } - ownProps.onHideSplashScreen(); - ownProps.initializeAccountData(); - return walletAddress; - } catch (error) { - // TODO specify error states more granular - ownProps.onHideSplashScreen(); - Alert.alert('Import failed due to an invalid seed phrase. Please try again.'); - return null; - } - }, - }), -)(Component); + }, + }) + )(Component); diff --git a/src/hoc/withDeepLink.js b/src/hoc/withDeepLink.js new file mode 100644 index 00000000000..19b38f5c8c4 --- /dev/null +++ b/src/hoc/withDeepLink.js @@ -0,0 +1,135 @@ +import { Linking } from 'react-native'; +import { connect } from 'react-redux'; +import { compose, withHandlers } from 'recompact'; +import { Navigation } from '../navigation'; +import { getRequestDisplayDetails } from '../parsers/requests'; +// eslint-disable-next-line import/default +import parseObjectToUrlQueryString from '../utils'; +import { + PERSONAL_SIGN, + SEND_TRANSACTION, + SIGN, + SIGN_TRANSACTION, +} from '../utils/signingMethods'; +import withAccountSettings from './withAccountSettings'; + +const mapStateToProps = ({ data: { assets } }) => ({ + assets, +}); + +const parseResultsForRedirect = (results, redirectUrl) => { + const queryString = parseObjectToUrlQueryString(results); + const querySeparator = redirectUrl.includes('?') ? '&' : '?'; + const updatedRedirectUrl = `${redirectUrl}${querySeparator}${queryString}`; + return Linking.openURL(updatedRedirectUrl); +}; + +export default Component => + compose( + connect(mapStateToProps), + withAccountSettings, + withHandlers({ + addDeepLinkRequest: ({ + accountAddress, + assets, + nativeCurrency, + }) => uriParams => { + const { + dappName, + imageUrl, + method, + redirectUrl, + ...remainingParams + } = uriParams; + let payload = {}; + let redirect = results => parseResultsForRedirect(results, redirectUrl); + switch (method) { + case SIGN: { + const { message } = remainingParams; + const params = [accountAddress, message]; + payload = { + method, + params, + }; + redirect = results => { + const updatedResults = { + ...results, + address: accountAddress, + msg: message, + }; + return parseResultsForRedirect(updatedResults, redirectUrl); + }; + break; + } + case PERSONAL_SIGN: { + const { message } = remainingParams; + const params = [message, accountAddress]; + payload = { + method, + params, + }; + redirect = results => { + const updatedResults = { + ...results, + address: accountAddress, + msg: message, + }; + return parseResultsForRedirect(updatedResults, redirectUrl); + }; + break; + } + case SEND_TRANSACTION: { + const { data, to, value } = remainingParams; + const transaction = { + data, + from: accountAddress, + to, + value, + }; + const params = [transaction]; + payload = { + method, + params, + }; + break; + } + case SIGN_TRANSACTION: { + const { data, to, value } = remainingParams; + const transaction = { + data, + from: accountAddress, + to, + value, + }; + const params = [transaction]; + payload = { + method, + params, + }; + break; + } + default: + break; + } + const displayDetails = getRequestDisplayDetails( + payload, + assets, + nativeCurrency + ); + const request = { + dappName, + displayDetails, + imageUrl, + payload, + }; + return Navigation.handleAction({ + params: { + callback: redirect, + openAutomatically: true, + transactionDetails: request, + }, + routeName: 'ConfirmRequest', + }); + }, + }) + )(Component); diff --git a/src/hoc/withFabSelection.js b/src/hoc/withFabSelection.js index 50a63c326e9..57deec92129 100644 --- a/src/hoc/withFabSelection.js +++ b/src/hoc/withFabSelection.js @@ -9,10 +9,7 @@ import { } from '../redux/selectedWithFab'; const mapStateToProps = ({ - selectedWithFab: { - scrollingVelocity, - selectedId, - }, + selectedWithFab: { scrollingVelocity, selectedId }, }) => ({ scrollingVelocity, selectedId, @@ -26,7 +23,7 @@ const withFabSelectionValidation = selectedId => ({ const withFabSelectionValidationSelector = createSelector( [fabSelectedIdSelector], - withFabSelectionValidation, + withFabSelectionValidation ); export default compose( @@ -35,5 +32,5 @@ export default compose( setScrollingVelocity, updateSelectedID, }), - withProps(withFabSelectionValidationSelector), + withProps(withFabSelectionValidationSelector) ); diff --git a/src/hoc/withFabSendAction.js b/src/hoc/withFabSendAction.js index dc2bae4362b..3db9e8ff2af 100644 --- a/src/hoc/withFabSendAction.js +++ b/src/hoc/withFabSendAction.js @@ -1,17 +1,13 @@ import { connect } from 'react-redux'; -import { - compose, - lifecycle, - omitProps, - pure, - withProps, -} from 'recompact'; +import { compose, lifecycle, omitProps, pure, withProps } from 'recompact'; import { createSelector } from 'reselect'; import withFabSelection from './withFabSelection'; import withOpenFamilyTabs from './withOpenFamilyTabs'; import { extraStates } from '../components/fab/MovableFabWrapper'; -const mapStateToProps = ({ selectedWithFab: { actionType } }) => ({ actionType }); +const mapStateToProps = ({ selectedWithFab: { actionType } }) => ({ + actionType, +}); const familyNameSelector = state => state.familyName; const selectedIdSelector = state => state.selectedId; @@ -20,16 +16,12 @@ const uniqueIdSelector = state => state.uniqueId; const derivePropsFromSelectedId = (familyName, selectedId, uniqueId) => ({ fabDropped: selectedId === extraStates.gestureInactive, family: selectedId === familyName, - highlight: (selectedId === uniqueId) || (selectedId === familyName), + highlight: selectedId === uniqueId || selectedId === familyName, }); const withPropsDerivedFromSelectedId = createSelector( - [ - familyNameSelector, - selectedIdSelector, - uniqueIdSelector, - ], - derivePropsFromSelectedId, + [familyNameSelector, selectedIdSelector, uniqueIdSelector], + derivePropsFromSelectedId ); let openFamilyCheck = 0; @@ -79,5 +71,5 @@ export default compose( } }, }), - pure, + pure ); diff --git a/src/hoc/withGas.js b/src/hoc/withGas.js new file mode 100644 index 00000000000..819c0c39c76 --- /dev/null +++ b/src/hoc/withGas.js @@ -0,0 +1,31 @@ +import { connect } from 'react-redux'; +import { + gasUpdateDefaultGasLimit, + gasUpdateGasPriceOption, + gasUpdateTxFee, +} from '../redux/gas'; + +const mapStateToProps = ({ + gas: { + gasLimit, + gasPrices, + isSufficientGas, + selectedGasPrice, + selectedGasPriceOption, + txFees, + }, +}) => ({ + gasLimit, + gasPrices, + isSufficientGas, + selectedGasPrice, + selectedGasPriceOption, + txFees, +}); + +export default Component => + connect(mapStateToProps, { + gasUpdateDefaultGasLimit, + gasUpdateGasPriceOption, + gasUpdateTxFee, + })(Component); diff --git a/src/hoc/withHideSplashScreen.js b/src/hoc/withHideSplashScreen.js index 5c8a33c79f4..51b81d26758 100644 --- a/src/hoc/withHideSplashScreen.js +++ b/src/hoc/withHideSplashScreen.js @@ -1,6 +1,11 @@ +import { StatusBar } from 'react-native'; import SplashScreen from 'react-native-splash-screen'; import { withHandlers } from 'recompact'; -export default Component => withHandlers({ - onHideSplashScreen: () => () => SplashScreen.hide(), -})(Component); +export default Component => + withHandlers({ + onHideSplashScreen: () => () => { + SplashScreen.hide(); + StatusBar.setHidden(false, 'fade'); // show the StatusBar + }, + })(Component); diff --git a/src/hoc/withImageDimensionsCache.js b/src/hoc/withImageDimensionsCache.js index 0632eb43305..53346f2a9ea 100644 --- a/src/hoc/withImageDimensionsCache.js +++ b/src/hoc/withImageDimensionsCache.js @@ -4,9 +4,12 @@ import { updateImageDimensionsCache, } from '../redux/imageDimensionsCache'; -const mapStateToProps = ({ imageDimensionsCache }) => ({ imageDimensionsCache }); +const mapStateToProps = ({ imageDimensionsCache }) => ({ + imageDimensionsCache, +}); -export default Component => connect(mapStateToProps, { - pruneCache: pruneImageDimensionsCache, - updateCache: updateImageDimensionsCache, -})(Component); +export default Component => + connect(mapStateToProps, { + pruneCache: pruneImageDimensionsCache, + updateCache: updateImageDimensionsCache, + })(Component); diff --git a/src/hoc/withIsWalletEmpty.js b/src/hoc/withIsWalletEmpty.js index 26e44139e60..d1679a587cd 100644 --- a/src/hoc/withIsWalletEmpty.js +++ b/src/hoc/withIsWalletEmpty.js @@ -3,4 +3,5 @@ import { setIsWalletEmpty } from '../redux/isWalletEmpty'; const mapStateToProps = ({ isWalletEmpty }) => isWalletEmpty; -export default Component => connect(mapStateToProps, { setIsWalletEmpty })(Component); +export default Component => + connect(mapStateToProps, { setIsWalletEmpty })(Component); diff --git a/src/hoc/withIsWalletEthZero.js b/src/hoc/withIsWalletEthZero.js index 2da2cd6a885..0f48a4773d7 100644 --- a/src/hoc/withIsWalletEthZero.js +++ b/src/hoc/withIsWalletEthZero.js @@ -3,4 +3,5 @@ import { setIsWalletEthZero } from '../redux/isWalletEthZero'; const mapStateToProps = ({ isWalletEthZero }) => isWalletEthZero; -export default Component => connect(mapStateToProps, { setIsWalletEthZero })(Component); +export default Component => + connect(mapStateToProps, { setIsWalletEthZero })(Component); diff --git a/src/hoc/withIsWalletImporting.js b/src/hoc/withIsWalletImporting.js deleted file mode 100644 index 1f689a15af6..00000000000 --- a/src/hoc/withIsWalletImporting.js +++ /dev/null @@ -1,6 +0,0 @@ -import { connect } from 'react-redux'; -import { setIsWalletImporting } from '../redux/isWalletImporting'; - -const mapStateToProps = ({ isWalletImporting }) => isWalletImporting; - -export default Component => connect(mapStateToProps, { setIsWalletImporting })(Component); diff --git a/src/hoc/withKeyboardHeight.js b/src/hoc/withKeyboardHeight.js new file mode 100644 index 00000000000..c6751fc5bd2 --- /dev/null +++ b/src/hoc/withKeyboardHeight.js @@ -0,0 +1,6 @@ +import { connect } from 'react-redux'; +import { setKeyboardHeight } from '../redux/keyboardHeight'; + +const mapStateToProps = ({ keyboardHeight }) => keyboardHeight; + +export default connect(mapStateToProps, { setKeyboardHeight }); diff --git a/src/hoc/withMessageSigningScreen.js b/src/hoc/withMessageSigningScreen.js index f84a88ed958..1842ca51737 100644 --- a/src/hoc/withMessageSigningScreen.js +++ b/src/hoc/withMessageSigningScreen.js @@ -1,12 +1,9 @@ import { connect } from 'react-redux'; import { removeRequest } from '../redux/requests'; -const mapStateToProps = ({ - walletconnect: { walletConnectors }, -}) => ({ +const mapStateToProps = ({ walletconnect: { walletConnectors } }) => ({ walletConnectors, }); -export default Component => connect(mapStateToProps, { - removeRequest, -})(Component); +export default Component => + connect(mapStateToProps, { removeRequest })(Component); diff --git a/src/hoc/withNetInfo.js b/src/hoc/withNetInfo.js deleted file mode 100644 index 5bf67bf1587..00000000000 --- a/src/hoc/withNetInfo.js +++ /dev/null @@ -1,20 +0,0 @@ -import NetInfo from '@react-native-community/netinfo'; -import { - compose, - lifecycle, - withState, -} from 'recompact'; - -const withNetInfo = ComponentToWrap => compose( - withState('isConnected', 'setIsConnected', true), - lifecycle({ - componentDidMount() { - NetInfo.isConnected.addEventListener('connectionChange', this.props.setIsConnected); - }, - componentWillUnmount() { - NetInfo.isConnected.removeEventListener('connectionChange', this.props.setIsConnected); - }, - }), -)(ComponentToWrap); - -export default withNetInfo; diff --git a/src/hoc/withOpenBalances.js b/src/hoc/withOpenBalances.js new file mode 100644 index 00000000000..ec47eba04bb --- /dev/null +++ b/src/hoc/withOpenBalances.js @@ -0,0 +1,9 @@ +import { connect } from 'react-redux'; +import { setOpenSmallBalances } from '../redux/openStateSettings'; + +const mapStateToProps = ({ openStateSettings: { openSmallBalances } }) => ({ + openSmallBalances, +}); + +export default Component => + connect(mapStateToProps, { setOpenSmallBalances })(Component); diff --git a/src/hoc/withOpenFamilyTabs.js b/src/hoc/withOpenFamilyTabs.js index 3b61972473c..7cf706bfde2 100644 --- a/src/hoc/withOpenFamilyTabs.js +++ b/src/hoc/withOpenFamilyTabs.js @@ -1,9 +1,15 @@ import { connect } from 'react-redux'; -import { pushOpenFamilyTab, setOpenFamilyTabs } from '../redux/openFamilyTabs'; - -const mapStateToProps = ({ openFamilyTabs: { openFamilyTabs } }) => ({ openFamilyTabs }); - -export default Component => connect(mapStateToProps, { +import { pushOpenFamilyTab, setOpenFamilyTabs, -})(Component); +} from '../redux/openStateSettings'; + +const mapStateToProps = ({ openStateSettings: { openFamilyTabs } }) => ({ + openFamilyTabs, +}); + +export default Component => + connect(mapStateToProps, { + pushOpenFamilyTab, + setOpenFamilyTabs, + })(Component); diff --git a/src/hoc/withOpenInvestmentCards.js b/src/hoc/withOpenInvestmentCards.js new file mode 100644 index 00000000000..456a3f9e5c9 --- /dev/null +++ b/src/hoc/withOpenInvestmentCards.js @@ -0,0 +1,15 @@ +import { connect } from 'react-redux'; +import { + pushOpenInvestmentCard, + setOpenInvestmentCards, +} from '../redux/openStateSettings'; + +const mapStateToProps = ({ openStateSettings: { openInvestmentCards } }) => ({ + openInvestmentCards, +}); + +export default Component => + connect(mapStateToProps, { + pushOpenInvestmentCard, + setOpenInvestmentCards, + })(Component); diff --git a/src/hoc/withRequests.js b/src/hoc/withRequests.js index e77a84ce348..e5627a228b9 100644 --- a/src/hoc/withRequests.js +++ b/src/hoc/withRequests.js @@ -9,8 +9,10 @@ const mapStateToProps = ({ requests: { requests } }) => ({ const requestsSelector = state => state.requests; -const withRequests = (requests) => { - const sortedRequests = reverse(sortBy(values(requests), 'displayDetails.timestampInMs')); +const withRequests = requests => { + const sortedRequests = reverse( + sortBy(values(requests), 'displayDetails.timestampInMs') + ); return { pendingRequestCount: sortedRequests.length, @@ -18,12 +20,7 @@ const withRequests = (requests) => { }; }; -const withRequestsSelector = createSelector( - [requestsSelector], - withRequests, -); +const withRequestsSelector = createSelector([requestsSelector], withRequests); -export default Component => compose( - connect(mapStateToProps), - withProps(withRequestsSelector), -)(Component); +export default Component => + compose(connect(mapStateToProps), withProps(withRequestsSelector))(Component); diff --git a/src/hoc/withRotationForDirection.js b/src/hoc/withRotationForDirection.js index 37e976e9f91..8d648751760 100644 --- a/src/hoc/withRotationForDirection.js +++ b/src/hoc/withRotationForDirection.js @@ -2,16 +2,17 @@ import { mapProps } from 'recompact'; import { calcDirectionToDegrees } from '../styles'; import { reduceArrayToObject } from '../utils'; -const withRotationForDirection = Component => mapProps(({ direction, style, ...props }) => { - const prevStyles = reduceArrayToObject(style); +const withRotationForDirection = Component => + mapProps(({ direction, style, ...props }) => { + const prevStyles = reduceArrayToObject(style); - return { - ...props, - style: reduceArrayToObject([ - prevStyles, - { transform: [{ rotate: `${calcDirectionToDegrees(direction)}deg` }] }, - ]), - }; -})(Component); + return { + ...props, + style: reduceArrayToObject([ + prevStyles, + { transform: [{ rotate: `${calcDirectionToDegrees(direction)}deg` }] }, + ]), + }; + })(Component); export default withRotationForDirection; diff --git a/src/hoc/withSafeAreaViewInsetValues.js b/src/hoc/withSafeAreaViewInsetValues.js index cf6124bab63..6ef28a10df7 100644 --- a/src/hoc/withSafeAreaViewInsetValues.js +++ b/src/hoc/withSafeAreaViewInsetValues.js @@ -1,4 +1,5 @@ import { withProps } from 'recompact'; import { safeAreaInsetValues } from '../utils'; -export default Component => withProps({ safeAreaInset: safeAreaInsetValues })(Component); +export default Component => + withProps({ safeAreaInset: safeAreaInsetValues })(Component); diff --git a/src/hoc/withSelectedInput.js b/src/hoc/withSelectedInput.js new file mode 100644 index 00000000000..f657b6a6c8a --- /dev/null +++ b/src/hoc/withSelectedInput.js @@ -0,0 +1,9 @@ +import { connect } from 'react-redux'; +import { setSelectedInputId } from '../redux/selectedInput'; + +const mapStateToProps = ({ selectedInput: { selectedInputId } }) => ({ + selectedInputId, +}); + +export default Component => + connect(mapStateToProps, { setSelectedInputId })(Component); diff --git a/src/hoc/withSendFeedback.js b/src/hoc/withSendFeedback.js index 3e190bbafd1..4600bf705ce 100644 --- a/src/hoc/withSendFeedback.js +++ b/src/hoc/withSendFeedback.js @@ -6,23 +6,29 @@ import { Alert } from '../components/alerts'; const FeedbackEmailAddress = 'support@rainbow.me'; -const setClipboardToFeedbackEmail = () => Clipboard.setString(FeedbackEmailAddress); +const setClipboardToFeedbackEmail = () => + Clipboard.setString(FeedbackEmailAddress); -const FeedbackErrorAlert = () => Alert({ - buttons: [{ - onPress: setClipboardToFeedbackEmail, - text: 'Copy email address', - }, { - style: 'cancel', - text: 'No thanks', - }], - message: 'Would you like to manually copy our feedback email address to your clipboard?', - title: 'Error launching email client', -}); +const FeedbackErrorAlert = () => + Alert({ + buttons: [ + { + onPress: setClipboardToFeedbackEmail, + text: 'Copy email address', + }, + { + style: 'cancel', + text: 'No thanks', + }, + ], + message: + 'Would you like to manually copy our feedback email address to your clipboard?', + title: 'Error launching email client', + }); const handleMailError = debounce( error => (error ? FeedbackErrorAlert() : null), - 250, + 250 ); const feedbackEmailOptions = { @@ -30,8 +36,10 @@ const feedbackEmailOptions = { subject: '🌈️ Rainbow Feedback', }; -const withSendFeedback = ComponentToWrap => withHandlers({ - onSendFeedback: () => () => Mailer.mail(feedbackEmailOptions, handleMailError), -})(ComponentToWrap); +const withSendFeedback = ComponentToWrap => + withHandlers({ + onSendFeedback: () => () => + Mailer.mail(feedbackEmailOptions, handleMailError), + })(ComponentToWrap); export default withSendFeedback; diff --git a/src/hoc/withStatusBarStyle.js b/src/hoc/withStatusBarStyle.js index 377a53885bb..2fc354bc89c 100644 --- a/src/hoc/withStatusBarStyle.js +++ b/src/hoc/withStatusBarStyle.js @@ -2,10 +2,12 @@ import React, { Fragment } from 'react'; import { NavigationEvents } from 'react-navigation'; import { statusBar } from '../utils'; -const withStatusBarStyle = (statusBarStyle) => (ComponentToWrap) => { - const ComponentWithStatusBarStyle = (props) => ( +const withStatusBarStyle = statusBarStyle => ComponentToWrap => { + const ComponentWithStatusBarStyle = props => ( - statusBar.setBarStyle(statusBarStyle, true)} /> + statusBar.setBarStyle(statusBarStyle, true)} + /> ); diff --git a/src/hoc/withTransactionConfirmationScreen.js b/src/hoc/withTransactionConfirmationScreen.js index 91fcd7fe0fb..ced2b7ce1d2 100644 --- a/src/hoc/withTransactionConfirmationScreen.js +++ b/src/hoc/withTransactionConfirmationScreen.js @@ -4,11 +4,14 @@ import { removeRequest } from '../redux/requests'; import { updateTransactionCountNonce } from '../redux/nonce'; import { walletConnectSendStatus } from '../redux/walletconnect'; -const mapStateToProps = ({ nonce: { transactionCountNonce } }) => ({ transactionCountNonce }); +const mapStateToProps = ({ nonce: { transactionCountNonce } }) => ({ + transactionCountNonce, +}); -export default Component => connect(mapStateToProps, { - dataAddNewTransaction, - removeRequest, - updateTransactionCountNonce, - walletConnectSendStatus, -})(Component); +export default Component => + connect(mapStateToProps, { + dataAddNewTransaction, + removeRequest, + updateTransactionCountNonce, + walletConnectSendStatus, + })(Component); diff --git a/src/hoc/withTransitionProps.js b/src/hoc/withTransitionProps.js index 8fa94b887f0..3e5b42a1621 100644 --- a/src/hoc/withTransitionProps.js +++ b/src/hoc/withTransitionProps.js @@ -1,6 +1,8 @@ import { connect } from 'react-redux'; -const mapStateToProps = ({ navigation: { transitionProps } }) => ({ transitionProps }); +const mapStateToProps = ({ navigation: { transitionProps } }) => ({ + transitionProps, +}); const withTransitionProps = Component => connect(mapStateToProps)(Component); diff --git a/src/hoc/withUniqueTokens.js b/src/hoc/withUniqueTokens.js index 5e92e583ab1..21d9a64b2f3 100644 --- a/src/hoc/withUniqueTokens.js +++ b/src/hoc/withUniqueTokens.js @@ -4,34 +4,34 @@ import { compose, withProps } from 'recompact'; import { sendableUniqueTokensSelector } from './uniqueTokenSelectors'; const mapStateToProps = ({ - uniqueTokens: { - uniqueTokens, - }, + uniqueTokens: { uniqueTokens }, settings: { nativeCurrency }, }) => ({ nativeCurrency, uniqueTokens, }); -const sendableUniqueTokens = (state) => { - const sendableUniqueTokens = sendableUniqueTokensSelector(state).sendableUniqueTokens; - const grouped = groupBy(sendableUniqueTokens, token => token.asset_contract.name); +const sendableUniqueTokens = state => { + const sendableUniqueTokens = sendableUniqueTokensSelector(state) + .sendableUniqueTokens; + const grouped = groupBy( + sendableUniqueTokens, + token => token.asset_contract.name + ); const families = Object.keys(grouped).sort(); - let sendableTokens = [] + let sendableTokens = []; for (let i = 0; i < families.length; i++) { let newObject = {}; newObject = { - name: families[i], - familyImage: grouped[families[i]][0].familyImage, - familyId: i, data: grouped[families[i]], + familyId: i, + familyImage: grouped[families[i]][0].familyImage, + name: families[i], }; sendableTokens.push(newObject); - }; - return { sendableUniqueTokens: sendableTokens}; -} + } + return { sendableUniqueTokens: sendableTokens }; +}; -export default Component => compose( - connect(mapStateToProps), - withProps(sendableUniqueTokens), -)(Component); +export default Component => + compose(connect(mapStateToProps), withProps(sendableUniqueTokens))(Component); diff --git a/src/hoc/withUniswapAllowances.js b/src/hoc/withUniswapAllowances.js new file mode 100644 index 00000000000..7a6d85f61d1 --- /dev/null +++ b/src/hoc/withUniswapAllowances.js @@ -0,0 +1,33 @@ +import { connect } from 'react-redux'; +import { + uniswapAddPendingApproval, + uniswapClearCurrenciesAndReserves, + uniswapUpdateAllowances, + uniswapUpdateInputCurrency, + uniswapUpdateOutputCurrency, +} from '../redux/uniswap'; + +const mapStateToProps = ({ + uniswap: { + allowances, + inputReserve, + outputReserve, + pendingApprovals, + tokenReserves, + }, +}) => ({ + allowances, + inputReserve, + outputReserve, + pendingApprovals, + tokenReserves, +}); + +export default Component => + connect(mapStateToProps, { + uniswapAddPendingApproval, + uniswapClearCurrenciesAndReserves, + uniswapUpdateAllowances, + uniswapUpdateInputCurrency, + uniswapUpdateOutputCurrency, + })(Component); diff --git a/src/hoc/withUniswapAssets.js b/src/hoc/withUniswapAssets.js new file mode 100644 index 00000000000..ce4b9a56c92 --- /dev/null +++ b/src/hoc/withUniswapAssets.js @@ -0,0 +1,88 @@ +import { + concat, + filter, + get, + includes, + keys, + map, + partition, + sortBy, + toLower, + values, +} from 'lodash'; +import { connect } from 'react-redux'; +import { compose, withProps } from 'recompact'; +import { createSelector } from 'reselect'; +import { uniswapUpdateFavorites } from '../redux/uniswap'; +import withAccountData from './withAccountData'; + +const allAssetsSelector = state => state.allAssets; +const uniswapAssetsSelector = state => state.uniswapAssets; +const uniswapFavoritesSelector = state => state.favorites; +const uniswapPairsSelector = state => state.pairs; + +const filterUniswapAssetsByAvailability = uniswapAssetAddresses => ({ + address, +}) => uniswapAssetAddresses.includes(address); + +export const includeExchangeAddress = uniswapPairs => asset => ({ + ...asset, + exchangeAddress: get( + uniswapPairs, + `[${toLower(asset.address)}].exchangeAddress` + ), +}); + +const appendFavoriteKey = asset => ({ + ...asset, + favorite: true, +}); + +const withAssetsAvailableOnUniswap = (allAssets, uniswapPairs) => { + const availableAssets = filter( + allAssets, + filterUniswapAssetsByAvailability(keys(uniswapPairs)) + ); + const assetsAvailableOnUniswap = map( + availableAssets, + includeExchangeAddress(uniswapPairs) + ); + return { assetsAvailableOnUniswap }; +}; + +const withSortedUniswapAssets = (assets, favorites) => { + const sorted = sortBy(values(assets), ({ name }) => toLower(name)); + const [favorited, notFavorited] = partition(sorted, ({ address }) => + includes(map(favorites, toLower), toLower(address)) + ); + + return { + sortedUniswapAssets: concat( + map(favorited, appendFavoriteKey), + notFavorited + ), + }; +}; + +const withAssetsAvailableOnUniswapSelector = createSelector( + [allAssetsSelector, uniswapPairsSelector], + withAssetsAvailableOnUniswap +); + +const withSortedUniswapAssetsSelector = createSelector( + [uniswapAssetsSelector, uniswapFavoritesSelector], + withSortedUniswapAssets +); + +const mapStateToProps = ({ uniswap: { favorites, pairs, uniswapAssets } }) => ({ + favorites, + pairs, + uniswapAssets, +}); + +export default compose( + connect(mapStateToProps, { uniswapUpdateFavorites }), + withAccountData, + withProps(withSortedUniswapAssetsSelector), + withProps(withAssetsAvailableOnUniswapSelector) +); diff --git a/src/hoc/withUniswapLiquidity.js b/src/hoc/withUniswapLiquidityTokenInfo.js similarity index 62% rename from src/hoc/withUniswapLiquidity.js rename to src/hoc/withUniswapLiquidityTokenInfo.js index ec131efdeb3..0ed070d61b1 100644 --- a/src/hoc/withUniswapLiquidity.js +++ b/src/hoc/withUniswapLiquidityTokenInfo.js @@ -20,18 +20,15 @@ import { import { ethereumUtils } from '../utils'; import withAccountSettings from './withAccountSettings'; -const mapStateToProps = ({ - settings: { nativeCurrency }, - uniswap: { uniswap }, -}) => ({ - nativeCurrency, - uniswap, +const mapStateToProps = ({ uniswap: { uniswapLiquidityTokenInfo } }) => ({ + uniswapLiquidityTokenInfo, }); const assetsSelector = state => state.assets; const nativeCurrencySelector = state => state.nativeCurrency; const nativeCurrencySymbolSelector = state => state.nativeCurrencySymbol; -const uniswapSelector = state => state.uniswap; +const uniswapLiquidityTokenInfoSelector = state => + state.uniswapLiquidityTokenInfo; export const transformPool = (liquidityPool, ethPrice, nativeCurrency) => { if (isEmpty(liquidityPool)) { @@ -41,11 +38,7 @@ export const transformPool = (liquidityPool, ethPrice, nativeCurrency) => { const { balance, ethBalance, - token: { - balance: tokenBalance, - name: tokenName, - symbol: tokenSymbol, - }, + token: { balance: tokenBalance, name: tokenName, symbol: tokenSymbol }, totalSupply, uniqueId, } = liquidityPool; @@ -54,9 +47,16 @@ export const transformPool = (liquidityPool, ethPrice, nativeCurrency) => { const { amount: balanceAmount, display: nativeDisplay, - } = convertAmountAndPriceToNativeDisplay(ethBalance, ethPrice, nativeCurrency); + } = convertAmountAndPriceToNativeDisplay( + ethBalance, + ethPrice, + nativeCurrency + ); const totalBalanceAmount = multiply(balanceAmount, 2); - const totalNativeDisplay = convertAmountToNativeDisplay(totalBalanceAmount, nativeCurrency); + const totalNativeDisplay = convertAmountToNativeDisplay( + totalBalanceAmount, + nativeCurrency + ); return { ethBalance: floor(parseFloat(ethBalance), 4) || '< 0.0001', @@ -71,16 +71,31 @@ export const transformPool = (liquidityPool, ethPrice, nativeCurrency) => { }; }; -const buildUniswapCards = (nativeCurrency, nativeCurrencySymbol, assets, uniswap) => { +const buildUniswapCards = ( + nativeCurrency, + nativeCurrencySymbol, + assets, + uniswapLiquidityTokenInfo +) => { const ethPrice = get(ethereumUtils.getAsset(assets), 'price.value', 0); - const uniswapPools = compact(map(values(uniswap), (liquidityPool) => transformPool(liquidityPool, ethPrice, nativeCurrency))); - const orderedUniswapPools = orderBy(uniswapPools, [({ totalBalanceAmount }) => Number(totalBalanceAmount)], ['desc']); + const uniswapPools = compact( + map(values(uniswapLiquidityTokenInfo), liquidityPool => + transformPool(liquidityPool, ethPrice, nativeCurrency) + ) + ); + const orderedUniswapPools = orderBy( + uniswapPools, + [({ totalBalanceAmount }) => Number(totalBalanceAmount)], + ['desc'] + ); let uniswapTotal = 0; if (Array.isArray(orderedUniswapPools) && orderedUniswapPools.length) { - uniswapTotal = sumBy(orderedUniswapPools, ({ totalBalanceAmount }) => Number(totalBalanceAmount)); + uniswapTotal = sumBy(orderedUniswapPools, ({ totalBalanceAmount }) => + Number(totalBalanceAmount) + ); } return { @@ -94,13 +109,14 @@ export const readableUniswapSelector = createSelector( nativeCurrencySelector, nativeCurrencySymbolSelector, assetsSelector, - uniswapSelector, + uniswapLiquidityTokenInfoSelector, ], - buildUniswapCards, + buildUniswapCards ); -export default Component => compose( - withAccountSettings, - connect(mapStateToProps), - withProps(readableUniswapSelector), -)(Component); +export default Component => + compose( + withAccountSettings, + connect(mapStateToProps), + withProps(readableUniswapSelector) + )(Component); diff --git a/src/hoc/withWalletConnectConfirmationModal.js b/src/hoc/withWalletConnectConfirmationModal.js index a06ede1700a..45318e355ed 100644 --- a/src/hoc/withWalletConnectConfirmationModal.js +++ b/src/hoc/withWalletConnectConfirmationModal.js @@ -4,7 +4,8 @@ import { walletConnectRejectSession, } from '../redux/walletconnect'; -export default Component => connect(null, { - walletConnectApproveSession, - walletConnectRejectSession, -})(Component); +export default Component => + connect(null, { + walletConnectApproveSession, + walletConnectRejectSession, + })(Component); diff --git a/src/hoc/withWalletConnectConnections.js b/src/hoc/withWalletConnectConnections.js index 89ed6ff2514..0fab67d1b58 100644 --- a/src/hoc/withWalletConnectConnections.js +++ b/src/hoc/withWalletConnectConnections.js @@ -1,31 +1,33 @@ -import { - get, - groupBy, - mapValues, - values, -} from 'lodash'; +import { get, groupBy, mapValues, values } from 'lodash'; import { connect } from 'react-redux'; import { compose, withProps } from 'recompact'; import { createSelector } from 'reselect'; import { sortList } from '../helpers/sortList'; -import { - walletConnectClearTimestamp, - walletConnectDisconnectAllByDappName, - walletConnectUpdateTimestamp, -} from '../redux/walletconnect'; +import { walletConnectDisconnectAllByDappName } from '../redux/walletconnect'; -const mapStateToProps = ({ walletconnect: { walletConnectors } }) => ({ walletConnectors }); +const mapStateToProps = ({ walletconnect: { walletConnectors } }) => ({ + walletConnectors, +}); const walletConnectorsSelector = state => state.walletConnectors; -const sortWalletConnectors = (walletConnectors) => { - const sortedWalletConnectors = sortList(Object.values(walletConnectors), 'peerMeta.name'); - const sortedWalletConnectorsByDappName = groupBy(sortedWalletConnectors, 'peerMeta.url'); - const dappWalletConnector = mapValues(sortedWalletConnectorsByDappName, (connectors) => ({ - dappIcon: get(connectors, '[0].peerMeta.icons[0]'), - dappName: get(connectors, '[0].peerMeta.name'), - dappUrl: get(connectors, '[0].peerMeta.url'), - })); +const sortWalletConnectors = walletConnectors => { + const sortedWalletConnectors = sortList( + Object.values(walletConnectors), + 'peerMeta.name' + ); + const sortedWalletConnectorsByDappName = groupBy( + sortedWalletConnectors, + 'peerMeta.url' + ); + const dappWalletConnector = mapValues( + sortedWalletConnectorsByDappName, + connectors => ({ + dappIcon: get(connectors, '[0].peerMeta.icons[0]'), + dappName: get(connectors, '[0].peerMeta.name'), + dappUrl: get(connectors, '[0].peerMeta.url'), + }) + ); return { sortedWalletConnectors, @@ -36,14 +38,13 @@ const sortWalletConnectors = (walletConnectors) => { const walletConnectSelector = createSelector( [walletConnectorsSelector], - sortWalletConnectors, + sortWalletConnectors ); -export default Component => compose( - connect(mapStateToProps, { - walletConnectClearTimestamp, - walletConnectDisconnectAllByDappName, - walletConnectUpdateTimestamp, - }), - withProps(walletConnectSelector), -)(Component); +export default Component => + compose( + connect(mapStateToProps, { + walletConnectDisconnectAllByDappName, + }), + withProps(walletConnectSelector) + )(Component); diff --git a/src/hoc/withWalletConnectOnSessionRequest.js b/src/hoc/withWalletConnectOnSessionRequest.js index 865198ad687..9b686564cb6 100644 --- a/src/hoc/withWalletConnectOnSessionRequest.js +++ b/src/hoc/withWalletConnectOnSessionRequest.js @@ -1,7 +1,5 @@ import { connect } from 'react-redux'; import { walletConnectOnSessionRequest } from '../redux/walletconnect'; -export default Component => connect( - null, - { walletConnectOnSessionRequest }, -)(Component); +export default Component => + connect(null, { walletConnectOnSessionRequest })(Component); diff --git a/src/hooks/index.js b/src/hooks/index.js new file mode 100644 index 00000000000..3264f26a0c8 --- /dev/null +++ b/src/hooks/index.js @@ -0,0 +1,5 @@ +export { default as useAppState } from './useAppState'; +export { default as useClipboard } from './useClipboard'; +export { default as useInternetStatus } from './useInternetStatus'; +export { default as usePrevious } from './usePrevious'; +export { default as useBiometryType, BiometryTypes } from './useBiometryType'; diff --git a/src/hooks/useAppState.js b/src/hooks/useAppState.js new file mode 100644 index 00000000000..cbcb4685662 --- /dev/null +++ b/src/hooks/useAppState.js @@ -0,0 +1,30 @@ +import { useEffect, useState } from 'react'; +import { AppState } from 'react-native'; +import usePrevious from './usePrevious'; + +const AppStateTypes = { + active: 'active', + background: 'background', + inactive: 'inactive', +}; + +export default function useAppState() { + const [appState, setAppState] = useState(AppState.currentState); + const prevAppState = usePrevious(appState); + + function onChange(newState) { + setAppState(newState); + } + + useEffect(() => { + AppState.addEventListener('change', onChange); + return () => AppState.removeEventListener('change', onChange); + }, []); + + return { + appState, + justBecameActive: + appState === AppStateTypes.active && + prevAppState !== AppStateTypes.active, + }; +} diff --git a/src/hooks/useBiometryType.js b/src/hooks/useBiometryType.js new file mode 100644 index 00000000000..73e6a317f5b --- /dev/null +++ b/src/hooks/useBiometryType.js @@ -0,0 +1,50 @@ +import { isNil } from 'lodash'; +import { useEffect, useState } from 'react'; +import { isPinOrFingerprintSet } from 'react-native-device-info'; +import * as Keychain from 'react-native-keychain'; +import useAppState from './useAppState'; +import usePrevious from './usePrevious'; + +export const BiometryTypes = { + FaceID: 'FaceID', + none: 'none', + passcode: 'passcode', + TouchID: 'TouchID', +}; + +export default function useBiometryType() { + const { justBecameActive } = useAppState(); + const [biometryType, setBiometryType] = useState(null); + const prevBiometricType = usePrevious(biometryType); + + useEffect(() => { + let mounted = true; + + const getSupportedBiometryType = async () => { + let type = await Keychain.getSupportedBiometryType(); + + if (isNil(type)) { + // πŸ’‘οΈ When `getSupportedBiometryType` returns `null` it can mean either: + // A) the user has no device passcode/biometrics at all + // B) the user has gone into Settings and disabled biometrics specifically for Rainbow + type = await isPinOrFingerprintSet().then(isPinOrFingerprintSet => + isPinOrFingerprintSet ? BiometryTypes.passcode : BiometryTypes.none + ); + } + + if (mounted && type !== prevBiometricType) { + setBiometryType(type); + } + }; + + if (!biometryType || justBecameActive) { + getSupportedBiometryType(); + } + + return () => { + mounted = false; + }; + }, [biometryType, justBecameActive, prevBiometricType]); + + return biometryType; +} diff --git a/src/hooks/useClipboard.js b/src/hooks/useClipboard.js new file mode 100644 index 00000000000..bcc749245d5 --- /dev/null +++ b/src/hooks/useClipboard.js @@ -0,0 +1,26 @@ +import { useCallback, useEffect, useState } from 'react'; +import { Clipboard } from 'react-native'; +import useAppState from './useAppState'; + +export default function useClipboard() { + const { justBecameActive } = useAppState(); + const [data, updateClipboardData] = useState(''); + + async function updateClipboard() { + const content = await Clipboard.getString(); + updateClipboardData(content); + } + + useEffect(() => { + if (justBecameActive) { + updateClipboard(); + } + }, [justBecameActive]); + + const setString = useCallback(content => { + Clipboard.setString(content); + updateClipboardData(content); + }, []); + + return [data, setString]; +} diff --git a/src/hooks/useInternetStatus.js b/src/hooks/useInternetStatus.js new file mode 100644 index 00000000000..7520325cbe1 --- /dev/null +++ b/src/hooks/useInternetStatus.js @@ -0,0 +1,27 @@ +import NetInfo from '@react-native-community/netinfo'; +import analytics from '@segment/analytics-react-native'; +import { isNil } from 'lodash'; +import { useEffect, useState } from 'react'; + +export default function useInternetStatus() { + const [isInternetReachable, setIsInternetReachable] = useState(true); + + function onChange(newState) { + const { isInternetReachable: newIsInternetReachable } = newState; + if (!isNil(newIsInternetReachable)) { + setIsInternetReachable(newIsInternetReachable); + if (newIsInternetReachable) { + analytics.track('Reconnected after offline'); + } else { + analytics.track('Offline / lost connection'); + } + } + } + + useEffect(() => { + const unsubscribe = NetInfo.addEventListener(onChange); + return unsubscribe; + }, []); + + return isInternetReachable; +} diff --git a/src/hooks/usePrevious.js b/src/hooks/usePrevious.js new file mode 100644 index 00000000000..ed46581cb01 --- /dev/null +++ b/src/hooks/usePrevious.js @@ -0,0 +1,11 @@ +import { useEffect, useRef } from 'react'; + +export default function usePrevious(value) { + const ref = useRef(); + + useEffect(() => { + ref.current = value; + }, [value]); + + return ref.current; +} diff --git a/src/languages/_english.json b/src/languages/_english.json index 31c07d0303d..adcece09793 100644 --- a/src/languages/_english.json +++ b/src/languages/_english.json @@ -209,25 +209,62 @@ "generic_error": "Oops, something went wrong" }, "time": { - "ms": "ms", - "milisecond": "milisecond", - "miliseconds": "miliseconds", - "s": "s", - "sec": "sec", - "secs": "secs", - "second": "second", - "seconds": "seconds", - "min": "min", - "mins": "mins", - "minute": "minute", - "minutes": "minutes", - "hr": "hr", - "hrs": "hrs", - "hour": "hour", - "hours": "hours", - "day": "day", - "days": "days", - "now": "Now" + "days": { + "long": { + "singular": "day", + "plural": "days" + }, + "micro": "d", + "short": { + "singular": "day", + "plural": "days" + } + }, + "hours": { + "long": { + "singular": "hour", + "plural": "hours" + }, + "micro": "h", + "short": { + "singular": "hr", + "plural": "hrs" + } + }, + "milliseconds": { + "long": { + "singular": "millisecond", + "plural": "milliseconds" + }, + "micro": "ms", + "short": { + "singular": "ms", + "plural": "ms" + } + }, + "minutes": { + "long": { + "singular": "minute", + "plural": "minutes" + }, + "micro": "m", + "short": { + "singular": "min", + "plural": "mins" + } + }, + "now": "Now", + "seconds": { + "long": { + "singular": "second", + "plural": "seconds" + }, + "micro": "s", + "short": { + "singular": "sec", + "plural": "secs" + } + } }, "wallet": { "action": { @@ -241,7 +278,7 @@ }, "authenticate": { "please": "Please authenticate", - "please_seed_phrase": "Please authenticate to view seed phrase" + "please_seed_phrase": "Please authenticate to view private key" }, "push_notifications": { "please_enable_title": "Rainbow would like to send you push notifications", diff --git a/src/languages/_french.json b/src/languages/_french.json index bfb97639a17..90f329033f5 100644 --- a/src/languages/_french.json +++ b/src/languages/_french.json @@ -180,26 +180,63 @@ "generic_error": "Oups, une erreur s’est produite" }, "time": { - "ms": "ms", - "milisecond": "milliseconde", - "miliseconds": "millisecondes", - "s": "s", - "sec": "sec", - "secs": "secs", - "second": "seconde", - "seconds": "secondes", - "min": "min", - "mins": "mins", - "minute": "minute", - "minutes": "minutes", - "hr": "h", - "hrs": "hres", - "hour": "heure", - "hours": "heures", - "day": "jour", - "days": "jours", - "now": "Maintenant" + "days": { + "long": { + "singular": "jour", + "plural": "jours" + }, + "micro": "j", + "short": { + "singular": "jour", + "plural": "jours" + } + }, + "hours": { + "long": { + "singular": "heure", + "plural": "heures" + }, + "micro": "h", + "short": { + "singular": "h", + "plural": "hres" + } + }, + "milliseconds": { + "long": { + "singular": "milliseconde", + "plural": "millisecondes" + }, + "micro": "ms", + "short": { + "singular": "ms", + "plural": "ms" + } }, + "minutes": { + "long": { + "singular": "minute", + "plural": "minutes" + }, + "micro": "m", + "short": { + "singular": "min", + "plural": "mins" + } + }, + "now": "Maintenant", + "seconds": { + "long": { + "singular": "seconde", + "plural": "secondes" + }, + "micro": "s", + "short": { + "singular": "sec", + "plural": "secs" + } + } + }, "wallet": { "action": { "cancel": "Annuler", diff --git a/src/model/__tests__/wallet.test.js b/src/model/__tests__/wallet.test.js index 1eebf8c55ae..796266a9b55 100644 --- a/src/model/__tests__/wallet.test.js +++ b/src/model/__tests__/wallet.test.js @@ -1,38 +1,39 @@ -import { loadAddress, walletInit, __RewireAPI__ as WalletRewireAPI } from '../wallet'; +import { walletInit, __RewireAPI__ as WalletRewireAPI } from '../wallet'; -test('import good seed phrase', async () => { - const goodSeedPhrase = "there night cash clap pottery cereal silly silent hybrid hour visual hurry"; - const expectedAddress = "0x41f99409865FB23b833C1cD40C1c03BDd3E2C575"; +xit('import good seed phrase', async () => { + const goodSeedPhrase = + 'there night cash clap pottery cereal silly silent hybrid hour visual hurry'; + const expectedAddress = '0x41f99409865FB23b833C1cD40C1c03BDd3E2C575'; const { isImported, isNew, walletAddress } = await walletInit(goodSeedPhrase); expect(isImported).toBeTruthy(); expect(isNew).toBeFalsy(); expect(walletAddress).toBe(expectedAddress); }); -test('import bad seed phrase should return null', async () => { - const badSeedPhrase = "merp merp merp"; +xit('import bad seed phrase should return null', async () => { + const badSeedPhrase = 'merp merp merp'; const { isImported, isNew, walletAddress } = await walletInit(badSeedPhrase); expect(isImported).toBeFalsy(); expect(isNew).toBeFalsy(); expect(walletAddress).toBeNull(); }); -test('create a new wallet', async () => { +xit('create a new wallet', async () => { WalletRewireAPI.__Rewire__('loadAddress', () => null); - WalletRewireAPI.__Rewire__('createWallet', () => "hello"); + WalletRewireAPI.__Rewire__('createWallet', () => 'hello'); const { isImported, isNew, walletAddress } = await walletInit(); expect(isImported).toBeFalsy(); expect(isNew).toBeTruthy(); - expect(walletAddress).toBe("hello"); + expect(walletAddress).toBe('hello'); WalletRewireAPI.__ResetDependency__('loadAddress'); WalletRewireAPI.__ResetDependency__('createWallet'); }); -test('load existing wallet', async () => { - WalletRewireAPI.__Rewire__('loadAddress', () => "hello"); +xit('load existing wallet', async () => { + WalletRewireAPI.__Rewire__('loadAddress', () => 'hello'); const { isImported, isNew, walletAddress } = await walletInit(); expect(isImported).toBeFalsy(); expect(isNew).toBeFalsy(); - expect(walletAddress).toBe("hello"); + expect(walletAddress).toBe('hello'); WalletRewireAPI.__ResetDependency__('loadAddress'); }); diff --git a/src/model/firebase.js b/src/model/firebase.js index 53bef4f6493..bc0b9b2214a 100644 --- a/src/model/firebase.js +++ b/src/model/firebase.js @@ -1,8 +1,8 @@ +import messaging from '@react-native-firebase/messaging'; import lang from 'i18n-js'; import { get } from 'lodash'; -import firebase from 'react-native-firebase'; import { Alert } from '../components/alerts'; -import { getLocal, saveLocal } from '../handlers/commonStorage'; +import { getLocal, saveLocal } from '../handlers/localstorage/common'; export const getFCMToken = async () => { const fcmTokenLocal = await getLocal('rainbowFcmToken'); @@ -15,7 +15,7 @@ export const getFCMToken = async () => { export const saveFCMToken = async () => { try { - const fcmToken = await firebase.messaging().getToken(); + const fcmToken = await messaging().getToken(); if (fcmToken) { saveLocal('rainbowFcmToken', { data: fcmToken }); } @@ -24,9 +24,9 @@ export const saveFCMToken = async () => { } }; -export const hasPermission = async () => firebase.messaging().hasPermission(); +export const hasPermission = () => messaging().hasPermission(); -export const requestPermission = async () => firebase.messaging().requestPermission(); +export const requestPermission = () => messaging().requestPermission(); export const checkPushNotificationPermissions = async () => { const arePushNotificationsAuthorized = await hasPermission(); @@ -49,18 +49,7 @@ export const checkPushNotificationPermissions = async () => { } }; -export const registerTokenRefreshListener = () => firebase.messaging().onTokenRefresh(fcmToken => { - saveLocal('rainbowFcmToken', { data: fcmToken }); -}); - -export const registerNotificationListener = () => firebase.notifications().onNotification(notification => { - console.log('onNotification'); -}); - -// TODO this.onPushNotificationOpened -export const registerNotificationOpenedListener = () => firebase.notifications().onNotificationOpened(notificationOpen => { - const { callId, sessionId } = notificationOpen.notification.data; - this.onPushNotificationOpened(callId, sessionId, false); -}); - -export const getInitialNotification = () => firebase.notifications().getInitialNotification(); +export const registerTokenRefreshListener = () => + messaging().onTokenRefresh(fcmToken => { + saveLocal('rainbowFcmToken', { data: fcmToken }); + }); diff --git a/src/model/keychain.js b/src/model/keychain.js index 21ff64439c5..ea7fe59f0a8 100644 --- a/src/model/keychain.js +++ b/src/model/keychain.js @@ -10,7 +10,9 @@ export async function saveString(key, value, accessControlOptions) { await setInternetCredentials(key, key, value, accessControlOptions); console.log(`Keychain: saved string for key: ${key}`); } catch (err) { - console.log(`Keychain: failed to save string for key: ${key} error: ${err}`); + console.log( + `Keychain: failed to save string for key: ${key} error: ${err}` + ); } } @@ -23,7 +25,9 @@ export async function loadString(key, authenticationPrompt) { } console.log(`Keychain: string does not exist for key: ${key}`); } catch (err) { - console.log(`Keychain: failed to load string for key: ${key} error: ${err}`); + console.log( + `Keychain: failed to load string for key: ${key} error: ${err}` + ); } return null; } @@ -40,7 +44,9 @@ export async function loadObject(key) { console.log(`Keychain: parsed object for key: ${key}`); return objectValue; } catch (err) { - console.log(`Keychain: failed to parse object for key: ${key} error: ${err}`); + console.log( + `Keychain: failed to parse object for key: ${key} error: ${err}` + ); } return null; } @@ -50,6 +56,8 @@ export async function remove(key) { await resetInternetCredentials(key); console.log(`Keychain: removed value for key: ${key}`); } catch (err) { - console.log(`Keychain: failed to remove value for key: ${key} error: ${err}`); + console.log( + `Keychain: failed to remove value for key: ${key} error: ${err}` + ); } } diff --git a/src/model/wallet.js b/src/model/wallet.js index dcab4280615..156122fa95e 100644 --- a/src/model/wallet.js +++ b/src/model/wallet.js @@ -1,3 +1,4 @@ +import { captureException } from '@sentry/react-native'; import { ethers } from 'ethers'; import lang from 'i18n-js'; import { get, isEmpty, isNil } from 'lodash'; @@ -55,7 +56,14 @@ export const getChainId = async () => { return get(wallet, 'provider.chainId'); }; -export const createTransaction = async (to, data, value, gasLimit, gasPrice, nonce = null) => ({ +export const createTransaction = async ( + to, + data, + value, + gasLimit, + gasPrice, + nonce = null +) => ({ data, gasLimit, gasPrice, @@ -73,46 +81,84 @@ export const sendTransaction = async ({ transaction }) => { return result.hash; } catch (error) { Alert.alert(lang.t('wallet.transaction.alert.failed_transaction')); + captureException(error); + return null; + } + } catch (error) { + Alert.alert(lang.t('wallet.transaction.alert.authentication')); + captureException(error); + return null; + } +}; + +export const signTransaction = async ({ transaction }) => { + try { + const wallet = await loadWallet(); + if (!wallet) return null; + try { + return await wallet.sign(transaction); + } catch (error) { + Alert.alert(lang.t('wallet.transaction.alert.failed_transaction')); + captureException(error); return null; } } catch (error) { Alert.alert(lang.t('wallet.transaction.alert.authentication')); + captureException(error); return null; } }; -export const signMessage = async (message, authenticationPrompt = lang.t('wallet.authenticate.please')) => { +export const signMessage = async ( + message, + authenticationPrompt = lang.t('wallet.authenticate.please') +) => { try { const wallet = await loadWallet(authenticationPrompt); try { const signingKey = new ethers.utils.SigningKey(wallet.privateKey); - const sigParams = await signingKey.signDigest(ethers.utils.arrayify(message)); + const sigParams = await signingKey.signDigest( + ethers.utils.arrayify(message) + ); return await ethers.utils.joinSignature(sigParams); } catch (error) { + captureException(error); return null; } } catch (error) { Alert.alert(lang.t('wallet.transaction.alert.authentication')); + captureException(error); return null; } }; -export const signPersonalMessage = async (message, authenticationPrompt = lang.t('wallet.authenticate.please')) => { +export const signPersonalMessage = async ( + message, + authenticationPrompt = lang.t('wallet.authenticate.please') +) => { try { const wallet = await loadWallet(authenticationPrompt); try { - return await wallet.signMessage(isHexString(message) ? ethers.utils.arrayify(message) : message); + return await wallet.signMessage( + isHexString(message) ? ethers.utils.arrayify(message) : message + ); } catch (error) { + captureException(error); return null; } } catch (error) { Alert.alert(lang.t('wallet.transaction.alert.authentication')); + captureException(error); return null; } }; -export const loadSeedPhrase = async (authenticationPrompt = lang.t('wallet.authenticate.please_seed_phrase')) => { - const seedPhrase = await keychain.loadString(seedPhraseKey, { authenticationPrompt }); +export const loadSeedPhrase = async ( + authenticationPrompt = lang.t('wallet.authenticate.please_seed_phrase') +) => { + const seedPhrase = await keychain.loadString(seedPhraseKey, { + authenticationPrompt, + }); return seedPhrase; }; @@ -120,16 +166,19 @@ export const loadAddress = async () => { try { return await keychain.loadString(addressKey); } catch (error) { + captureException(error); return null; } }; -const createWallet = async (seed) => { +const createWallet = async seed => { const walletSeed = seed || generateSeedPhrase(); let wallet = null; try { - if (isHexStringIgnorePrefix(walletSeed) - && addHexPrefix(walletSeed).length === 66) { + if ( + isHexStringIgnorePrefix(walletSeed) && + addHexPrefix(walletSeed).length === 66 + ) { wallet = new ethers.Wallet(walletSeed); } else if (isValidMnemonic(walletSeed)) { wallet = ethers.Wallet.fromMnemonic(walletSeed); @@ -144,15 +193,21 @@ const createWallet = async (seed) => { } return null; } catch (error) { + captureException(error); return null; } }; const saveWalletDetails = async (seedPhrase, privateKey, address) => { - const canAuthenticate = await canImplyAuthentication({ authenticationType: AUTHENTICATION_TYPE.DEVICE_PASSCODE_OR_BIOMETRICS }); + const canAuthenticate = await canImplyAuthentication({ + authenticationType: AUTHENTICATION_TYPE.DEVICE_PASSCODE_OR_BIOMETRICS, + }); let accessControlOptions = {}; if (canAuthenticate) { - accessControlOptions = { accessControl: ACCESS_CONTROL.USER_PRESENCE, accessible: ACCESSIBLE.WHEN_UNLOCKED_THIS_DEVICE_ONLY }; + accessControlOptions = { + accessControl: ACCESS_CONTROL.USER_PRESENCE, + accessible: ACCESSIBLE.WHEN_UNLOCKED_THIS_DEVICE_ONLY, + }; } saveSeedPhrase(seedPhrase, accessControlOptions); savePrivateKey(privateKey, accessControlOptions); @@ -167,15 +222,20 @@ const savePrivateKey = async (privateKey, accessControlOptions = {}) => { await keychain.saveString(privateKeyKey, privateKey, accessControlOptions); }; -const loadPrivateKey = async (authenticationPrompt = lang.t('wallet.authenticate.please')) => { +const loadPrivateKey = async ( + authenticationPrompt = lang.t('wallet.authenticate.please') +) => { try { - const privateKey = await keychain.loadString(privateKeyKey, { authenticationPrompt }); + const privateKey = await keychain.loadString(privateKeyKey, { + authenticationPrompt, + }); return privateKey; } catch (error) { + captureException(error); return null; } }; -const saveAddress = async (address) => { +const saveAddress = async address => { await keychain.saveString(addressKey, address); }; diff --git a/src/navigation/ExchangeModalNavigator.js b/src/navigation/ExchangeModalNavigator.js new file mode 100644 index 00000000000..fcb50040405 --- /dev/null +++ b/src/navigation/ExchangeModalNavigator.js @@ -0,0 +1,61 @@ +import { get } from 'lodash'; +import React from 'react'; +import Animated from 'react-native-reanimated'; +import { createMaterialTopTabNavigator } from 'react-navigation-tabs'; +import CurrencySelectModal from '../screens/CurrencySelectModal'; +import ExchangeModal from '../screens/ExchangeModal'; +import { deviceUtils } from '../utils'; + +const ExchangeModalTabPosition = new Animated.Value(0); + +const ExchangeModalNavigator = createMaterialTopTabNavigator( + { + MainExchangeScreen: { + params: { + position: ExchangeModalTabPosition, + }, + screen: ExchangeModal, + }, + // eslint-disable-next-line sort-keys + CurrencySelectScreen: { + params: { + position: ExchangeModalTabPosition, + }, + screen: CurrencySelectModal, + }, + }, + { + headerMode: 'none', + initialLayout: deviceUtils.dimensions, + mode: 'modal', + position: ExchangeModalTabPosition, + springConfig: { + damping: 40, + mass: 1, + overshootClamping: false, + restDisplacementThreshold: 0.01, + restSpeedThreshold: 0.01, + stiffness: 300, + }, + swipeDistanceMinimum: 0, + swipeVelocityImpact: 1, + swipeVelocityScale: 1, + tabBarComponent: null, + transparentCard: true, + } +); + +// I need it for changing navigationOptions dynamically +// for preventing swipe down to close on CurrencySelectScreen +// TODO +// eslint-disable-next-line react/display-name +const EnhancedExchangeModalNavigator = React.memo(props => ( + +)); +EnhancedExchangeModalNavigator.router = ExchangeModalNavigator.router; +EnhancedExchangeModalNavigator.navigationOptions = ({ navigation }) => ({ + ...navigation.state.params, + gestureEnabled: !get(navigation, 'state.params.isGestureBlocked'), +}); + +export default EnhancedExchangeModalNavigator; diff --git a/src/navigation/SpringConfig.js b/src/navigation/SpringConfig.js index 28b8daacef3..013c82518c8 100644 --- a/src/navigation/SpringConfig.js +++ b/src/navigation/SpringConfig.js @@ -1,5 +1,5 @@ // import Animated from 'react-native-reanimated'; -import sortList from '../helpers/sortList'; +import { sortList } from '../helpers/sortList'; import { reduceArrayToObject } from '../utils'; // const { SpringUtils } = Animated; @@ -18,14 +18,16 @@ let config = { ...DefaultConfig }; const getSpringConfig = () => config; -const setSpringConfig = (changesToConfig) => { +const setSpringConfig = changesToConfig => { const newConfig = { ...config, ...changesToConfig, }; const alphabeticalConfigKeys = sortList(Object.keys(newConfig)); - const arrayOfConfigObjects = alphabeticalConfigKeys.map(key => ({ [key]: newConfig[key] })); + const arrayOfConfigObjects = alphabeticalConfigKeys.map(key => ({ + [key]: newConfig[key], + })); config = reduceArrayToObject(arrayOfConfigObjects); }; diff --git a/src/navigation/index.js b/src/navigation/index.js index 0d40aae2802..173a70eda2e 100644 --- a/src/navigation/index.js +++ b/src/navigation/index.js @@ -1,2 +1,3 @@ +export { default as ExchangeModalNavigator } from './ExchangeModalNavigator'; export { default as Navigation } from './Navigation'; export { default as SpringConfig } from './SpringConfig'; diff --git a/src/navigation/transitions/effects.js b/src/navigation/transitions/effects.js new file mode 100644 index 00000000000..1fd61d669c8 --- /dev/null +++ b/src/navigation/transitions/effects.js @@ -0,0 +1,210 @@ +import { StatusBar } from 'react-native'; +import Animated from 'react-native-reanimated'; +import { getStatusBarHeight } from 'react-native-iphone-x-helper'; +import { interpolate } from '../../components/animations'; +import { deviceUtils } from '../../utils'; +import { colors } from '../../styles'; + +const { color, SpringUtils } = Animated; + +const statusBarHeight = getStatusBarHeight(true); + +const expand = {}; +expand.translateY = deviceUtils.dimensions.height; + +export const sheetVerticalOffset = statusBarHeight; + +const exchangeStyleInterpolator = ({ + current: { progress: current }, + layouts: { screen }, +}) => { + const backgroundOpacity = interpolate(current, { + extrapolate: Animated.Extrapolate.CLAMP, + inputRange: [-1, 0, 0.975, 2], + outputRange: [0, 0, 1, 1], + }); + + const translateY = interpolate(current, { + inputRange: [0, 1], + outputRange: [screen.height, 0], + }); + + return { + cardStyle: { + opacity: 1, + shadowColor: colors.black, + shadowOffset: { height: 10, width: 0 }, + shadowOpacity: 0.4, + shadowRadius: 25, + // Translation for the animation of the current card + transform: [{ translateY }], + }, + containerStyle: { + backgroundColor: color(20, 20, 20, backgroundOpacity), + }, + }; +}; + +const expandStyleInterpolator = ({ + current: { progress: current }, + layouts: { screen }, +}) => { + const backgroundOpacity = interpolate(current, { + extrapolate: Animated.Extrapolate.CLAMP, + inputRange: [-1, 0, 0.975, 2], + outputRange: [0, 0, 0.7, 0.7], + }); + + const translateY = interpolate(current, { + inputRange: [0, 1], + outputRange: [screen.height, 0], + }); + + return { + cardStyle: { + opacity: 1, + shadowColor: colors.dark, + shadowOffset: { height: 10, width: 0 }, + shadowOpacity: 0.6, + shadowRadius: 25, + // Translation for the animation of the current card + transform: [{ translateY }], + }, + containerStyle: { + backgroundColor: color(37, 41, 46, backgroundOpacity), + }, + }; +}; + +const sheetStyleInterpolator = ({ + current: { progress: current }, + layouts: { screen }, +}) => { + const backgroundOpacity = interpolate(current, { + extrapolate: Animated.Extrapolate.CLAMP, + inputRange: [-1, 0, 0.975, 2], + outputRange: [0, 0, 0.9, 0.9], + }); + + const cardBackgroundOpacity = interpolate(current, { + extrapolate: Animated.Extrapolate.CLAMP, + inputRange: [-1, 0, 0.99, 1, 2], + outputRange: [0, 0, 0, 1, 1], + }); + + const translateY = interpolate(current, { + inputRange: [0, 1], + outputRange: [screen.height, 0], + }); + + return { + cardStyle: { + backgroundColor: color(20, 20, 20, cardBackgroundOpacity), + shadowColor: colors.black, + shadowOffset: { height: 10, width: 0 }, + shadowOpacity: 0.4, + shadowRadius: 25, + // Translation for the animation of the current card + transform: [{ translateY }], + }, + containerStyle: { + backgroundColor: color(0, 0, 0, backgroundOpacity), + }, + }; +}; + +const backgroundInterpolator = ({ + next: { progress: next } = { next: undefined }, +}) => { + if (next === undefined) { + return { cardStyle: {} }; + } + + return { cardStyle: { opacity: 1 } }; +}; + +const closeSpec = { + animation: 'spring', + config: SpringUtils.makeConfigFromBouncinessAndSpeed({ + ...SpringUtils.makeDefaultConfig(), + bounciness: 0, + mass: 1, + overshootClamping: true, + speed: 25, + }), +}; + +const openSpec = { + animation: 'spring', + config: SpringUtils.makeConfigFromBouncinessAndSpeed({ + ...SpringUtils.makeDefaultConfig(), + bounciness: 4, + mass: 1, + speed: 25, + }), +}; + +const sheetOpenSpec = { + animation: 'spring', + config: SpringUtils.makeConfigFromBouncinessAndSpeed({ + ...SpringUtils.makeDefaultConfig(), + bounciness: 0, + mass: 1, + speed: 22, + }), +}; + +const gestureResponseDistance = { + vertical: deviceUtils.dimensions.height, +}; + +export const onTransitionStart = props => { + if (props.closing) { + StatusBar.setBarStyle('dark-content'); + } else { + StatusBar.setBarStyle('light-content'); + } +}; + +export const exchangePreset = { + cardShadowEnabled: true, + cardStyleInterpolator: exchangeStyleInterpolator, + cardTransparent: true, + gestureDirection: 'vertical', + gestureResponseDistance, + onTransitionStart, + transitionSpec: { close: closeSpec, open: sheetOpenSpec }, +}; + +export const overlayExpandedPreset = { + cardShadowEnabled: true, + cardStyleInterpolator: expandStyleInterpolator, + cardTransparent: true, + gestureDirection: 'vertical', + gestureResponseDistance, + transitionSpec: { close: closeSpec, open: openSpec }, +}; + +export const expandedPreset = { + cardShadowEnabled: true, + cardStyleInterpolator: expandStyleInterpolator, + cardTransparent: true, + gestureDirection: 'vertical', + gestureResponseDistance, + onTransitionStart, + transitionSpec: { close: closeSpec, open: openSpec }, +}; + +export const sheetPreset = { + cardShadowEnabled: true, + cardStyleInterpolator: sheetStyleInterpolator, + cardTransparent: true, + gestureDirection: 'vertical', + gestureResponseDistance, + onTransitionStart, + transitionSpec: { close: closeSpec, open: sheetOpenSpec }, +}; + +export const backgroundPreset = { + cardStyleInterpolator: backgroundInterpolator, +}; diff --git a/src/navigation/transitions/expanded.js b/src/navigation/transitions/expanded.js deleted file mode 100644 index 26e7c16d40f..00000000000 --- a/src/navigation/transitions/expanded.js +++ /dev/null @@ -1,114 +0,0 @@ -import { get } from 'lodash'; -import { Animated, Easing } from 'react-native'; -import { updateTransitionProps } from '../../redux/navigation'; -import store from '../../redux/store'; -import { colors } from '../../styles'; -import { deviceUtils, statusBar } from '../../utils'; - -export const transitionName = 'expanded'; - -export default function expanded(navigation, transitionProps, prevTransitionProps) { - const nextEffect = get(transitionProps, 'scene.descriptor.options.effect'); - const prevEffect = get(prevTransitionProps, 'scene.descriptor.options.effect'); - const nextIndex = get(transitionProps, 'index'); - const prevIndex = get(prevTransitionProps, 'index', nextIndex - 1); - - if (nextEffect === transitionName) { - statusBar.setBarStyle('light-content', true); - } - - if (prevEffect === transitionName) { - statusBar.setBarStyle('dark-content', true); - } - - return { - containerStyle: { - backgroundColor: colors.alpha(colors.blueGreyDarker, 0.72), - opacity: 1, - }, - screenInterpolator: (sceneProps = {}) => { - const { - layout, - position, - scene, - } = sceneProps; - - store.dispatch(updateTransitionProps({ - effect: transitionName, - nextIndex, - position, - prevIndex, - })); - - const opacityEnd = 1; - const translateYStart = deviceUtils.dimensions.height; - - if (nextEffect === transitionName && scene.index === prevIndex && nextIndex > prevIndex) { - const opacity = position.interpolate({ - inputRange: [prevIndex, nextIndex], - outputRange: [1, opacityEnd], - }); - - return { - opacity, - }; - } - - if (nextEffect === transitionName && scene.index === nextIndex && nextIndex > prevIndex) { - const translateY = position.interpolate({ - inputRange: [prevIndex, nextIndex], - outputRange: [translateYStart, 0], - }); - - return { - transform: [{ - translateY, - }], - }; - } - - if (prevEffect === transitionName && scene.index === nextIndex && nextIndex < prevIndex) { - const opacity = position.interpolate({ - inputRange: [nextIndex, prevIndex], - outputRange: [1, opacityEnd], - }); - - return { - opacity, - }; - } - - if (prevEffect === transitionName && scene.index === prevIndex && nextIndex < prevIndex) { - const translateY = position.interpolate({ - inputRange: [nextIndex, prevIndex], - outputRange: [translateYStart, 0], - }); - - return { - transform: [{ - translateY, - }], - }; - } - - const width = layout.initWidth; - const translateX = position.interpolate({ - inputRange: [scene.index - 1, scene.index], - outputRange: [width, 0], - }); - - return { - overflow: 'hidden', - transform: [{ - translateX, - }], - }; - }, - transitionSpec: { - duration: 315, - easing: Easing.bezier(0.19, 1, 0.22, 1), - timing: Animated.timing, - useNativeDriver: true, - }, - }; -} diff --git a/src/navigation/transitions/index.js b/src/navigation/transitions/index.js deleted file mode 100644 index 78b9e062cef..00000000000 --- a/src/navigation/transitions/index.js +++ /dev/null @@ -1,34 +0,0 @@ -import { get, each } from 'lodash'; -import expandedTransition from './expanded'; -import sheetTransition, { sheetVerticalOffset } from './sheet'; - -export function buildTransitions(navigation, transitions) { - return (transitionProps, prevTransitionProps) => { - const nextEffect = get(transitionProps, 'scene.descriptor.options.effect'); - const prevEffect = get(prevTransitionProps, 'scene.descriptor.options.effect'); - - let currentTransition = null; - - each(transitions, (transition, key) => { - if (nextEffect === key || prevEffect === key) { - currentTransition = transition; - } - }); - - if (typeof currentTransition === 'function') { - return currentTransition(navigation, transitionProps, prevTransitionProps); - } - - return {}; - }; -} - -export const expanded = expandedTransition; -export const sheet = sheetTransition; - -export default { - buildTransitions, - expanded, - sheet, - sheetVerticalOffset, -}; diff --git a/src/navigation/transitions/sheet.js b/src/navigation/transitions/sheet.js deleted file mode 100644 index 6aebefb54cd..00000000000 --- a/src/navigation/transitions/sheet.js +++ /dev/null @@ -1,241 +0,0 @@ -import { get } from 'lodash'; -import { Animated, Easing } from 'react-native'; -import { getStatusBarHeight, isIphoneX } from 'react-native-iphone-x-helper'; -import { updateTransitionProps } from '../../redux/navigation'; -import store from '../../redux/store'; -import { colors } from '../../styles'; -import { deviceUtils, statusBar } from '../../utils'; - -const distanceFromTop = 14; -const statusBarHeight = getStatusBarHeight(true); - -export const sheetVerticalOffset = distanceFromTop + statusBarHeight; -export const transitionName = 'sheet'; - -export default function sheet(navigation, transitionProps, prevTransitionProps) { - const nextEffect = get(transitionProps, 'scene.descriptor.options.effect'); - const prevEffect = get(prevTransitionProps, 'scene.descriptor.options.effect'); - const nextIndex = get(transitionProps, 'index'); - const prevIndex = get(prevTransitionProps, 'index', nextIndex - 1); - - if (nextEffect === transitionName) { - statusBar.setBarStyle('light-content', true); - } - - if (prevEffect === transitionName) { - statusBar.setBarStyle('dark-content', true); - } - - return { - containerStyle: { - backgroundColor: colors.black, - opacity: 1, - }, - screenInterpolator: (sceneProps = {}) => { - const { - layout, - position, - scene, - } = sceneProps; - - store.dispatch(updateTransitionProps({ - effect: transitionName, - nextIndex, - position, - prevIndex, - })); - - const scaleEnd = 1 - ((statusBarHeight + (isIphoneX() ? distanceFromTop : 0)) / deviceUtils.dimensions.height); - const heightEnd = statusBarHeight + distanceFromTop; - const borderRadiusEnd = 12; - const borderRadiusScaledEnd = borderRadiusEnd / scaleEnd; - const opacityEnd = 0.5; - - if (nextEffect === transitionName && scene.index === prevIndex && nextIndex > prevIndex) { - const translateY = position.interpolate({ - inputRange: [prevIndex, nextIndex], - outputRange: [0, distanceFromTop], - }); - - const opacity = position.interpolate({ - inputRange: [prevIndex, nextIndex], - outputRange: [1, opacityEnd], - }); - - const scale = position.interpolate({ - inputRange: [prevIndex, nextIndex], - outputRange: [1, scaleEnd], - }); - - const borderRadius = position.interpolate({ - inputRange: [prevIndex, nextIndex], - outputRange: [isIphoneX() ? 38.5 : 0, borderRadiusScaledEnd], - }); - - return { - borderTopLeftRadius: borderRadius, - borderTopRightRadius: borderRadius, - opacity, - overflow: 'hidden', - transform: [{ - translateY, - }, { - scale, - }], - zIndex: 1, - }; - } - - if (nextEffect === transitionName && scene.index === nextIndex && nextIndex > prevIndex) { - const height = layout.initHeight; - const translateY = position.interpolate({ - inputRange: [prevIndex, nextIndex], - outputRange: [height, heightEnd], - }); - - return { - borderTopLeftRadius: borderRadiusEnd, - borderTopRightRadius: borderRadiusEnd, - height: height - heightEnd, - overflow: 'hidden', - transform: [{ - translateY, - }], - zIndex: 2, - }; - } - - if (prevEffect === transitionName && scene.index === nextIndex && nextIndex < prevIndex) { - const opacity = position.interpolate({ - inputRange: [nextIndex, prevIndex], - outputRange: [1, opacityEnd], - }); - - const scale = position.interpolate({ - inputRange: [nextIndex, prevIndex], - outputRange: [1, scaleEnd], - }); - - const borderRadius = position.interpolate({ - inputRange: [nextIndex, prevIndex], - outputRange: [0, borderRadiusEnd], - }); - - return { - borderTopLeftRadius: borderRadius, - borderTopRightRadius: borderRadius, - opacity, - overflow: 'hidden', - transform: [{ - scale, - }], - zIndex: 1, - }; - } - - if (prevEffect === transitionName && scene.index === prevIndex && nextIndex < prevIndex) { - const height = layout.initHeight; - const translateY = position.interpolate({ - inputRange: [nextIndex, prevIndex], - outputRange: [height, heightEnd], - }); - - return { - borderTopLeftRadius: borderRadiusEnd, - borderTopRightRadius: borderRadiusEnd, - height: height - heightEnd, - overflow: 'hidden', - transform: [{ - translateY, - }], - zIndex: 2, - }; - } - - if ((prevEffect === transitionName && scene.index === prevIndex) || (nextEffect === transitionName && scene.index === nextIndex)) { - const height = layout.initHeight; - const width = layout.initWidth; - const translateX = position.interpolate({ - inputRange: [scene.index - 1, scene.index], - outputRange: [width, 0], - }); - - return { - borderTopLeftRadius: borderRadiusEnd, - borderTopRightRadius: borderRadiusEnd, - height: height - heightEnd, - overflow: 'hidden', - transform: [{ - translateX, - }, { - translateY: heightEnd, - }], - zIndex: 2, - }; - } - - if (nextEffect === transitionName && prevIndex > nextIndex && scene.index === nextIndex - 1) { - const width = layout.initWidth; - const translateX = position.interpolate({ - inputRange: [nextIndex - 1, nextIndex], - outputRange: [width, 0], - }); - - return { - borderTopLeftRadius: borderRadiusEnd, - borderTopRightRadius: borderRadiusEnd, - opacity: opacityEnd, - overflow: 'hidden', - transform: [{ - translateX, - }, { - translateY: distanceFromTop, - }, { - scale: scaleEnd, - }], - }; - } - - if (prevEffect === transitionName && prevIndex < nextIndex && scene.index === prevIndex - 1) { - const width = layout.initWidth; - const translateX = position.interpolate({ - inputRange: [prevIndex - 1, prevIndex], - outputRange: [width, 0], - }); - - return { - borderTopLeftRadius: borderRadiusEnd, - borderTopRightRadius: borderRadiusEnd, - opacity: opacityEnd, - overflow: 'hidden', - transform: [{ - translateX, - }, { - translateY: distanceFromTop, - }, { - scale: scaleEnd, - }], - }; - } - - const width = layout.initWidth; - const translateX = position.interpolate({ - inputRange: [scene.index - 1, scene.index], - outputRange: [width, 0], - }); - - return { - overflow: 'hidden', - transform: [{ - translateX, - }], - }; - }, - transitionSpec: { - duration: 375, - easing: Easing.bezier(0.19, 1, 0.22, 1), - timing: Animated.timing, - useNativeDriver: true, - }, - }; -} diff --git a/src/parsers/accounts.js b/src/parsers/accounts.js index 29ec6217f02..5396cdd3cd0 100644 --- a/src/parsers/accounts.js +++ b/src/parsers/accounts.js @@ -1,37 +1,45 @@ -import { get } from 'lodash'; +import { get, toUpper } from 'lodash'; import { convertRawAmountToBalance } from '../helpers/utilities'; +import { dedupeUniqueTokens } from './uniqueTokens'; /** * @desc parse account assets * @param {Object} [data] * @return {Array} */ -export const parseAccountAssets = data => { - try { - let assets = [...data]; - assets = assets.map(assetData => { - const name = get(assetData, 'asset.name') || 'Unknown Token'; - const symbol = get(assetData, 'asset.symbol') || 'β€”β€”β€”'; - const asset = { - address: get(assetData, 'asset.asset_code', null), - decimals: get(assetData, 'asset.decimals'), - name, - price: get(assetData, 'asset.price'), - symbol: symbol.toUpperCase(), - uniqueId: get(assetData, 'asset.asset_code') || name, - }; - return { - ...asset, - balance: convertRawAmountToBalance(assetData.quantity, asset), - }; - }); +export const parseAccountAssets = (data, uniqueTokens, tokenOverrides) => { + const dedupedAssets = dedupeUniqueTokens(data, uniqueTokens); + let assets = dedupedAssets.map(assetData => { + const asset = parseAsset(assetData.asset, tokenOverrides); + return { + ...asset, + balance: convertRawAmountToBalance(assetData.quantity, asset), + }; + }); - assets = assets.filter( - asset => !!Number(get(asset, 'balance.amount')), - ); + return assets.filter(asset => !!Number(get(asset, 'balance.amount'))); +}; - return assets; - } catch (error) { - throw error; +/** + * @desc parse asset + * @param {Object} assetData + * @return {Object} + */ +export const parseAsset = (assetData, tokenOverrides) => { + const address = get(assetData, 'asset_code', null); + const name = get(assetData, 'name') || 'Unknown Token'; + let symbol = get(assetData, 'symbol') || 'β€”β€”β€”'; + if (symbol && symbol.includes('*')) { + symbol = symbol.replace(/[*]/g, ''); } + const asset = { + address, + decimals: get(assetData, 'decimals'), + name, + price: get(assetData, 'price'), + symbol: toUpper(symbol), + uniqueId: address || name, + ...tokenOverrides[address], + }; + return asset; }; diff --git a/src/parsers/gas.js b/src/parsers/gas.js index 357366deb9d..8249b186a4e 100644 --- a/src/parsers/gas.js +++ b/src/parsers/gas.js @@ -1,121 +1,110 @@ -import timeUnits from '../references/time-units.json'; -import ethUnits from '../references/ethereum-units.json'; -import { getTimeString } from '../helpers/time'; +import { get, map, zipObject } from 'lodash'; +import { getMinimalTimeUnitStringForMs } from '../helpers/time'; import { convertRawAmountToBalance, convertRawAmountToNativeDisplay, divide, multiply, } from '../helpers/utilities'; +import timeUnits from '../references/time-units.json'; +import ethUnits from '../references/ethereum-units.json'; +import { gasUtils } from '../utils'; /** * @desc parse ether gas prices * @param {Object} data - * @param {Object} prices - * @param {Number} gasLimit + * @param {Boolean} short - use short format or not */ -export const parseGasPrices = (data, priceUnit, gasLimit, nativeCurrency, short) => { - const gasPrices = { - average: null, - fast: null, - slow: null, - }; - if (!data) { - gasPrices.fast = defaultGasPriceFormat('fast', '30000', '5000000000', '5 Gwei', short); - gasPrices.average = defaultGasPriceFormat('average', '360000', '2000000000', '2 Gwei', short); - gasPrices.slow = defaultGasPriceFormat('slow', '1800000', '1000000000', '1 Gwei', short); - } else { - const fastTimeAmount = multiply(data.fastWait, timeUnits.ms.minute); - const fastValueAmount = divide(data.fast, 10); - gasPrices.fast = defaultGasPriceFormat( - 'fast', - fastTimeAmount, - multiply(fastValueAmount, ethUnits.gwei), - `${fastValueAmount} Gwei`, - short, - ); +export const getFallbackGasPrices = (short = true) => ({ + [gasUtils.FAST]: defaultGasPriceFormat(gasUtils.FAST, '0.5', '200', short), + [gasUtils.NORMAL]: defaultGasPriceFormat( + gasUtils.NORMAL, + '2.5', + '100', + short + ), + [gasUtils.SLOW]: defaultGasPriceFormat(gasUtils.SLOW, '2.5', '100', short), +}); - const avgTimeAmount = multiply(data.avgWait, timeUnits.ms.minute); - const avgValueAmount = divide(data.average, 10); - gasPrices.average = defaultGasPriceFormat( - 'average', - avgTimeAmount, - multiply(avgValueAmount, ethUnits.gwei), - `${avgValueAmount} Gwei`, - short, - ); +/** + * @desc parse ether gas prices + * @param {Object} data + * @param {Boolean} short - use short format or not + */ +export const parseGasPrices = (data, short = true) => + !data + ? getFallbackGasPrices() + : { + [gasUtils.FAST]: defaultGasPriceFormat( + gasUtils.FAST, + data.fastestWait, + data.fastest, + short + ), + [gasUtils.NORMAL]: defaultGasPriceFormat( + gasUtils.NORMAL, + data.fastWait, + data.fast, + short + ), + [gasUtils.SLOW]: defaultGasPriceFormat( + gasUtils.SLOW, + data.avgWait, + data.average, + short + ), + }; - const slowTimeAmount = multiply(data.safeLowWait, timeUnits.ms.minute); - const slowValueAmount = divide(data.safeLow, 10); - gasPrices.slow = defaultGasPriceFormat( - 'slow', - slowTimeAmount, - multiply(slowValueAmount, ethUnits.gwei), - `${slowValueAmount} Gwei`, - short, - ); - } - return parseGasPricesTxFee(gasPrices, priceUnit, gasLimit, nativeCurrency); +const defaultGasPriceFormat = (option, timeWait, value) => { + const timeAmount = multiply(timeWait, timeUnits.ms.minute); + const gweiAmount = divide(value, 10); + const weiAmount = multiply(gweiAmount, ethUnits.gwei); + return { + estimatedTime: { + amount: timeAmount, + display: getMinimalTimeUnitStringForMs(timeAmount), + }, + option, + value: { + amount: weiAmount, + display: `${gweiAmount} Gwei`, + }, + }; }; -const defaultGasPriceFormat = (option, timeAmount, valueAmount, valueDisplay, short) => ({ - estimatedTime: { - amount: timeAmount, - display: getTimeString(timeAmount, 'ms', short), - }, - option, - value: { - amount: valueAmount, - display: valueDisplay, - }, -}); - /** * @desc parse ether gas prices with updated gas limit * @param {Object} data * @param {Object} prices * @param {Number} gasLimit */ -export const parseGasPricesTxFee = (gasPrices, priceUnit, gasLimit, nativeCurrency) => { - gasPrices.fast.txFee = getTxFee(gasPrices.fast.value.amount, gasLimit); - gasPrices.average.txFee = getTxFee(gasPrices.average.value.amount, gasLimit); - gasPrices.slow.txFee = getTxFee(gasPrices.slow.value.amount, gasLimit); - return convertGasPricesToNative(priceUnit, gasPrices, nativeCurrency); +export const parseTxFees = (gasPrices, priceUnit, gasLimit, nativeCurrency) => { + const txFees = map(gasUtils.GasSpeedOrder, speed => { + const gasPrice = get(gasPrices, `${speed}.value.amount`); + return { + txFee: getTxFee(gasPrice, gasLimit, priceUnit, nativeCurrency), + }; + }); + return zipObject(gasUtils.GasSpeedOrder, txFees); }; -const getTxFee = (gasPrice, gasLimit) => { +const getTxFee = (gasPrice, gasLimit, priceUnit, nativeCurrency) => { const amount = multiply(gasPrice, gasLimit); return { - native: null, - value: { - amount, - display: convertRawAmountToBalance( + native: { + value: convertRawAmountToNativeDisplay( amount, - { - decimals: 18, - symbol: 'ETH', - }, + 18, + priceUnit, + nativeCurrency ), }, - }; -}; - -const convertGasPricesToNative = (priceUnit, gasPrices, nativeCurrency) => { - const nativeGases = { ...gasPrices }; - nativeGases.fast.txFee.native = getNativeGasPrice(priceUnit, gasPrices.fast.txFee.value.amount, nativeCurrency); - nativeGases.average.txFee.native = getNativeGasPrice(priceUnit, gasPrices.average.txFee.value.amount, nativeCurrency); - nativeGases.slow.txFee.native = getNativeGasPrice(priceUnit, gasPrices.slow.txFee.value.amount, nativeCurrency); - return nativeGases; -}; - -const getNativeGasPrice = (priceUnit, feeAmount, nativeCurrency) => { - const nativeDisplay = convertRawAmountToNativeDisplay( - feeAmount, - 18, - priceUnit, - nativeCurrency, - ); - return { - value: nativeDisplay, + value: { + amount, + display: convertRawAmountToBalance(amount, { + decimals: 18, + symbol: 'ETH', + }), + }, }; }; diff --git a/src/parsers/newTransaction.js b/src/parsers/newTransaction.js index 195c17b57b9..3f82473e31d 100644 --- a/src/parsers/newTransaction.js +++ b/src/parsers/newTransaction.js @@ -4,6 +4,7 @@ import { convertAmountToBalanceDisplay, } from '../helpers/utilities'; import { getTransactionCount } from '../handlers/web3'; +import TransactionStatusTypes from '../helpers/transactionStatusTypes'; /** * @desc parse transactions from native prices @@ -13,7 +14,7 @@ import { getTransactionCount } from '../handlers/web3'; */ export const parseNewTransaction = async ( txDetails = null, - nativeCurrency = '', + nativeCurrency = '' ) => { let balance = null; const { amount } = txDetails; @@ -26,26 +27,20 @@ export const parseNewTransaction = async ( const native = convertAmountAndPriceToNativeDisplay( amount, get(txDetails, 'asset.price.value', 0), - nativeCurrency, + nativeCurrency ); - let tx = pick(txDetails, [ - 'asset', - 'dappName', - 'from', - 'hash', - 'nonce', - 'to', - ]); - const nonce = tx.nonce - || (tx.from ? await getTransactionCount(tx.from) : ''); + let tx = pick(txDetails, ['dappName', 'from', 'hash', 'nonce', 'to']); + const nonce = tx.nonce || (tx.from ? await getTransactionCount(tx.from) : ''); tx = { ...tx, balance, - error: false, - mined_at: null, // eslint-disable-line camelcase + minedAt: null, + name: get(txDetails, 'asset.name'), native, nonce, pending: !!txDetails.hash, + status: TransactionStatusTypes.sending, + symbol: get(txDetails, 'asset.symbol'), }; return tx; diff --git a/src/parsers/requests.js b/src/parsers/requests.js new file mode 100644 index 00000000000..3382bf46df4 --- /dev/null +++ b/src/parsers/requests.js @@ -0,0 +1,152 @@ +import { convertHexToUtf8 } from '@walletconnect/utils'; +import BigNumber from 'bignumber.js'; +import { get } from 'lodash'; +import { isHexString } from '../handlers/web3'; +import { + convertAmountAndPriceToNativeDisplay, + convertHexToString, + convertRawAmountToDecimalFormat, + fromWei, +} from '../helpers/utilities'; +import smartContractMethods from '../references/smartcontract-methods.json'; +import { ethereumUtils } from '../utils'; +import { + PERSONAL_SIGN, + SEND_TRANSACTION, + SIGN, + SIGN_TRANSACTION, + SIGN_TYPED, + SIGN_TYPED_V3, +} from '../utils/signingMethods'; + +export const getRequestDisplayDetails = (payload, assets, nativeCurrency) => { + let timestampInMs = Date.now(); + if (payload.id) { + timestampInMs = getTimestampFromPayload(payload); + } + if ( + payload.method === SEND_TRANSACTION || + payload.method === SIGN_TRANSACTION + ) { + const transaction = get(payload, 'params[0]', null); + return getTransactionDisplayDetails( + transaction, + assets, + nativeCurrency, + timestampInMs + ); + } + if (payload.method === SIGN) { + const message = get(payload, 'params[1]'); + const result = getMessageDisplayDetails(message, timestampInMs); + return result; + } + if (payload.method === PERSONAL_SIGN) { + let message = get(payload, 'params[0]'); + try { + if (isHexString(message)) { + message = convertHexToUtf8(message); + } + } catch (error) { + // TODO error handling + } + return getMessageDisplayDetails(message, timestampInMs); + } + if (payload.method === SIGN_TYPED || payload.method === SIGN_TYPED_V3) { + const request = get(payload, 'params[1]', null); + const jsonRequest = JSON.stringify(request.message); + return getMessageDisplayDetails(jsonRequest, timestampInMs); + } + return {}; +}; + +const getMessageDisplayDetails = (message, timestampInMs) => ({ + request: message, + timestampInMs, +}); + +const getTransactionDisplayDetails = ( + transaction, + assets, + nativeCurrency, + timestampInMs +) => { + const tokenTransferHash = smartContractMethods.token_transfer.hash; + if (transaction.data === '0x') { + const value = fromWei(convertHexToString(transaction.value)); + const asset = ethereumUtils.getAsset(assets); + const priceUnit = get(asset, 'price.value', 0); + const { amount, display } = convertAmountAndPriceToNativeDisplay( + value, + priceUnit, + nativeCurrency + ); + return { + request: { + asset, + from: transaction.from, + gasLimit: BigNumber(convertHexToString(transaction.gasLimit)), + gasPrice: BigNumber(convertHexToString(transaction.gasPrice)), + nativeAmount: amount, + nativeAmountDisplay: display, + nonce: Number(convertHexToString(transaction.nonce)), + to: transaction.to, + value, + }, + timestampInMs, + }; + } + if (transaction.data.startsWith(tokenTransferHash)) { + const contractAddress = transaction.to; + const asset = ethereumUtils.getAsset(assets, contractAddress); + const dataPayload = transaction.data.replace(tokenTransferHash, ''); + const toAddress = `0x${dataPayload.slice(0, 64).replace(/^0+/, '')}`; + const amount = `0x${dataPayload.slice(64, 128).replace(/^0+/, '')}`; + const value = convertRawAmountToDecimalFormat( + convertHexToString(amount), + asset.decimals + ); + const priceUnit = get(asset, 'price.value', 0); + const native = convertAmountAndPriceToNativeDisplay( + value, + priceUnit, + nativeCurrency + ); + return { + request: { + asset, + from: transaction.from, + gasLimit: BigNumber(convertHexToString(transaction.gasLimit)), + gasPrice: BigNumber(convertHexToString(transaction.gasPrice)), + nativeAmount: native.amount, + nativeAmountDisplay: native.display, + nonce: Number(convertHexToString(transaction.nonce)), + to: toAddress, + value, + }, + timestampInMs, + }; + } + if (transaction.data) { + const value = transaction.value + ? fromWei(convertHexToString(transaction.value)) + : 0; + return { + request: { + data: transaction.data, + from: transaction.from, + gasLimit: BigNumber(convertHexToString(transaction.gasLimit)), + gasPrice: BigNumber(convertHexToString(transaction.gasPrice)), + nonce: Number(convertHexToString(transaction.nonce)), + to: transaction.to, + value, + }, + timestampInMs, + }; + } + + return null; +}; + +const getTimestampFromPayload = payload => + parseInt(payload.id.toString().slice(0, -3), 10); diff --git a/src/parsers/transactions.js b/src/parsers/transactions.js index 7f8dbe61105..17a74a0de8b 100644 --- a/src/parsers/transactions.js +++ b/src/parsers/transactions.js @@ -1,41 +1,168 @@ import { + compact, + concat, + filter, + find, + findIndex, flatten, get, isEmpty, + partition, pick, reverse, + slice, + startsWith, + toLower, + toUpper, + uniqBy, } from 'lodash'; +import TransactionStatusTypes from '../helpers/transactionStatusTypes'; import { convertRawAmountToBalance, convertRawAmountToNativeDisplay, } from '../helpers/utilities'; +import { isLowerCaseMatch } from '../utils'; -export const parseTransactions = (data, nativeCurrency) => { - const allTxns = data.map(txn => parseTransaction(txn, nativeCurrency)); - return flatten(allTxns); +const DIRECTION_OUT = 'out'; + +const dataFromLastTxHash = (transactionData, transactions) => { + const lastSuccessfulTxn = find(transactions, txn => txn.hash && !txn.pending); + const lastTxHash = lastSuccessfulTxn ? lastSuccessfulTxn.hash : ''; + if (lastTxHash) { + const lastTxnHashIndex = findIndex(transactionData, txn => + lastTxHash.startsWith(txn.hash) + ); + if (lastTxnHashIndex > -1) { + return slice(transactionData, 0, lastTxnHashIndex); + } + } + return transactionData; +}; + +export default ( + transactionData, + accountAddress, + nativeCurrency, + existingTransactions, + tokenOverrides, + appended = false +) => { + const data = appended + ? dataFromLastTxHash(transactionData, existingTransactions) + : transactionData; + const parsedNewTransactions = flatten( + data.map(txn => + parseTransaction(txn, accountAddress, nativeCurrency, tokenOverrides) + ) + ); + const [pendingTransactions, remainingTransactions] = partition( + existingTransactions, + txn => txn.pending + ); + const [approvalTransactions, parsedTransactions] = partition( + parsedNewTransactions, + txn => txn.type === 'authorize' + ); + const updatedPendingTransactions = dedupePendingTransactions( + pendingTransactions, + parsedTransactions + ); + const updatedResults = concat( + updatedPendingTransactions, + parsedTransactions, + remainingTransactions + ); + const dedupedResults = uniqBy(updatedResults, txn => txn.hash); + return { approvalTransactions, dedupedResults }; +}; + +const transformUniswapRefund = internalTransactions => { + const [txnsOut, txnsIn] = partition( + internalTransactions, + txn => txn.direction === DIRECTION_OUT + ); + const isSuccessfulSwap = + txnsOut.length === 1 && (txnsIn.length === 1 || txnsIn.length === 2); + if (!isSuccessfulSwap) return internalTransactions; + + const txnOut = txnsOut[0]; + const txnIn = find( + txnsIn, + txn => txn.asset.asset_code !== txnOut.asset.asset_code + ); + const refund = find( + txnsIn, + txn => txn.asset.asset_code === txnOut.asset.asset_code + ); + let updatedOut = txnOut; + if (refund && txnOut) { + updatedOut = { + ...txnOut, + value: txnOut.value - refund.value, + }; + } + return compact([updatedOut, txnIn]); }; -const parseTransaction = (txn, nativeCurrency) => { +const parseTransaction = ( + txn, + accountAddress, + nativeCurrency, + tokenOverrides +) => { const transaction = pick(txn, [ 'hash', - 'mined_at', 'nonce', 'protocol', 'status', 'type', ]); + transaction.from = txn.address_from; + transaction.minedAt = txn.mined_at; transaction.pending = false; - transaction.from = txn.address_from; // eslint-disable-line camelcase - transaction.to = txn.address_to; // eslint-disable-line camelcase + transaction.to = txn.address_to; const changes = get(txn, 'changes', []); let internalTransactions = changes; - if (changes.length === 2 && get(changes, '[0].asset.asset_code') === get(changes, '[1].asset.asset_code')) { + if ( + isEmpty(changes) && + txn.status === 'failed' && + txn.type === 'execution' && + txn.direction === 'out' + ) { + const assetInternalTransaction = { + address_from: transaction.from, + address_to: transaction.to, + asset: { + address: 'eth', + decimals: 18, + name: 'Ethereum', + symbol: 'ETH', + }, + value: 0, + }; + internalTransactions = [assetInternalTransaction]; + } + if (isEmpty(changes) && txn.type === 'authorize') { + const approveInternalTransaction = { + address_from: transaction.from, + address_to: transaction.to, + asset: get(txn, 'meta.asset'), + }; + internalTransactions = [approveInternalTransaction]; + } + // logic below: prevent sending yourself money to be seen as a trade + if ( + changes.length === 2 && + get(changes, '[0].asset.asset_code') === + get(changes, '[1].asset.asset_code') + ) { internalTransactions = [changes[0]]; } + // logic below: prevent sending a WalletConnect 0 amount to be seen as a Cancel if (isEmpty(internalTransactions) && transaction.type === 'cancel') { const ethInternalTransaction = { - address_from: transaction.from, // eslint-disable-line camelcase - address_to: transaction.to, // eslint-disable-line camelcase + address_from: transaction.from, + address_to: transaction.to, asset: { address: 'eth', decimals: 18, @@ -46,29 +173,83 @@ const parseTransaction = (txn, nativeCurrency) => { }; internalTransactions = [ethInternalTransaction]; } + if (transaction.type === 'trade' && transaction.protocol === 'uniswap') { + internalTransactions = transformUniswapRefund(internalTransactions); + } internalTransactions = internalTransactions.map((internalTxn, index) => { - const symbol = get(internalTxn, 'asset.symbol') || ''; + const address = toLower(get(internalTxn, 'asset.asset_code')); const updatedAsset = { - ...internalTxn.asset, - symbol: symbol.toUpperCase(), + address, + decimals: get(internalTxn, 'asset.decimals'), + name: get(internalTxn, 'asset.name'), + symbol: toUpper(get(internalTxn, 'asset.symbol') || ''), + ...tokenOverrides[address], }; const priceUnit = internalTxn.price || 0; + const valueUnit = internalTxn.value || 0; const nativeDisplay = convertRawAmountToNativeDisplay( - internalTxn.value, - internalTxn.asset.decimals, + valueUnit, + updatedAsset.decimals, priceUnit, - nativeCurrency, + nativeCurrency + ); + + const status = getTransactionLabel( + accountAddress, + internalTxn.address_from, + transaction.pending, + transaction.status, + internalTxn.address_to ); return { ...transaction, - asset: updatedAsset, - balance: convertRawAmountToBalance(internalTxn.value, updatedAsset), + balance: convertRawAmountToBalance(valueUnit, updatedAsset), from: internalTxn.address_from, hash: `${transaction.hash}-${index}`, + name: updatedAsset.name, native: nativeDisplay, + status, + symbol: updatedAsset.symbol, to: internalTxn.address_to, }; }); return reverse(internalTransactions); }; + +const dedupePendingTransactions = (pendingTransactions, parsedTransactions) => { + let updatedPendingTransactions = pendingTransactions; + if (pendingTransactions.length) { + updatedPendingTransactions = filter( + updatedPendingTransactions, + pendingTxn => { + const matchingElement = find( + parsedTransactions, + txn => + txn.hash && + (startsWith(toLower(txn.hash), toLower(pendingTxn.hash)) || + (txn.nonce && txn.nonce >= pendingTxn.nonce)) + ); + return !matchingElement; + } + ); + } + return updatedPendingTransactions; +}; + +const getTransactionLabel = (accountAddress, from, pending, status, to) => { + const isFromAccount = isLowerCaseMatch(from, accountAddress); + const isToAccount = isLowerCaseMatch(to, accountAddress); + + if (pending && isFromAccount) return TransactionStatusTypes.sending; + if (pending && isToAccount) return TransactionStatusTypes.receiving; + + if (status === 'failed') return TransactionStatusTypes.failed; + + if (isFromAccount && isToAccount) return TransactionStatusTypes.self; + + if (isFromAccount) return TransactionStatusTypes.sent; + if (isToAccount) return TransactionStatusTypes.received; + + return TransactionStatusTypes.unknown; +}; diff --git a/src/parsers/uniqueTokens.js b/src/parsers/uniqueTokens.js index 992f6afa1b2..de4fd42de28 100644 --- a/src/parsers/uniqueTokens.js +++ b/src/parsers/uniqueTokens.js @@ -1,67 +1,77 @@ -import { - filter, - get, - map, - pick, - uniq, -} from 'lodash'; +import { filter, find, get, isNil, map, pick, uniq } from 'lodash'; /** * @desc parse unique tokens from opensea * @param {Object} * @return {Array} */ -/* eslint-disable camelcase */ export const parseAccountUniqueTokens = data => { - const erc721s = get(data, 'data.assets', []); - return erc721s.map(({ - asset_contract, - background_color, - token_id, - ...asset - }) => ({ - ...pick(asset, [ - 'animation_url', - 'current_price', - 'description', - 'external_link', - 'image_original_url', - 'image_preview_url', - 'image_thumbnail_url', - 'image_url', - 'name', - 'permalink', - 'traits', - ]), - asset_contract: pick(asset_contract, [ - 'address', - 'description', - 'external_link', - 'featured_image_url', - 'hidden', - 'image_url', - 'name', - 'nft_version', - 'schema_name', - 'short_description', - 'symbol', - 'total_supply', - 'wiki_link', - ]), - background: background_color ? `#${background_color}` : null, - familyImage: asset_contract.image_url, - id: token_id, - isNft: true, - isSendable: (asset_contract.nft_version === '1.0' - || asset_contract.nft_version === '3.0'), - lastPrice: ( - asset.last_sale - ? Number(asset.last_sale.total_price) - : null - ), - uniqueId: `${get(asset_contract, 'address')}_${token_id}`, - })); + const erc721s = get(data, 'data.assets', null); + if (isNil(erc721s)) throw new Error('Invalid data from OpenSea'); + return erc721s.map( + ({ asset_contract, background_color, token_id, ...asset }) => ({ + ...pick(asset, [ + 'animation_url', + 'current_price', + 'description', + 'external_link', + 'image_original_url', + 'image_preview_url', + 'image_thumbnail_url', + 'image_url', + 'name', + 'permalink', + 'traits', + ]), + asset_contract: pick(asset_contract, [ + 'address', + 'description', + 'external_link', + 'featured_image_url', + 'hidden', + 'image_url', + 'name', + 'nft_version', + 'schema_name', + 'short_description', + 'symbol', + 'total_supply', + 'wiki_link', + ]), + background: background_color ? `#${background_color}` : null, + familyImage: asset_contract.image_url, + id: token_id, + isNft: true, + isSendable: + asset_contract.nft_version === '1.0' || + asset_contract.nft_version === '3.0', + lastPrice: asset.last_sale ? Number(asset.last_sale.total_price) : null, + uniqueId: `${get(asset_contract, 'address')}_${token_id}`, + }) + ); }; -/* eslint-disable camelcase */ -export const getFamilies = (uniqueTokens) => uniq(map(uniqueTokens, (u) => get(u, 'asset_contract.address', ''))); +export const getFamilies = uniqueTokens => + uniq(map(uniqueTokens, u => get(u, 'asset_contract.address', ''))); + +export const dedupeUniqueTokens = (assets, uniqueTokens) => { + const uniqueTokenFamilies = getFamilies(uniqueTokens); + let updatedAssets = assets; + if (assets.length) { + updatedAssets = filter(updatedAssets, asset => { + const matchingElement = find( + uniqueTokenFamilies, + uniqueTokenFamily => + uniqueTokenFamily === get(asset, 'asset.asset_code') + ); + return !matchingElement; + }); + } + return updatedAssets; +}; + +export const dedupeAssetsWithFamilies = (assets, families) => + filter( + assets, + asset => !find(families, family => family === get(asset, 'address')) + ); diff --git a/src/redux/actionSheetManager.js b/src/redux/actionSheetManager.js index a4cd8b35aae..b7e318a2e1a 100644 --- a/src/redux/actionSheetManager.js +++ b/src/redux/actionSheetManager.js @@ -3,20 +3,20 @@ import produce from 'immer'; // -- Constants --------------------------------------- // const SET_IS_ACTION_SHEET_OPEN = 'actionSheetManager/SET_IS_ACTION_SHEET_OPEN'; -export const setIsActionSheetOpen = payload => dispatch => dispatch({ - payload, - type: SET_IS_ACTION_SHEET_OPEN, -}); +export const setIsActionSheetOpen = payload => dispatch => + dispatch({ + payload, + type: SET_IS_ACTION_SHEET_OPEN, + }); // -- Reducer ----------------------------------------- // const INITIAL_STATE = { isActionSheetOpen: false, }; -export default (state = INITIAL_STATE, action) => ( +export default (state = INITIAL_STATE, action) => produce(state, draft => { if (action.type === SET_IS_ACTION_SHEET_OPEN) { draft.isActionSheetOpen = action.payload; } - }) -); + }); diff --git a/src/redux/contacts.js b/src/redux/contacts.js new file mode 100644 index 00000000000..5e972e0a7d2 --- /dev/null +++ b/src/redux/contacts.js @@ -0,0 +1,74 @@ +import { omit, toLower } from 'lodash'; +import { getContacts, saveContacts } from '../handlers/localstorage/contacts'; + +// -- Constants --------------------------------------- // +const CONTACTS_UPDATE = 'contacts/CONTACTS_UPDATE'; +const CONTACTS_LOAD = 'contacts/CONTACTS_LOAD'; +const CONTACTS_CLEAR_STATE = 'contacts/CONTACTS_CLEAR_STATE'; + +// -- Actions ---------------------------------------- // +export const contactsLoadState = () => async dispatch => { + try { + const contacts = await getContacts(); + dispatch({ + payload: contacts, + type: CONTACTS_LOAD, + }); + // eslint-disable-next-line no-empty + } catch (error) {} +}; + +export const contactsAddOrUpdate = (address, nickname, color) => ( + dispatch, + getState +) => { + const loweredAddress = toLower(address); + const { contacts } = getState().contacts; + const updatedContacts = { + ...contacts, + [loweredAddress]: { + address: loweredAddress, + color, + nickname, + }, + }; + saveContacts(updatedContacts); + dispatch({ + payload: updatedContacts, + type: CONTACTS_UPDATE, + }); +}; + +export const removeContact = address => (dispatch, getState) => { + const { contacts } = getState().contacts; + const updatedContacts = omit(contacts, toLower(address)); + saveContacts(updatedContacts); + dispatch({ + payload: updatedContacts, + type: CONTACTS_UPDATE, + }); +}; + +// -- Reducer ----------------------------------------- // +const INITIAL_STATE = { + contacts: {}, +}; + +export default (state = INITIAL_STATE, action) => { + switch (action.type) { + case CONTACTS_UPDATE: + return { ...state, contacts: action.payload }; + case CONTACTS_LOAD: + return { + ...state, + contacts: action.payload, + }; + case CONTACTS_CLEAR_STATE: + return { + ...state, + ...INITIAL_STATE, + }; + default: + return state; + } +}; diff --git a/src/redux/data.js b/src/redux/data.js index dfd2abcde95..2d8817a4e63 100644 --- a/src/redux/data.js +++ b/src/redux/data.js @@ -1,19 +1,4 @@ -import { - concat, - filter, - find, - findIndex, - get, - includes, - isEmpty, - isNil, - map, - partition, - remove, - slice, - uniqBy, -} from 'lodash'; -import { DATA_API_KEY, DATA_ORIGIN } from 'react-native-dotenv'; +import { concat, get, includes, isNil, map, remove, uniqBy } from 'lodash'; import { getAssets, getLocalTransactions, @@ -21,20 +6,25 @@ import { removeLocalTransactions, saveAssets, saveLocalTransactions, -} from '../handlers/commonStorage'; -import io from 'socket.io-client'; import { parseAccountAssets } from '../parsers/accounts'; +} from '../handlers/localstorage/accountLocal'; +import { apiGetTokenOverrides } from '../handlers/tokenOverrides'; +import { parseAccountAssets, parseAsset } from '../parsers/accounts'; import { parseNewTransaction } from '../parsers/newTransaction'; -import { parseTransactions } from '../parsers/transactions'; -import { getFamilies } from '../parsers/uniqueTokens'; +import parseTransactions from '../parsers/transactions'; +import { loweredTokenOverridesFallback } from '../references'; import { isLowerCaseMatch } from '../utils'; -import { uniswapAddLiquidityTokens, uniswapUpdateLiquidityTokens } from './uniswap'; +import { + uniswapRemovePendingApproval, + uniswapUpdateAssetPrice, + uniswapUpdateAssets, + uniswapUpdateLiquidityTokens, +} from './uniswap'; // -- Constants --------------------------------------- // const DATA_UPDATE_ASSETS = 'data/DATA_UPDATE_ASSETS'; const DATA_UPDATE_TRANSACTIONS = 'data/DATA_UPDATE_TRANSACTIONS'; - -const DATA_UPDATE_ADDRESS_SOCKET = 'data/DATA_UPDATE_ADDRESS_SOCKET'; +const DATA_UPDATE_TOKEN_OVERRIDES = 'data/DATA_UPDATE_TOKEN_OVERRIDES'; const DATA_LOAD_ASSETS_REQUEST = 'data/DATA_LOAD_ASSETS_REQUEST'; const DATA_LOAD_ASSETS_SUCCESS = 'data/DATA_LOAD_ASSETS_SUCCESS'; @@ -44,51 +34,12 @@ const DATA_LOAD_TRANSACTIONS_REQUEST = 'data/DATA_LOAD_TRANSACTIONS_REQUEST'; const DATA_LOAD_TRANSACTIONS_SUCCESS = 'data/DATA_LOAD_TRANSACTIONS_SUCCESS'; const DATA_LOAD_TRANSACTIONS_FAILURE = 'data/DATA_LOAD_TRANSACTIONS_FAILURE'; -const DATA_ADD_NEW_TRANSACTION_SUCCESS = 'data/DATA_ADD_NEW_TRANSACTION_SUCCESS'; +const DATA_ADD_NEW_TRANSACTION_SUCCESS = + 'data/DATA_ADD_NEW_TRANSACTION_SUCCESS'; const DATA_CLEAR_STATE = 'data/DATA_CLEAR_STATE'; -const messages = { - ASSETS: { - APPENDED: 'appended address assets', - CHANGED: 'changed address assets', - RECEIVED: 'received address assets', - }, - CONNECT: 'connect', - DISCONNECT: 'disconnect', - ERROR: 'error', - RECONNECT_ATTEMPT: 'reconnect_attempt', - TRANSACTIONS: { - APPENDED: 'appended address transactions', - RECEIVED: 'received address transactions', - REMOVED: 'removed address transactions', - }, -}; - // -- Actions ---------------------------------------- // - -const createSocket = endpoint => io( - `wss://api.zerion.io/${endpoint}?api_token=${DATA_API_KEY}`, - { - extraHeaders: { Origin: DATA_ORIGIN }, - transports: ['websocket'], - }, -); - -/* eslint-disable camelcase */ -const addressSubscription = (address, currency, action = 'subscribe') => [ - action, - { - payload: { - address, - currency, - transactions_limit: 1000, - }, - scope: ['assets', 'transactions'], - }, -]; -/* eslint-disable camelcase */ - export const dataLoadState = () => async (dispatch, getState) => { const { accountAddress, network } = getState().settings; try { @@ -113,150 +64,70 @@ export const dataLoadState = () => async (dispatch, getState) => { } }; -const dataUnsubscribe = () => (dispatch, getState) => { - const { addressSocket } = getState().data; - const { accountAddress, nativeCurrency } = getState().settings; - if (!isNil(addressSocket)) { - addressSocket.emit(...addressSubscription( - accountAddress, - nativeCurrency.toLowerCase(), - 'unsubscribe', - )); - addressSocket.close(); - } +export const dataTokenOverridesInit = () => async dispatch => { + try { + const tokenOverrides = await apiGetTokenOverrides(); + dispatch(dataUpdateTokenOverrides(tokenOverrides)); + // eslint-disable-next-line no-empty + } catch (error) {} }; export const dataClearState = () => (dispatch, getState) => { - dispatch(dataUnsubscribe()); const { accountAddress, network } = getState().settings; removeAssets(accountAddress, network); removeLocalTransactions(accountAddress, network); dispatch({ type: DATA_CLEAR_STATE }); }; -export const dataInit = () => (dispatch, getState) => { - const { accountAddress, nativeCurrency } = getState().settings; - const addressSocket = createSocket('address'); - dispatch({ - payload: addressSocket, - type: DATA_UPDATE_ADDRESS_SOCKET, - }); - addressSocket.on(messages.CONNECT, () => { - addressSocket.emit(...addressSubscription(accountAddress, nativeCurrency.toLowerCase())); - dispatch(listenOnNewMessages(addressSocket)); - }); -}; - -const dedupePendingTransactions = (pendingTransactions, parsedTransactions) => { - let updatedPendingTransactions = pendingTransactions; - if (pendingTransactions.length) { - updatedPendingTransactions = filter(updatedPendingTransactions, (pendingTxn) => { - const matchingElement = find(parsedTransactions, (txn) => txn.hash - && (txn.hash.toLowerCase().startsWith(pendingTxn.hash.toLowerCase()) - || (txn.nonce && (txn.nonce >= pendingTxn.nonce)))); - return !matchingElement; - }); - } - return updatedPendingTransactions; -}; - -export const dedupeAssetsWithFamilies = (families) => (dispatch, getState) => { +export const dataUpdateAssets = assets => (dispatch, getState) => { const { accountAddress, network } = getState().settings; - const { assets } = getState().data; if (assets.length) { - const dedupedAssets = filter(assets, (asset) => { - const matchingElement = find(families, (family) => family === get(asset, 'address')); - return !matchingElement; - }); - saveAssets(accountAddress, dedupedAssets, network); + saveAssets(assets, accountAddress, network); dispatch({ - payload: dedupedAssets, + payload: assets, type: DATA_UPDATE_ASSETS, }); } }; -const dedupeUniqueTokens = assets => (dispatch, getState) => { - const { uniqueTokens } = getState().uniqueTokens; - const uniqueTokenFamilies = getFamilies(uniqueTokens); - let updatedAssets = assets; - if (assets.length) { - updatedAssets = filter(updatedAssets, (asset) => { - const matchingElement = find(uniqueTokenFamilies, (uniqueTokenFamily) => uniqueTokenFamily === get(asset, 'asset.asset_code')); - return !matchingElement; - }); - } - return updatedAssets; -}; - const checkMeta = message => (dispatch, getState) => { const { accountAddress, nativeCurrency } = getState().settings; const address = get(message, 'meta.address'); const currency = get(message, 'meta.currency'); - return isLowerCaseMatch(address, accountAddress) && isLowerCaseMatch(currency, nativeCurrency); -}; - -const transactionsReceived = message => (dispatch, getState) => { - const isValidMeta = dispatch(checkMeta(message)); - if (!isValidMeta) return; - - let transactionData = get(message, 'payload.transactions', []); - if (!transactionData.length) return; - - const { accountAddress, nativeCurrency, network } = getState().settings; - const { transactions } = getState().data; - - const lastSuccessfulTxn = find(transactions, (txn) => txn.hash && !txn.pending); - const lastTxHash = lastSuccessfulTxn ? lastSuccessfulTxn.hash : ''; - if (lastTxHash) { - const lastTxnHashIndex = findIndex(transactionData, (txn) => lastTxHash.startsWith(txn.hash)); - if (lastTxnHashIndex > -1) { - transactionData = slice(transactionData, 0, lastTxnHashIndex); - } - } - if (!transactionData.length) return; - - const parsedTransactions = parseTransactions(transactionData, nativeCurrency); - const partitions = partition(transactions, (txn) => txn.pending); - const pendingTransactions = partitions[0]; - const remainingTransactions = partitions[1]; - - const updatedPendingTransactions = dedupePendingTransactions(pendingTransactions, parsedTransactions); - const updatedResults = concat(updatedPendingTransactions, parsedTransactions, remainingTransactions); - const dedupedResults = uniqBy(updatedResults, (txn) => txn.hash); - - saveLocalTransactions(accountAddress, dedupedResults, network); - dispatch({ - payload: dedupedResults, - type: DATA_UPDATE_TRANSACTIONS, - }); + return ( + isLowerCaseMatch(address, accountAddress) && + isLowerCaseMatch(currency, nativeCurrency) + ); }; -const transactionsAppended = message => (dispatch, getState) => { +export const transactionsReceived = (message, appended = false) => ( + dispatch, + getState +) => { const isValidMeta = dispatch(checkMeta(message)); if (!isValidMeta) return; - const transactionData = get(message, 'payload.transactions', []); if (!transactionData.length) return; const { accountAddress, nativeCurrency, network } = getState().settings; - const { transactions } = getState().data; - const partitions = partition(transactions, (txn) => txn.pending); - const pendingTransactions = partitions[0]; - const remainingTransactions = partitions[1]; - - const parsedTransactions = parseTransactions(transactionData, nativeCurrency); - const updatedPendingTransactions = dedupePendingTransactions(pendingTransactions, parsedTransactions); - const updatedResults = concat(updatedPendingTransactions, parsedTransactions, remainingTransactions); - const dedupedResults = uniqBy(updatedResults, (txn) => txn.hash); - - saveLocalTransactions(accountAddress, updatedResults, network); + const { transactions, tokenOverrides } = getState().data; + if (!transactionData.length) return; + const { approvalTransactions, dedupedResults } = parseTransactions( + transactionData, + accountAddress, + nativeCurrency, + transactions, + tokenOverrides, + appended + ); + dispatch(uniswapRemovePendingApproval(approvalTransactions)); + saveLocalTransactions(dedupedResults, accountAddress, network); dispatch({ payload: dedupedResults, type: DATA_UPDATE_TRANSACTIONS, }); }; -const transactionsRemoved = message => (dispatch, getState) => { +export const transactionsRemoved = message => (dispatch, getState) => { const isValidMeta = dispatch(checkMeta(message)); if (!isValidMeta) return; @@ -265,149 +136,147 @@ const transactionsRemoved = message => (dispatch, getState) => { const { accountAddress, network } = getState().settings; const { transactions } = getState().data; const removeHashes = map(transactionData, txn => txn.hash); - remove(transactions, (txn) => includes(removeHashes, txn.hash)); + remove(transactions, txn => includes(removeHashes, txn.hash)); - saveLocalTransactions(accountAddress, transactions, network); + saveLocalTransactions(transactions, accountAddress, network); dispatch({ payload: transactions, type: DATA_UPDATE_TRANSACTIONS, }); }; -const assetsReceived = (message, append = false, change = false) => (dispatch, getState) => { +export const addressAssetsReceived = ( + message, + append = false, + change = false +) => (dispatch, getState) => { const isValidMeta = dispatch(checkMeta(message)); if (!isValidMeta) return; + const { tokenOverrides } = getState().data; const { accountAddress, network } = getState().settings; + const { uniqueTokens } = getState().uniqueTokens; const assets = get(message, 'payload.assets', []); - const liquidityTokens = remove( - assets, - asset => get(asset, 'asset.symbol', '') === 'UNI' - ); - if (append) { - dispatch(uniswapAddLiquidityTokens(liquidityTokens)); - } - if (!append && !change) { - dispatch(uniswapUpdateLiquidityTokens(liquidityTokens)); - } - const updatedAssets = dispatch(dedupeUniqueTokens(assets)); - if (!updatedAssets.length) return; - let parsedAssets = parseAccountAssets(updatedAssets); + const liquidityTokens = remove(assets, asset => { + const symbol = get(asset, 'asset.symbol', ''); + return symbol === 'UNI' || symbol === 'uni-v1'; + }); + dispatch(uniswapUpdateLiquidityTokens(liquidityTokens, append || change)); + let parsedAssets = parseAccountAssets(assets, uniqueTokens, tokenOverrides); if (append || change) { const { assets: existingAssets } = getState().data; - parsedAssets = uniqBy(concat(parsedAssets, existingAssets), (item) => item.uniqueId); + parsedAssets = uniqBy( + concat(parsedAssets, existingAssets), + item => item.uniqueId + ); } - saveAssets(accountAddress, parsedAssets, network); + saveAssets(parsedAssets, accountAddress, network); dispatch({ payload: parsedAssets, type: DATA_UPDATE_ASSETS, }); }; -const listenOnNewMessages = socket => (dispatch, getState) => { - socket.on(messages.TRANSACTIONS.RECEIVED, (message) => { - dispatch(transactionsReceived(message)); - }); - - socket.on(messages.TRANSACTIONS.APPENDED, (message) => { - dispatch(transactionsAppended(message)); - }); - - socket.on(messages.TRANSACTIONS.REMOVED, (message) => { - dispatch(transactionsRemoved(message)); - }); - - socket.on(messages.ASSETS.RECEIVED, (message) => { - dispatch(assetsReceived(message)); +export const dataUpdateTokenOverrides = tokenOverrides => dispatch => + dispatch({ + payload: tokenOverrides, + type: DATA_UPDATE_TOKEN_OVERRIDES, }); - socket.on(messages.ASSETS.APPENDED, (message) => { - dispatch(assetsReceived(message, true)); - }); +export const assetsReceived = message => (dispatch, getState) => { + const { tokenOverrides } = getState().data; + const assets = get(message, 'payload.assets', []); + if (!assets.length) return; + const parsedAssets = map(assets, asset => parseAsset(asset, tokenOverrides)); + dispatch(uniswapUpdateAssets(parsedAssets)); +}; - socket.on(messages.ASSETS.CHANGED, (message) => { - dispatch(assetsReceived(message, false, true)); - }); +export const priceChanged = message => dispatch => { + const address = get(message, 'meta.asset_code'); + const price = get(message, 'payload.price'); + if (isNil(price)) return; + dispatch(uniswapUpdateAssetPrice(address, price)); }; -export const dataAddNewTransaction = txDetails => (dispatch, getState) => new Promise((resolve, reject) => { - const { transactions } = getState().data; - const { accountAddress, nativeCurrency, network } = getState().settings; - parseNewTransaction(txDetails, nativeCurrency) - .then(parsedTransaction => { - const _transactions = [parsedTransaction, ...transactions]; - saveLocalTransactions(accountAddress, _transactions, network); - dispatch({ - payload: _transactions, - type: DATA_ADD_NEW_TRANSACTION_SUCCESS, +export const dataAddNewTransaction = txDetails => (dispatch, getState) => + new Promise((resolve, reject) => { + const { transactions } = getState().data; + const { accountAddress, nativeCurrency, network } = getState().settings; + parseNewTransaction(txDetails, nativeCurrency) + .then(parsedTransaction => { + const _transactions = [parsedTransaction, ...transactions]; + saveLocalTransactions(_transactions, accountAddress, network); + dispatch({ + payload: _transactions, + type: DATA_ADD_NEW_TRANSACTION_SUCCESS, + }); + resolve(true); + }) + .catch(error => { + reject(error); }); - resolve(true); - }) - .catch(error => { - reject(error); - }); -}); + }); // -- Reducer ----------------------------------------- // const INITIAL_STATE = { - addressSocket: null, assets: [], loadingAssets: false, loadingTransactions: false, + tokenOverrides: loweredTokenOverridesFallback, transactions: [], }; export default (state = INITIAL_STATE, action) => { switch (action.type) { - case DATA_UPDATE_ADDRESS_SOCKET: - return { ...state, addressSocket: action.payload }; - case DATA_UPDATE_ASSETS: - return { ...state, assets: action.payload }; - case DATA_UPDATE_TRANSACTIONS: - return { ...state, transactions: action.payload }; - case DATA_LOAD_TRANSACTIONS_REQUEST: - return { - ...state, - loadingTransactions: true, - }; - case DATA_LOAD_TRANSACTIONS_SUCCESS: - return { - ...state, - loadingTransactions: false, - transactions: action.payload, - }; - case DATA_LOAD_TRANSACTIONS_FAILURE: - return { - ...state, - loadingTransactions: false, - }; - case DATA_LOAD_ASSETS_REQUEST: - return { - ...state, - loadingAssets: true, - }; - case DATA_LOAD_ASSETS_SUCCESS: - return { - ...state, - assets: action.payload, - loadingAssets: false, - }; - case DATA_LOAD_ASSETS_FAILURE: - return { - ...state, - loadingAssets: false, - }; - case DATA_ADD_NEW_TRANSACTION_SUCCESS: - return { - ...state, - transactions: action.payload, - }; - case DATA_CLEAR_STATE: - return { - ...state, - ...INITIAL_STATE, - }; - default: - return state; + case DATA_UPDATE_ASSETS: + return { ...state, assets: action.payload }; + case DATA_UPDATE_TOKEN_OVERRIDES: + return { ...state, tokenOverrides: action.payload }; + case DATA_UPDATE_TRANSACTIONS: + return { ...state, transactions: action.payload }; + case DATA_LOAD_TRANSACTIONS_REQUEST: + return { + ...state, + loadingTransactions: true, + }; + case DATA_LOAD_TRANSACTIONS_SUCCESS: + return { + ...state, + loadingTransactions: false, + transactions: action.payload, + }; + case DATA_LOAD_TRANSACTIONS_FAILURE: + return { + ...state, + loadingTransactions: false, + }; + case DATA_LOAD_ASSETS_REQUEST: + return { + ...state, + loadingAssets: true, + }; + case DATA_LOAD_ASSETS_SUCCESS: + return { + ...state, + assets: action.payload, + loadingAssets: false, + }; + case DATA_LOAD_ASSETS_FAILURE: + return { + ...state, + loadingAssets: false, + }; + case DATA_ADD_NEW_TRANSACTION_SUCCESS: + return { + ...state, + transactions: action.payload, + }; + case DATA_CLEAR_STATE: + return { + ...state, + ...INITIAL_STATE, + }; + default: + return state; } }; diff --git a/src/redux/explorer.js b/src/redux/explorer.js new file mode 100644 index 00000000000..30f73b00405 --- /dev/null +++ b/src/redux/explorer.js @@ -0,0 +1,182 @@ +import { isNil, keys, toLower } from 'lodash'; +import { DATA_API_KEY, DATA_ORIGIN } from 'react-native-dotenv'; +import io from 'socket.io-client'; +import { + addressAssetsReceived, + assetsReceived, + priceChanged, + transactionsReceived, + transactionsRemoved, +} from './data'; + +// -- Constants --------------------------------------- // + +const EXPLORER_UPDATE_SOCKETS = 'explorer/EXPLORER_UPDATE_SOCKETS'; +const EXPLORER_CLEAR_STATE = 'explorer/EXPLORER_CLEAR_STATE'; + +const messages = { + ADDRESS_ASSETS: { + APPENDED: 'appended address assets', + CHANGED: 'changed address assets', + RECEIVED: 'received address assets', + }, + ADDRESS_TRANSACTIONS: { + APPENDED: 'appended address transactions', + RECEIVED: 'received address transactions', + REMOVED: 'removed address transactions', + }, + ASSETS: { + CHANGED: 'changed price', + RECEIVED: 'received assets', + }, + CONNECT: 'connect', + DISCONNECT: 'disconnect', + ERROR: 'error', + RECONNECT_ATTEMPT: 'reconnect_attempt', +}; + +// -- Actions ---------------------------------------- // + +const createSocket = endpoint => + io(`wss://api.zerion.io/${endpoint}?api_token=${DATA_API_KEY}`, { + extraHeaders: { Origin: DATA_ORIGIN }, + transports: ['websocket'], + }); + +const addressSubscription = (address, currency, action = 'subscribe') => [ + action, + { + payload: { + address, + currency: toLower(currency), + transactions_limit: 1000, + }, + scope: ['assets', 'transactions'], + }, +]; + +const assetsSubscription = (assetCodes, currency, action = 'subscribe') => [ + action, + { + payload: { + asset_codes: assetCodes, + currency: toLower(currency), + }, + }, +]; + +const explorerUnsubscribe = () => (dispatch, getState) => { + const { addressSocket, assetsSocket } = getState().explorer; + const { accountAddress, nativeCurrency } = getState().settings; + const { pairs } = getState().uniswap; + if (!isNil(addressSocket)) { + addressSocket.emit( + ...addressSubscription(accountAddress, nativeCurrency, 'unsubscribe') + ); + addressSocket.close(); + } + if (!isNil(assetsSocket)) { + assetsSocket.emit( + ...assetsSubscription(keys(pairs), nativeCurrency, 'unsubscribe') + ); + assetsSocket.close(); + } +}; + +export const explorerClearState = () => dispatch => { + dispatch(explorerUnsubscribe()); + dispatch({ type: EXPLORER_CLEAR_STATE }); +}; + +export const resubscribeAssets = (oldAddresses, addresses) => ( + dispatch, + getState +) => { + const { nativeCurrency } = getState().settings; + const { assetsSocket } = getState().explorer; + if (!isNil(assetsSocket)) { + assetsSocket.emit( + ...assetsSubscription(keys(oldAddresses), nativeCurrency, 'unsubscribe') + ); + assetsSocket.emit(...assetsSubscription(addresses, nativeCurrency)); + } +}; + +export const explorerInit = () => (dispatch, getState) => { + const { accountAddress, nativeCurrency } = getState().settings; + const { pairs } = getState().uniswap; + const addressSocket = createSocket('address'); + const assetsSocket = createSocket('assets'); + dispatch({ + payload: { addressSocket, assetsSocket }, + type: EXPLORER_UPDATE_SOCKETS, + }); + assetsSocket.on(messages.CONNECT, () => { + assetsSocket.emit(...assetsSubscription(keys(pairs), nativeCurrency)); + dispatch(listenOnAssetMessages(assetsSocket)); + }); + addressSocket.on(messages.CONNECT, () => { + addressSocket.emit(...addressSubscription(accountAddress, nativeCurrency)); + dispatch(listenOnAddressMessages(addressSocket)); + }); +}; + +const listenOnAssetMessages = socket => dispatch => { + socket.on(messages.ASSETS.RECEIVED, message => { + dispatch(assetsReceived(message)); + }); + + socket.on(messages.ASSETS.CHANGED, message => { + dispatch(priceChanged(message)); + }); +}; + +const listenOnAddressMessages = socket => dispatch => { + socket.on(messages.ADDRESS_TRANSACTIONS.RECEIVED, message => { + dispatch(transactionsReceived(message)); + }); + + socket.on(messages.ADDRESS_TRANSACTIONS.APPENDED, message => { + dispatch(transactionsReceived(message, true)); + }); + + socket.on(messages.ADDRESS_TRANSACTIONS.REMOVED, message => { + dispatch(transactionsRemoved(message)); + }); + + socket.on(messages.ADDRESS_ASSETS.RECEIVED, message => { + dispatch(addressAssetsReceived(message)); + }); + + socket.on(messages.ADDRESS_ASSETS.APPENDED, message => { + dispatch(addressAssetsReceived(message, true)); + }); + + socket.on(messages.ADDRESS_ASSETS.CHANGED, message => { + dispatch(addressAssetsReceived(message, false, true)); + }); +}; + +// -- Reducer ----------------------------------------- // +const INITIAL_STATE = { + addressSocket: null, + assetsSocket: null, +}; + +export default (state = INITIAL_STATE, action) => { + switch (action.type) { + case EXPLORER_UPDATE_SOCKETS: + return { + ...state, + addressSocket: action.payload.addressSocket, + assetsSocket: action.payload.assetsSocket, + }; + case EXPLORER_CLEAR_STATE: + return { + ...state, + ...INITIAL_STATE, + }; + default: + return state; + } +}; diff --git a/src/redux/gas.js b/src/redux/gas.js new file mode 100644 index 00000000000..2e3d0b919ca --- /dev/null +++ b/src/redux/gas.js @@ -0,0 +1,239 @@ +import { captureException } from '@sentry/react-native'; +import { get, isEmpty } from 'lodash'; +import { apiGetGasPrices } from '../handlers/gasPrices'; +import { fromWei } from '../helpers/utilities'; +import { + getFallbackGasPrices, + parseGasPrices, + parseTxFees, +} from '../parsers/gas'; +import ethUnits from '../references/ethereum-units.json'; +import { ethereumUtils, gasUtils } from '../utils'; + +// -- Constants ------------------------------------------------------------- // + +const GAS_UPDATE_DEFAULT_GAS_LIMIT = 'gas/GAS_UPDATE_DEFAULT_GAS_LIMIT'; +const GAS_PRICES_DEFAULT = 'gas/GAS_PRICES_DEFAULT'; +const GAS_PRICES_SUCCESS = 'gas/GAS_PRICES_SUCCESS'; +const GAS_PRICES_FAILURE = 'gas/GAS_PRICES_FAILURE'; + +const GAS_UPDATE_TX_FEE = 'gas/GAS_UPDATE_TX_FEE'; +const GAS_UPDATE_GAS_PRICE_OPTION = 'gas/GAS_UPDATE_GAS_PRICE_OPTION'; + +// -- Actions --------------------------------------------------------------- // +let getGasPricesInterval = null; + +const getDefaultTxFees = () => (dispatch, getState) => { + const { assets } = getState().data; + const { defaultGasLimit } = getState().gas; + const { nativeCurrency } = getState().settings; + const fallbackGasPrices = getFallbackGasPrices(); + const ethPriceUnit = ethereumUtils.getEthPriceUnit(assets); + const txFees = parseTxFees( + fallbackGasPrices, + ethPriceUnit, + defaultGasLimit, + nativeCurrency + ); + const selectedGasPrice = { + ...txFees[gasUtils.NORMAL], + ...fallbackGasPrices[gasUtils.NORMAL], + }; + return { + fallbackGasPrices, + selectedGasPrice, + txFees, + }; +}; + +export const gasPricesInit = () => (dispatch, getState) => + new Promise((resolve, reject) => { + const { fallbackGasPrices, selectedGasPrice, txFees } = dispatch( + getDefaultTxFees() + ); + dispatch({ + payload: { + gasPrices: fallbackGasPrices, + selectedGasPrice, + txFees, + }, + type: GAS_PRICES_DEFAULT, + }); + + const getGasPrices = () => + new Promise((fetchResolve, fetchReject) => { + const { useShortGasFormat } = getState().gas; + apiGetGasPrices() + .then(({ data }) => { + const gasPrices = parseGasPrices(data, useShortGasFormat); + dispatch({ + payload: gasPrices, + type: GAS_PRICES_SUCCESS, + }); + fetchResolve(true); + }) + .catch(error => { + dispatch({ + payload: fallbackGasPrices, + type: GAS_PRICES_FAILURE, + }); + captureException(error); + fetchReject(error); + }); + }); + return getGasPrices() + .then(() => { + clearInterval(getGasPricesInterval); + getGasPricesInterval = setInterval(getGasPrices, 15000); // 15 secs + resolve(true); + }) + .catch(error => { + clearInterval(getGasPricesInterval); + getGasPricesInterval = setInterval(getGasPrices, 15000); // 15 secs + reject(error); + }); + }); + +export const gasUpdateGasPriceOption = newGasPriceOption => ( + dispatch, + getState +) => { + const { gasPrices, txFees } = getState().gas; + if (isEmpty(gasPrices)) return; + const { assets } = getState().data; + const results = getSelectedGasPrice( + assets, + gasPrices, + txFees, + newGasPriceOption + ); + dispatch({ + payload: { + ...results, + selectedGasPriceOption: newGasPriceOption, + }, + type: GAS_UPDATE_GAS_PRICE_OPTION, + }); +}; + +export const gasUpdateDefaultGasLimit = ( + defaultGasLimit = ethUnits.basic_tx +) => dispatch => { + dispatch({ + payload: defaultGasLimit, + type: GAS_UPDATE_DEFAULT_GAS_LIMIT, + }); + dispatch(gasUpdateTxFee(defaultGasLimit)); +}; + +export const gasUpdateTxFee = (gasLimit, overrideGasOption) => ( + dispatch, + getState +) => { + const { defaultGasLimit, gasPrices, selectedGasPriceOption } = getState().gas; + const _gasLimit = gasLimit || defaultGasLimit; + const _selectedGasPriceOption = overrideGasOption || selectedGasPriceOption; + if (isEmpty(gasPrices)) return; + const { assets } = getState().data; + const { nativeCurrency } = getState().settings; + const ethPriceUnit = ethereumUtils.getEthPriceUnit(assets); + const txFees = parseTxFees( + gasPrices, + ethPriceUnit, + _gasLimit, + nativeCurrency + ); + const results = getSelectedGasPrice( + assets, + gasPrices, + txFees, + _selectedGasPriceOption + ); + dispatch({ + payload: { + ...results, + gasLimit, + txFees, + }, + type: GAS_UPDATE_TX_FEE, + }); +}; + +const getSelectedGasPrice = ( + assets, + gasPrices, + txFees, + selectedGasPriceOption +) => { + const txFee = txFees[selectedGasPriceOption]; + const ethAsset = ethereumUtils.getAsset(assets); + const balanceAmount = get(ethAsset, 'balance.amount', 0); + const txFeeAmount = fromWei(get(txFee, 'value.amount', 0)); + return { + isSufficientGas: Number(balanceAmount) > Number(txFeeAmount), + selectedGasPrice: { + ...txFee, + ...gasPrices[selectedGasPriceOption], + }, + }; +}; + +export const gasClearState = () => () => { + clearInterval(getGasPricesInterval); +}; + +// -- Reducer --------------------------------------------------------------- // +const INITIAL_STATE = { + defaultGasLimit: ethUnits.basic_tx, + gasLimit: null, + gasPrices: {}, + isSufficientGas: false, + selectedGasPrice: {}, + selectedGasPriceOption: gasUtils.NORMAL, + txFees: {}, + useShortGasFormat: true, +}; + +export default (state = INITIAL_STATE, action) => { + switch (action.type) { + case GAS_UPDATE_DEFAULT_GAS_LIMIT: + return { + ...state, + defaultGasLimit: action.payload, + }; + case GAS_PRICES_DEFAULT: + return { + ...state, + gasPrices: action.payload.gasPrices, + selectedGasPrice: action.payload.selectedGasPrice, + txFees: action.payload.txFees, + }; + case GAS_PRICES_SUCCESS: + return { + ...state, + gasPrices: action.payload, + }; + case GAS_PRICES_FAILURE: + return { + ...state, + gasPrices: action.payload, + }; + case GAS_UPDATE_TX_FEE: + return { + ...state, + gasLimit: action.payload.gasLimit, + isSufficientGas: action.payload.isSufficientGas, + selectedGasPrice: action.payload.selectedGasPrice, + txFees: action.payload.txFees, + }; + case GAS_UPDATE_GAS_PRICE_OPTION: + return { + ...state, + isSufficientGas: action.payload.isSufficientGas, + selectedGasPrice: action.payload.selectedGasPrice, + selectedGasPriceOption: action.payload.selectedGasPriceOption, + }; + default: + return state; + } +}; diff --git a/src/redux/imageDimensionsCache.js b/src/redux/imageDimensionsCache.js index bd265535361..0745983f2c6 100644 --- a/src/redux/imageDimensionsCache.js +++ b/src/redux/imageDimensionsCache.js @@ -5,30 +5,31 @@ import { omit } from 'lodash'; const MERGE = 'imageDimensionsCache/MERGE'; const PRUNE = 'imageDimensionsCache/PRUNE'; -export const pruneImageDimensionsCache = idsToPrune => dispatch => dispatch({ - idsToPrune, - type: PRUNE, -}); +export const pruneImageDimensionsCache = idsToPrune => dispatch => + dispatch({ + idsToPrune, + type: PRUNE, + }); -export const updateImageDimensionsCache = payload => dispatch => dispatch({ - ...payload, - type: MERGE, -}); +export const updateImageDimensionsCache = payload => dispatch => + dispatch({ + ...payload, + type: MERGE, + }); // // -- Reducer ----------------------------------------- // const INITIAL_STATE = {}; -export default (state = INITIAL_STATE, action) => ( +export default (state = INITIAL_STATE, action) => produce(state, draft => { switch (action.type) { - case MERGE: - draft[action.id] = action.dimensions; - break; - case PRUNE: - omit(draft, action.idsToPrune); - break; - default: - break; + case MERGE: + draft[action.id] = action.dimensions; + break; + case PRUNE: + omit(draft, action.idsToPrune); + break; + default: + break; } - }) -); + }); diff --git a/src/redux/isWalletEmpty.js b/src/redux/isWalletEmpty.js index aea6a231bf3..b697cb0b850 100644 --- a/src/redux/isWalletEmpty.js +++ b/src/redux/isWalletEmpty.js @@ -4,7 +4,7 @@ import { getIsWalletEmpty, removeIsWalletEmpty, saveIsWalletEmpty, -} from '../handlers/commonStorage'; +} from '../handlers/localstorage/accountLocal'; // -- Constants --------------------------------------- // const SET_IS_WALLET_EMPTY = 'isWalletEmpty/SET_IS_WALLET_EMPTY'; @@ -27,7 +27,7 @@ export const setIsWalletEmpty = payload => (dispatch, getState) => { type: SET_IS_WALLET_EMPTY, }); const { accountAddress, network } = getState().settings; - saveIsWalletEmpty(accountAddress, payload, network); + saveIsWalletEmpty(payload, accountAddress, network); }; export const clearIsWalletEmpty = () => (dispatch, getState) => { @@ -36,20 +36,18 @@ export const clearIsWalletEmpty = () => (dispatch, getState) => { dispatch({ type: CLEAR_IS_WALLET_EMPTY }); }; - // -- Reducer ----------------------------------------- // const INITIAL_STATE = { isWalletEmpty: true }; -export default (state = INITIAL_STATE, action) => ( +export default (state = INITIAL_STATE, action) => produce(state, draft => { switch (action.type) { - case SET_IS_WALLET_EMPTY: - draft.isWalletEmpty = action.payload; - break; - case CLEAR_IS_WALLET_EMPTY: - return INITIAL_STATE; - default: - break; + case SET_IS_WALLET_EMPTY: + draft.isWalletEmpty = action.payload; + break; + case CLEAR_IS_WALLET_EMPTY: + return INITIAL_STATE; + default: + break; } - }) -); + }); diff --git a/src/redux/isWalletEthZero.js b/src/redux/isWalletEthZero.js index b689ac5fae5..2625d753313 100644 --- a/src/redux/isWalletEthZero.js +++ b/src/redux/isWalletEthZero.js @@ -3,20 +3,18 @@ import produce from 'immer'; // -- Constants --------------------------------------- // const SET_IS_WALLET_ETH_ZERO = 'isWalletEthZero/SET_IS_WALLET_ETH_ZERO'; -export const setIsWalletEthZero = payload => dispatch => ( +export const setIsWalletEthZero = payload => dispatch => dispatch({ payload, type: SET_IS_WALLET_ETH_ZERO, - }) -); + }); // -- Reducer ----------------------------------------- // -const INITIAL_STATE = { isWalletEthZero: true }; +const INITIAL_STATE = { isWalletEthZero: false }; -export default (state = INITIAL_STATE, action) => ( +export default (state = INITIAL_STATE, action) => produce(state, draft => { if (action.type === SET_IS_WALLET_ETH_ZERO) { draft.isWalletEthZero = action.payload; } - }) -); + }); diff --git a/src/redux/isWalletImporting.js b/src/redux/isWalletImporting.js deleted file mode 100644 index a7719114db1..00000000000 --- a/src/redux/isWalletImporting.js +++ /dev/null @@ -1,22 +0,0 @@ -import produce from 'immer'; - -// -- Constants --------------------------------------- // -const SET_IS_WALLET_IMPORTING = 'isWalletImporting/SET_IS_WALLET_IMPORTING'; - -export const setIsWalletImporting = payload => dispatch => ( - dispatch({ - payload, - type: SET_IS_WALLET_IMPORTING, - }) -); - -// -- Reducer ----------------------------------------- // -const INITIAL_STATE = { isImporting: false }; - -export default (state = INITIAL_STATE, action) => ( - produce(state, draft => { - if (action.type === SET_IS_WALLET_IMPORTING) { - draft.isImporting = action.payload; - } - }) -); diff --git a/src/redux/keyboardHeight.js b/src/redux/keyboardHeight.js new file mode 100644 index 00000000000..2eb96a42874 --- /dev/null +++ b/src/redux/keyboardHeight.js @@ -0,0 +1,20 @@ +import produce from 'immer'; + +// -- Constants --------------------------------------- // +const SET_KEYBOARD_HEIGHT = 'keyboardHeight/SET_KEYBOARD_HEIGHT'; + +export const setKeyboardHeight = payload => dispatch => + dispatch({ + payload, + type: SET_KEYBOARD_HEIGHT, + }); + +// -- Reducer ----------------------------------------- // +const INITIAL_STATE = { keyboardHeight: 0 }; + +export default (state = INITIAL_STATE, action) => + produce(state, draft => { + if (action.type === SET_KEYBOARD_HEIGHT) { + draft.keyboardHeight = action.payload; + } + }); diff --git a/src/redux/navigation.js b/src/redux/navigation.js index 75643ce0f07..6546b792835 100644 --- a/src/redux/navigation.js +++ b/src/redux/navigation.js @@ -1,26 +1,21 @@ -import { Animated } from 'react-native'; - // -- Constants --------------------------------------- // const UPDATE_TRANSITION_PROPS = 'navigation/UPDATE_TRANSITION_PROPS'; -export const updateTransitionProps = (payload) => (dispatch) => { +export const updateTransitionProps = payload => dispatch => { dispatch({ payload, type: UPDATE_TRANSITION_PROPS }); }; // -- Reducer ----------------------------------------- // const INITIAL_STATE = { transitionProps: { + blurColor: null, effect: '', isTransitioning: false, - nextIndex: 1, - position: new Animated.Value(0), - prevIndex: 0, }, }; export default (state = INITIAL_STATE, action) => { - switch (action.type) { - case UPDATE_TRANSITION_PROPS: + if (action.type === UPDATE_TRANSITION_PROPS) { return { ...state, transitionProps: { @@ -28,7 +23,6 @@ export default (state = INITIAL_STATE, action) => { ...action.payload, }, }; - default: - return state; } + return state; }; diff --git a/src/redux/nonce.js b/src/redux/nonce.js index c0daee7003c..ea8a6e425a5 100644 --- a/src/redux/nonce.js +++ b/src/redux/nonce.js @@ -1,16 +1,23 @@ // -- Constants --------------------------------------- // -const NONCE_UPDATE_TRANSACTION_COUNT_NONCE = 'nonce/NONCE_UPDATE_TRANSACTION_COUNT_NONCE'; +const NONCE_UPDATE_TRANSACTION_COUNT_NONCE = + 'nonce/NONCE_UPDATE_TRANSACTION_COUNT_NONCE'; const NONCE_CLEAR_STATE = 'nonce/NONCE_CLEAR_STATE'; -export const updateTransactionCountNonce = (transactionCount) => (dispatch, getState) => { +export const updateTransactionCountNonce = transactionCount => ( + dispatch, + getState +) => { const { transactionCountNonce } = getState().nonce; if (transactionCount > transactionCountNonce) { - dispatch({ payload: transactionCount, type: NONCE_UPDATE_TRANSACTION_COUNT_NONCE }); + dispatch({ + payload: transactionCount, + type: NONCE_UPDATE_TRANSACTION_COUNT_NONCE, + }); } }; -export const nonceClearState = () => (dispatch, getState) => dispatch({ type: NONCE_CLEAR_STATE }); - +export const nonceClearState = () => dispatch => + dispatch({ type: NONCE_CLEAR_STATE }); // -- Reducer ----------------------------------------- // const INITIAL_STATE = { @@ -19,11 +26,11 @@ const INITIAL_STATE = { export default (state = INITIAL_STATE, action) => { switch (action.type) { - case NONCE_UPDATE_TRANSACTION_COUNT_NONCE: - return { ...state, transactionCountNonce: action.payload }; - case NONCE_CLEAR_STATE: - return { ...state, ...INITIAL_STATE }; - default: - return state; + case NONCE_UPDATE_TRANSACTION_COUNT_NONCE: + return { ...state, transactionCountNonce: action.payload }; + case NONCE_CLEAR_STATE: + return { ...state, ...INITIAL_STATE }; + default: + return state; } }; diff --git a/src/redux/openFamilyTabs.js b/src/redux/openFamilyTabs.js deleted file mode 100644 index 8276c6426e1..00000000000 --- a/src/redux/openFamilyTabs.js +++ /dev/null @@ -1,37 +0,0 @@ -import produce from 'immer'; - -// -- Constants --------------------------------------- // -const CLEAR_OPEN_FAMILY_TAB = 'openFamilyTabs/CLEAR_OPEN_FAMILY_TAB'; -const PUSH_OPEN_FAMILY_TAB = 'openFamilyTabs/PUSH_OPEN_FAMILY_TAB'; -const SET_OPEN_FAMILY_TABS = 'openFamilyTabs/SET_OPEN_FAMILY_TABS'; - -export const clearOpenFamilyTab = () => dispatch => dispatch({ - type: CLEAR_OPEN_FAMILY_TAB, -}); - -export const pushOpenFamilyTab = payload => dispatch => dispatch({ - payload, - type: PUSH_OPEN_FAMILY_TAB, -}); - -export const setOpenFamilyTabs = payload => dispatch => dispatch({ - payload, - type: SET_OPEN_FAMILY_TABS, -}); - -// -- Reducer ----------------------------------------- // -const INITIAL_STATE = { - openFamilyTabs: [], -}; - -export default (state = INITIAL_STATE, action) => ( - produce(state, draft => { - if (action.type === SET_OPEN_FAMILY_TABS) { - draft.openFamilyTabs[action.payload.index] = action.payload.state; - } else if (action.type === PUSH_OPEN_FAMILY_TAB) { - draft.openFamilyTabs = state.openFamilyTabs.concat(false); - } else if (action.type === CLEAR_OPEN_FAMILY_TAB) { - return INITIAL_STATE; - } - }) -); diff --git a/src/redux/openStateSettings.js b/src/redux/openStateSettings.js new file mode 100644 index 00000000000..6735da3f588 --- /dev/null +++ b/src/redux/openStateSettings.js @@ -0,0 +1,137 @@ +import produce from 'immer'; +import { + getOpenFamilies, + getOpenInvestmentCards, + getSmallBalanceToggle, + saveOpenFamilies, + saveOpenInvestmentCards, + saveSmallBalanceToggle, + removeOpenFamilies, + removeOpenInvestmentCards, + removeSmallBalanceToggle, +} from '../handlers/localstorage/accountLocal'; + +// -- Constants ------------------------------------------------------------- // +const OPEN_STATE_SETTINGS_LOAD_SUCCESS = + 'openStateSettings/OPEN_STATE_SETTINGS_LOAD_SUCCESS'; +const OPEN_STATE_SETTINGS_LOAD_FAILURE = + 'openStateSettings/OPEN_STATE_SETTINGS_LOAD_FAILURE'; +const CLEAR_OPEN_STATE_SETTINGS = 'openStateSettings/CLEAR_OPEN_STATE_SETTINGS'; +const PUSH_OPEN_FAMILY_TAB = 'openStateSettings/PUSH_OPEN_FAMILY_TAB'; +const SET_OPEN_FAMILY_TABS = 'openStateSettings/SET_OPEN_FAMILY_TABS'; +const SET_OPEN_SMALL_BALANCES = 'openStateSettings/SET_OPEN_SMALL_BALANCES'; +const SET_OPEN_INVESTMENT_CARDS = 'openStateSettings/SET_OPEN_INVESTMENT_CARDS'; +const PUSH_OPEN_INVESTMENT_CARD = 'openStateSettings/PUSH_OPEN_INVESTMENT_CARD'; + +// -- Actions --------------------------------------------------------------- // +export const openStateSettingsLoadState = () => async (dispatch, getState) => { + try { + const { accountAddress, network } = getState().settings; + const openSmallBalances = await getSmallBalanceToggle( + accountAddress, + network + ); + const openInvestmentCards = await getOpenInvestmentCards( + accountAddress, + network + ); + const openFamilyTabs = await getOpenFamilies(accountAddress, network); + dispatch({ + payload: { + openFamilyTabs, + openInvestmentCards, + openSmallBalances, + }, + type: OPEN_STATE_SETTINGS_LOAD_SUCCESS, + }); + } catch (error) { + dispatch({ type: OPEN_STATE_SETTINGS_LOAD_FAILURE }); + } +}; + +export const setOpenSmallBalances = payload => (dispatch, getState) => { + const { accountAddress, network } = getState().settings; + saveSmallBalanceToggle(payload, accountAddress, network); + dispatch({ + payload, + type: SET_OPEN_SMALL_BALANCES, + }); +}; + +export const pushOpenFamilyTab = payload => dispatch => + dispatch({ + payload, + type: PUSH_OPEN_FAMILY_TAB, + }); + +export const setOpenFamilyTabs = payload => (dispatch, getState) => { + const { accountAddress, network } = getState().settings; + const { openFamilyTabs } = getState().openStateSettings; + const updatedFamilyTabs = { + ...openFamilyTabs, + [payload.index]: payload.state, + }; + saveOpenFamilies(updatedFamilyTabs, accountAddress, network); + dispatch({ + payload: updatedFamilyTabs, + type: SET_OPEN_FAMILY_TABS, + }); +}; + +export const setOpenInvestmentCards = payload => (dispatch, getState) => { + const { accountAddress, network } = getState().settings; + const { openInvestmentCards } = getState().openStateSettings; + const updatedOpenInvestmentCards = { + ...openInvestmentCards, + [payload.index]: payload.state, + }; + saveOpenInvestmentCards(updatedOpenInvestmentCards, accountAddress, network); + dispatch({ + payload: updatedOpenInvestmentCards, + type: SET_OPEN_INVESTMENT_CARDS, + }); +}; + +export const pushOpenInvestmentCard = payload => dispatch => + dispatch({ + payload, + type: PUSH_OPEN_INVESTMENT_CARD, + }); + +export const clearOpenStateSettings = () => (dispatch, getState) => { + const { accountAddress, network } = getState().settings; + removeOpenFamilies(accountAddress, network); + removeOpenInvestmentCards(accountAddress, network); + removeSmallBalanceToggle(accountAddress, network); + dispatch({ + type: CLEAR_OPEN_STATE_SETTINGS, + }); +}; + +// -- Reducer --------------------------------------------------------------- // +export const INITIAL_STATE = { + openFamilyTabs: {}, + openInvestmentCards: {}, + openSmallBalances: false, +}; + +export default (state = INITIAL_STATE, action) => + produce(state, draft => { + if (action.type === OPEN_STATE_SETTINGS_LOAD_SUCCESS) { + draft.openFamilyTabs = action.payload.openFamilyTabs; + draft.openInvestmentCards = action.payload.openInvestmentCards; + draft.openSmallBalances = action.payload.openSmallBalances; + } else if (action.type === SET_OPEN_FAMILY_TABS) { + draft.openFamilyTabs = action.payload; + } else if (action.type === PUSH_OPEN_FAMILY_TAB) { + draft.openFamilyTabs = action.payload; + } else if (action.type === SET_OPEN_SMALL_BALANCES) { + draft.openSmallBalances = action.payload; + } else if (action.type === SET_OPEN_INVESTMENT_CARDS) { + draft.openInvestmentCards = action.payload; + } else if (action.type === PUSH_OPEN_INVESTMENT_CARD) { + draft.openInvestmentCards = action.payload; + } else if (action.type === CLEAR_OPEN_STATE_SETTINGS) { + return INITIAL_STATE; + } + }); diff --git a/src/redux/reducers.js b/src/redux/reducers.js index 3d481529cb6..7ae90502b48 100644 --- a/src/redux/reducers.js +++ b/src/redux/reducers.js @@ -1,15 +1,19 @@ import { combineReducers } from 'redux'; import actionSheetManager from './actionSheetManager'; +import contacts from './contacts'; import data from './data'; +import explorer from './explorer'; +import gas from './gas'; import imageDimensionsCache from './imageDimensionsCache'; import isWalletEmpty from './isWalletEmpty'; import isWalletEthZero from './isWalletEthZero'; -import isWalletImporting from './isWalletImporting'; +import keyboardHeight from './keyboardHeight'; import navigation from './navigation'; import nonce from './nonce'; -import openFamilyTabs from './openFamilyTabs'; +import openStateSettings from './openStateSettings'; import requests from './requests'; +import selectedInput from './selectedInput'; import selectedWithFab from './selectedWithFab'; import send from './send'; import settings from './settings'; @@ -19,15 +23,19 @@ import walletconnect from './walletconnect'; export default combineReducers({ actionSheetManager, + contacts, data, + explorer, + gas, imageDimensionsCache, isWalletEmpty, isWalletEthZero, - isWalletImporting, + keyboardHeight, navigation, nonce, - openFamilyTabs, + openStateSettings, requests, + selectedInput, selectedWithFab, send, settings, diff --git a/src/redux/requests.js b/src/redux/requests.js index aa64ccae383..7bc6989ae59 100644 --- a/src/redux/requests.js +++ b/src/redux/requests.js @@ -1,28 +1,15 @@ -import { convertHexToUtf8 } from '@walletconnect/utils'; -import BigNumber from 'bignumber.js'; -import { - filter, - get, - omit, - values, -} from 'lodash'; +import { filter, get, omit, values } from 'lodash'; import { getLocalRequests, removeLocalRequest, removeLocalRequests, saveLocalRequests, -} from '../handlers/commonStorage'; -import { - convertAmountAndPriceToNativeDisplay, - convertHexToString, - convertRawAmountToDecimalFormat, - fromWei, -} from '../helpers/utilities'; -import smartContractMethods from '../references/smartcontract-methods.json'; -import { ethereumUtils } from '../utils'; +} from '../handlers/localstorage/walletconnect'; +import { getRequestDisplayDetails } from '../parsers/requests'; // -- Constants --------------------------------------- // -const REQUESTS_UPDATE_REQUESTS_TO_APPROVE = 'requests/REQUESTS_UPDATE_REQUESTS_TO_APPROVE'; +const REQUESTS_UPDATE_REQUESTS_TO_APPROVE = + 'requests/REQUESTS_UPDATE_REQUESTS_TO_APPROVE'; const REQUESTS_CLEAR_STATE = 'requests/REQUESTS_CLEAR_STATE'; export const requestsLoadState = () => async (dispatch, getState) => { @@ -31,124 +18,25 @@ export const requestsLoadState = () => async (dispatch, getState) => { const requests = await getLocalRequests(accountAddress, network); const _requests = requests || {}; dispatch({ payload: _requests, type: REQUESTS_UPDATE_REQUESTS_TO_APPROVE }); - } catch (error) { - } -}; - -const getTimestampFromPayload = payload => parseInt(payload.id.toString().slice(0, -3), 10); - -const getRequestDisplayDetails = (payload, assets, nativeCurrency) => { - const timestampInMs = getTimestampFromPayload(payload); - if (payload.method === 'eth_sendTransaction') { - const transaction = get(payload, 'params[0]', null); - return getTransactionDisplayDetails( - transaction, - assets, - nativeCurrency, - timestampInMs, - ); - } - if (payload.method === 'eth_sign') { - const message = get(payload, 'params[1]'); - return getMessageDisplayDetails(message, timestampInMs); - } - if (payload.method === 'personal_sign') { - let message = ''; - try { - message = convertHexToUtf8(get(payload, 'params[0]')); - } catch (error) { - message = get(payload, 'params[0]'); - } - return getMessageDisplayDetails(message, timestampInMs, 'messagePersonal'); - } - if (payload.method === 'eth_signTypedData' - || payload.method === 'eth_signTypedData_v3') { - const request = get(payload, 'params[1]', null); - const jsonRequest = JSON.stringify(request.message); - return getMessageDisplayDetails(jsonRequest, timestampInMs); - } - return {}; + // eslint-disable-next-line no-empty + } catch (error) {} }; -const getMessageDisplayDetails = (message, timestampInMs, type = 'message') => ({ - payload: message, - timestampInMs, - type, -}); - -const getTransactionDisplayDetails = (transaction, assets, nativeCurrency, timestampInMs) => { - const tokenTransferHash = smartContractMethods.token_transfer.hash; - if (transaction.data === '0x') { - const value = fromWei(convertHexToString(transaction.value)); - const asset = ethereumUtils.getAsset(assets); - const priceUnit = get(asset, 'price.value', 0); - const { amount, display } = convertAmountAndPriceToNativeDisplay(value, priceUnit, nativeCurrency); - return { - payload: { - asset, - from: transaction.from, - gasLimit: BigNumber(convertHexToString(transaction.gasLimit)), - gasPrice: BigNumber(convertHexToString(transaction.gasPrice)), - nativeAmount: amount, - nativeAmountDisplay: display, - nonce: Number(convertHexToString(transaction.nonce)), - to: transaction.to, - value, - }, - timestampInMs, - type: 'transaction', - }; - } - if (transaction.data.startsWith(tokenTransferHash)) { - const contractAddress = transaction.to; - const asset = ethereumUtils.getAsset(assets, contractAddress); - const dataPayload = transaction.data.replace(tokenTransferHash, ''); - const toAddress = `0x${dataPayload.slice(0, 64).replace(/^0+/, '')}`; - const amount = `0x${dataPayload.slice(64, 128).replace(/^0+/, '')}`; - const value = convertRawAmountToDecimalFormat(convertHexToString(amount), asset.decimals); - const priceUnit = get(asset, 'price.value', 0); - const native = convertAmountAndPriceToNativeDisplay(value, priceUnit, nativeCurrency); - return { - payload: { - asset, - from: transaction.from, - gasLimit: BigNumber(convertHexToString(transaction.gasLimit)), - gasPrice: BigNumber(convertHexToString(transaction.gasPrice)), - nativeAmount: native.amount, - nativeAmountDisplay: native.display, - nonce: Number(convertHexToString(transaction.nonce)), - to: toAddress, - value, - }, - timestampInMs, - type: 'transaction', - }; - } - if (transaction.data) { - const value = transaction.value ? fromWei(convertHexToString(transaction.value)) : 0; - return { - payload: { - data: transaction.data, - from: transaction.from, - gasLimit: BigNumber(convertHexToString(transaction.gasLimit)), - gasPrice: BigNumber(convertHexToString(transaction.gasPrice)), - nonce: Number(convertHexToString(transaction.nonce)), - to: transaction.to, - value, - }, - timestampInMs, - type: 'default', - }; - } - - return null; -}; - -export const addRequestToApprove = (clientId, peerId, requestId, payload, peerMeta) => (dispatch, getState) => { +export const addRequestToApprove = ( + clientId, + peerId, + requestId, + payload, + peerMeta +) => (dispatch, getState) => { const { requests } = getState().requests; const { accountAddress, network, nativeCurrency } = getState().settings; const { assets } = getState().data; - const displayDetails = getRequestDisplayDetails(payload, assets, nativeCurrency); + const displayDetails = getRequestDisplayDetails( + payload, + assets, + nativeCurrency + ); const dappName = peerMeta.name; const imageUrl = get(peerMeta, 'icons[0]'); const request = { @@ -165,11 +53,11 @@ export const addRequestToApprove = (clientId, peerId, requestId, payload, peerMe payload: updatedRequests, type: REQUESTS_UPDATE_REQUESTS_TO_APPROVE, }); - saveLocalRequests(accountAddress, network, updatedRequests); + saveLocalRequests(updatedRequests, accountAddress, network); return request; }; -export const requestsForTopic = (topic) => (dispatch, getState) => { +export const requestsForTopic = topic => (dispatch, getState) => { const { requests } = getState().requests; return filter(values(requests), { clientId: topic }); }; @@ -180,7 +68,7 @@ export const requestsClearState = () => (dispatch, getState) => { dispatch({ type: REQUESTS_CLEAR_STATE }); }; -export const removeRequest = (requestId) => (dispatch, getState) => { +export const removeRequest = requestId => (dispatch, getState) => { const { accountAddress, network } = getState().settings; const { requests } = getState().requests; const updatedRequests = omit(requests, [requestId]); @@ -198,17 +86,17 @@ const INITIAL_STATE = { export default (state = INITIAL_STATE, action) => { switch (action.type) { - case REQUESTS_UPDATE_REQUESTS_TO_APPROVE: - return { - ...state, - requests: action.payload, - }; - case REQUESTS_CLEAR_STATE: - return { - ...state, - ...INITIAL_STATE, - }; - default: - return state; + case REQUESTS_UPDATE_REQUESTS_TO_APPROVE: + return { + ...state, + requests: action.payload, + }; + case REQUESTS_CLEAR_STATE: + return { + ...state, + ...INITIAL_STATE, + }; + default: + return state; } }; diff --git a/src/redux/selectedInput.js b/src/redux/selectedInput.js new file mode 100644 index 00000000000..821d17ecc68 --- /dev/null +++ b/src/redux/selectedInput.js @@ -0,0 +1,23 @@ +import produce from 'immer'; + +// -- Constants --------------------------------------- // +const SET_SELECTED_INPUT_ID = 'selectedInput/SET_SELECTED_INPUT_ID'; + +export const setSelectedInputId = payload => dispatch => { + dispatch({ + payload, + type: SET_SELECTED_INPUT_ID, + }); +}; + +// -- Reducer ----------------------------------------- // +const INITIAL_STATE = { + selectedInputId: null, +}; + +export default (state = INITIAL_STATE, action) => + produce(state, draft => { + if (action.type === SET_SELECTED_INPUT_ID) { + draft.selectedInputId = action.payload; + } + }); diff --git a/src/redux/selectedWithFab.js b/src/redux/selectedWithFab.js index dfd00cd3554..452227377bc 100644 --- a/src/redux/selectedWithFab.js +++ b/src/redux/selectedWithFab.js @@ -5,20 +5,23 @@ const UPDATE_ACTION_TYPE = 'selected/UPDATE_ACTION_TYPE'; const UPDATE_SELECTED_ID = 'selected/UPDATE_SELECTED_ID'; const UPDATE_VELOCITY = 'selected/UPDATE_VELOCITY'; -export const setActionType = actionType => dispatch => dispatch({ - actionType, - type: UPDATE_ACTION_TYPE, -}); +export const setActionType = actionType => dispatch => + dispatch({ + actionType, + type: UPDATE_ACTION_TYPE, + }); -export const setScrollingVelocity = scrollingVelocity => dispatch => dispatch({ - scrollingVelocity, - type: UPDATE_VELOCITY, -}); +export const setScrollingVelocity = scrollingVelocity => dispatch => + dispatch({ + scrollingVelocity, + type: UPDATE_VELOCITY, + }); -export const updateSelectedID = selectedId => dispatch => dispatch({ - selectedId, - type: UPDATE_SELECTED_ID, -}); +export const updateSelectedID = selectedId => dispatch => + dispatch({ + selectedId, + type: UPDATE_SELECTED_ID, + }); // -- Reducer ----------------------------------------- // const INITIAL_STATE = { @@ -27,20 +30,19 @@ const INITIAL_STATE = { selectedId: -1, }; -export default (state = INITIAL_STATE, action) => ( +export default (state = INITIAL_STATE, action) => produce(state, draft => { switch (action.type) { - case UPDATE_ACTION_TYPE: - draft.actionType = action.actionType; - break; - case UPDATE_SELECTED_ID: - draft.selectedId = action.selectedId; - break; - case UPDATE_VELOCITY: - draft.scrollingVelocity = action.scrollingVelocity; - break; - default: - break; + case UPDATE_ACTION_TYPE: + draft.actionType = action.actionType; + break; + case UPDATE_SELECTED_ID: + draft.selectedId = action.selectedId; + break; + case UPDATE_VELOCITY: + draft.scrollingVelocity = action.scrollingVelocity; + break; + default: + break; } - }) -); + }); diff --git a/src/redux/send.js b/src/redux/send.js index b6a5e74755b..6e534552e83 100644 --- a/src/redux/send.js +++ b/src/redux/send.js @@ -1,35 +1,16 @@ import { get, isEmpty } from 'lodash'; -import { apiGetGasPrices } from '../handlers/api'; -import ethUnits from '../references/ethereum-units.json'; -import { dataAddNewTransaction } from './data'; -import { ethereumUtils } from '../utils'; import { convertAmountAndPriceToNativeDisplay, convertAmountFromNativeValue, - convertNumberToString, formatInputDecimals, - fromWei, - greaterThan, - subtract, } from '../helpers/utilities'; -import { - parseGasPrices, - parseGasPricesTxFee, -} from '../parsers/gas'; -import { - createSignableTransaction, - estimateGasLimit, -} from '../handlers/web3'; +import { createSignableTransaction } from '../handlers/web3'; +import { ethereumUtils } from '../utils'; +import { dataAddNewTransaction } from './data'; // -- Constants ------------------------------------------------------------- // -const SEND_GET_GAS_PRICES_REQUEST = 'send/SEND_GET_GAS_PRICES_REQUEST'; -const SEND_GET_GAS_PRICES_SUCCESS = 'send/SEND_GET_GAS_PRICES_SUCCESS'; -const SEND_GET_GAS_PRICES_FAILURE = 'send/SEND_GET_GAS_PRICES_FAILURE'; - -const SEND_UPDATE_GAS_PRICE_REQUEST = 'send/SEND_UPDATE_GAS_PRICE_REQUEST'; -const SEND_UPDATE_GAS_PRICE_SUCCESS = 'send/SEND_UPDATE_GAS_PRICE_SUCCESS'; -const SEND_UPDATE_GAS_PRICE_FAILURE = 'send/SEND_UPDATE_GAS_PRICE_FAILURE'; +const SEND_MODAL_INIT = 'send/SEND_MODAL_INIT'; const SEND_TRANSACTION_REQUEST = 'send/SEND_TRANSACTION_REQUEST'; const SEND_TRANSACTION_SUCCESS = 'send/SEND_TRANSACTION_SUCCESS'; @@ -46,175 +27,81 @@ const SEND_UPDATE_NFT_SELECTED = 'send/SEND_UPDATE_NFT_SELECTED'; const SEND_CLEAR_FIELDS = 'send/SEND_CLEAR_FIELDS'; -function getBalanceAmount(assets, gasPrice, selected) { - let amount = ''; - - if (selected.address === 'eth') { - const balanceAmount = get(selected, 'balance.amount', 0); - const txFeeRaw = get(gasPrice, 'txFee.value.amount'); - const txFeeAmount = fromWei(txFeeRaw); - const remaining = subtract(balanceAmount, txFeeAmount); - amount = convertNumberToString(greaterThan(remaining, 0) ? remaining : 0); - } else { - amount = get(selected, 'balance.amount', 0); - } - - return amount; -} - // -- Actions --------------------------------------------------------------- // -const getEthPriceUnit = (assets) => { - const ethAsset = ethereumUtils.getAsset(assets); - return get(ethAsset, 'price.value', 0); -}; export const sendModalInit = (options = {}) => (dispatch, getState) => { - const { accountAddress, nativeCurrency } = getState().settings; + const { accountAddress } = getState().settings; const { assets } = getState().data; - const { gasLimit } = getState().send; - const ethPriceUnit = getEthPriceUnit(assets); - - const fallbackGasPrices = parseGasPrices(null, ethPriceUnit, gasLimit, nativeCurrency, options.gasFormat === 'short'); - const selected = assets.filter(asset => asset.address === options.defaultAsset)[0] || {}; - + const selected = + assets.filter(asset => asset.address === options.defaultAsset)[0] || {}; dispatch({ payload: { address: accountAddress, - gasPrices: fallbackGasPrices, selected, }, - type: SEND_GET_GAS_PRICES_REQUEST, + type: SEND_MODAL_INIT, }); - - apiGetGasPrices() - .then(({ data }) => { - const gasPrices = parseGasPrices(data, ethPriceUnit, gasLimit, nativeCurrency, options.gasFormat === 'short'); - dispatch({ - payload: gasPrices, - type: SEND_GET_GAS_PRICES_SUCCESS, - }); - }) - .catch(error => { - console.error(error); - - dispatch({ - payload: fallbackGasPrices, - type: SEND_GET_GAS_PRICES_FAILURE, - }); - }); }; -export const sendUpdateGasPrice = newGasPriceOption => (dispatch, getState) => { - const { - selected, - address, - recipient, - assetAmount, - gasPrice, - gasPrices: existingGasPrices, - gasPriceOption, - fetchingGasPrices, - } = getState().send; - if (isEmpty(selected)) return; - if (fetchingGasPrices) return; - let gasPrices = existingGasPrices; - if (!Object.keys(gasPrices).length) return; - const _gasPriceOption = newGasPriceOption || gasPriceOption; - let _gasPrice = _gasPriceOption ? gasPrices[_gasPriceOption] : gasPrice; - dispatch({ type: SEND_UPDATE_GAS_PRICE_REQUEST }); - estimateGasLimit({ - address, - amount: assetAmount, - asset: selected, - recipient, - }) - .then(gasLimit => { - const { assets } = getState().data; - const { nativeCurrency } = getState().settings; - const ethPriceUnit = getEthPriceUnit(assets); - gasPrices = parseGasPricesTxFee(gasPrices, ethPriceUnit, gasLimit, nativeCurrency); - _gasPrice = gasPriceOption ? gasPrices[_gasPriceOption] : gasPrice; - - const ethereum = ethereumUtils.getAsset(assets); - const balanceAmount = get(ethereum, 'balance.amount', 0); - const txFeeAmount = fromWei(get(_gasPrice, 'txFee.value.amount', 0)); - - dispatch({ - payload: { - gasLimit, - gasPrice: _gasPrice, - gasPriceOption: _gasPriceOption, - gasPrices, - isSufficientGas: Number(balanceAmount) > Number(txFeeAmount), - }, - type: SEND_UPDATE_GAS_PRICE_SUCCESS, - }); - }) - .catch(error => { - dispatch({ - payload: { - gasPrice: _gasPrice, - gasPriceOption: _gasPriceOption, - gasPrices, - }, - type: SEND_UPDATE_GAS_PRICE_FAILURE, - }); - }); -}; - -export const sendTransaction = (transactionDetails, signAndSendTransactionCb) => (dispatch, getState) => new Promise((resolve, reject) => { - dispatch({ type: SEND_TRANSACTION_REQUEST }); - const { - address, - recipient, - amount, - asset, - gasPrice, - gasLimit, - } = transactionDetails; - const { accountType } = getState().settings; - const txDetails = { - amount, - asset, - from: address, - gasLimit, - gasPrice: gasPrice.value.amount, - nonce: null, - to: recipient, - }; - return createSignableTransaction(txDetails) - .then(signableTransactionDetails => { - signAndSendTransactionCb({ - accountType, - transaction: signableTransactionDetails, - }) - .then((txHash) => { - if (!isEmpty(txHash)) { - txDetails.hash = txHash; - dispatch(dataAddNewTransaction(txDetails)) - .then(success => { - dispatch({ - payload: txHash, - type: SEND_TRANSACTION_SUCCESS, +export const sendTransaction = ( + transactionDetails, + signAndSendTransactionCb +) => (dispatch, getState) => + new Promise((resolve, reject) => { + dispatch({ type: SEND_TRANSACTION_REQUEST }); + const { + address, + recipient, + amount, + asset, + gasPrice, + gasLimit, + } = transactionDetails; + const { accountType } = getState().settings; + const txDetails = { + amount, + asset, + from: address, + gasLimit, + gasPrice: gasPrice.value.amount, + nonce: null, + to: recipient, + }; + return createSignableTransaction(txDetails) + .then(signableTransactionDetails => { + signAndSendTransactionCb({ + accountType, + transaction: signableTransactionDetails, + }) + .then(txHash => { + if (!isEmpty(txHash)) { + txDetails.hash = txHash; + dispatch(dataAddNewTransaction(txDetails)) + .then(() => { + dispatch({ + payload: txHash, + type: SEND_TRANSACTION_SUCCESS, + }); + resolve(txHash); + }) + .catch(error => { + reject(error); }); - resolve(txHash); - }).catch(error => { - reject(error); - }); - } else { + } else { + dispatch({ type: SEND_TRANSACTION_FAILURE }); + reject(new Error('No transaction hash.')); + } + }) + .catch(error => { dispatch({ type: SEND_TRANSACTION_FAILURE }); - reject(new Error('No transaction hash.')); - } - }).catch(error => { - dispatch({ type: SEND_TRANSACTION_FAILURE }); - reject(error); - }); - }) - .catch(error => { - dispatch({ type: SEND_TRANSACTION_FAILURE }); - reject(error); - }); -}); + reject(error); + }); + }) + .catch(error => { + dispatch({ type: SEND_TRANSACTION_FAILURE }); + reject(error); + }); + }); export const sendToggleConfirmationView = boolean => (dispatch, getState) => { let confirm = boolean; @@ -227,18 +114,16 @@ export const sendToggleConfirmationView = boolean => (dispatch, getState) => { }); }; -export const sendUpdateRecipient = recipient => dispatch => { - const input = recipient.replace(/[^\w.]/g, ''); +export const sendUpdateRecipient = recipient => dispatch => dispatch({ - payload: input, + payload: recipient, type: SEND_UPDATE_RECIPIENT, }); -}; export const sendUpdateAssetAmount = assetAmount => (dispatch, getState) => { - const { assets } = getState().data; const { nativeCurrency } = getState().settings; - const { gasPrice, selected } = getState().send; + const { selected } = getState().send; + const { selectedGasPrice } = getState().gas; const _assetAmount = assetAmount.replace(/[^0-9.]/g, ''); let _nativeAmount = ''; if (_assetAmount.length) { @@ -246,11 +131,14 @@ export const sendUpdateAssetAmount = assetAmount => (dispatch, getState) => { const { amount: nativeAmount } = convertAmountAndPriceToNativeDisplay( _assetAmount, priceUnit, - nativeCurrency, + nativeCurrency ); _nativeAmount = formatInputDecimals(nativeAmount, _assetAmount); } - const balanceAmount = getBalanceAmount(assets, gasPrice, selected); + const balanceAmount = ethereumUtils.getBalanceAmount( + selectedGasPrice, + selected + ); dispatch({ payload: { assetAmount: _assetAmount, @@ -262,21 +150,24 @@ export const sendUpdateAssetAmount = assetAmount => (dispatch, getState) => { }; export const sendUpdateNativeAmount = nativeAmount => (dispatch, getState) => { - const { assets } = getState().data; - const { gasPrice, selected } = getState().send; + const { selected } = getState().send; + const { selectedGasPrice } = getState().gas; const _nativeAmount = nativeAmount.replace(/[^0-9.]/g, ''); let _assetAmount = ''; if (_nativeAmount.length) { const priceUnit = get(selected, 'price.value', 0); const assetAmount = convertAmountFromNativeValue( _nativeAmount, - selected, priceUnit, + selected.decimals ); _assetAmount = formatInputDecimals(assetAmount, _nativeAmount); } - const balanceAmount = getBalanceAmount(assets, gasPrice, selected); + const balanceAmount = ethereumUtils.getBalanceAmount( + selectedGasPrice, + selected + ); dispatch({ payload: { @@ -288,7 +179,7 @@ export const sendUpdateNativeAmount = nativeAmount => (dispatch, getState) => { }); }; -export const sendUpdateSelected = (asset) => (dispatch, getState) => { +export const sendUpdateSelected = asset => (dispatch, getState) => { if (get(asset, 'isNft')) { dispatch({ payload: { @@ -299,7 +190,6 @@ export const sendUpdateSelected = (asset) => (dispatch, getState) => { }, type: SEND_UPDATE_NFT_SELECTED, }); - dispatch(sendUpdateGasPrice()); } else { const state = getState(); const assetAmount = get(state, 'send.assetAmount'); @@ -308,17 +198,17 @@ export const sendUpdateSelected = (asset) => (dispatch, getState) => { type: SEND_UPDATE_SELECTED, }); dispatch(sendUpdateAssetAmount(assetAmount)); - dispatch(sendUpdateGasPrice()); } }; export const sendMaxBalance = () => (dispatch, getState) => { - const { gasPrice, selected } = getState().send; - const { assets } = getState().data; - const balanceAmount = getBalanceAmount(assets, gasPrice, selected); - + const { selected } = getState().send; + const { selectedGasPrice } = getState().gas; + const balanceAmount = ethereumUtils.getBalanceAmount( + selectedGasPrice, + selected + ); dispatch(sendUpdateAssetAmount(balanceAmount)); - dispatch(sendUpdateGasPrice()); }; export const sendClearFields = () => ({ type: SEND_CLEAR_FIELDS }); @@ -329,13 +219,7 @@ const INITIAL_STATE = { assetAmount: '', confirm: false, fetching: false, - fetchingGasPrices: false, - gasLimit: ethUnits.basic_tx, - gasPrice: {}, - gasPriceOption: 'average', - gasPrices: {}, isSufficientBalance: false, - isSufficientGas: false, nativeAmount: '', recipient: '', selected: {}, @@ -344,93 +228,51 @@ const INITIAL_STATE = { export default (state = INITIAL_STATE, action) => { switch (action.type) { - case SEND_GET_GAS_PRICES_REQUEST: - return { - ...state, - address: action.payload.address, - fetchingGasPrices: true, - gasPrice: action.payload.gasPrices.average, - gasPriceOption: action.payload.gasPrices.average.option, - gasPrices: action.payload.gasPrices, - selected: action.payload.selected, - }; - case SEND_GET_GAS_PRICES_SUCCESS: - return { - ...state, - fetchingGasPrices: false, - gasPrice: action.payload.average, - gasPriceOption: action.payload.average.option, - gasPrices: action.payload, - }; - case SEND_GET_GAS_PRICES_FAILURE: - return { - ...state, - fetchingGasPrices: false, - gasPrice: action.payload.average, - gasPriceOption: action.payload.average.option, - gasPrices: action.payload, - }; - case SEND_UPDATE_GAS_PRICE_REQUEST: - return { ...state, fetchingGasPrices: true }; - case SEND_UPDATE_GAS_PRICE_SUCCESS: - return { - ...state, - fetchingGasPrices: false, - gasLimit: action.payload.gasLimit, - gasPrice: action.payload.gasPrice, - gasPriceOption: action.payload.gasPriceOption, - gasPrices: action.payload.gasPrices, - isSufficientGas: action.payload.isSufficientGas, - }; - - case SEND_UPDATE_GAS_PRICE_FAILURE: - return { - ...state, - fetchingGasPrices: false, - gasPrice: action.payload.gasPrice, - gasPriceOption: action.payload.gasPriceOption, - gasPrices: action.payload.gasPrices, - }; - case SEND_TRANSACTION_REQUEST: - return { ...state, fetching: true }; - case SEND_TRANSACTION_SUCCESS: - return { - ...state, - fetching: false, - gasPrices: {}, - txHash: action.payload, - }; - case SEND_TRANSACTION_FAILURE: - return { - ...state, - confirm: false, - fetching: false, - txHash: '', - }; - case SEND_TOGGLE_CONFIRMATION_VIEW: - return { ...state, confirm: action.payload }; - case SEND_UPDATE_RECIPIENT: - return { ...state, recipient: action.payload }; - case SEND_UPDATE_NATIVE_AMOUNT: - case SEND_UPDATE_ASSET_AMOUNT: - return { - ...state, - assetAmount: action.payload.assetAmount, - isSufficientBalance: action.payload.isSufficientBalance, - nativeAmount: action.payload.nativeAmount, - }; - case SEND_UPDATE_SELECTED: - return { ...state, selected: action.payload }; - case SEND_UPDATE_NFT_SELECTED: - return { - ...state, - assetAmount: '1', - isSufficientBalance: true, - selected: action.payload.selected, - }; - case SEND_CLEAR_FIELDS: - return { ...state, ...INITIAL_STATE }; - default: - return state; + case SEND_MODAL_INIT: + return { + ...state, + address: action.payload.address, + selected: action.payload.selected, + }; + case SEND_TRANSACTION_REQUEST: + return { ...state, fetching: true }; + case SEND_TRANSACTION_SUCCESS: + return { + ...state, + fetching: false, + txHash: action.payload, + }; + case SEND_TRANSACTION_FAILURE: + return { + ...state, + confirm: false, + fetching: false, + txHash: '', + }; + case SEND_TOGGLE_CONFIRMATION_VIEW: + return { ...state, confirm: action.payload }; + case SEND_UPDATE_RECIPIENT: + return { ...state, recipient: action.payload }; + case SEND_UPDATE_NATIVE_AMOUNT: + case SEND_UPDATE_ASSET_AMOUNT: + return { + ...state, + assetAmount: action.payload.assetAmount, + isSufficientBalance: action.payload.isSufficientBalance, + nativeAmount: action.payload.nativeAmount, + }; + case SEND_UPDATE_SELECTED: + return { ...state, selected: action.payload }; + case SEND_UPDATE_NFT_SELECTED: + return { + ...state, + assetAmount: '1', + isSufficientBalance: true, + selected: action.payload.selected, + }; + case SEND_CLEAR_FIELDS: + return { ...state, ...INITIAL_STATE }; + default: + return state; } }; diff --git a/src/redux/settings.js b/src/redux/settings.js index 4e23a125985..57c048a3f19 100644 --- a/src/redux/settings.js +++ b/src/redux/settings.js @@ -4,21 +4,27 @@ import { getNativeCurrency, saveLanguage, saveNativeCurrency, -} from '../handlers/commonStorage'; -import { dataClearState, dataInit } from './data'; +} from '../handlers/localstorage/globalSettings'; +import { dataClearState } from './data'; +import { explorerInit } from './explorer'; import { ethereumUtils } from '../utils'; import { web3SetHttpProvider } from '../handlers/web3'; // -- Constants ------------------------------------------------------------- // const SETTINGS_UPDATE_NETWORK = 'settings/SETTINGS_UPDATE_NETWORK'; const SETTINGS_UPDATE_CHAIN_ID = 'settings/SETTINGS_UPDATE_CHAIN_ID'; -const SETTINGS_UPDATE_SETTINGS_ADDRESS = 'settings/SETTINGS_UPDATE_SETTINGS_ADDRESS'; +const SETTINGS_UPDATE_SETTINGS_ADDRESS = + 'settings/SETTINGS_UPDATE_SETTINGS_ADDRESS'; -const SETTINGS_UPDATE_NATIVE_CURRENCY_SUCCESS = 'settings/SETTINGS_UPDATE_NATIVE_CURRENCY_SUCCESS'; -const SETTINGS_UPDATE_NATIVE_CURRENCY_FAILURE = 'settings/SETTINGS_UPDATE_NATIVE_CURRENCY_FAILURE'; +const SETTINGS_UPDATE_NATIVE_CURRENCY_SUCCESS = + 'settings/SETTINGS_UPDATE_NATIVE_CURRENCY_SUCCESS'; +const SETTINGS_UPDATE_NATIVE_CURRENCY_FAILURE = + 'settings/SETTINGS_UPDATE_NATIVE_CURRENCY_FAILURE'; -const SETTINGS_UPDATE_LANGUAGE_SUCCESS = 'settings/SETTINGS_UPDATE_LANGUAGE_SUCCESS'; -const SETTINGS_UPDATE_LANGUAGE_FAILURE = 'settings/SETTINGS_UPDATE_LANGUAGE_FAILURE'; +const SETTINGS_UPDATE_LANGUAGE_SUCCESS = + 'settings/SETTINGS_UPDATE_LANGUAGE_SUCCESS'; +const SETTINGS_UPDATE_LANGUAGE_FAILURE = + 'settings/SETTINGS_UPDATE_LANGUAGE_FAILURE'; // -- Actions --------------------------------------------------------------- // export const settingsLoadState = () => async dispatch => { @@ -42,15 +48,11 @@ export const settingsLoadState = () => async dispatch => { } }; -export const settingsUpdateAccountAddress = (accountAddress, accountType) => ( - dispatch, - getState, -) => { +export const settingsUpdateAccountAddress = accountAddress => dispatch => dispatch({ - payload: { accountAddress, accountType }, + payload: accountAddress, type: SETTINGS_UPDATE_SETTINGS_ADDRESS, }); -}; export const settingsUpdateNetwork = network => dispatch => { const chainId = ethereumUtils.getChainIdFromNetwork(network); @@ -72,39 +74,40 @@ export const settingsUpdateChainId = chainId => dispatch => { export const settingsChangeLanguage = language => dispatch => { updateLanguage(language); - saveLanguage(language).then(() => { - dispatch({ - payload: language, - type: SETTINGS_UPDATE_LANGUAGE_SUCCESS, - }); - }).catch(error => { - dispatch({ - type: SETTINGS_UPDATE_LANGUAGE_FAILURE, - }); - }); + saveLanguage(language) + .then(() => + dispatch({ + payload: language, + type: SETTINGS_UPDATE_LANGUAGE_SUCCESS, + }) + ) + .catch(() => + dispatch({ + type: SETTINGS_UPDATE_LANGUAGE_FAILURE, + }) + ); }; -export const settingsChangeNativeCurrency = nativeCurrency => ( - dispatch, -) => { +export const settingsChangeNativeCurrency = nativeCurrency => dispatch => { dispatch(dataClearState()); - saveNativeCurrency(nativeCurrency).then(() => { - dispatch({ - payload: nativeCurrency, - type: SETTINGS_UPDATE_NATIVE_CURRENCY_SUCCESS, + saveNativeCurrency(nativeCurrency) + .then(() => { + dispatch({ + payload: nativeCurrency, + type: SETTINGS_UPDATE_NATIVE_CURRENCY_SUCCESS, + }); + dispatch(explorerInit()); + }) + .catch(() => { + dispatch({ + type: SETTINGS_UPDATE_NATIVE_CURRENCY_FAILURE, + }); }); - dispatch(dataInit()); - }).catch(error => { - dispatch({ - type: SETTINGS_UPDATE_NATIVE_CURRENCY_FAILURE, - }); - }); }; // -- Reducer --------------------------------------------------------------- // export const INITIAL_STATE = { accountAddress: '', - accountType: '', chainId: 1, language: 'en', nativeCurrency: 'USD', @@ -113,43 +116,42 @@ export const INITIAL_STATE = { export default (state = INITIAL_STATE, action) => { switch (action.type) { - case SETTINGS_UPDATE_SETTINGS_ADDRESS: - return { - ...state, - accountAddress: action.payload.accountAddress, - accountType: action.payload.accountType, - }; - case SETTINGS_UPDATE_NATIVE_CURRENCY_SUCCESS: - return { - ...state, - nativeCurrency: action.payload, - }; - case SETTINGS_UPDATE_NATIVE_CURRENCY_FAILURE: - return { - ...state, - }; - case SETTINGS_UPDATE_NETWORK: - return { - ...state, - chainId: action.payload.chainId, - network: action.payload.network, - }; - case SETTINGS_UPDATE_CHAIN_ID: - return { - ...state, - chainId: action.payload.chainId, - network: action.payload.network, - }; - case SETTINGS_UPDATE_LANGUAGE_SUCCESS: - return { - ...state, - language: action.payload, - }; - case SETTINGS_UPDATE_LANGUAGE_FAILURE: - return { - ...state, - }; - default: - return state; + case SETTINGS_UPDATE_SETTINGS_ADDRESS: + return { + ...state, + accountAddress: action.payload, + }; + case SETTINGS_UPDATE_NATIVE_CURRENCY_SUCCESS: + return { + ...state, + nativeCurrency: action.payload, + }; + case SETTINGS_UPDATE_NATIVE_CURRENCY_FAILURE: + return { + ...state, + }; + case SETTINGS_UPDATE_NETWORK: + return { + ...state, + chainId: action.payload.chainId, + network: action.payload.network, + }; + case SETTINGS_UPDATE_CHAIN_ID: + return { + ...state, + chainId: action.payload.chainId, + network: action.payload.network, + }; + case SETTINGS_UPDATE_LANGUAGE_SUCCESS: + return { + ...state, + language: action.payload, + }; + case SETTINGS_UPDATE_LANGUAGE_FAILURE: + return { + ...state, + }; + default: + return state; } }; diff --git a/src/redux/store.js b/src/redux/store.js index a96c757ec91..b333227d69d 100644 --- a/src/redux/store.js +++ b/src/redux/store.js @@ -6,5 +6,5 @@ import reducers from './reducers'; export default createStore( reducers, - composeWithDevTools(applyMiddleware(thunk)), + composeWithDevTools(applyMiddleware(thunk)) ); diff --git a/src/redux/uniqueTokens.js b/src/redux/uniqueTokens.js index f50ec77b42b..5251a105aa3 100644 --- a/src/redux/uniqueTokens.js +++ b/src/redux/uniqueTokens.js @@ -1,21 +1,28 @@ +import { captureException } from '@sentry/react-native'; import { without } from 'lodash'; import { apiGetAccountUniqueTokens } from '../handlers/opensea-api'; import { getUniqueTokens, saveUniqueTokens, removeUniqueTokens, -} from '../handlers/commonStorage'; -import { dedupeAssetsWithFamilies } from './data'; -import { getFamilies } from '../parsers/uniqueTokens'; +} from '../handlers/localstorage/accountLocal'; +import { dedupeAssetsWithFamilies, getFamilies } from '../parsers/uniqueTokens'; +import { dataUpdateAssets } from './data'; // -- Constants ------------------------------------------------------------- // -const UNIQUE_TOKENS_LOAD_UNIQUE_TOKENS_REQUEST = 'uniqueTokens/UNIQUE_TOKENS_LOAD_UNIQUE_TOKENS_REQUEST'; -const UNIQUE_TOKENS_LOAD_UNIQUE_TOKENS_SUCCESS = 'uniqueTokens/UNIQUE_TOKENS_LOAD_UNIQUE_TOKENS_SUCCESS'; -const UNIQUE_TOKENS_LOAD_UNIQUE_TOKENS_FAILURE = 'uniqueTokens/UNIQUE_TOKENS_LOAD_UNIQUE_TOKENS_FAILURE'; +const UNIQUE_TOKENS_LOAD_UNIQUE_TOKENS_REQUEST = + 'uniqueTokens/UNIQUE_TOKENS_LOAD_UNIQUE_TOKENS_REQUEST'; +const UNIQUE_TOKENS_LOAD_UNIQUE_TOKENS_SUCCESS = + 'uniqueTokens/UNIQUE_TOKENS_LOAD_UNIQUE_TOKENS_SUCCESS'; +const UNIQUE_TOKENS_LOAD_UNIQUE_TOKENS_FAILURE = + 'uniqueTokens/UNIQUE_TOKENS_LOAD_UNIQUE_TOKENS_FAILURE'; -const UNIQUE_TOKENS_GET_UNIQUE_TOKENS_REQUEST = 'uniqueTokens/UNIQUE_TOKENS_GET_UNIQUE_TOKENS_REQUEST'; -const UNIQUE_TOKENS_GET_UNIQUE_TOKENS_SUCCESS = 'uniqueTokens/UNIQUE_TOKENS_GET_UNIQUE_TOKENS_SUCCESS'; -const UNIQUE_TOKENS_GET_UNIQUE_TOKENS_FAILURE = 'uniqueTokens/UNIQUE_TOKENS_GET_UNIQUE_TOKENS_FAILURE'; +const UNIQUE_TOKENS_GET_UNIQUE_TOKENS_REQUEST = + 'uniqueTokens/UNIQUE_TOKENS_GET_UNIQUE_TOKENS_REQUEST'; +const UNIQUE_TOKENS_GET_UNIQUE_TOKENS_SUCCESS = + 'uniqueTokens/UNIQUE_TOKENS_GET_UNIQUE_TOKENS_SUCCESS'; +const UNIQUE_TOKENS_GET_UNIQUE_TOKENS_FAILURE = + 'uniqueTokens/UNIQUE_TOKENS_GET_UNIQUE_TOKENS_FAILURE'; const UNIQUE_TOKENS_CLEAR_STATE = 'uniqueTokens/UNIQUE_TOKENS_CLEAR_STATE'; @@ -43,43 +50,52 @@ export const uniqueTokensClearState = () => (dispatch, getState) => { dispatch({ type: UNIQUE_TOKENS_CLEAR_STATE }); }; -export const uniqueTokensRefreshState = () => (dispatch, getState) => ( +export const uniqueTokensRefreshState = () => (dispatch, getState) => new Promise((resolve, reject) => { - const fetchUniqueTokens = () => new Promise((fetchResolve, fetchReject) => { - dispatch({ type: UNIQUE_TOKENS_GET_UNIQUE_TOKENS_REQUEST }); - const { accountAddress, network } = getState().settings; - const { uniqueTokens: existingUniqueTokens } = getState().uniqueTokens; - apiGetAccountUniqueTokens(accountAddress) - .then(uniqueTokens => { - const existingFamilies = getFamilies(existingUniqueTokens); - const newFamilies = getFamilies(uniqueTokens); - const incomingFamilies = without(newFamilies, ...existingFamilies); - if (incomingFamilies.length) { - dispatch(dedupeAssetsWithFamilies(incomingFamilies)); - } - saveUniqueTokens(accountAddress, uniqueTokens, network); - dispatch({ - payload: uniqueTokens, - type: UNIQUE_TOKENS_GET_UNIQUE_TOKENS_SUCCESS, + const fetchUniqueTokens = () => + new Promise((fetchResolve, fetchReject) => { + dispatch({ type: UNIQUE_TOKENS_GET_UNIQUE_TOKENS_REQUEST }); + const { accountAddress, network } = getState().settings; + const { assets } = getState().data; + const { uniqueTokens: existingUniqueTokens } = getState().uniqueTokens; + apiGetAccountUniqueTokens(accountAddress) + .then(uniqueTokens => { + const existingFamilies = getFamilies(existingUniqueTokens); + const newFamilies = getFamilies(uniqueTokens); + const incomingFamilies = without(newFamilies, ...existingFamilies); + if (incomingFamilies.length) { + const dedupedAssets = dedupeAssetsWithFamilies( + assets, + incomingFamilies + ); + dispatch(dataUpdateAssets(dedupedAssets)); + } + saveUniqueTokens(uniqueTokens, accountAddress, network); + dispatch({ + payload: uniqueTokens, + type: UNIQUE_TOKENS_GET_UNIQUE_TOKENS_SUCCESS, + }); + fetchResolve(true); + }) + .catch(error => { + dispatch({ type: UNIQUE_TOKENS_GET_UNIQUE_TOKENS_FAILURE }); + captureException(error); + fetchReject(error); }); - fetchResolve(true); - }).catch(error => { - dispatch({ type: UNIQUE_TOKENS_GET_UNIQUE_TOKENS_FAILURE }); - fetchReject(error); - }); - }); + }); - return fetchUniqueTokens().then(() => { - clearInterval(getUniqueTokensInterval); - getUniqueTokensInterval = setInterval(fetchUniqueTokens, 15000); // 15 secs - resolve(true); - }).catch(error => { - clearInterval(getUniqueTokensInterval); - getUniqueTokensInterval = setInterval(fetchUniqueTokens, 15000); // 15 secs - reject(error); - }); - }) -); + return fetchUniqueTokens() + .then(() => { + clearInterval(getUniqueTokensInterval); + getUniqueTokensInterval = setInterval(fetchUniqueTokens, 15000); // 15 secs + resolve(true); + }) + .catch(error => { + clearInterval(getUniqueTokensInterval); + getUniqueTokensInterval = setInterval(fetchUniqueTokens, 15000); // 15 secs + reject(error); + }); + }); // -- Reducer --------------------------------------------------------------- // export const INITIAL_UNIQUE_TOKENS_STATE = { @@ -90,44 +106,44 @@ export const INITIAL_UNIQUE_TOKENS_STATE = { export default (state = INITIAL_UNIQUE_TOKENS_STATE, action) => { switch (action.type) { - case UNIQUE_TOKENS_LOAD_UNIQUE_TOKENS_REQUEST: - return { - ...state, - loadingUniqueTokens: true, - }; - case UNIQUE_TOKENS_LOAD_UNIQUE_TOKENS_SUCCESS: - return { - ...state, - loadingUniqueTokens: false, - uniqueTokens: action.payload, - }; - case UNIQUE_TOKENS_LOAD_UNIQUE_TOKENS_FAILURE: - return { - ...state, - loadingUniqueTokens: false, - }; - case UNIQUE_TOKENS_GET_UNIQUE_TOKENS_REQUEST: - return { - ...state, - fetchingUniqueTokens: true, - }; - case UNIQUE_TOKENS_GET_UNIQUE_TOKENS_SUCCESS: - return { - ...state, - fetchingUniqueTokens: false, - uniqueTokens: action.payload, - }; - case UNIQUE_TOKENS_GET_UNIQUE_TOKENS_FAILURE: - return { - ...state, - fetchingUniqueTokens: false, - }; - case UNIQUE_TOKENS_CLEAR_STATE: - return { - ...state, - ...INITIAL_UNIQUE_TOKENS_STATE, - }; - default: - return state; + case UNIQUE_TOKENS_LOAD_UNIQUE_TOKENS_REQUEST: + return { + ...state, + loadingUniqueTokens: true, + }; + case UNIQUE_TOKENS_LOAD_UNIQUE_TOKENS_SUCCESS: + return { + ...state, + loadingUniqueTokens: false, + uniqueTokens: action.payload, + }; + case UNIQUE_TOKENS_LOAD_UNIQUE_TOKENS_FAILURE: + return { + ...state, + loadingUniqueTokens: false, + }; + case UNIQUE_TOKENS_GET_UNIQUE_TOKENS_REQUEST: + return { + ...state, + fetchingUniqueTokens: true, + }; + case UNIQUE_TOKENS_GET_UNIQUE_TOKENS_SUCCESS: + return { + ...state, + fetchingUniqueTokens: false, + uniqueTokens: action.payload, + }; + case UNIQUE_TOKENS_GET_UNIQUE_TOKENS_FAILURE: + return { + ...state, + fetchingUniqueTokens: false, + }; + case UNIQUE_TOKENS_CLEAR_STATE: + return { + ...state, + ...INITIAL_UNIQUE_TOKENS_STATE, + }; + default: + return state; } }; diff --git a/src/redux/uniswap.js b/src/redux/uniswap.js index 385fb91daa6..00f5b61fc5e 100644 --- a/src/redux/uniswap.js +++ b/src/redux/uniswap.js @@ -1,41 +1,112 @@ import produce from 'immer'; import { + compact, concat, + filter, get, + invertBy, isEmpty, + keyBy, + keys, map, + mapValues, + omit, + toLower, + uniq, + without, } from 'lodash'; import { - getUniswap, - getUniswapLiquidityTokens, - removeUniswap, - removeUniswapLiquidityTokens, - saveUniswap, - saveUniswapLiquidityTokens, -} from '../handlers/commonStorage'; -import getUniswapLiquidityInfo from '../handlers/uniswap'; + getAllowances, + getLiquidity, + getUniswapAssets, + getUniswapFavorites, + getUniswapLiquidityInfo, + getUniswapPendingApprovals, + removeUniswapStorage, + saveAllowances, + saveLiquidity, + saveLiquidityInfo, + saveUniswapAssets, + saveUniswapFavorites, + saveUniswapPendingApprovals, +} from '../handlers/localstorage/uniswap'; +import { + getLiquidityInfo, + getReserve, + getUniswapPairs, +} from '../handlers/uniswap'; +import { includeExchangeAddress } from '../hoc/withUniswapAssets'; +import { + cleanUniswapAssetsFallback, + DefaultUniswapFavorites, +} from '../references'; +import { resubscribeAssets } from './explorer'; // -- Constants ------------------------------------------------------------- // const UNISWAP_LOAD_REQUEST = 'uniswap/UNISWAP_LOAD_REQUEST'; const UNISWAP_LOAD_SUCCESS = 'uniswap/UNISWAP_LOAD_SUCCESS'; const UNISWAP_LOAD_FAILURE = 'uniswap/UNISWAP_LOAD_FAILURE'; +const UNISWAP_LOAD_LIQUIDITY_TOKEN_INFO_SUCCESS = + 'uniswap/UNISWAP_LOAD_LIQUIDITY_TOKEN_INFO_SUCCESS'; + +const UNISWAP_UPDATE_PAIRS = 'uniswap/UNISWAP_UPDATE_PAIRS'; + const UNISWAP_UPDATE_REQUEST = 'uniswap/UNISWAP_UPDATE_REQUEST'; const UNISWAP_UPDATE_SUCCESS = 'uniswap/UNISWAP_UPDATE_SUCCESS'; const UNISWAP_UPDATE_FAILURE = 'uniswap/UNISWAP_UPDATE_FAILURE'; -const UNISWAP_UPDATE_LIQUIDITY_TOKENS = 'uniswap/UNISWAP_UPDATE_LIQUIDITY_TOKENS'; +const UNISWAP_RESET_CURRENCIES_AND_RESERVES = + 'uniswap/UNISWAP_RESET_CURRENCIES_AND_RESERVES'; +const UNISWAP_UPDATE_FAVORITES = 'uniswap/UNISWAP_UPDATE_FAVORITES'; +const UNISWAP_UPDATE_TOKEN_RESERVES = 'uniswap/UNISWAP_UPDATE_TOKEN_RESERVES'; +const UNISWAP_UPDATE_INPUT_CURRENCY_AND_RESERVE = + 'uniswap/UNISWAP_UPDATE_INPUT_CURRENCY_AND_RESERVE'; +const UNISWAP_UPDATE_OUTPUT_CURRENCY_AND_RESERVE = + 'uniswap/UNISWAP_UPDATE_OUTPUT_CURRENCY_AND_RESERVE'; +const UNISWAP_UPDATE_PENDING_APPROVALS = + 'uniswap/UNISWAP_UPDATE_PENDING_APPROVALS'; +const UNISWAP_UPDATE_ASSETS = 'uniswap/UNISWAP_UPDATE_ASSETS'; +const UNISWAP_UPDATE_ALLOWANCES = 'uniswap/UNISWAP_UPDATE_ALLOWANCES'; +const UNISWAP_UPDATE_LIQUIDITY_TOKENS = + 'uniswap/UNISWAP_UPDATE_LIQUIDITY_TOKENS'; const UNISWAP_CLEAR_STATE = 'uniswap/UNISWAP_CLEAR_STATE'; // -- Actions --------------------------------------------------------------- // +const extractTransactionHash = txn => toLower(txn.hash).split('-')[0]; +const firstItem = value => get(value, '[0]'); +const lowerAddress = asset => toLower(asset.address); +const hasTokenQuantity = token => token.quantity > 0; +const getAssetCode = token => get(token, 'asset.asset_code'); + export const uniswapLoadState = () => async (dispatch, getState) => { const { accountAddress, network } = getState().settings; dispatch({ type: UNISWAP_LOAD_REQUEST }); try { - const uniswap = await getUniswap(accountAddress, network); - const liquidityTokens = await getUniswapLiquidityTokens(accountAddress, network); + const uniswapLiquidityTokenInfo = await getUniswapLiquidityInfo( + accountAddress, + network + ); dispatch({ - payload: { liquidityTokens, uniswap }, + payload: uniswapLiquidityTokenInfo, + type: UNISWAP_LOAD_LIQUIDITY_TOKEN_INFO_SUCCESS, + }); + const allowances = await getAllowances(accountAddress, network); + const favorites = await getUniswapFavorites(); + const liquidityTokens = await getLiquidity(accountAddress, network); + const pendingApprovals = await getUniswapPendingApprovals( + accountAddress, + network + ); + const uniswapAssets = await getUniswapAssets(accountAddress, network); + dispatch({ + payload: { + allowances, + favorites, + liquidityTokens, + pendingApprovals, + uniswapAssets, + }, type: UNISWAP_LOAD_SUCCESS, }); } catch (error) { @@ -43,44 +114,202 @@ export const uniswapLoadState = () => async (dispatch, getState) => { } }; +export const uniswapPairsInit = () => async (dispatch, getState) => { + try { + const { tokenOverrides } = getState().data; + const { pairs: existingPairs } = getState().uniswap; + const pairs = await getUniswapPairs(tokenOverrides); + dispatch(uniswapUpdatePairs(pairs)); + dispatch(resubscribeAssets(keys(existingPairs), keys(pairs))); + // eslint-disable-next-line no-empty + } catch (error) {} +}; + +export const uniswapUpdateTokenReserves = ( + inputReserve, + outputReserve +) => dispatch => { + dispatch({ + payload: { + inputReserve, + outputReserve, + }, + type: UNISWAP_UPDATE_TOKEN_RESERVES, + }); +}; + +export const uniswapUpdateInputCurrency = inputCurrency => async dispatch => { + const inputReserve = await getReserve(get(inputCurrency, 'address', null)); + dispatch({ + payload: { + inputCurrency, + inputReserve, + }, + type: UNISWAP_UPDATE_INPUT_CURRENCY_AND_RESERVE, + }); +}; + +export const uniswapUpdateOutputCurrency = outputCurrency => async dispatch => { + const outputReserve = await getReserve(get(outputCurrency, 'address', null)); + dispatch({ + payload: { + outputCurrency, + outputReserve, + }, + type: UNISWAP_UPDATE_OUTPUT_CURRENCY_AND_RESERVE, + }); +}; + +export const uniswapClearCurrenciesAndReserves = () => dispatch => + dispatch({ type: UNISWAP_RESET_CURRENCIES_AND_RESERVES }); + export const uniswapClearState = () => (dispatch, getState) => { const { accountAddress, network } = getState().settings; - removeUniswap(accountAddress, network); - removeUniswapLiquidityTokens(accountAddress, network); + removeUniswapStorage(accountAddress, network); dispatch({ type: UNISWAP_CLEAR_STATE }); }; -export const uniswapUpdateLiquidityTokens = liquidityTokens => ( +export const uniswapAddPendingApproval = ( + tokenAddress, + txHash, + creationTimestamp, + estimatedTimeInMs +) => (dispatch, getState) => { + const { accountAddress, network } = getState().settings; + const { pendingApprovals } = getState().uniswap; + const updatedPendingApprovals = { + ...pendingApprovals, + [toLower(tokenAddress)]: { + creationTimestamp, + estimatedTimeInMs, + hash: toLower(txHash), + }, + }; + dispatch({ + payload: updatedPendingApprovals, + type: UNISWAP_UPDATE_PENDING_APPROVALS, + }); + saveUniswapPendingApprovals(updatedPendingApprovals, accountAddress, network); +}; + +export const uniswapRemovePendingApproval = transactions => ( + dispatch, + getState +) => { + const loweredTxHashes = map(transactions, extractTransactionHash); + const { pendingApprovals } = getState().uniswap; + const invertedPendingApprovals = mapValues( + invertBy(pendingApprovals, value => value.hash), + firstItem + ); + const updatedAddresses = compact( + map(loweredTxHashes, hash => invertedPendingApprovals[hash]) + ); + if (isEmpty(updatedAddresses)) return; + const updatedPendingApprovals = omit(pendingApprovals, ...updatedAddresses); + dispatch({ + payload: updatedPendingApprovals, + type: UNISWAP_UPDATE_PENDING_APPROVALS, + }); + const { accountAddress, network } = getState().settings; + saveUniswapPendingApprovals(updatedPendingApprovals, accountAddress, network); +}; + +export const uniswapUpdateFavorites = (assetAddress, add = true) => ( + dispatch, + getState +) => { + const address = toLower(assetAddress); + const { favorites } = getState().uniswap; + const normalizedFavorites = map(favorites, toLower); + + const updatedFavorites = add + ? uniq(concat(normalizedFavorites, address)) + : without(normalizedFavorites, address); + dispatch({ + payload: updatedFavorites, + type: UNISWAP_UPDATE_FAVORITES, + }); + saveUniswapFavorites(updatedFavorites); +}; + +export const uniswapUpdateAllowances = tokenAddressAllowances => ( dispatch, getState ) => { - const { liquidityTokens: existingLiquidityTokens } = getState().uniswap; - if (isEmpty(liquidityTokens) && isEmpty(existingLiquidityTokens)) return; const { accountAddress, network } = getState().settings; + const { allowances } = getState().uniswap; + const updatedAllowances = { + ...allowances, + ...tokenAddressAllowances, + }; dispatch({ - payload: liquidityTokens, - type: UNISWAP_UPDATE_LIQUIDITY_TOKENS, + payload: updatedAllowances, + type: UNISWAP_UPDATE_ALLOWANCES, }); - saveUniswapLiquidityTokens(accountAddress, liquidityTokens, network); - dispatch(uniswapUpdateState()); + saveAllowances(updatedAllowances, accountAddress, network); }; +export const uniswapUpdateAssets = assets => (dispatch, getState) => { + const { accountAddress, network } = getState().settings; + const { pairs } = getState().uniswap; + const uniswapAssetPrices = map(assets, includeExchangeAddress(pairs)); + const mappedAssets = keyBy(uniswapAssetPrices, lowerAddress); + dispatch({ + payload: mappedAssets, + type: UNISWAP_UPDATE_ASSETS, + }); + saveUniswapAssets(mappedAssets, accountAddress, network); +}; -export const uniswapAddLiquidityTokens = (newLiquidityTokens) => (dispatch, getState) => { - if (isEmpty(newLiquidityTokens)) return; +export const uniswapUpdatePairs = pairs => dispatch => + dispatch({ + payload: pairs, + type: UNISWAP_UPDATE_PAIRS, + }); + +export const uniswapUpdateAssetPrice = (address, price) => ( + dispatch, + getState +) => { + const addressKey = toLower(address); + const { accountAddress, network } = getState().settings; + const { uniswapAssets } = getState().uniswap; + const updatedAsset = { ...uniswapAssets[addressKey], price }; + const updatedAssets = { + ...uniswapAssets, + [addressKey]: updatedAsset, + }; + dispatch({ + payload: updatedAssets, + type: UNISWAP_UPDATE_ASSETS, + }); + saveUniswapAssets(updatedAssets, accountAddress, network); +}; + +export const uniswapUpdateLiquidityTokens = ( + liquidityTokens, + appendOrChange +) => (dispatch, getState) => { + let updatedLiquidityTokens = filter(liquidityTokens, hasTokenQuantity); + if (appendOrChange) { + const { liquidityTokens: existingLiquidityTokens } = getState().uniswap; + updatedLiquidityTokens = uniq( + concat(existingLiquidityTokens, ...updatedLiquidityTokens), + getAssetCode + ); + } const { accountAddress, network } = getState().settings; - const { liquidityTokens } = getState().uniswap; - const updatedLiquidityTokens = concat(liquidityTokens, ...newLiquidityTokens); dispatch({ payload: updatedLiquidityTokens, type: UNISWAP_UPDATE_LIQUIDITY_TOKENS, }); - saveUniswapLiquidityTokens(accountAddress, updatedLiquidityTokens, network); + saveLiquidity(updatedLiquidityTokens, accountAddress, network); dispatch(uniswapUpdateState()); }; -export const uniswapUpdateState = () => (dispatch, getState) => ( - new Promise((resolve, reject) => { +export const uniswapUpdateState = () => (dispatch, getState) => + new Promise((resolve, promiseReject) => { const { accountAddress, network } = getState().settings; const { liquidityTokens } = getState().uniswap; @@ -90,60 +319,108 @@ export const uniswapUpdateState = () => (dispatch, getState) => ( dispatch({ type: UNISWAP_UPDATE_REQUEST }); - const exchangeContracts = map(liquidityTokens, x => get(x, 'asset.asset_code')); - return getUniswapLiquidityInfo(accountAddress, exchangeContracts) - .then(uniswap => { - saveUniswap(accountAddress, uniswap, network); + const exchangeContracts = map(liquidityTokens, getAssetCode); + return getLiquidityInfo(accountAddress, exchangeContracts) + .then(liquidityInfo => { + saveLiquidityInfo(liquidityInfo, accountAddress, network); dispatch({ - payload: uniswap, + payload: liquidityInfo, type: UNISWAP_UPDATE_SUCCESS, }); resolve(true); }) .catch(error => { dispatch({ type: UNISWAP_UPDATE_FAILURE }); - reject(error); + promiseReject(error); }); - }) -); + }); // -- Reducer --------------------------------------------------------------- // export const INITIAL_UNISWAP_STATE = { + allowances: {}, + favorites: DefaultUniswapFavorites, fetchingUniswap: false, + inputCurrency: null, + inputReserve: null, liquidityTokens: [], loadingUniswap: false, - uniswap: {}, + outputCurrency: null, + outputReserve: null, + pairs: cleanUniswapAssetsFallback, + pendingApprovals: {}, + uniswapAssets: {}, + uniswapLiquidityTokenInfo: {}, }; -export default (state = INITIAL_UNISWAP_STATE, action) => produce(state, draft => { - switch (action.type) { - case UNISWAP_LOAD_REQUEST: - draft.loadingUniswap = true; - break; - case UNISWAP_LOAD_SUCCESS: - draft.loadingUniswap = false; - draft.uniswap = action.payload.uniswap; - draft.liquidityTokens = action.payload.liquidityTokens; - break; - case UNISWAP_LOAD_FAILURE: - draft.loadingUniswap = false; - break; - case UNISWAP_UPDATE_REQUEST: - draft.fetchingUniswap = true; - break; - case UNISWAP_UPDATE_SUCCESS: - draft.fetchingUniswap = false; - draft.uniswap = action.payload; - break; - case UNISWAP_UPDATE_FAILURE: - draft.fetchingUniswap = false; - break; - case UNISWAP_UPDATE_LIQUIDITY_TOKENS: - draft.liquidityTokens = action.payload; - break; - case UNISWAP_CLEAR_STATE: - return INITIAL_UNISWAP_STATE; - default: - break; - } -}); +export default (state = INITIAL_UNISWAP_STATE, action) => + produce(state, draft => { + switch (action.type) { + case UNISWAP_LOAD_REQUEST: + draft.loadingUniswap = true; + break; + case UNISWAP_LOAD_LIQUIDITY_TOKEN_INFO_SUCCESS: + draft.uniswapLiquidityTokenInfo = action.payload; + break; + case UNISWAP_UPDATE_PAIRS: + draft.pairs = action.payload; + break; + case UNISWAP_LOAD_SUCCESS: + draft.allowances = action.payload.allowances; + draft.favorites = action.payload.favorites; + draft.liquidityTokens = action.payload.liquidityTokens; + draft.loadingUniswap = false; + draft.pendingApprovals = action.payload.pendingApprovals; + draft.uniswapAssets = action.payload.uniswapAssets; + break; + case UNISWAP_UPDATE_FAVORITES: + draft.favorites = action.payload; + break; + case UNISWAP_UPDATE_TOKEN_RESERVES: + draft.inputReserve = action.payload.inputReserve; + draft.outputReserve = action.payload.outputReserve; + break; + case UNISWAP_UPDATE_INPUT_CURRENCY_AND_RESERVE: + draft.inputCurrency = action.payload.inputCurrency; + draft.inputReserve = action.payload.inputReserve; + break; + case UNISWAP_UPDATE_OUTPUT_CURRENCY_AND_RESERVE: + draft.outputCurrency = action.payload.outputCurrency; + draft.outputReserve = action.payload.outputReserve; + break; + case UNISWAP_LOAD_FAILURE: + draft.loadingUniswap = false; + break; + case UNISWAP_UPDATE_REQUEST: + draft.fetchingUniswap = true; + break; + case UNISWAP_UPDATE_SUCCESS: + draft.fetchingUniswap = false; + draft.uniswapLiquidityTokenInfo = action.payload; + break; + case UNISWAP_UPDATE_FAILURE: + draft.fetchingUniswap = false; + break; + case UNISWAP_UPDATE_LIQUIDITY_TOKENS: + draft.liquidityTokens = action.payload; + break; + case UNISWAP_UPDATE_PENDING_APPROVALS: + draft.pendingApprovals = action.payload; + break; + case UNISWAP_UPDATE_ALLOWANCES: + draft.allowances = action.payload; + break; + case UNISWAP_UPDATE_ASSETS: + draft.uniswapAssets = action.payload; + break; + case UNISWAP_RESET_CURRENCIES_AND_RESERVES: + draft.inputCurrency = INITIAL_UNISWAP_STATE.inputCurrency; + draft.inputReserve = INITIAL_UNISWAP_STATE.inputReserve; + draft.outputCurrency = INITIAL_UNISWAP_STATE.outputCurrency; + draft.outputReserve = INITIAL_UNISWAP_STATE.outputReserve; + break; + case UNISWAP_CLEAR_STATE: + return INITIAL_UNISWAP_STATE; + default: + break; + } + }); diff --git a/src/redux/walletconnect.js b/src/redux/walletconnect.js index 06e82e5092b..48dfb6d7a2a 100644 --- a/src/redux/walletconnect.js +++ b/src/redux/walletconnect.js @@ -1,45 +1,36 @@ import analytics from '@segment/analytics-react-native'; -import { - forEach, - mapValues, - omitBy, - pickBy, - values, -} from 'lodash'; -import { Alert } from 'react-native'; -import lang from 'i18n-js'; import WalletConnect from '@walletconnect/react-native'; +import lang from 'i18n-js'; +import { forEach, mapValues, omitBy, pickBy, values } from 'lodash'; +import { Alert } from 'react-native'; import { getAllValidWalletConnectSessions, saveWalletConnectSession, removeWalletConnect, removeWalletConnectSessions, -} from '../handlers/commonStorage'; +} from '../handlers/localstorage/walletconnect'; import { sendRpcCall } from '../handlers/web3'; -import { getFCMToken, checkPushNotificationPermissions } from '../model/firebase'; +import { + getFCMToken, + checkPushNotificationPermissions, +} from '../model/firebase'; +import { isSigningMethod } from '../utils/signingMethods'; import { addRequestToApprove } from './requests'; // -- Constants --------------------------------------- // const WALLETCONNECT_ADD_REQUEST = 'walletconnect/WALLETCONNECT_ADD_REQUEST'; -const WALLETCONNECT_REMOVE_REQUEST = 'walletconnect/WALLETCONNECT_REMOVE_REQUEST'; +const WALLETCONNECT_REMOVE_REQUEST = + 'walletconnect/WALLETCONNECT_REMOVE_REQUEST'; const WALLETCONNECT_ADD_SESSION = 'walletconnect/WALLETCONNECT_ADD_SESSION'; -const WALLETCONNECT_REMOVE_SESSION = 'walletconnect/WALLETCONNECT_REMOVE_SESSION'; +const WALLETCONNECT_REMOVE_SESSION = + 'walletconnect/WALLETCONNECT_REMOVE_SESSION'; const WALLETCONNECT_INIT_SESSIONS = 'walletconnect/WALLETCONNECT_INIT_SESSIONS'; -const WALLETCONNECT_INIT_TIMESTAMP = 'walletconnect/WALLETCONNECT_INIT_TIMESTAMP'; -const WALLETCONNECT_CLEAR_TIMESTAMP = 'walletconnect/WALLETCONNECT_CLEAR_TIMESTAMP'; const WALLETCONNECT_CLEAR_STATE = 'walletconnect/WALLETCONNECT_CLEAR_STATE'; // -- Actions ---------------------------------------- // - -// TODO store approved list -/* -const previouslyApprovedDapps = [ -]; -*/ - const getNativeOptions = async () => { const language = 'en'; // TODO use lang from settings const token = await getFCMToken(); @@ -64,7 +55,10 @@ const getNativeOptions = async () => { return nativeOptions; }; -export const walletConnectOnSessionRequest = (uri, callback) => async (dispatch) => { +export const walletConnectOnSessionRequest = ( + uri, + callback +) => async dispatch => { let walletConnector = null; try { const nativeOptions = await getNativeOptions(); @@ -94,65 +88,59 @@ export const walletConnectOnSessionRequest = (uri, callback) => async (dispatch) } }; -const signingMethods = [ - "eth_sendTransaction", - "eth_signTransaction", - "personal_sign", - "eth_sign", - "eth_signTypedData", -]; - -const listenOnNewMessages = walletConnector => (dispatch, getState) => { +const listenOnNewMessages = walletConnector => dispatch => { walletConnector.on('call_request', (error, payload) => { if (error) throw error; const { clientId, peerId, peerMeta } = walletConnector; const requestId = payload.id; - if (!signingMethods.includes(payload.method)) { + if (!isSigningMethod(payload.method)) { sendRpcCall(payload) .then(result => { walletConnector.approveRequest({ id: payload.id, result, }); - }).catch(error => { + }) + .catch(() => { walletConnector.rejectRequest({ + error: { message: 'JSON RPC method not supported' }, id: payload.id, - error: { message: "JSON RPC method not supported" }, }); }); return; } - dispatch(addRequestToApprove(clientId, peerId, requestId, payload, peerMeta)); + dispatch( + addRequestToApprove(clientId, peerId, requestId, payload, peerMeta) + ); }); - walletConnector.on('disconnect', (error, payload) => { + walletConnector.on('disconnect', error => { if (error) throw error; - dispatch(walletConnectDisconnectAllByDappName(walletConnector.peerMeta.name)); + dispatch( + walletConnectDisconnectAllByDappName(walletConnector.peerMeta.name) + ); }); return walletConnector; }; -export const walletConnectUpdateTimestamp = () => dispatch => dispatch({ payload: Date.now(), type: WALLETCONNECT_INIT_TIMESTAMP }); - -export const walletConnectClearTimestamp = () => dispatch => dispatch({ type: WALLETCONNECT_CLEAR_TIMESTAMP }); - export const walletConnectClearState = () => (dispatch, getState) => { - removeWalletConnect(); + const { accountAddress, network } = getState().settings; + removeWalletConnect(accountAddress, network); dispatch({ type: WALLETCONNECT_CLEAR_STATE }); }; -export const walletConnectLoadState = () => async dispatch => { - dispatch(walletConnectUpdateTimestamp()); +export const walletConnectLoadState = () => async (dispatch, getState) => { + const { accountAddress, network } = getState().settings; let walletConnectors = {}; try { - const allSessions = await getAllValidWalletConnectSessions(); + const allSessions = await getAllValidWalletConnectSessions( + accountAddress, + network + ); const nativeOptions = await getNativeOptions(); walletConnectors = mapValues(allSessions, session => { - const walletConnector = new WalletConnect( - { session }, - nativeOptions, - ); + const walletConnector = new WalletConnect({ session }, nativeOptions); return dispatch(listenOnNewMessages(walletConnector)); }); } catch (error) { @@ -166,7 +154,10 @@ export const walletConnectLoadState = () => async dispatch => { } }; -export const setPendingRequest = (peerId, walletConnector) => (dispatch, getState) => { +export const setPendingRequest = (peerId, walletConnector) => ( + dispatch, + getState +) => { const { pendingRequests } = getState().walletconnect; const updatedPendingRequests = { ...pendingRequests, @@ -178,12 +169,12 @@ export const setPendingRequest = (peerId, walletConnector) => (dispatch, getStat }); }; -export const getPendingRequest = (peerId) => (dispatch, getState) => { +export const getPendingRequest = peerId => (dispatch, getState) => { const { pendingRequests } = getState().walletconnect; return pendingRequests[peerId]; }; -export const removePendingRequest = (peerId) => (dispatch, getState) => { +export const removePendingRequest = peerId => (dispatch, getState) => { const { pendingRequests } = getState().walletconnect; const updatedPendingRequests = pendingRequests; if (updatedPendingRequests[peerId]) { @@ -195,7 +186,7 @@ export const removePendingRequest = (peerId) => (dispatch, getState) => { }); }; -export const setWalletConnector = (walletConnector) => (dispatch, getState) => { +export const setWalletConnector = walletConnector => (dispatch, getState) => { const { walletConnectors } = getState().walletconnect; const updatedWalletConnectors = { ...walletConnectors, @@ -207,13 +198,13 @@ export const setWalletConnector = (walletConnector) => (dispatch, getState) => { }); }; -export const getWalletConnector = (peerId) => (dispatch, getState) => { +export const getWalletConnector = peerId => (dispatch, getState) => { const { walletConnectors } = getState().walletconnect; const walletConnector = walletConnectors[peerId]; return walletConnector; }; -export const removeWalletConnector = (peerId) => (dispatch, getState) => { +export const removeWalletConnector = peerId => (dispatch, getState) => { const { walletConnectors } = getState().walletconnect; const updatedWalletConnectors = walletConnectors; if (updatedWalletConnectors[peerId]) { @@ -225,8 +216,11 @@ export const removeWalletConnector = (peerId) => (dispatch, getState) => { }); }; -export const walletConnectApproveSession = (peerId, callback) => (dispatch, getState) => { - const { accountAddress, chainId } = getState().settings; +export const walletConnectApproveSession = (peerId, callback) => ( + dispatch, + getState +) => { + const { accountAddress, chainId, network } = getState().settings; const walletConnector = dispatch(getPendingRequest(peerId)); walletConnector.approveSession({ @@ -235,9 +229,16 @@ export const walletConnectApproveSession = (peerId, callback) => (dispatch, getS }); dispatch(removePendingRequest(peerId)); - saveWalletConnectSession(walletConnector.peerId, walletConnector.session); + saveWalletConnectSession( + walletConnector.peerId, + walletConnector.session, + accountAddress, + network + ); - const listeningWalletConnector = dispatch(listenOnNewMessages(walletConnector)); + const listeningWalletConnector = dispatch( + listenOnNewMessages(walletConnector) + ); dispatch(setWalletConnector(listeningWalletConnector)); if (callback) { @@ -245,7 +246,7 @@ export const walletConnectApproveSession = (peerId, callback) => (dispatch, getS } }; -export const walletConnectRejectSession = (peerId) => (dispatch, getState) => { +export const walletConnectRejectSession = peerId => dispatch => { const walletConnector = dispatch(getPendingRequest(peerId)); walletConnector.rejectSession(); @@ -253,15 +254,28 @@ export const walletConnectRejectSession = (peerId) => (dispatch, getState) => { dispatch(removePendingRequest(peerId)); }; -export const walletConnectDisconnectAllByDappName = dappName => async (dispatch, getState) => { +export const walletConnectDisconnectAllByDappName = dappName => async ( + dispatch, + getState +) => { const { walletConnectors } = getState().walletconnect; - const matchingWalletConnectors = values(pickBy(walletConnectors, session => session.peerMeta.name === dappName)); + const { accountAddress, network } = getState().settings; + const matchingWalletConnectors = values( + pickBy(walletConnectors, session => session.peerMeta.name === dappName) + ); try { - const peerIds = values(mapValues(matchingWalletConnectors, walletConnector => walletConnector.peerId)); - await removeWalletConnectSessions(peerIds); - forEach(matchingWalletConnectors, walletConnector => walletConnector.killSession()); + const peerIds = values( + mapValues( + matchingWalletConnectors, + walletConnector => walletConnector.peerId + ) + ); + await removeWalletConnectSessions(peerIds, accountAddress, network); + forEach(matchingWalletConnectors, walletConnector => + walletConnector.killSession() + ); dispatch({ - payload: omitBy(walletConnectors, (wc) => wc.peerMeta.name === dappName), + payload: omitBy(walletConnectors, wc => wc.peerMeta.name === dappName), type: WALLETCONNECT_REMOVE_SESSION, }); } catch (error) { @@ -269,7 +283,10 @@ export const walletConnectDisconnectAllByDappName = dappName => async (dispatch, } }; -export const walletConnectSendStatus = (peerId, requestId, result) => async (dispatch, getState) => { +export const walletConnectSendStatus = (peerId, requestId, result) => async ( + dispatch, + getState +) => { const walletConnector = getState().walletconnect.walletConnectors[peerId]; if (walletConnector) { try { @@ -285,36 +302,33 @@ export const walletConnectSendStatus = (peerId, requestId, result) => async (dis Alert.alert('Failed to send request status to WalletConnect.'); } } else { - Alert.alert('WalletConnect session has expired while trying to send request status. Please reconnect.'); + Alert.alert( + 'WalletConnect session has expired while trying to send request status. Please reconnect.' + ); } }; // -- Reducer ----------------------------------------- // const INITIAL_STATE = { - appInitTimestamp: null, pendingRequests: {}, walletConnectors: {}, }; export default (state = INITIAL_STATE, action) => { switch (action.type) { - case WALLETCONNECT_ADD_REQUEST: - return { ...state, pendingRequests: action.payload }; - case WALLETCONNECT_REMOVE_REQUEST: - return { ...state, pendingRequests: action.payload }; - case WALLETCONNECT_ADD_SESSION: - return { ...state, walletConnectors: action.payload }; - case WALLETCONNECT_REMOVE_SESSION: - return { ...state, walletConnectors: action.payload }; - case WALLETCONNECT_INIT_SESSIONS: - return { ...state, walletConnectors: action.payload }; - case WALLETCONNECT_INIT_TIMESTAMP: - return { ...state, appInitTimestamp: action.payload }; - case WALLETCONNECT_CLEAR_TIMESTAMP: - return { ...state, appInitTimestamp: null }; - case WALLETCONNECT_CLEAR_STATE: - return { ...state, ...INITIAL_STATE }; - default: - return state; + case WALLETCONNECT_ADD_REQUEST: + return { ...state, pendingRequests: action.payload }; + case WALLETCONNECT_REMOVE_REQUEST: + return { ...state, pendingRequests: action.payload }; + case WALLETCONNECT_ADD_SESSION: + return { ...state, walletConnectors: action.payload }; + case WALLETCONNECT_REMOVE_SESSION: + return { ...state, walletConnectors: action.payload }; + case WALLETCONNECT_INIT_SESSIONS: + return { ...state, walletConnectors: action.payload }; + case WALLETCONNECT_CLEAR_STATE: + return { ...state, ...INITIAL_STATE }; + default: + return state; } }; diff --git a/src/redux/web3listener.js b/src/redux/web3listener.js new file mode 100644 index 00000000000..66f53b562e4 --- /dev/null +++ b/src/redux/web3listener.js @@ -0,0 +1,24 @@ +import { get } from 'lodash'; +import { getReserve } from '../handlers/uniswap'; +import { web3Provider } from '../handlers/web3'; +import { promiseUtils } from '../utils'; +import { uniswapUpdateTokenReserves } from './uniswap'; + +// -- Actions ---------------------------------------- // +const web3UpdateReserves = () => async (dispatch, getState) => { + const { inputCurrency, outputCurrency } = getState().uniswap; + if (!(inputCurrency || outputCurrency)) return; + const [inputReserve, outputReserve] = await promiseUtils.PromiseAllWithFails([ + getReserve(get(inputCurrency, 'address')), + getReserve(get(outputCurrency, 'address')), + ]); + dispatch(uniswapUpdateTokenReserves(inputReserve, outputReserve)); +}; + +export const web3ListenerInit = () => dispatch => { + web3Provider.on('block', () => dispatch(web3UpdateReserves())); +}; + +export const web3ListenerClearState = () => { + web3Provider.removeAllListeners('block'); +}; diff --git a/src/references/ethereum-units.json b/src/references/ethereum-units.json index 8674ee3aaac..3acf717a9a7 100644 --- a/src/references/ethereum-units.json +++ b/src/references/ethereum-units.json @@ -1,4 +1,5 @@ { + "basic_swap": 80000, "basic_tx": 21000, "noether": 0, "wei": 1, diff --git a/src/references/index.js b/src/references/index.js new file mode 100644 index 00000000000..4206cb7ce04 --- /dev/null +++ b/src/references/index.js @@ -0,0 +1,30 @@ +import { mapKeys, mapValues, toLower } from 'lodash'; +import tokenOverridesFallback from './token-overrides.json'; +import uniswapAssetsFallback from './uniswap-pairs.json'; + +export const DefaultUniswapFavorites = [ + // Ethereum + 'eth', + // DAI + '0x6b175474e89094c44da98b954eedeac495271d0f', + // SOCKS + '0x23B608675a2B2fB1890d3ABBd85c5775c51691d5', +]; + +export const loweredTokenOverridesFallback = mapKeys( + tokenOverridesFallback, + (_, address) => toLower(address) +); + +const loweredUniswapAssetsFallback = mapKeys( + uniswapAssetsFallback, + (value, key) => toLower(key) +); + +export const cleanUniswapAssetsFallback = mapValues( + loweredUniswapAssetsFallback, + (value, key) => ({ + ...value, + ...loweredTokenOverridesFallback[key], + }) +); diff --git a/src/references/native-currencies.json b/src/references/native-currencies.json index e736541b57d..8f8aabc9a7d 100644 --- a/src/references/native-currencies.json +++ b/src/references/native-currencies.json @@ -1,55 +1,67 @@ { "USD": { - "symbol": "$", - "currency": "USD", - "label": "United States Dollar", - "decimals": 2, "alignment": "left", "assetLimit": 1, - "emojiName": "us" + "currency": "USD", + "decimals": 2, + "emojiName": "us", + "label": "United States Dollar", + "mask": "[099999999999]{.}[00]", + "placeholder": "0.00", + "symbol": "$" }, "CNY": { - "symbol": "Β₯", - "currency": "CNY", - "label": "Chinese Yuan", - "decimals": 2, "alignment": "left", "assetLimit": 1, - "emojiName": "cn" + "currency": "CNY", + "decimals": 2, + "emojiName": "cn", + "label": "Chinese Yuan", + "mask": "[099999999999]{.}[00]", + "placeholder": "0.00", + "symbol": "Β₯" }, "KRW": { - "symbol": "β‚©", - "currency": "KRW", - "label": "South Korean Won", - "decimals": 0, "alignment": "left", "assetLimit": 1, - "emojiName": "kr" + "currency": "KRW", + "decimals": 0, + "emojiName": "kr", + "label": "South Korean Won", + "mask": "[099999999999]{.}[00]", + "placeholder": "0.00", + "symbol": "β‚©" }, "RUB": { - "symbol": "β‚½", - "currency": "RUB", - "label": "Russian Ruble", - "decimals": 2, "alignment": "right", "assetLimit": 1, - "emojiName": "ru" + "currency": "RUB", + "decimals": 2, + "emojiName": "ru", + "label": "Russian Ruble", + "mask": "[099999999999]{.}[00]", + "placeholder": "0.00", + "symbol": "β‚½" }, "EUR": { - "symbol": "€", - "currency": "EUR", - "label": "Euro", - "decimals": 2, "alignment": "left", "assetLimit": 1, - "emojiName": "flag-eu" + "currency": "EUR", + "decimals": 2, + "emojiName": "flag-eu", + "label": "Euro", + "mask": "[099999999999]{.}[00]", + "placeholder": "0.00", + "symbol": "€" }, "ETH": { - "symbol": "Ξ", + "alignment": "right", + "assetLimit": 0.001, "currency": "ETH", - "label": "Ethereum", "decimals": 8, - "alignment": "right", - "assetLimit": 0.001 + "label": "Ethereum", + "mask": "[99999999999]{.}[999999999999999999]{ ETH}", + "placeholder": "0 ETH", + "symbol": "Ξ" } } diff --git a/src/references/token-overrides.json b/src/references/token-overrides.json new file mode 100644 index 00000000000..a12605a1b50 --- /dev/null +++ b/src/references/token-overrides.json @@ -0,0 +1,190 @@ +{ + "ETH": { + "name": "Ethereum" + }, + "0xE41d2489571d322189246DaFA5ebDe1F4699F498": { + "name": "0x" + }, + "0x960b236A07cf122663c4303350609A66A7B288C0": { + "name": "Aragon" + }, + "0x1985365e9f78359a9B6AD760e32412f4a445E862": { + "name": "Augur" + }, + "0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C": { + "name": "Bancor" + }, + "0x0D8775F648430679A709E98d2b0Cb6250d2887EF": { + "name": "Basic Attention Token" + }, + "0x107c4504cd79C5d2696Ea0030a8dD4e92601B82e": { + "name": "Bloom" + }, + "0x514910771AF9Ca656af840dff83E8264EcF986CA": { + "name": "Chainlink" + }, + "0x41e5560054824eA6B0732E656E3Ad64E20e94E45": { + "name": "Civic" + }, + "0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643": { + "name": "Compound Dai", + "symbol": "cDAI" + }, + "0xF5DCe57282A584D2746FaF1593d3121Fcac444dC": { + "name": "Compound Sai", + "symbol": "cSAI" + }, + "0x39aa39c021dfbae8fac545936693ac917d5e7563": { + "name": "Compound USD Coin", + "symbol": "cUSDC" + }, + "0xB4272071eCAdd69d933AdcD19cA99fe80664fc08": { + "name": "CryptoFranc" + }, + "0x6b175474e89094c44da98b954eedeac495271d0f": { + "name": "Dai" + }, + "0x543Ff227F64Aa17eA132Bf9886cAb5DB55DCAddf": { + "name": "DAOstack" + }, + "0x0F5D2fB29fb7d3CFeE444a200298f468908cC942": { + "name": "Decentraland" + }, + "0xe0b7927c4af23765cb51314a0e0521a9645f0e2a": { + "name": "DigixDAO" + }, + "0x4f3AfEC4E5a3F2A6a1A411DEF7D7dFe50eE057bF": { + "name": "Digix Gold" + }, + "0x4946Fcea7C692606e8908002e55A582af44AC121": { + "name": "FOAM" + }, + "0x493c57c4763932315a328269e1adad09653b9081": { + "name": "Fulcrum Dai", + "symbol": "iDAI" + }, + "0x14094949152eddbfcd073717200da82fed8dc960": { + "name": "Fulcrum Sai", + "symbol": "iSAI" + }, + "0xf013406a0b1d544238083df0b93ad0d2cbe0f65f": { + "name": "Fulcrum USD Coin", + "symbol": "iUSDC" + }, + "0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b": { + "name": "FunFair" + }, + "0x6810e776880C02933D47DB1b9fc05908e5386b96": { + "name": "Gnosis" + }, + "0xa74476443119A942dE498590Fe1f2454d7D4aC0d": { + "name": "Golem" + }, + "0x12B19D3e2ccc14Da04FAe33e63652ce469b3F2FD": { + "name": "Grid+" + }, + "0x6c6EE5e31d828De241282B9606C8e98Ea48526E2": { + "name": "Holo" + }, + "0x607F4C5BB672230e8672085532f7e901544a7375": { + "name": "iExec" + }, + "0x93ED3FBe21207Ec2E8f2d3c3de6e058Cb73Bc04d": { + "name": "Kleros" + }, + "0xdd974D5C2e2928deA5F71b9825b8b646686BD200": { + "name": "Kyber Network" + }, + "0x58b6A8A3302369DAEc383334672404Ee733aB239": { + "name": "Livepeer" + }, + "0xA4e8C3Ec456107eA67d3075bF9e3DF3A75823DB0": { + "name": "Loom" + }, + "0xBBbbCA6A901c926F240b89EacB641d8Aec7AEafD": { + "name": "Loopring" + }, + "0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2": { + "name": "Maker" + }, + "0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0": { + "name": "Matic Network" + }, + "0xec67005c4E498Ec7f55E092bd1d35cbC47C91892": { + "name": "Melon" + }, + "0xaAAf91D9b90dF800Df4F55c205fd6989c977E73a": { + "name": "Monolith" + }, + "0xB62132e35a6c13ee1EE0f84dC5d40bad8d815206": { + "name": "Nexo" + }, + "0x1776e1F26f98b1A5dF9cD347953a26dd3Cb46671": { + "name": "Numeraire" + }, + "0x8E870D67F660D95d5be530380D0eC0bd388289E1": { + "name": "Paxos Standard" + }, + "0x6758B7d441a9739b98552B373703d8d3d14f9e62": { + "name": "POA Network", + "symbol": "POA20" + }, + "0x255Aa6DF07540Cb5d3d297f0D0D4D84cb52bc8e6": { + "name": "Raiden" + }, + "0x408e41876cCCDC0F92210600ef50372656052a38": { + "name": "Republic" + }, + "0xB4EFd85c19999D84251304bDA99E90B92300Bd93": { + "name": "Rocket Pool" + }, + "0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359": { + "name": "Sai" + }, + "0x06f65b8cfcb13a9fe37d836fe9708da38ecb29b2": { + "name": "Saint Fame" + }, + "0x4156D3342D5c385a87D264F90653733592000581": { + "name": "SALT" + }, + "0x42d6622deCe394b54999Fbd73D108123806f6a18": { + "name": "SpankChain" + }, + "0x744d70FDBE2Ba4CF95131626614a1763DF805B9E": { + "name": "Status" + }, + "0xB64ef51C888972c908CFacf59B47C1AfBC0Ab8aC": { + "name": "Storj" + }, + "0xc011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f": { + "name": "Synthetix" + }, + "0x5e74c9036fb86bd7ecdcb084a0673efc32ea31cb": { + "name": "Synthetix ETH" + }, + "0x57ab1ec28d129707052df4df418d58a2d46d5f51": { + "name": "Synthetix USD" + }, + "0xdac17f958d2ee523a2206206994597c13d831ec7": { + "name": "Tether" + }, + "0x8dd5fbCe2F6a956C3022bA3663759011Dd51e73E": { + "name": "TrueUSD" + }, + "0x23B608675a2B2fB1890d3ABBd85c5775c51691d5": { + "name": "Unisocks Edition 0" + }, + "0x09cabEC1eAd1c0Ba254B09efb3EE13841712bE14": { + "name": "Uniswap V1", + "symbol": "UNI-V1:SAI" + }, + "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48": { + "name": "USD Coin" + }, + "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599": { + "name": "Wrapped Bitcoin" + }, + "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2": { + "name": "Wrapped Ether" + } +} diff --git a/src/references/uniswap-pairs.json b/src/references/uniswap-pairs.json new file mode 100644 index 00000000000..b789cedfbd6 --- /dev/null +++ b/src/references/uniswap-pairs.json @@ -0,0 +1,338 @@ +{ + "ETH": { + "name": "Ethereum", + "symbol": "ETH", + "decimals": 18, + "exchangeAddress": null + }, + "0xE41d2489571d322189246DaFA5ebDe1F4699F498": { + "name": "0x", + "symbol": "ZRX", + "decimals": 18, + "exchangeAddress": "0xaE76c84C9262Cdb9abc0C2c8888e62Db8E22A0bF" + }, + "0x960b236A07cf122663c4303350609A66A7B288C0": { + "name": "Aragon", + "symbol": "ANT", + "decimals": 18, + "exchangeAddress": "0x077d52B047735976dfdA76feF74d4d988AC25196" + }, + "0x1985365e9f78359a9B6AD760e32412f4a445E862": { + "name": "Augur", + "symbol": "REP", + "decimals": 18, + "exchangeAddress": "0x48B04d2A05B6B604d8d5223Fd1984f191DED51af" + }, + "0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C": { + "name": "Bancor", + "symbol": "BNT", + "decimals": 18, + "exchangeAddress": "0x87d80DBD37E551F58680B4217b23aF6a752DA83F" + }, + "0x0D8775F648430679A709E98d2b0Cb6250d2887EF": { + "name": "Basic Attention Token", + "symbol": "BAT", + "decimals": 18, + "exchangeAddress": "0x2E642b8D59B45a1D8c5aEf716A84FF44ea665914" + }, + "0x107c4504cd79C5d2696Ea0030a8dD4e92601B82e": { + "name": "Bloom", + "symbol": "BLT", + "decimals": 18, + "exchangeAddress": "0x0E6A53B13688018A3df8C69f99aFB19A3068D04f" + }, + "0x514910771AF9Ca656af840dff83E8264EcF986CA": { + "name": "Chainlink", + "symbol": "LINK", + "decimals": 18, + "exchangeAddress": "0xF173214C720f58E03e194085B1DB28B50aCDeeaD" + }, + "0x41e5560054824eA6B0732E656E3Ad64E20e94E45": { + "name": "Civic", + "symbol": "CVC", + "decimals": 8, + "exchangeAddress": "0x1C6c712b1F4a7c263B1DBd8F97fb447c945d3b9a" + }, + "0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643": { + "name": "Compound Dai", + "symbol": "cDAI", + "decimals": 8, + "exchangeAddress": "0x34E89740adF97C3A9D3f63Cc2cE4a914382c230b" + }, + "0xF5DCe57282A584D2746FaF1593d3121Fcac444dC": { + "name": "Compound Sai", + "symbol": "cSAI", + "decimals": 8, + "exchangeAddress": "0x45A2FDfED7F7a2c791fb1bdF6075b83faD821ddE" + }, + "0x39aa39c021dfbae8fac545936693ac917d5e7563": { + "name": "Compound USD Coin", + "symbol": "cUSDC", + "decimals": 8, + "exchangeAddress": "0xb791c10824296881f91bdbc16367bbd9743fd99b" + }, + "0xB4272071eCAdd69d933AdcD19cA99fe80664fc08": { + "name": "CryptoFranc", + "symbol": "XCHF", + "decimals": 18, + "exchangeAddress": "0x8dE0d002DC83478f479dC31F76cB0a8aa7CcEa17" + }, + "0x6b175474e89094c44da98b954eedeac495271d0f": { + "name": "Dai", + "symbol": "DAI", + "decimals": 18, + "exchangeAddress": "0x2a1530c4c41db0b0b2bb646cb5eb1a67b7158667" + }, + "0x543Ff227F64Aa17eA132Bf9886cAb5DB55DCAddf": { + "name": "DAOstack", + "symbol": "GEN", + "decimals": 18, + "exchangeAddress": "0x26Cc0EAb6Cb650B0Db4D0d0dA8cB5BF69F4ad692" + }, + "0x0F5D2fB29fb7d3CFeE444a200298f468908cC942": { + "name": "Decentraland", + "symbol": "MANA", + "decimals": 18, + "exchangeAddress": "0xC6581Ce3A005e2801c1e0903281BBd318eC5B5C2" + }, + "0xe0b7927c4af23765cb51314a0e0521a9645f0e2a": { + "name": "DigixDAO", + "symbol": "DGD", + "decimals": 9, + "exchangeAddress": "0xd55c1ca9f5992a2e5e379dce49abf24294abe055" + }, + "0x4f3AfEC4E5a3F2A6a1A411DEF7D7dFe50eE057bF": { + "name": "Digix Gold", + "symbol": "DGX", + "decimals": 9, + "exchangeAddress": "0xb92dE8B30584392Af27726D5ce04Ef3c4e5c9924" + }, + "0x4946Fcea7C692606e8908002e55A582af44AC121": { + "name": "FOAM", + "symbol": "FOAM", + "decimals": 18, + "exchangeAddress": "0xf79cb3BEA83BD502737586A6E8B133c378FD1fF2" + }, + "0x14094949152eddbfcd073717200da82fed8dc960": { + "name": "Fulcrum Sai", + "symbol": "iSAI", + "decimals": 18, + "exchangeAddress": "0x81eed7f1ecbd7fa9978fcc7584296fb0c215dc5c" + }, + "0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b": { + "name": "FunFair", + "symbol": "FUN", + "decimals": 8, + "exchangeAddress": "0x60a87cC7Fca7E53867facB79DA73181B1bB4238B" + }, + "0x6810e776880C02933D47DB1b9fc05908e5386b96": { + "name": "Gnosis", + "symbol": "GNO", + "decimals": 18, + "exchangeAddress": "0xe8e45431b93215566BA923a7E611B7342Ea954DF" + }, + "0x12B19D3e2ccc14Da04FAe33e63652ce469b3F2FD": { + "name": "Grid+", + "symbol": "GRID", + "decimals": 12, + "exchangeAddress": "0x4B17685b330307C751B47f33890c8398dF4Fe407" + }, + "0x6c6EE5e31d828De241282B9606C8e98Ea48526E2": { + "name": "Holo", + "symbol": "HOT", + "decimals": 18, + "exchangeAddress": "0xd4777E164c6C683E10593E08760B803D58529a8E" + }, + "0x607F4C5BB672230e8672085532f7e901544a7375": { + "name": "iExec", + "symbol": "RLC", + "decimals": 9, + "exchangeAddress": "0xA825CAE02B310E9901b4776806CE25db520c8642" + }, + "0x93ED3FBe21207Ec2E8f2d3c3de6e058Cb73Bc04d": { + "name": "Kleros", + "symbol": "PNK", + "decimals": 18, + "exchangeAddress": "0xF506828B166de88cA2EDb2A98D960aBba0D2402A" + }, + "0xdd974D5C2e2928deA5F71b9825b8b646686BD200": { + "name": "Kyber Network", + "symbol": "KNC", + "decimals": 18, + "exchangeAddress": "0x49c4f9bc14884f6210F28342ceD592A633801a8b" + }, + "0x58b6A8A3302369DAEc383334672404Ee733aB239": { + "name": "Livepeer", + "symbol": "LPT", + "decimals": 18, + "exchangeAddress": "0xc4a1C45D5546029Fd57128483aE65b56124BFA6A" + }, + "0xA4e8C3Ec456107eA67d3075bF9e3DF3A75823DB0": { + "name": "Loom", + "symbol": "LOOM", + "decimals": 18, + "exchangeAddress": "0x417CB32bc991fBbDCaE230C7c4771CC0D69daA6b" + }, + "0xBBbbCA6A901c926F240b89EacB641d8Aec7AEafD": { + "name": "Loopring", + "symbol": "LRC", + "decimals": 18, + "exchangeAddress": "0xA539BAaa3aCA455c986bB1E25301CEF936CE1B65" + }, + "0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2": { + "name": "Maker", + "symbol": "MKR", + "decimals": 18, + "exchangeAddress": "0x2C4Bd064b998838076fa341A83d007FC2FA50957" + }, + "0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0": { + "name": "Matic Network", + "symbol": "MATIC", + "decimals": 18, + "exchangeAddress": "0x9a7A75E66B325a3BD46973B2b57c9b8d9D26a621" + }, + "0xec67005c4E498Ec7f55E092bd1d35cbC47C91892": { + "name": "Melon", + "symbol": "MLN", + "decimals": 18, + "exchangeAddress": "0xA931F4eB165AC307fD7431b5EC6eADde53E14b0C" + }, + "0xaAAf91D9b90dF800Df4F55c205fd6989c977E73a": { + "name": "Monolith", + "symbol": "TKN", + "decimals": 8, + "exchangeAddress": "0xb6cFBf322db47D39331E306005DC7E5e6549942B" + }, + "0xB62132e35a6c13ee1EE0f84dC5d40bad8d815206": { + "name": "Nexo", + "symbol": "NEXO", + "decimals": 18, + "exchangeAddress": "0x069C97DBA948175D10af4b2414969e0B88d44669" + }, + "0x1776e1F26f98b1A5dF9cD347953a26dd3Cb46671": { + "name": "Numeraire", + "symbol": "NMR", + "decimals": 18, + "exchangeAddress": "0x2Bf5A5bA29E60682fC56B2Fcf9cE07Bef4F6196f" + }, + "0x8E870D67F660D95d5be530380D0eC0bd388289E1": { + "name": "Paxos Standard", + "symbol": "PAX", + "decimals": 18, + "exchangeAddress": "0xC040d51b07Aea5d94a89Bc21E8078B77366Fc6C7" + }, + "0x6758B7d441a9739b98552B373703d8d3d14f9e62": { + "name": "POA Network", + "symbol": "POA20", + "decimals": 18, + "exchangeAddress": "0xA2E6B3EF205FeAEe475937c4883b24E6eB717eeF" + }, + "0x255Aa6DF07540Cb5d3d297f0D0D4D84cb52bc8e6": { + "name": "Raiden", + "symbol": "RDN", + "decimals": 18, + "exchangeAddress": "0x7D03CeCb36820b4666F45E1b4cA2538724Db271C" + }, + "0x408e41876cCCDC0F92210600ef50372656052a38": { + "name": "Republic", + "symbol": "REN", + "decimals": 18, + "exchangeAddress": "0x43892992B0b102459E895B88601Bb2C76736942c" + }, + "0xB4EFd85c19999D84251304bDA99E90B92300Bd93": { + "name": "Rocket Pool", + "symbol": "RPL", + "decimals": 18, + "exchangeAddress": "0x3Fb2F18065926DdB33E7571475c509541d15dA0e" + }, + "0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359": { + "name": "Sai", + "symbol": "SAI", + "decimals": 18, + "exchangeAddress": "0x09cabEC1eAd1c0Ba254B09efb3EE13841712bE14" + }, + "0x06f65b8cfcb13a9fe37d836fe9708da38ecb29b2": { + "name": "Saint Fame", + "symbol": "FAME", + "decimals": 18, + "exchangeAddress": "0x5e7907aC70b9a781365c72F2acEE96710bdA042e" + }, + "0x4156D3342D5c385a87D264F90653733592000581": { + "name": "SALT", + "symbol": "SALT", + "decimals": 8, + "exchangeAddress": "0xC0C59cDe851bfcbdddD3377EC10ea54A18Efb937" + }, + "0x42d6622deCe394b54999Fbd73D108123806f6a18": { + "name": "SpankChain", + "symbol": "SPANK", + "decimals": 18, + "exchangeAddress": "0x4e395304655F0796bc3bc63709DB72173b9DdF98" + }, + "0x744d70FDBE2Ba4CF95131626614a1763DF805B9E": { + "name": "Status", + "symbol": "SNT", + "decimals": 18, + "exchangeAddress": "0x1aEC8F11A7E78dC22477e91Ed924Fab46e3A88Fd" + }, + "0xB64ef51C888972c908CFacf59B47C1AfBC0Ab8aC": { + "name": "Storj", + "symbol": "STORJ", + "decimals": 8, + "exchangeAddress": "0xA7298541E52f96d42382eCBe4f242cBcBC534d02" + }, + "0xc011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f": { + "name": "Synthetix", + "symbol": "SNX", + "decimals": 18, + "exchangeAddress": "0x3958b4ec427f8fa24eb60f42821760e88d485f7f" + }, + "0x5e74c9036fb86bd7ecdcb084a0673efc32ea31cb": { + "name": "Synthetix ETH", + "symbol": "sETH", + "decimals": 18, + "exchangeAddress": "0xe9cf7887b93150d4f2da7dfc6d502b216438f244" + }, + "0x57ab1ec28d129707052df4df418d58a2d46d5f51": { + "name": "Synthetix USD", + "symbol": "sUSD", + "decimals": 18, + "exchangeAddress": "0xb944d13b2f4047fc7bd3f7013bcf01b115fb260d" + }, + "0x8dd5fbCe2F6a956C3022bA3663759011Dd51e73E": { + "name": "TrueUSD", + "symbol": "TUSD", + "decimals": 18, + "exchangeAddress": "0x4F30E682D0541eAC91748bd38A648d759261b8f3" + }, + "0x23B608675a2B2fB1890d3ABBd85c5775c51691d5": { + "symbol": "SOCKS", + "name": "Unisocks Edition 0", + "decimals": 18, + "exchangeAddress": "0x22d8432cc7aA4f8712a655fC4cdfB1baEC29FCA9" + }, + "0x09cabEC1eAd1c0Ba254B09efb3EE13841712bE14": { + "name": "Uniswap V1", + "symbol": "UNI-V1:SAI", + "decimals": 18, + "exchangeAddress": "0x601c32E0580D3aef9437dB52D09f5a5D7E60eC22" + }, + "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48": { + "name": "USD Coin", + "symbol": "USDC", + "decimals": 6, + "exchangeAddress": "0x97deC872013f6B5fB443861090ad931542878126" + }, + "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599": { + "name": "Wrapped Bitcoin", + "symbol": "WBTC", + "decimals": 8, + "exchangeAddress": "0x4d2f5cFbA55AE412221182D8475bC85799A5644b" + }, + "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2": { + "name": "Wrapped Ether", + "symbol": "WETH", + "decimals": 18, + "exchangeAddress": "0xA2881A90Bf33F03E7a3f803765Cd2ED5c8928dFb" + } +} diff --git a/src/screens/CurrencySelectModal.js b/src/screens/CurrencySelectModal.js new file mode 100644 index 00000000000..611443b8dbe --- /dev/null +++ b/src/screens/CurrencySelectModal.js @@ -0,0 +1,241 @@ +import { get, map, property } from 'lodash'; +import PropTypes from 'prop-types'; +import { produce } from 'immer'; +import React, { Component } from 'react'; +import Animated from 'react-native-reanimated'; +import { NavigationEvents, withNavigationFocus } from 'react-navigation'; +import { compose, mapProps } from 'recompact'; +import { withUniswapAssets } from '../hoc'; +import { position } from '../styles'; +import { isNewValueForObjectPaths } from '../utils'; +import { filterList } from '../utils/search'; +import { interpolate } from '../components/animations'; +import { + CurrencySelectionList, + CurrencySelectModalHeader, + ExchangeSearch, +} from '../components/exchange'; +import GestureBlocker from '../components/GestureBlocker'; +import { Column, KeyboardFixedOpenLayout } from '../components/layout'; +import { Modal } from '../components/modal'; +import { exchangeModalBorderRadius } from './ExchangeModal'; + +const EMPTY_ARRAY = []; + +const appendAssetWithSearchableKey = asset => ({ + ...asset, + uniqueId: `${asset.name} ${asset.symbol}`, +}); + +const buildUniqueIdForListData = (items = EMPTY_ARRAY) => + items.map(property('address')).join('_'); + +const normalizeAssetItems = assetsArray => + map(assetsArray, appendAssetWithSearchableKey); + +export const CurrencySelectionTypes = { + input: 'input', + output: 'output', +}; + +class CurrencySelectModal extends Component { + static propTypes = { + assetsAvailableOnUniswap: PropTypes.arrayOf(PropTypes.object), + isFocused: PropTypes.bool, + navigation: PropTypes.object, + sortedUniswapAssets: PropTypes.array, + transitionPosition: PropTypes.object, + type: PropTypes.oneOf(Object.keys(CurrencySelectionTypes)), + }; + + state = { + assetsToFavoriteQueue: {}, + searchQuery: '', + }; + + shouldComponentUpdate = (nextProps, nextState) => { + let currentAssets = this.props.sortedUniswapAssets; + let nextAssets = EMPTY_ARRAY; + + if (nextProps.type === CurrencySelectionTypes.input) { + currentAssets = this.props.assetsAvailableOnUniswap; + nextAssets = nextProps.assetsAvailableOnUniswap; + } else if (nextProps.type === CurrencySelectionTypes.output) { + nextAssets = nextProps.sortedUniswapAssets; + } + + const currentAssetsUniqueId = buildUniqueIdForListData(currentAssets); + const nextAssetsUniqueId = buildUniqueIdForListData(nextAssets); + const isNewAssets = currentAssetsUniqueId !== nextAssetsUniqueId; + + const isNewProps = isNewValueForObjectPaths(this.props, nextProps, [ + 'isFocused', + 'type', + ]); + + const isNewState = isNewValueForObjectPaths(this.state, nextState, [ + 'searchQuery', + 'assetsToFavoriteQueue', + ]); + + return isNewAssets || isNewProps || isNewState; + }; + + dangerouslySetIsGestureBlocked = isGestureBlocked => { + // dangerouslyGetParent is a bad pattern in general, but in this case is exactly what we expect + this.props.navigation + .dangerouslyGetParent() + .setParams({ isGestureBlocked }); + }; + + handleChangeSearchQuery = searchQuery => { + this.setState({ searchQuery }); + }; + + handleFavoriteAsset = (assetAddress, isFavorited) => { + this.setState( + produce(draft => { + draft.assetsToFavoriteQueue[assetAddress] = isFavorited; + }) + ); + }; + + handlePressBack = () => { + this.props.navigation.navigate('MainExchangeScreen'); + }; + + handleSelectAsset = item => { + const { navigation } = this.props; + // It's a bit weird and I'm not sure why on invoking + // navigation.getParam('onSelectCurrency')(item) + // but this small hack seems to be a legit workaround + const onSelectCurrency = navigation.getParam('onSelectCurrency'); + onSelectCurrency(item); + navigation.navigate('MainExchangeScreen'); + }; + + handleDidBlur = () => { + const { uniswapUpdateFavorites } = this.props; + const { assetsToFavoriteQueue } = this.state; + + Object.keys(assetsToFavoriteQueue).map(assetToFavorite => + uniswapUpdateFavorites( + assetToFavorite, + assetsToFavoriteQueue[assetToFavorite] + ) + ); + + this.handleChangeSearchQuery(''); + }; + + handleWillBlur = () => this.dangerouslySetIsGestureBlocked(false); + + handleWillFocus = () => { + this.dangerouslySetIsGestureBlocked(true); + if (this.searchInputRef.current) { + this.searchInputRef.current.focus(); + } + }; + + searchInputRef = React.createRef(); + + render = () => { + const { + assetsAvailableOnUniswap, + isFocused, + sortedUniswapAssets, + transitionPosition, + type, + } = this.props; + + if (type === null || type === undefined) { + return null; + } + + const { searchQuery } = this.state; + + let headerTitle = ''; + let assets = sortedUniswapAssets; + if (type === CurrencySelectionTypes.input) { + headerTitle = 'Swap'; + assets = assetsAvailableOnUniswap; + } else if (type === CurrencySelectionTypes.output) { + headerTitle = 'Receive'; + } + + const listItems = filterList(assets, searchQuery, 'uniqueId'); + + return ( + + + + + + + + + + + + + + + ); + }; +} + +export default compose( + withNavigationFocus, + withUniswapAssets, + mapProps( + ({ + assetsAvailableOnUniswap, + navigation, + sortedUniswapAssets, + ...props + }) => ({ + ...props, + assetsAvailableOnUniswap: normalizeAssetItems(assetsAvailableOnUniswap), + navigation, + sortedUniswapAssets: normalizeAssetItems(sortedUniswapAssets), + transitionPosition: get(navigation, 'state.params.position'), + type: get(navigation, 'state.params.type', null), + }) + ) +)(CurrencySelectModal); diff --git a/src/screens/ExampleScreen.js b/src/screens/ExampleScreen.js index e8e04c3c275..32e3ce9768d 100644 --- a/src/screens/ExampleScreen.js +++ b/src/screens/ExampleScreen.js @@ -1,20 +1,29 @@ import PropTypes from 'prop-types'; import React, { PureComponent } from 'react'; -import { Page } from '../components/layout'; -import { withHideSplashScreen } from '../hoc'; -import { position } from '../styles'; +import { compose } from 'recompact'; +import { GasSpeedButton } from '../components/gas'; +import { Centered, Page } from '../components/layout'; +import { withDataInit, withAccountData } from '../hoc'; +import { colors, position } from '../styles'; class ExampleScreen extends PureComponent { static propTypes = { - onHideSplashScreen: PropTypes.func, - } + initializeWallet: PropTypes.func, + }; - componentDidMount = () => this.props.onHideSplashScreen() + componentDidMount = async () => { + try { + await this.props.initializeWallet(); + } catch (error) { + console.log('lol error on ExampleScreen like a n00b: ', error); + } + }; render = () => ( {/* @@ -22,8 +31,11 @@ class ExampleScreen extends PureComponent { // ... i dont want to set up storybook right now */} + + + - ) + ); } -export default withHideSplashScreen(ExampleScreen); +export default compose(withAccountData, withDataInit)(ExampleScreen); diff --git a/src/screens/ExchangeModal.js b/src/screens/ExchangeModal.js new file mode 100644 index 00000000000..dc809f6eab3 --- /dev/null +++ b/src/screens/ExchangeModal.js @@ -0,0 +1,950 @@ +import { + getMarketDetails as getUniswapMarketDetails, + tradeEthForExactTokensWithData, + tradeExactEthForTokensWithData, + tradeExactTokensForEthWithData, + tradeExactTokensForTokensWithData, + tradeTokensForExactEthWithData, + tradeTokensForExactTokensWithData, +} from '@uniswap/sdk'; +import BigNumber from 'bignumber.js'; +import { find, get, isNil, toLower } from 'lodash'; +import PropTypes from 'prop-types'; +import React, { Component, Fragment } from 'react'; +import { TextInput, InteractionManager } from 'react-native'; +import Animated from 'react-native-reanimated'; +import { withNavigationFocus, NavigationEvents } from 'react-navigation'; +import { compose, toClass, withProps } from 'recompact'; +import { interpolate } from '../components/animations'; +import { + ConfirmExchangeButton, + ExchangeInputField, + ExchangeModalHeader, + ExchangeOutputField, + SlippageWarning, +} from '../components/exchange'; +import { FloatingPanel, FloatingPanels } from '../components/expanded-state'; +import { GasSpeedButton } from '../components/gas'; +import GestureBlocker from '../components/GestureBlocker'; +import { + Centered, + Column, + KeyboardFixedOpenLayout, +} from '../components/layout'; +import { estimateSwapGasLimit, executeSwap } from '../handlers/uniswap'; +import { + convertAmountFromNativeValue, + convertAmountToNativeAmount, + convertAmountToNativeDisplay, + convertAmountToRawAmount, + convertNumberToString, + convertRawAmountToDecimalFormat, + divide, + greaterThan, + subtract, + updatePrecisionToDisplay, +} from '../helpers/utilities'; +import { + withAccountData, + withAccountSettings, + withBlockedHorizontalSwipe, + withGas, + withTransactionConfirmationScreen, + withTransitionProps, + withUniswapAllowances, + withUniswapAssets, +} from '../hoc'; +import ethUnits from '../references/ethereum-units.json'; +import { colors, padding, position } from '../styles'; +import { + isNewValueForObjectPaths, + contractUtils, + ethereumUtils, + gasUtils, + isNewValueForPath, +} from '../utils'; +import { CurrencySelectionTypes } from './CurrencySelectModal'; + +export const exchangeModalBorderRadius = 30; + +const AnimatedFloatingPanels = Animated.createAnimatedComponent( + toClass(FloatingPanels) +); + +const isSameAsset = (a, b) => { + if (!a || !b) return false; + const assetA = toLower(get(a, 'address', '')); + const assetB = toLower(get(b, 'address', '')); + return assetA === assetB; +}; + +const getNativeTag = field => get(field, '_inputRef._nativeTag'); + +class ExchangeModal extends Component { + static propTypes = { + accountAddress: PropTypes.string, + allAssets: PropTypes.array, + allowances: PropTypes.object, + assetsAvailableOnUniswap: PropTypes.arrayOf(PropTypes.object), + chainId: PropTypes.number, + dataAddNewTransaction: PropTypes.func, + gasLimit: PropTypes.number, + gasUpdateDefaultGasLimit: PropTypes.func, + gasUpdateTxFee: PropTypes.func, + inputReserve: PropTypes.object, + isFocused: PropTypes.bool, + nativeCurrency: PropTypes.string, + navigation: PropTypes.object, + outputReserve: PropTypes.object, + pendingApprovals: PropTypes.object, + selectedGasPrice: PropTypes.object, + tabPosition: PropTypes.object, // animated value + tokenReserves: PropTypes.object, + tradeDetails: PropTypes.object, + txFees: PropTypes.object, + uniswapAddPendingApproval: PropTypes.func, + uniswapUpdateAllowances: PropTypes.func, + }; + + state = { + approvalCreationTimestamp: null, + approvalEstimatedTimeInMs: null, + inputAllowance: null, + inputAmount: null, + inputAmountDisplay: null, + inputAsExactAmount: false, + inputCurrency: ethereumUtils.getAsset(this.props.allAssets), + inputExecutionRate: null, + inputNativePrice: null, + isAssetApproved: true, + isAuthorizing: false, + isSufficientBalance: true, + isUnlockingAsset: false, + nativeAmount: null, + outputAmount: null, + outputAmountDisplay: null, + outputCurrency: null, + outputExecutionRate: null, + outputNativePrice: null, + showConfirmButton: false, + slippage: null, + tradeDetails: null, + }; + + componentDidMount() { + this.props.gasUpdateDefaultGasLimit(ethUnits.basic_swap); + } + + shouldComponentUpdate = (nextProps, nextState) => { + const isNewProps = isNewValueForObjectPaths(this.props, nextProps, [ + 'inputReserve.token.address', + 'outputReserve.token.address', + 'pendingApprovals', + ]); + + // Code below is a workaround. We noticed that opening keyboard while animation + // (with autofocus) can lead to frame drops. In order not to limit this + // I manually can focus instead of relying on built-in autofocus. + // Maybe that's not perfect, but works for now Β―\_(ツ)_/Β― + if ( + this.props.isTransitioning && + !nextProps.isTransitioning && + this.lastFocusedInput === null + ) { + this.inputFocusInteractionHandle = InteractionManager.runAfterInteractions( + this.focusInputField + ); + } + + const isNewState = isNewValueForObjectPaths(this.state, nextState, [ + 'approvalCreationTimestamp', + 'approvalEstimatedTimeInMs', + 'inputAmount', + 'inputCurrency.uniqueId', + 'isAssetApproved', + 'isAuthorizing', + 'isSufficientBalance', + 'isUnlockingAsset', + 'nativeAmount', + 'outputAmount', + 'outputCurrency.uniqueId', + 'slippage', + ]); + + return isNewProps || isNewState; + }; + + componentDidUpdate = (prevProps, prevState) => { + if (prevProps.isTransitioning && !this.props.isTransitioning) { + this.props.navigation.emit('refocus'); + } + + const isNewAmountOrCurrency = isNewValueForObjectPaths( + this.state, + prevState, + [ + 'inputAmount', + 'inputCurrency.uniqueId', + 'outputAmount', + 'outputCurrency.uniqueId', + ] + ); + + let isNewNativeAmount = isNewValueForPath( + this.state, + prevState, + 'nativeAmount' + ); + + if (isNewNativeAmount) { + // Only consider 'new' if the native input isnt focused, + // otherwise itll fight with the user's keystrokes + isNewNativeAmount = this.nativeFieldRef.isFocused(); + } + + const isNewOutputReserveCurrency = isNewValueForPath( + this.props, + prevProps, + 'outputReserve.token.address' + ); + + if ( + isNewAmountOrCurrency || + isNewNativeAmount || + isNewOutputReserveCurrency + ) { + this.getMarketDetails(isNewOutputReserveCurrency); + } + + const inputCurrencyAddressPath = 'inputCurrency.address'; + const inputCurrencyAddress = toLower( + get(this.state, inputCurrencyAddressPath) + ); + + const removedFromPending = + !get(this.props, `pendingApprovals[${inputCurrencyAddress}]`, null) && + get(prevProps, `pendingApprovals[${inputCurrencyAddress}]`, null); + + if ( + removedFromPending || + isNewValueForPath(this.state, prevState, inputCurrencyAddressPath) + ) { + this.getCurrencyAllowance(); + } + }; + + componentWillUnmount = () => { + if (this.inputFocusInteractionHandle) { + InteractionManager.clearInteractionHandle( + this.inputFocusInteractionHandle + ); + } + this.props.uniswapClearCurrenciesAndReserves(); + }; + + lastFocusedInput = null; + inputFieldRef = null; + nativeFieldRef = null; + outputFieldRef = null; + + assignInputFieldRef = ref => { + this.inputFieldRef = ref; + }; + assignNativeFieldRef = ref => { + this.nativeFieldRef = ref; + }; + assignOutputFieldRef = ref => { + this.outputFieldRef = ref; + }; + + clearForm = () => { + if (this.inputFieldRef) this.inputFieldRef.clear(); + if (this.nativeFieldRef) this.nativeFieldRef.clear(); + if (this.outputFieldRef) this.outputFieldRef.clear(); + }; + + focusInputField = () => { + if (this.inputFieldRef) { + this.inputFieldRef.focus(); + } + }; + + getCurrencyAllowance = async () => { + const { + accountAddress, + allowances, + gasUpdateTxFee, + pendingApprovals, + uniswapUpdateAllowances, + } = this.props; + const { inputCurrency } = this.state; + + if (isNil(inputCurrency)) { + return this.setState({ isAssetApproved: true }); + } + + const { address: inputAddress, exchangeAddress } = inputCurrency; + + if (inputAddress === 'eth') { + return this.setState({ isAssetApproved: true }); + } + + let allowance = allowances[inputAddress]; + if (!greaterThan(allowance, 0)) { + allowance = await contractUtils.getAllowance( + accountAddress, + inputCurrency, + exchangeAddress + ); + uniswapUpdateAllowances({ [toLower(inputAddress)]: allowance }); + } + const isAssetApproved = greaterThan(allowance, 0); + if (isAssetApproved) { + return this.setState({ + approvalCreationTimestamp: null, + approvalEstimatedTimeInMs: null, + isAssetApproved, + isUnlockingAsset: false, + }); + } + const pendingApproval = pendingApprovals[toLower(inputCurrency.address)]; + const isUnlockingAsset = !!pendingApproval; + + try { + const gasLimit = await contractUtils.estimateApprove( + inputCurrency.address, + exchangeAddress + ); + gasUpdateTxFee(gasLimit, gasUtils.FAST); + return this.setState({ + approvalCreationTimestamp: isUnlockingAsset + ? pendingApproval.creationTimestamp + : null, + approvalEstimatedTimeInMs: isUnlockingAsset + ? pendingApproval.estimatedTimeInMs + : null, + isAssetApproved, + isUnlockingAsset, + }); + } catch (error) { + gasUpdateTxFee(); + return this.setState({ + approvalCreationTimestamp: null, + approvalEstimatedTimeInMs: null, + isAssetApproved, + isUnlockingAsset: false, + }); + } + }; + + getMarketDetails = async isNewOutputReserveCurrency => { + const { + accountAddress, + chainId, + gasUpdateTxFee, + inputReserve, + nativeCurrency, + outputReserve, + selectedGasPrice, + } = this.props; + const { + inputAmount, + inputAsExactAmount, + inputCurrency, + isAssetApproved, + nativeAmount, + outputAmount, + outputCurrency, + } = this.state; + + const isMissingAmounts = !inputAmount && !outputAmount; + const isMissingCurrency = !inputCurrency || !outputCurrency; + const isMissingReserves = + (inputCurrency && inputCurrency.address !== 'eth' && !inputReserve) || + (outputCurrency && outputCurrency.address !== 'eth' && !outputReserve); + if (isMissingAmounts || isMissingCurrency || isMissingReserves) { + return; + } + + try { + const { address: inputAddress, decimals: inputDecimals } = inputCurrency; + const { + address: outputAddress, + decimals: outputDecimals, + } = outputCurrency; + + const isInputEth = inputAddress === 'eth'; + const isOutputEth = outputAddress === 'eth'; + + const rawInputAmount = convertAmountToRawAmount( + parseFloat(inputAmount) || 0, + inputDecimals + ); + const rawOutputAmount = convertAmountToRawAmount( + parseFloat(outputAmount) || 0, + outputDecimals + ); + + let tradeDetails = null; + + if (isInputEth && !isOutputEth) { + tradeDetails = inputAsExactAmount + ? tradeExactEthForTokensWithData( + outputReserve, + rawInputAmount, + chainId + ) + : tradeEthForExactTokensWithData( + outputReserve, + rawOutputAmount, + chainId + ); + } else if (!isInputEth && isOutputEth) { + tradeDetails = inputAsExactAmount + ? tradeExactTokensForEthWithData( + inputReserve, + rawInputAmount, + chainId + ) + : tradeTokensForExactEthWithData( + inputReserve, + rawOutputAmount, + chainId + ); + } else if (!isInputEth && !isOutputEth) { + tradeDetails = inputAsExactAmount + ? tradeExactTokensForTokensWithData( + inputReserve, + outputReserve, + rawInputAmount, + chainId + ) + : tradeTokensForExactTokensWithData( + inputReserve, + outputReserve, + rawOutputAmount, + chainId + ); + } + + let inputExecutionRate = ''; + let outputExecutionRate = ''; + let inputNativePrice = ''; + let outputNativePrice = ''; + + if (inputCurrency) { + const inputPriceValue = get(inputCurrency, 'price.value', 0); + inputExecutionRate = updatePrecisionToDisplay( + get(tradeDetails, 'executionRate.rate', BigNumber(0)), + inputPriceValue + ); + + inputNativePrice = convertAmountToNativeDisplay( + inputPriceValue, + nativeCurrency + ); + } + + if (outputCurrency) { + const outputPriceValue = get(outputCurrency, 'price.value', 0); + outputExecutionRate = updatePrecisionToDisplay( + get(tradeDetails, 'executionRate.rateInverted', BigNumber(0)), + outputPriceValue, + true + ); + + outputNativePrice = convertAmountToNativeDisplay( + outputPriceValue, + nativeCurrency + ); + } + + const slippage = convertNumberToString( + get(tradeDetails, 'executionRateSlippage', 0) + ); + const inputBalance = ethereumUtils.getBalanceAmount( + selectedGasPrice, + inputCurrency + ); + + const isSufficientBalance = + !parseFloat(inputAmount) || + parseFloat(inputBalance) >= parseFloat(inputAmount); + + this.setState({ + inputExecutionRate, + inputNativePrice, + isSufficientBalance, + outputExecutionRate, + outputNativePrice, + slippage, + tradeDetails, + }); + + const isInputEmpty = !inputAmount; + const isNativeEmpty = !nativeAmount; + const isOutputEmpty = !outputAmount; + + const isInputZero = Number(inputAmount) === 0; + const isOutputZero = Number(outputAmount) === 0; + + if (this.nativeFieldRef.isFocused() && isNativeEmpty) { + this.clearForm(); + } + + if ( + inputAsExactAmount || + (isNewOutputReserveCurrency && inputAsExactAmount) + ) { + if ((isInputEmpty || isInputZero) && !this.outputFieldRef.isFocused()) { + this.setOutputAmount(); + } else { + const updatedOutputAmount = get(tradeDetails, 'outputAmount.amount'); + const rawUpdatedOutputAmount = convertRawAmountToDecimalFormat( + updatedOutputAmount, + outputDecimals + ); + if (rawUpdatedOutputAmount !== '0') { + let outputNativePrice = get(outputCurrency, 'price.value', null); + if (isNil(outputNativePrice)) { + outputNativePrice = this.getMarketPrice(); + } + const updatedOutputAmountDisplay = updatePrecisionToDisplay( + rawUpdatedOutputAmount, + outputNativePrice + ); + + this.setOutputAmount( + rawUpdatedOutputAmount, + updatedOutputAmountDisplay, + inputAsExactAmount + ); + } + } + } + + if (!inputAsExactAmount && !this.inputFieldRef.isFocused()) { + if (isOutputEmpty || isOutputZero) { + this.setInputAmount(); + this.setState({ + isSufficientBalance: true, + }); + } else { + const updatedInputAmount = get(tradeDetails, 'inputAmount.amount'); + const rawUpdatedInputAmount = convertRawAmountToDecimalFormat( + updatedInputAmount, + inputDecimals + ); + + const updatedInputAmountDisplay = updatePrecisionToDisplay( + rawUpdatedInputAmount, + get(inputCurrency, 'price.value'), + true + ); + + this.setInputAmount( + rawUpdatedInputAmount, + updatedInputAmountDisplay, + inputAsExactAmount + ); + + this.setState({ + isSufficientBalance: + parseFloat(inputBalance) >= parseFloat(rawUpdatedInputAmount), + }); + } + } + + if (isAssetApproved) { + const gasLimit = await estimateSwapGasLimit( + accountAddress, + tradeDetails + ); + gasUpdateTxFee(gasLimit); + } + } catch (error) { + console.log('error getting market details', error); + // TODO error state + } + }; + + handleFocusField = ({ currentTarget }) => { + this.lastFocusedInput = currentTarget; + }; + + handlePressMaxBalance = () => { + const { inputCurrency } = this.state; + let maxBalance = get(inputCurrency, 'balance.amount', 0); + if (inputCurrency.address === 'eth') { + maxBalance = subtract(maxBalance, 0.01); + } + + return this.setInputAmount(maxBalance); + }; + + handleSubmit = async () => { + this.setState({ isAuthorizing: true }); + const { + accountAddress, + dataAddNewTransaction, + gasLimit, + navigation, + selectedGasPrice, + } = this.props; + const { inputAmount, inputCurrency, tradeDetails } = this.state; + + try { + const gasPrice = get(selectedGasPrice, 'value.amount'); + const txn = await executeSwap(tradeDetails, gasLimit, gasPrice); + this.setState({ isAuthorizing: false }); + if (txn) { + dataAddNewTransaction({ + amount: inputAmount, + asset: inputCurrency, + from: accountAddress, + hash: txn.hash, + nonce: get(txn, 'nonce'), + to: get(txn, 'to'), + }); + navigation.navigate('ProfileScreen'); + } + } catch (error) { + this.setState({ isAuthorizing: false }); + console.log('error submitting swap', error); + navigation.navigate('WalletScreen'); + } + }; + + handleUnlockAsset = async () => { + try { + const { inputCurrency } = this.state; + const { gasLimit, gasPrices, uniswapAddPendingApproval } = this.props; + const fastGasPrice = get(gasPrices, `[${gasUtils.FAST}]`); + const { + creationTimestamp: approvalCreationTimestamp, + approval: { hash }, + } = await contractUtils.approve( + inputCurrency.address, + inputCurrency.exchangeAddress, + gasLimit, + get(fastGasPrice, 'value.amount') + ); + const approvalEstimatedTimeInMs = get( + fastGasPrice, + 'estimatedTime.amount' + ); + uniswapAddPendingApproval( + inputCurrency.address, + hash, + approvalCreationTimestamp, + approvalEstimatedTimeInMs + ); + this.setState({ + approvalCreationTimestamp, + approvalEstimatedTimeInMs, + isUnlockingAsset: true, + }); + } catch (error) { + console.log('could not unlock asset', error); + this.setState({ + approvalCreationTimestamp: null, + approvalEstimatedTimeInMs: null, + isUnlockingAsset: false, + }); + } + }; + + findNextFocused = () => { + const inputRefTag = getNativeTag(this.inputFieldRef); + const nativeInputRefTag = getNativeTag(this.nativeFieldRef); + const outputRefTag = getNativeTag(this.outputFieldRef); + + const lastFocusedIsInputType = + this.lastFocusedInput === inputRefTag || + this.lastFocusedInput === nativeInputRefTag; + + const lastFocusedIsOutputType = this.lastFocusedInput === outputRefTag; + + if (lastFocusedIsInputType && !this.state.inputCurrency) { + return outputRefTag; + } + + if (lastFocusedIsOutputType && !this.state.outputCurrency) { + return inputRefTag; + } + + return this.lastFocusedInput; + }; + + handleKeyboardManagement = () => { + if (this.lastFocusedInput !== TextInput.State.currentlyFocusedField()) { + TextInput.State.focusTextInput(this.findNextFocused()); + this.lastFocusedInput = null; + } + }; + + navigateToSelectInputCurrency = () => { + this.props.navigation.navigate('CurrencySelectScreen', { + onSelectCurrency: this.setInputCurrency, + type: CurrencySelectionTypes.input, + }); + }; + + navigateToSelectOutputCurrency = () => { + this.props.navigation.navigate('CurrencySelectScreen', { + onSelectCurrency: this.setOutputCurrency, + type: CurrencySelectionTypes.output, + }); + }; + + getMarketPrice = () => { + const { allAssets, inputReserve } = this.props; + if (!inputReserve) return 0; + const ethPrice = ethereumUtils.getEthPriceUnit(allAssets); + const inputMarketDetails = getUniswapMarketDetails(undefined, inputReserve); + const assetToEthPrice = get(inputMarketDetails, 'marketRate.rate'); + return divide(ethPrice, assetToEthPrice) || 0; + }; + + setInputAmount = (inputAmount, amountDisplay, inputAsExactAmount = true) => { + this.setState(({ inputCurrency }) => { + const newState = { + inputAmount, + inputAmountDisplay: + amountDisplay !== undefined ? amountDisplay : inputAmount, + inputAsExactAmount, + }; + + if (!this.nativeFieldRef.isFocused()) { + let nativeAmount = null; + + const isInputZero = parseFloat(inputAmount) === 0; + + if (inputAmount && !isInputZero) { + let nativePrice = get(inputCurrency, 'native.price.amount', null); + if (isNil(nativePrice)) { + nativePrice = this.getMarketPrice(); + } + nativeAmount = convertAmountToNativeAmount(inputAmount, nativePrice); + } + + newState.nativeAmount = nativeAmount; + } + + return newState; + }); + }; + + setInputCurrency = (inputCurrency, userSelected = true) => { + const { inputCurrency: previousInputCurrency, outputCurrency } = this.state; + + if (!isSameAsset(inputCurrency, previousInputCurrency)) { + this.clearForm(); + } + + this.setState({ + inputCurrency, + showConfirmButton: !!inputCurrency && !!outputCurrency, + }); + this.props.uniswapUpdateInputCurrency(inputCurrency); + + if (userSelected && isSameAsset(inputCurrency, outputCurrency)) { + this.setOutputCurrency(previousInputCurrency, false); + } + }; + + setNativeAmount = nativeAmount => + this.setState(({ inputCurrency }) => { + let inputAmount = null; + let inputAmountDisplay = null; + + const isNativeZero = parseFloat(nativeAmount) === 0; + + if (nativeAmount && !isNativeZero) { + let nativePrice = get(inputCurrency, 'native.price.amount', null); + if (isNil(nativePrice)) { + nativePrice = this.getMarketPrice(); + } + inputAmount = convertAmountFromNativeValue( + nativeAmount, + nativePrice, + inputCurrency.decimals + ); + inputAmountDisplay = updatePrecisionToDisplay( + inputAmount, + nativePrice, + true + ); + } + + return { + inputAmount, + inputAmountDisplay, + inputAsExactAmount: true, + nativeAmount, + }; + }); + + setOutputAmount = (outputAmount, amountDisplay, inputAsExactAmount = false) => + this.setState({ + inputAsExactAmount, + outputAmount, + outputAmountDisplay: + amountDisplay !== undefined ? amountDisplay : outputAmount, + }); + + setOutputCurrency = (outputCurrency, userSelected = true) => { + const { + inputCurrency, + outputCurrency: previousOutputCurrency, + } = this.state; + const { assetsAvailableOnUniswap } = this.props; + + this.props.uniswapUpdateOutputCurrency(outputCurrency); + + this.setState({ + inputAsExactAmount: true, + outputCurrency, + showConfirmButton: !!inputCurrency && !!outputCurrency, + }); + + const existsInWallet = find( + assetsAvailableOnUniswap, + asset => get(asset, 'address') === get(previousOutputCurrency, 'address') + ); + if (userSelected && isSameAsset(inputCurrency, outputCurrency)) { + if (existsInWallet) { + this.setInputCurrency(previousOutputCurrency, false); + } else { + this.setInputCurrency(null, false); + } + } + }; + + render = () => { + const { nativeCurrency, tabPosition } = this.props; + + const { + approvalCreationTimestamp, + approvalEstimatedTimeInMs, + inputAmount, + inputAmountDisplay, + inputCurrency, + // inputExecutionRate, + // inputNativePrice, + isAssetApproved, + isAuthorizing, + isSufficientBalance, + isUnlockingAsset, + nativeAmount, + outputAmount, + outputAmountDisplay, + outputCurrency, + // outputExecutionRate, + // outputNativePrice, + showConfirmButton, + slippage, + } = this.state; + + const isSlippageWarningVisible = + isSufficientBalance && !!inputAmount && !!outputAmount; + return ( + + + + + + + + + + + {isSlippageWarningVisible && ( + + )} + {(showConfirmButton || !isAssetApproved) && ( + + + + + + + )} + + + + + + + ); + }; +} + +export default compose( + withAccountData, + withAccountSettings, + withBlockedHorizontalSwipe, + withGas, + withNavigationFocus, + withTransactionConfirmationScreen, + withTransitionProps, + withUniswapAllowances, + withUniswapAssets, + withProps(({ navigation, transitionProps: { isTransitioning } }) => ({ + isTransitioning, + tabPosition: get(navigation, 'state.params.position'), + })) +)(ExchangeModal); diff --git a/src/screens/ExpandedAssetScreen.js b/src/screens/ExpandedAssetScreen.js index a77018d95ea..0998c985b4b 100644 --- a/src/screens/ExpandedAssetScreen.js +++ b/src/screens/ExpandedAssetScreen.js @@ -1,55 +1,58 @@ import PropTypes from 'prop-types'; -import React, { createElement } from 'react'; +import React, { Component, createElement } from 'react'; import { StatusBar } from 'react-native'; import { + AddContactState, InvestmentExpandedState, TokenExpandedState, UniqueTokenExpandedState, } from '../components/expanded-state'; import { Centered } from '../components/layout'; import TouchableBackdrop from '../components/TouchableBackdrop'; -import { withNeverRerender } from '../hoc'; import { padding } from '../styles'; import { deviceUtils, safeAreaInsetValues } from '../utils'; -const { - bottom: safeAreaBottom, - top: safeAreaTop, -} = safeAreaInsetValues; +const { bottom: safeAreaBottom, top: safeAreaTop } = safeAreaInsetValues; const ScreenTypes = { + contact: AddContactState, token: TokenExpandedState, unique_token: UniqueTokenExpandedState, uniswap: InvestmentExpandedState, }; -const ExpandedAssetScreen = withNeverRerender(({ - containerPadding, - onPressBackground, - type, - ...props -}) => ( - - - - {createElement(ScreenTypes[type], props)} - -)); +export default class ExpandedAssetScreen extends Component { + static propTypes = { + address: PropTypes.string, + asset: PropTypes.object, + containerPadding: PropTypes.number.isRequired, + onCloseModal: PropTypes.func, + onPressBackground: PropTypes.func, + panelWidth: PropTypes.number, + type: PropTypes.oneOf(Object.keys(ScreenTypes)).isRequired, + }; -ExpandedAssetScreen.propTypes = { - asset: PropTypes.object, - containerPadding: PropTypes.number.isRequired, - onPressBackground: PropTypes.func, - panelWidth: PropTypes.number, - type: PropTypes.oneOf(['token', 'unique_token', 'uniswap']), -}; + static defaultProps = { + containerPadding: 15, + }; -ExpandedAssetScreen.defaultProps = { - containerPadding: 15, -}; + shouldComponentUpdate = () => false; -export default ExpandedAssetScreen; + render = () => ( + + + + {createElement(ScreenTypes[this.props.type], { + ...this.props, + })} + + ); +} diff --git a/src/screens/ExpandedAssetScreenWithData.js b/src/screens/ExpandedAssetScreenWithData.js index 36dd1b3049c..71828a7c23f 100644 --- a/src/screens/ExpandedAssetScreenWithData.js +++ b/src/screens/ExpandedAssetScreenWithData.js @@ -1,10 +1,5 @@ import { get } from 'lodash'; -import { - compose, - defaultProps, - withHandlers, - withProps, -} from 'recompact'; +import { compose, defaultProps, withHandlers, withProps } from 'recompact'; import { createSelector } from 'reselect'; import { withAccountData, withUniqueTokens } from '../hoc'; import { deviceUtils } from '../utils'; @@ -15,15 +10,12 @@ const navigationSelector = state => state.navigation; const withExpandedAssets = (containerPadding, navigation) => ({ ...get(navigation, 'state.params', {}), - panelWidth: deviceUtils.dimensions.width - (containerPadding * 2), + panelWidth: deviceUtils.dimensions.width - containerPadding * 2, }); const buildExpandedAssetsSelector = createSelector( - [ - containerPaddingSelector, - navigationSelector, - ], - withExpandedAssets, + [containerPaddingSelector, navigationSelector], + withExpandedAssets ); export default compose( @@ -31,5 +23,7 @@ export default compose( withUniqueTokens, defaultProps(ExpandedAssetScreen.defaultProps), withProps(buildExpandedAssetsSelector), - withHandlers({ onPressBackground: ({ navigation }) => () => navigation.goBack() }), + withHandlers({ + onPressBackground: ({ navigation }) => () => navigation.goBack(), + }) )(ExpandedAssetScreen); diff --git a/src/screens/ImportSeedPhraseSheet.js b/src/screens/ImportSeedPhraseSheet.js index cb9ef3edc20..8fb508796a6 100644 --- a/src/screens/ImportSeedPhraseSheet.js +++ b/src/screens/ImportSeedPhraseSheet.js @@ -1,24 +1,33 @@ +import analytics from '@segment/analytics-react-native'; import PropTypes from 'prop-types'; -import React from 'react'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { KeyboardAvoidingView } from 'react-native'; import { BorderlessButton } from 'react-native-gesture-handler'; -import { pure } from 'recompact'; +import { getStatusBarHeight } from 'react-native-iphone-x-helper'; +import { useNavigation } from 'react-navigation-hooks'; import styled from 'styled-components/primitives'; +import { Alert } from '../components/alerts'; import { Icon } from '../components/icons'; import { MultiLineInput } from '../components/inputs'; -import { Centered, Column, Row } from '../components/layout'; +import { Centered, Column, Row, RowWithMargins } from '../components/layout'; import { LoadingOverlay } from '../components/modal'; import { Text } from '../components/text'; -import transitionConfig from '../navigation/transitions'; -import { borders, colors, padding } from '../styles'; +import { useClipboard } from '../hooks'; +import { sheetVerticalOffset } from '../navigation/transitions/effects'; +import { borders, colors, padding, shadow } from '../styles'; +import { isValidSeed as validateSeed } from '../helpers/validators'; + +const keyboardVerticalOffset = sheetVerticalOffset + 19; +const statusBarHeight = getStatusBarHeight(true); const Container = styled(Column).attrs({ align: 'center', flex: 1, })` - ${borders.buildRadius('top', 12)}; + ${borders.buildRadius('top', 16)}; ${padding(0, 16, 16)}; background: ${colors.white}; + top: ${statusBarHeight}; `; const HandleIcon = styled(Icon).attrs({ @@ -29,95 +38,165 @@ const HandleIcon = styled(Icon).attrs({ margin-bottom: 2; `; -const ImportButton = styled(Row).attrs({ - align: 'center', - component: BorderlessButton, -})` - ${padding(6, 8)} - background: ${props => (props.disabled ? '#D2D3D7' : colors.appleBlue)}; +const StyledImportButton = styled(BorderlessButton)` + ${padding(6, 8)}; + ${shadow.build(0, 6, 10, colors.dark, 0.14)}; + background-color: ${({ disabled }) => + disabled ? '#D2D3D7' : colors.appleBlue}; border-radius: 15px; - shadow-color: ${colors.dark}; - shadow-offset: 0px 6px; - shadow-opacity: 0.14; - shadow-radius: 10; `; -const ImportSeedPhraseSheet = ({ - isClipboardContentsValidSeedPhrase, - isImporting, - isSeedPhraseValid, - onImportSeedPhrase, - onInputChange, - onPasteSeedPhrase, - onPressEnterKey, - onPressHelp, - seedPhrase, -}) => ( - - - Import - - - - - - - {!!seedPhrase && ( - - )} - - {seedPhrase ? 'Import' : 'Paste'} - - - - - {isImporting && ( - - )} - +const ConfirmImportAlert = onSuccess => + Alert({ + buttons: [ + { + onPress: onSuccess, + text: 'Import Wallet', + }, + { + style: 'cancel', + text: 'Cancel', + }, + ], + message: + 'This will replace your existing wallet.\n\nBefore continuing, please make sure you’ve backed up or emptied it!', + title: '🚨 Careful 🚨', + }); + +const ImportButton = ({ disabled, onPress, seedPhrase }) => ( + + + {!!seedPhrase && ( + + )} + + {seedPhrase ? 'Import' : 'Paste'} + + + ); +const ImportSeedPhraseSheet = ({ initializeWallet, isEmpty }) => { + const [clipboard] = useClipboard(); + const { navigate, setParams } = useNavigation(); + const [isImporting, setImporting] = useState(false); + const [seedPhrase, setSeedPhrase] = useState(''); + + const isClipboardValidSeedPhrase = useMemo(() => validateSeed(clipboard), [ + clipboard, + ]); + + const isSeedPhraseValid = useMemo(() => validateSeed(seedPhrase), [ + seedPhrase, + ]); + + const toggleImporting = useCallback( + newImportingState => { + setImporting(newImportingState); + setParams({ gesturesEnabled: !newImportingState }); + }, + [setImporting, setParams] + ); + + const handleSetSeedPhrase = useCallback( + text => { + if (isImporting) return null; + return setSeedPhrase(text); + }, + [isImporting, setSeedPhrase] + ); + + const onPressImportButton = () => { + if (isSeedPhraseValid && seedPhrase) { + return ConfirmImportAlert(() => toggleImporting(true)); + } + + if (isClipboardValidSeedPhrase && clipboard) { + return handleSetSeedPhrase(clipboard); + } + }; + + useEffect(() => { + if (isImporting) { + const id = setTimeout(() => { + initializeWallet(seedPhrase.trim()) + .then(success => { + if (success) { + toggleImporting(false); + analytics.track('Imported seed phrase', { + hadPreviousAddressWithValue: isEmpty, + }); + navigate('WalletScreen'); + } else { + toggleImporting(false); + } + }) + .catch(error => { + toggleImporting(false); + console.error('error importing seed phrase: ', error); + }); + }, 50); + + return () => clearTimeout(id); + } + }, [ + initializeWallet, + isEmpty, + isImporting, + navigate, + seedPhrase, + toggleImporting, + ]); + + return ( + + + + Import + + + + + + + + + {isImporting && ( + + )} + + + ); +}; + ImportSeedPhraseSheet.propTypes = { - isClipboardContentsValidSeedPhrase: PropTypes.bool, - isImporting: PropTypes.bool, - isSeedPhraseValid: PropTypes.bool, - navigation: PropTypes.object, - onImportSeedPhrase: PropTypes.func, - onInputChange: PropTypes.func, - onPasteSeedPhrase: PropTypes.func, - onPressEnterKey: PropTypes.func, - onPressHelp: PropTypes.func, - screenProps: PropTypes.shape({ handleWalletConfig: PropTypes.func }), - seedPhrase: PropTypes.string, - setSeedPhrase: PropTypes.func, + initializeWallet: PropTypes.func, + isEmpty: PropTypes.bool, }; -export default pure(ImportSeedPhraseSheet); +const neverRerender = () => true; +export default React.memo(ImportSeedPhraseSheet, neverRerender); diff --git a/src/screens/ImportSeedPhraseSheetWithData.js b/src/screens/ImportSeedPhraseSheetWithData.js index 0018dee9a2d..c83ba754591 100644 --- a/src/screens/ImportSeedPhraseSheetWithData.js +++ b/src/screens/ImportSeedPhraseSheetWithData.js @@ -1,128 +1,16 @@ -import analytics from '@segment/analytics-react-native'; import { get } from 'lodash'; -import { Clipboard, InteractionManager, Linking } from 'react-native'; -import { withNavigation } from 'react-navigation'; -import { - compose, - lifecycle, - onlyUpdateForKeys, - withHandlers, - withProps, - withState, -} from 'recompact'; -import { Alert } from '../components/alerts'; -import { withDataInit, withIsWalletEmpty, withIsWalletImporting } from '../hoc'; +import { compose, pure } from 'recompact'; +import { withDataInit, withIsWalletEmpty } from '../hoc'; import { deviceUtils } from '../utils'; import ImportSeedPhraseSheet from './ImportSeedPhraseSheet'; -import { isValidSeed as validateSeed } from '../helpers/validators'; - -const ConfirmImportAlert = onSuccess => ( - Alert({ - buttons: [{ - onPress: onSuccess, - style: 'destructive', - text: 'Delete and Import', - }, { - style: 'cancel', - text: 'Cancel', - }], - // eslint-disable-next-line - message: 'Importing this private key will overwrite your existing wallet. Before continuing, please make sure you’ve transferred its contents or backed up its private key.', - title: 'Are you sure you want to import?', - }) -); const ImportSeedPhraseSheetWithData = compose( withDataInit, withIsWalletEmpty, - withIsWalletImporting, - withNavigation, - withState('clipboardContents', 'setClipboardContents', ''), - withState('seedPhrase', 'setSeedPhrase', ''), - withHandlers({ - importSeedPhrase: ({ - initializeWallet, - isEmpty, - navigation, - seedPhrase, - setIsWalletImporting, - }) => async () => { - try { - const address = await initializeWallet(seedPhrase.trim()); - if (address) { - analytics.track('Imported seed phrase', { - hadPreviousAddressWithValue: isEmpty, - }); - setIsWalletImporting(false); - navigation.navigate('WalletScreen'); - } else { - setIsWalletImporting(false); - } - } catch (error) { - setIsWalletImporting(false); - console.error('error importing seed phrase: ', error); - } - }, - }), - withHandlers({ - getClipboardContents: ({ setClipboardContents }) => async () => Clipboard.getString().then(setClipboardContents), - onImportSeedPhrase: ({ setIsWalletImporting }) => () => ConfirmImportAlert(() => setIsWalletImporting(true)), - onInputChange: ({ isImporting, setSeedPhrase }) => ({ nativeEvent }) => { - if (!isImporting) { - setSeedPhrase(nativeEvent.text); - } - }, - onPasteSeedPhrase: ({ setSeedPhrase }) => () => { - Clipboard.getString() - .then(setSeedPhrase) - .catch(error => console.log(error)); - }, - onPressHelp: () => () => Linking.openURL('http://rainbow.me'), - }), - withProps(({ clipboardContents, seedPhrase }) => ({ - isClipboardContentsValidSeedPhrase: validateSeed(clipboardContents), - isSeedPhraseValid: validateSeed(seedPhrase), - })), - onlyUpdateForKeys([ - 'isClipboardContentsValidSeedPhrase', - 'isImporting', - 'isSeedPhraseValid', - 'seedPhrase', - ]), - lifecycle({ - componentDidMount() { - this.props.getClipboardContents(); - }, - componentDidUpdate(prevProps) { - const { - getClipboardContents, - importSeedPhrase, - isImporting, - navigation, - } = this.props; - - getClipboardContents(); - - if (isImporting !== prevProps.isImporting) { - navigation.setParams({ gesturesEnabled: !isImporting }); - } - - if (!prevProps.isImporting && isImporting) { - InteractionManager.runAfterInteractions(importSeedPhrase); - } - }, - }), - withHandlers({ - onPressEnterKey: ({ onImportSeedPhrase, seedPhrase }) => ({ nativeEvent: { key } }) => { - if (seedPhrase) { - onImportSeedPhrase(); - } - }, - }), + pure )(ImportSeedPhraseSheet); ImportSeedPhraseSheetWithData.navigationOptions = ({ navigation }) => ({ - effect: 'sheet', gestureResponseDistance: { vertical: deviceUtils.dimensions.height / 2, }, diff --git a/src/screens/ProfileScreen.js b/src/screens/ProfileScreen.js index 3dc859c9746..6669a38ae10 100644 --- a/src/screens/ProfileScreen.js +++ b/src/screens/ProfileScreen.js @@ -2,8 +2,6 @@ import PropTypes from 'prop-types'; import React from 'react'; import { ActivityList } from '../components/activity-list'; import AddFundsInterstitial from '../components/AddFundsInterstitial'; -import { FadeInAnimation } from '../components/animations'; -import BlurOverlay from '../components/BlurOverlay'; import { BackButton, Header, HeaderButton } from '../components/header'; import { FlexItem, Page } from '../components/layout'; import { Icon } from '../components/icons'; @@ -12,36 +10,35 @@ import { colors, position } from '../styles'; const ProfileScreen = ({ accountAddress, - blurOpacity, isEmpty, nativeCurrency, navigation, onPressBackButton, onPressSettings, requests, - showBlur, transactions, transactionsCount, }) => (
- +
- )} + } isEmpty={isEmpty} nativeCurrency={nativeCurrency} requests={requests} @@ -49,28 +46,17 @@ const ProfileScreen = ({ transactionsCount={transactionsCount} /> {isEmpty && } - {showBlur && ( - - - - )}
); ProfileScreen.propTypes = { accountAddress: PropTypes.string, - blurOpacity: PropTypes.object, isEmpty: PropTypes.bool, nativeCurrency: PropTypes.string, navigation: PropTypes.object, onPressBackButton: PropTypes.func, onPressSettings: PropTypes.func, requests: PropTypes.array, - showBlur: PropTypes.bool, transactions: PropTypes.array, transactionsCount: PropTypes.number, }; diff --git a/src/screens/ProfileScreenWithData.js b/src/screens/ProfileScreenWithData.js index b97227c9f71..05c1402e642 100644 --- a/src/screens/ProfileScreenWithData.js +++ b/src/screens/ProfileScreenWithData.js @@ -1,14 +1,8 @@ -import { - compose, - withHandlers, - withProps, -} from 'recompact'; +import { compose, withHandlers, withProps } from 'recompact'; import { setDisplayName } from 'recompose'; import { - withAccountAddress, withAccountSettings, withAccountTransactions, - withBlurTransitionProps, withIsWalletEmpty, withRequests, } from '../hoc'; @@ -16,17 +10,17 @@ import ProfileScreen from './ProfileScreen'; export default compose( setDisplayName('ProfileScreen'), - withAccountAddress, withAccountSettings, withAccountTransactions, - withBlurTransitionProps, withIsWalletEmpty, withRequests, withHandlers({ - onPressBackButton: ({ navigation }) => () => navigation.navigate('WalletScreen'), - onPressSettings: ({ navigation }) => () => navigation.navigate('SettingsModal'), + onPressBackButton: ({ navigation }) => () => + navigation.navigate('WalletScreen'), + onPressSettings: ({ navigation }) => () => + navigation.navigate('SettingsModal'), }), withProps(({ isWalletEmpty, transactionsCount }) => ({ isEmpty: isWalletEmpty && !transactionsCount, - })), + })) )(ProfileScreen); diff --git a/src/screens/QRScannerScreen.js b/src/screens/QRScannerScreen.js index 5c38986a09d..fe89d8ad067 100644 --- a/src/screens/QRScannerScreen.js +++ b/src/screens/QRScannerScreen.js @@ -1,29 +1,18 @@ import PropTypes from 'prop-types'; import React from 'react'; -import DeviceInfo from 'react-native-device-info'; -import { onlyUpdateForKeys } from 'recompact'; -import styled from 'styled-components/primitives'; +import { useIsEmulator } from 'react-native-device-info'; +import { useSafeArea } from 'react-native-safe-area-context'; import { BubbleSheet } from '../components/bubble-sheet'; import { Button } from '../components/buttons'; import { BackButton, Header } from '../components/header'; import { Centered } from '../components/layout'; import { QRCodeScanner } from '../components/qrcode-scanner'; -import { WalletConnectExplainer, WalletConnectList } from '../components/walletconnect-list'; +import { + WalletConnectExplainer, + WalletConnectList, +} from '../components/walletconnect-list'; import { colors, position } from '../styles'; -import { safeAreaInsetValues } from '../utils'; - -const Container = styled(Centered)` - ${position.size('100%')}; - background-color: ${colors.black}; - overflow: hidden; -`; - -const QRScannerScreenHeader = styled(Header).attrs({ - justify: 'space-between', -})` - position: absolute; - top: 0; -`; +import { isNewValueForObjectPaths } from '../utils'; const QRScannerScreen = ({ enableScanning, @@ -37,51 +26,58 @@ const QRScannerScreen = ({ walletConnectorsByDappName, walletConnectorsCount, ...props -}) => ( - - - - - {DeviceInfo.isEmulator() && ( - - )} - - { + const { result: isEmulator } = useIsEmulator(); + const insets = useSafeArea(); + + return ( + - {walletConnectorsCount - ? - : - } - - -); + +
+ + {isEmulator && ( + + )} +
+ + {walletConnectorsCount ? ( + + ) : ( + + )} + + + ); +}; QRScannerScreen.propTypes = { enableScanning: PropTypes.bool, @@ -92,20 +88,17 @@ QRScannerScreen.propTypes = { onScanSuccess: PropTypes.func, onSheetLayout: PropTypes.func, sheetHeight: PropTypes.number, - showSheet: PropTypes.bool, - showWalletConnectSheet: PropTypes.bool, walletConnectorsByDappName: PropTypes.arrayOf(PropTypes.object), walletConnectorsCount: PropTypes.number, }; -QRScannerScreen.defaultProps = { - showWalletConnectSheet: true, -}; +const arePropsEqual = (prev, next) => + !isNewValueForObjectPaths(prev, next, [ + 'enableScanning', + 'isCameraAuthorized', + 'isFocused', + 'sheetHeight', + 'walletConnectorsCount', + ]); -export default onlyUpdateForKeys([ - 'enableScanning', - 'isCameraAuthorized', - 'isFocused', - 'sheetHeight', - 'walletConnectorsCount', -])(QRScannerScreen); +export default React.memo(QRScannerScreen, arePropsEqual); diff --git a/src/screens/QRScannerScreenWithData.js b/src/screens/QRScannerScreenWithData.js index d3ee2a9c933..03802d9301e 100644 --- a/src/screens/QRScannerScreenWithData.js +++ b/src/screens/QRScannerScreenWithData.js @@ -31,7 +31,7 @@ class QRScannerScreenWithData extends Component { enableScanning: true, isCameraAuthorized: true, sheetHeight: 240, - } + }; componentDidUpdate = (prevProps, prevState) => { if (this.props.isFocused && !prevProps.isFocused) { @@ -43,17 +43,18 @@ class QRScannerScreenWithData extends Component { } }); + // eslint-disable-next-line react/no-did-update-set-state this.setState({ enableScanning: true }); } - } + }; handleSheetLayout = ({ nativeEvent }) => { this.setState({ sheetHeight: get(nativeEvent, 'layout.height') }); - } + }; - handlePastedUri = async (uri) => this.props.walletConnectOnSessionRequest(uri) + handlePastedUri = async uri => this.props.walletConnectOnSessionRequest(uri); - handlePressBackButton = () => this.props.navigation.navigate('WalletScreen') + handlePressBackButton = () => this.props.navigation.navigate('WalletScreen'); handlePressPasteSessionUri = () => { Prompt({ @@ -62,9 +63,9 @@ class QRScannerScreenWithData extends Component { title: 'New WalletConnect Session', type: 'plain-text', }); - } + }; - handleReenableScanning = () => this.setState({ enableScanning: true }) + handleReenableScanning = () => this.setState({ enableScanning: true }); handleScanSuccess = async ({ data }) => { const { @@ -92,28 +93,27 @@ class QRScannerScreenWithData extends Component { return setSafeTimeout(this.handleReenableScanning, 2000); } - analytics.track('Scanned broken or unsupported QR code', { qrCodeData: data }); + analytics.track('Scanned broken or unsupported QR code', { + qrCodeData: data, + }); return Alert({ callback: this.handleReenableScanning, message: lang.t('wallet.unrecognized_qrcode'), title: lang.t('wallet.unrecognized_qrcode_title'), }); - } + }; render = () => ( - ) + ); } export default compose( @@ -122,5 +122,5 @@ export default compose( withAccountAddress, withSafeTimeout, withWalletConnectConnections, - withStatusBarStyle('light-content'), + withStatusBarStyle('light-content') )(QRScannerScreenWithData); diff --git a/src/screens/ReceiveModal.js b/src/screens/ReceiveModal.js index d8e71295e8d..b79668df467 100644 --- a/src/screens/ReceiveModal.js +++ b/src/screens/ReceiveModal.js @@ -2,12 +2,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import { Clipboard, Share } from 'react-native'; import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; -import { - compose, - onlyUpdateForKeys, - withHandlers, - withState, -} from 'recompact'; +import { compose, onlyUpdateForKeys, withHandlers, withState } from 'recompact'; import styled from 'styled-components/primitives'; import Divider from '../components/Divider'; import { Column } from '../components/layout'; @@ -19,11 +14,7 @@ import { } from '../components/modal'; import QRCodeDisplay from '../components/QRCodeDisplay'; import { FloatingEmojis } from '../components/floating-emojis'; -import { - Br, - Monospace, - Text, -} from '../components/text'; +import { Br, Monospace, Text } from '../components/text'; import { withAccountAddress } from '../hoc'; import { colors, padding } from '../styles'; @@ -65,20 +56,15 @@ const ReceiveScreen = ({ onPressShareAddress, }) => ( - + - Send Ether, ERC-20 tokens, or
+ Send Ether, ERC-20 tokens, or +
collectibles to your wallet:
- + {accountAddress.substring(0, accountAddress.length / 2)} @@ -114,7 +100,6 @@ const ReceiveScreen = ({ ReceiveScreen.propTypes = { accountAddress: PropTypes.string.isRequired, emojiCount: PropTypes.number, - navigation: PropTypes.object.isRequired, onCloseModal: PropTypes.func.isRequired, onPressCopyAddress: PropTypes.func, onPressShareAddress: PropTypes.func, @@ -125,17 +110,20 @@ export default compose( withState('emojiCount', 'setEmojiCount', 0), withHandlers({ onCloseModal: ({ navigation }) => () => navigation.goBack(), - onPressCopyAddress: ({ accountAddress, emojiCount, setEmojiCount }) => () => { + onPressCopyAddress: ({ + accountAddress, + emojiCount, + setEmojiCount, + }) => () => { ReactNativeHapticFeedback.trigger('impactLight'); setEmojiCount(emojiCount + 1); Clipboard.setString(accountAddress); }, - onPressShareAddress: ({ accountAddress }) => () => ( + onPressShareAddress: ({ accountAddress }) => () => Share.share({ message: accountAddress, title: 'My account address:', - }) - ), + }), }), - onlyUpdateForKeys(['accountAddress', 'emojiCount']), + onlyUpdateForKeys(['accountAddress', 'emojiCount']) )(ReceiveScreen); diff --git a/src/screens/Routes.js b/src/screens/Routes.js index 17ad4ac388e..15e15b03e8e 100644 --- a/src/screens/Routes.js +++ b/src/screens/Routes.js @@ -1,13 +1,10 @@ import analytics from '@segment/analytics-react-native'; -import { get } from 'lodash'; +import { get, omit } from 'lodash'; import React from 'react'; -import { - createAppContainer, - createMaterialTopTabNavigator, - createStackNavigator, -} from 'react-navigation'; -import { Navigation } from '../navigation'; -import { buildTransitions, expanded, sheet } from '../navigation/transitions'; +import { createAppContainer } from 'react-navigation'; +import { createMaterialTopTabNavigator } from 'react-navigation-tabs-v1'; +import { createStackNavigator } from 'react-navigation-stack'; +import { ExchangeModalNavigator, Navigation } from '../navigation'; import { updateTransitionProps } from '../redux/navigation'; import store from '../redux/store'; import { deviceUtils } from '../utils'; @@ -22,113 +19,195 @@ import SendSheetWithData from './SendSheetWithData'; import SettingsModal from './SettingsModal'; import TransactionConfirmationScreenWithData from './TransactionConfirmationScreenWithData'; import WalletScreen from './WalletScreen'; +import { + exchangePreset, + expandedPreset, + sheetPreset, + backgroundPreset, + overlayExpandedPreset, +} from '../navigation/transitions/effects'; -const onTransitionEnd = () => store.dispatch(updateTransitionProps({ isTransitioning: false })); -const onTransitionStart = () => store.dispatch(updateTransitionProps({ isTransitioning: true })); +const onTransitionEnd = () => + store.dispatch(updateTransitionProps({ isTransitioning: false })); +const onTransitionStart = () => + store.dispatch(updateTransitionProps({ isTransitioning: true })); -const SwipeStack = createMaterialTopTabNavigator({ - ProfileScreen: { - name: 'ProfileScreen', - screen: ProfileScreenWithData, - }, - WalletScreen: { - name: 'WalletScreen', - screen: WalletScreen, - }, - // eslint-disable-next-line sort-keys - QRScannerScreen: { - name: 'QRScannerScreen', - screen: QRScannerScreenWithData, - }, -}, { - headerMode: 'none', - initialRouteName: 'WalletScreen', - mode: 'modal', - springConfig: { - damping: 16, - mass: 0.3, - overshootClamping: false, - restDisplacementThreshold: 1, - restSpeedThreshold: 1, - stiffness: 140, +const SwipeStack = createMaterialTopTabNavigator( + { + ProfileScreen: { + name: 'ProfileScreen', + screen: ProfileScreenWithData, + }, + WalletScreen: { + name: 'WalletScreen', + screen: WalletScreen, + }, + // eslint-disable-next-line sort-keys + QRScannerScreen: { + name: 'QRScannerScreen', + screen: QRScannerScreenWithData, + }, }, - swipeDistanceThreshold: 30, - swipeVelocityThreshold: 10, - tabBarComponent: null, -}); + { + headerMode: 'none', + initialLayout: deviceUtils.dimensions, + initialRouteName: 'WalletScreen', + tabBarComponent: null, + } +); -const MainNavigator = createStackNavigator({ - ConfirmRequest: TransactionConfirmationScreenWithData, - ExampleScreen, - ExpandedAssetScreen: { - navigationOptions: { - effect: 'expanded', - gestureResponseDistance: { - vertical: deviceUtils.dimensions.height, +const MainNavigator = createStackNavigator( + { + ConfirmRequest: { + navigationOptions: { + ...sheetPreset, + onTransitionStart: props => { + sheetPreset.onTransitionStart(props); + onTransitionStart(); + }, }, + screen: TransactionConfirmationScreenWithData, }, - screen: ExpandedAssetScreenWithData, - }, - ImportSeedPhraseSheet: ImportSeedPhraseSheetWithData, - ReceiveModal: { - navigationOptions: { - effect: 'expanded', - gestureResponseDistance: { - vertical: deviceUtils.dimensions.height, + ExampleScreen, + ExchangeModal: { + navigationOptions: { + ...exchangePreset, + onTransitionEnd, + onTransitionStart: props => { + expandedPreset.onTransitionStart(props); + onTransitionStart(); + }, }, + params: { + isGestureBlocked: false, + }, + screen: ExchangeModalNavigator, }, - screen: ReceiveModal, - }, - SendSheet: SendSheetWithData, - SettingsModal: { - navigationOptions: { - effect: 'expanded', - gesturesEnabled: false, + ExpandedAssetScreen: { + navigationOptions: { + ...expandedPreset, + // onTransitionStart: props => { + // expandedPreset.onTransitionStart(props); + // onTransitionStart(); + // }, + }, + screen: ExpandedAssetScreenWithData, }, - screen: SettingsModal, - }, - SwipeLayout: SwipeStack, - WalletConnectConfirmationModal: { - navigationOptions: { - effect: 'expanded', - gestureResponseDistance: { - vertical: deviceUtils.dimensions.height, + ImportSeedPhraseSheet: { + navigationOptions: { + ...sheetPreset, + onTransitionStart: props => { + sheetPreset.onTransitionStart(props); + onTransitionStart(); + }, + }, + screen: ImportSeedPhraseSheetWithData, + }, + OverlayExpandedAssetScreen: { + navigationOptions: overlayExpandedPreset, + screen: ExpandedAssetScreenWithData, + }, + ReceiveModal: { + navigationOptions: { + ...expandedPreset, + onTransitionStart: props => { + expandedPreset.onTransitionStart(props); + onTransitionStart(); + }, + }, + screen: ReceiveModal, + }, + SendSheet: { + navigationOptions: { + ...omit(sheetPreset, 'gestureResponseDistance'), + onTransitionStart: props => { + onTransitionStart(props); + sheetPreset.onTransitionStart(props); + }, + }, + screen: SendSheetWithData, + }, + SettingsModal: { + navigationOptions: { + ...expandedPreset, + gesturesEnabled: false, + onTransitionStart: props => { + expandedPreset.onTransitionStart(props); + onTransitionStart(); + }, + }, + screen: SettingsModal, + transparentCard: true, + }, + SwipeLayout: { + navigationOptions: { + ...backgroundPreset, }, + screen: SwipeStack, + }, + WalletConnectConfirmationModal: { + navigationOptions: { + ...expandedPreset, + onTransitionStart: props => { + expandedPreset.onTransitionStart(props); + onTransitionStart(); + }, + }, + screen: WalletConnectConfirmationModal, }, - screen: WalletConnectConfirmationModal, }, -}, { - headerMode: 'none', - initialRouteName: 'SwipeLayout', - mode: 'modal', - onTransitionEnd, - onTransitionStart, - transitionConfig: buildTransitions(Navigation, { expanded, sheet }), - transparentCard: true, -}); + { + defaultNavigationOptions: { + onTransitionEnd, + onTransitionStart, + }, + headerMode: 'none', + initialRouteName: 'SwipeLayout', + mode: 'modal', + } +); const AppContainer = createAppContainer(MainNavigator); -// eslint-disable-next-line react/prop-types -const AppContainerWithAnalytics = ({ ref, screenProps }) => ( +// eslint-disable-next-line react/display-name +const AppContainerWithAnalytics = React.forwardRef((props, ref) => ( { + onNavigationStateChange={(prevState, currentState) => { const { params, routeName } = Navigation.getActiveRoute(currentState); const prevRouteName = Navigation.getActiveRouteName(prevState); if (routeName === 'SettingsModal') { let subRoute = get(params, 'section.title'); if (subRoute === 'Settings') subRoute = null; - return analytics.screen(`${routeName}${subRoute ? `>${subRoute}` : ''}`); + return analytics.screen( + `${routeName}${subRoute ? `>${subRoute}` : ''}` + ); } if (routeName !== prevRouteName) { let paramsToTrack = null; + if ( + prevRouteName === 'MainExchangeScreen' && + routeName === 'WalletScreen' + ) { + // store.dispatch(updateTransitionProps({ blurColor: null })); + } else if ( + prevRouteName === 'WalletScreen' && + routeName === 'MainExchangeScreen' + ) { + // store.dispatch( + // updateTransitionProps({ + // blurColor: colors.alpha(colors.black, 0.9), + // }) + // ); + } + if (routeName === 'ExpandedAssetScreen') { const { asset, type } = params; paramsToTrack = { - assetContractAddress: asset.address || get(asset, 'asset_contract.address'), + assetContractAddress: + asset.address || get(asset, 'asset_contract.address'), assetName: asset.name, assetSymbol: asset.symbol || get(asset, 'asset_contract.symbol'), assetType: type, @@ -139,8 +218,7 @@ const AppContainerWithAnalytics = ({ ref, screenProps }) => ( } }} ref={ref} - screenProps={screenProps} /> -); +)); export default React.memo(AppContainerWithAnalytics); diff --git a/src/screens/SendSheet.js b/src/screens/SendSheet.js index 44e9175d9b5..11305645f7d 100644 --- a/src/screens/SendSheet.js +++ b/src/screens/SendSheet.js @@ -1,71 +1,53 @@ import analytics from '@segment/analytics-react-native'; -import { - get, - indexOf, - isEmpty, - isFunction, - isString, - map, - property, - sortBy, - upperFirst, -} from 'lodash'; +import { get, isEmpty, isString, toLower } from 'lodash'; import PropTypes from 'prop-types'; import React, { Component } from 'react'; import { Keyboard, KeyboardAvoidingView } from 'react-native'; -import { isIphoneX } from 'react-native-iphone-x-helper'; -import { compose, withHandlers } from 'recompact'; +import { getStatusBarHeight, isIphoneX } from 'react-native-iphone-x-helper'; +import { compose, withHandlers, withProps } from 'recompact'; import styled from 'styled-components/primitives'; import { Column } from '../components/layout'; import { SendAssetForm, SendAssetList, SendButton, - SendEmptyState, + SendContactList, SendHeader, SendTransactionSpeed, } from '../components/send'; import { withAccountData, withAccountSettings, + withContacts, withDataInit, + withTransitionProps, withUniqueTokens, } from '../hoc'; -import { colors } from '../styles'; -import { deviceUtils, isNewValueForPath } from '../utils'; -import { showActionSheetWithOptions } from '../utils/actionsheet'; +import { borders, colors } from '../styles'; +import { deviceUtils, gasUtils, isNewValueForPath } from '../utils'; + +const statusBarHeight = getStatusBarHeight(true); const Container = styled(Column)` - background-color: ${colors.white}; + background-color: ${colors.transparent}; height: 100%; `; -const formatGastSpeedItem = (value, key) => { - const cost = get(value, 'txFee.native.value.display'); - const gwei = get(value, 'value.display'); - const time = get(value, 'estimatedTime.display'); - - return { - gweiValue: gwei, - label: `${upperFirst(key)}: ${cost} ~${time.slice(0, -1)}`, - value: key, - }; -}; - -const labelOrder = ['slow', 'average', 'fast']; - -const formatGasSpeedItems = (gasPrices) => { - const gasItems = map(gasPrices, formatGastSpeedItem); - return sortBy(gasItems, ({ value }) => indexOf(labelOrder, value)); -}; +const SheetContainer = styled(Column)` + ${borders.buildRadius('top', 16)}; + background-color: ${colors.white}; + height: 100%; + top: ${statusBarHeight}; +`; class SendSheet extends Component { static propTypes = { allAssets: PropTypes.array, assetAmount: PropTypes.string, + contacts: PropTypes.object, fetchData: PropTypes.func, - gasPrice: PropTypes.object, gasPrices: PropTypes.object, + gasUpdateGasPriceOption: PropTypes.func, isSufficientBalance: PropTypes.bool, isSufficientGas: PropTypes.bool, isValidAddress: PropTypes.bool, @@ -73,38 +55,42 @@ class SendSheet extends Component { navigation: PropTypes.object, onSubmit: PropTypes.func, recipient: PropTypes.string, + removeContact: PropTypes.func, selected: PropTypes.object, + selectedGasPrice: PropTypes.object, sendableUniqueTokens: PropTypes.arrayOf(PropTypes.object), sendClearFields: PropTypes.func, sendMaxBalance: PropTypes.func, sendUpdateAssetAmount: PropTypes.func, - sendUpdateGasPrice: PropTypes.func, sendUpdateNativeAmount: PropTypes.func, sendUpdateRecipient: PropTypes.func, sendUpdateSelected: PropTypes.func, - } + sortedContacts: PropTypes.array, + }; static defaultProps = { isSufficientBalance: false, isSufficientGas: false, isValidAddress: false, - } + }; state = { + currentInput: '', isAuthorizing: false, - } + }; - componentDidMount() { + componentDidMount = async () => { const { navigation, sendUpdateRecipient } = this.props; const address = get(navigation, 'state.params.address'); if (address) { sendUpdateRecipient(address); } - } + }; componentDidUpdate(prevProps) { const { + contacts, isValidAddress, navigation, selected, @@ -122,13 +108,26 @@ class SendSheet extends Component { } const isNewSelected = isNewValueForPath(this.props, prevProps, 'selected'); - const isNewValidAddress = isNewValueForPath(this.props, prevProps, 'isValidAddress'); + const isNewValidAddress = isNewValueForPath( + this.props, + prevProps, + 'isValidAddress' + ); + const isNewContactList = isNewValueForPath( + this.props, + prevProps, + 'contacts' + ); - if (isNewValidAddress || isNewSelected) { - let verticalGestureResponseDistance = 0; + if (isNewValidAddress || isNewSelected || isNewContactList) { + let verticalGestureResponseDistance = 140; - if (isValidAddress) { - verticalGestureResponseDistance = isEmpty(selected) ? 150 : deviceUtils.dimensions.height; + if (!isValidAddress && !isEmpty(contacts)) { + verticalGestureResponseDistance = 140; + } else if (isValidAddress) { + verticalGestureResponseDistance = isEmpty(selected) + ? 140 + : deviceUtils.dimensions.height; } else { verticalGestureResponseDistance = deviceUtils.dimensions.height; } @@ -141,19 +140,19 @@ class SendSheet extends Component { this.props.sendClearFields(); } - onChangeAssetAmount = (assetAmount) => { + onChangeAssetAmount = assetAmount => { if (isString(assetAmount)) { this.props.sendUpdateAssetAmount(assetAmount); analytics.track('Changed token input in Send flow'); } - } + }; - onChangeNativeAmount = (nativeAmount) => { + onChangeNativeAmount = nativeAmount => { if (isString(nativeAmount)) { this.props.sendUpdateNativeAmount(nativeAmount); analytics.track('Changed native currency input in Send flow'); } - } + }; onLongPressSend = () => { this.setState({ isAuthorizing: true }); @@ -163,39 +162,24 @@ class SendSheet extends Component { } else { this.onPressTransactionSpeed(this.sendTransaction); } - } - - onPressTransactionSpeed = (onSuccess) => { - const { gasPrices, sendUpdateGasPrice } = this.props; - - const options = [ - { label: 'Cancel' }, - ...formatGasSpeedItems(gasPrices), - ]; - - showActionSheetWithOptions({ - cancelButtonIndex: 0, - options: options.map(property('label')), - }, (buttonIndex) => { - if (buttonIndex > 0) { - const selectedGasPriceItem = options[buttonIndex]; - - sendUpdateGasPrice(selectedGasPriceItem.value); - analytics.track('Updated Gas Price', { gasPrice: selectedGasPriceItem.gweiValue }); - } + }; - if (isFunction(onSuccess)) { - onSuccess(); - } - }); - } + onPressTransactionSpeed = onSuccess => { + const { gasPrices, gasUpdateGasPriceOption, txFees } = this.props; + gasUtils.showTransactionSpeedOptions( + gasPrices, + txFees, + gasUpdateGasPriceOption, + onSuccess + ); + }; onResetAssetSelection = () => { analytics.track('Reset asset selection in Send flow'); this.props.sendUpdateSelected({}); - } + }; - onSelectAsset = asset => this.props.sendUpdateSelected(asset) + onSelectAsset = asset => this.props.sendUpdateSelected(asset); sendTransaction = () => { const { @@ -209,31 +193,41 @@ class SendSheet extends Component { if (Number(assetAmount) <= 0) return false; - return onSubmit().then(() => { - this.setState({ isAuthorizing: false }); - analytics.track('Sent transaction', { - assetName: selected.name, - assetType: selected.isNft ? 'unique_token' : 'token', - isRecepientENS: recipient.slice(-4).toLowerCase() === '.eth', + return onSubmit() + .then(() => { + this.setState({ isAuthorizing: false }); + analytics.track('Sent transaction', { + assetName: selected.name, + assetType: selected.isNft ? 'unique_token' : 'token', + isRecepientENS: toLower(recipient.slice(-4)) === '.eth', + }); + sendClearFields(); + navigation.navigate('ProfileScreen'); + }) + .catch(() => { + this.setState({ isAuthorizing: false }); }); - sendClearFields(); - navigation.navigate('ProfileScreen'); - }).catch(error => { - this.setState({ isAuthorizing: false }); - }); - } + }; + + onChangeInput = event => { + this.setState({ currentInput: event }); + this.props.sendUpdateRecipient(event); + }; render() { const { allAssets, + contacts, fetchData, - gasPrice, isValidAddress, nativeCurrencySymbol, recipient, + removeContact, selected, + selectedGasPrice, sendableUniqueTokens, sendUpdateRecipient, + sortedContacts, ...props } = this.props; const showEmptyState = !isValidAddress; @@ -241,15 +235,26 @@ class SendSheet extends Component { const showAssetForm = isValidAddress && !isEmpty(selected); return ( - - + + - {showEmptyState && } + {showEmptyState && ( + + )} {showAssetList && ( - )} + } onChangeAssetAmount={this.onChangeAssetAmount} onChangeNativeAmount={this.onChangeNativeAmount} onResetAssetSelection={this.onResetAssetSelection} selected={selected} - txSpeedRenderer={( + txSpeedRenderer={ isIphoneX() && ( ) - )} + } /> )} - + ); } } export default compose( withAccountData, + withContacts, withUniqueTokens, withAccountSettings, withDataInit, + withTransitionProps, + withProps(({ transitionProps: { isTransitioning } }) => ({ + isTransitioning, + })), withHandlers({ fetchData: ({ refreshAccountData }) => async () => refreshAccountData(), - }), + }) )(SendSheet); diff --git a/src/screens/SendSheetWithData.js b/src/screens/SendSheetWithData.js index 8b8864a8252..3e8d7a77d6b 100644 --- a/src/screens/SendSheetWithData.js +++ b/src/screens/SendSheetWithData.js @@ -7,8 +7,11 @@ const SendSheetWithData = withSendComponentWithData(SendSheet, { sendTransactionCallback: sendTransaction, }); -SendSheetWithData.navigationOptions = ({ navigation: { state: { params } } }) => ({ - effect: 'sheet', +SendSheetWithData.navigationOptions = ({ + navigation: { + state: { params }, + }, +}) => ({ gestureResponseDistance: { vertical: params && params.verticalGestureResponseDistance, }, diff --git a/src/screens/SettingsModal.js b/src/screens/SettingsModal.js index 2a07eed9596..f89d690ae41 100644 --- a/src/screens/SettingsModal.js +++ b/src/screens/SettingsModal.js @@ -2,12 +2,7 @@ import { get } from 'lodash'; import PropTypes from 'prop-types'; import React, { createElement } from 'react'; import { InteractionManager } from 'react-native'; -import { - compose, - onlyUpdateForKeys, - withHandlers, - withProps, -} from 'recompact'; +import { compose, onlyUpdateForKeys, withHandlers, withProps } from 'recompact'; import { Column } from '../components/layout'; import { Modal, ModalHeader } from '../components/modal'; import { AnimatedPager } from '../components/pager'; @@ -92,18 +87,24 @@ SettingsModal.propTypes = { export default compose( withProps(({ navigation }) => ({ - currentSettingsPage: get(navigation, 'state.params.section', SettingsPages.default), + currentSettingsPage: get( + navigation, + 'state.params.section', + SettingsPages.default + ), })), withHandlers({ onCloseModal: ({ navigation }) => () => navigation.goBack(), - onPressBack: ({ navigation }) => () => navigation.setParams({ section: SettingsPages.default }), - onPressImportSeedPhrase: ({ navigation, setSafeTimeout }) => () => { + onPressBack: ({ navigation }) => () => + navigation.setParams({ section: SettingsPages.default }), + onPressImportSeedPhrase: ({ navigation }) => () => { navigation.goBack(); InteractionManager.runAfterInteractions(() => { navigation.navigate('ImportSeedPhraseSheet'); }); }, - onPressSection: ({ navigation }) => (section) => () => navigation.setParams({ section }), + onPressSection: ({ navigation }) => section => () => + navigation.setParams({ section }), }), - onlyUpdateForKeys(['currentSettingsPage']), + onlyUpdateForKeys(['currentSettingsPage']) )(SettingsModal); diff --git a/src/screens/TransactionConfirmationScreen.js b/src/screens/TransactionConfirmationScreen.js index 8549bb70da3..f77cb8d96ec 100644 --- a/src/screens/TransactionConfirmationScreen.js +++ b/src/screens/TransactionConfirmationScreen.js @@ -3,7 +3,6 @@ import PropTypes from 'prop-types'; import React, { PureComponent } from 'react'; import lang from 'i18n-js'; import { Animated } from 'react-native'; -import TouchID from 'react-native-touch-id'; import styled from 'styled-components'; import { Button, HoldToAuthorizeButton } from '../components/buttons'; import { RequestVendorLogoIcon } from '../components/coin-icon'; @@ -15,16 +14,20 @@ import { } from '../components/transaction'; import { Text } from '../components/text'; import { colors, position } from '../styles'; +import { + isMessageDisplayType, + isTransactionDisplayType, + SEND_TRANSACTION, +} from '../utils/signingMethods'; const CancelButtonContainer = styled.View` - bottom: 22; + bottom: 19; position: absolute; right: 19; `; const Container = styled(Column)` ${position.size('100%')} - background-color: ${colors.black}; flex: 1; `; @@ -43,26 +46,16 @@ export default class TransactionConfirmationScreen extends PureComponent { static propTypes = { dappName: PropTypes.string, imageUrl: PropTypes.string, + method: PropTypes.string, onCancel: PropTypes.func, onConfirm: PropTypes.func, request: PropTypes.object, - requestType: PropTypes.string, - } + }; state = { - biometryType: null, + isAuthorizing: false, sendLongPressProgress: new Animated.Value(0), - } - - componentDidMount() { - TouchID.isSupported() - .then(biometryType => { - this.setState({ biometryType }); - }) - .catch(() => { - this.setState({ biometryType: 'FaceID' }); - }); - } + }; componentWillUnmount() { this.state.sendLongPressProgress.stopAnimation(); @@ -75,7 +68,7 @@ export default class TransactionConfirmationScreen extends PureComponent { duration: 800, toValue: 100, }).start(); - } + }; onReleaseSend = () => { const { sendLongPressProgress } = this.state; @@ -84,34 +77,51 @@ export default class TransactionConfirmationScreen extends PureComponent { duration: (sendLongPressProgress._value / 100) * 800, toValue: 0, }).start(); - } + }; onLongPressSend = async () => { - const { onConfirm, requestType } = this.props; + const { onConfirm } = this.props; const { sendLongPressProgress } = this.state; + this.setState({ isAuthorizing: true }); Animated.timing(sendLongPressProgress, { duration: (sendLongPressProgress._value / 100) * 800, toValue: 0, }).start(); - await onConfirm(requestType); - } + try { + await onConfirm(); + this.setState({ isAuthorizing: false }); + } catch (error) { + this.setState({ isAuthorizing: false }); + } + }; - renderSendButton = () => ( - - {`Hold to ${(this.props.requestType === 'message' || this.props.requestType === 'messagePersonal') ? 'Sign' : 'Send'}`} - - ) + renderSendButton = () => { + const { method } = this.props; + const { isAuthorizing } = this.state; + const label = `Hold to ${method === SEND_TRANSACTION ? 'Send' : 'Sign'}`; + + return ( + + ); + }; + + requestHeader = () => { + const { method } = this.props; + return isMessageDisplayType(method) + ? lang.t('wallet.message_signing.request') + : lang.t('wallet.transaction.request'); + }; renderTransactionSection = () => { - const { request, requestType } = this.props; + const { request, method } = this.props; - if (requestType === 'message' - || requestType === 'messagePersonal') { + if (isMessageDisplayType(method)) { return ( ); - } + }; render = () => ( - + {this.props.dappName} - - {lang.t('wallet.transaction.request')} - + {this.requestHeader()} @@ -181,5 +185,5 @@ export default class TransactionConfirmationScreen extends PureComponent { {this.renderTransactionSection()} - ) + ); } diff --git a/src/screens/TransactionConfirmationScreenWithData.js b/src/screens/TransactionConfirmationScreenWithData.js index 50cc89ca646..bbf99b7f066 100644 --- a/src/screens/TransactionConfirmationScreenWithData.js +++ b/src/screens/TransactionConfirmationScreenWithData.js @@ -4,50 +4,82 @@ import lang from 'i18n-js'; import { get, isNil, omit } from 'lodash'; import PropTypes from 'prop-types'; import React, { PureComponent } from 'react'; -import { Alert, StatusBar, Vibration } from 'react-native'; +import { Alert, Vibration } from 'react-native'; import { withNavigationFocus } from 'react-navigation'; import { compose } from 'recompact'; -import { withTransactionConfirmationScreen } from '../hoc'; +import { withGas, withTransactionConfirmationScreen } from '../hoc'; import { signMessage, signPersonalMessage, + signTransaction, sendTransaction, } from '../model/wallet'; import { estimateGas, getTransactionCount, toHex } from '../handlers/web3'; +import { gasUtils } from '../utils'; +import { + isMessageDisplayType, + isSignFirstParamType, + isSignSecondParamType, + SEND_TRANSACTION, +} from '../utils/signingMethods'; import TransactionConfirmationScreen from './TransactionConfirmationScreen'; class TransactionConfirmationScreenWithData extends PureComponent { static propTypes = { dataAddNewTransaction: PropTypes.func, - isFocused: PropTypes.bool.isRequired, + gasPrices: PropTypes.object, navigation: PropTypes.any, removeRequest: PropTypes.func, transactionCountNonce: PropTypes.number, updateTransactionCountNonce: PropTypes.func, walletConnectSendStatus: PropTypes.func, - } + }; componentDidMount() { - StatusBar.setBarStyle('light-content', true); - - const autoOpened = get(this.props, 'navigation.state.params.autoOpened'); - if (autoOpened) { + const openAutomatically = get( + this.props, + 'navigation.state.params.openAutomatically' + ); + if (openAutomatically) { Vibration.vibrate(); } } - handleConfirm = async (requestType) => { - if (requestType === 'message' || requestType === 'messagePersonal') { - return this.handleSignMessage(requestType); + handleConfirm = async () => { + const { + transactionDetails: { + payload: { method }, + }, + } = this.props.navigation.state.params; + if (isMessageDisplayType(method)) { + return this.handleSignMessage(); } return this.handleConfirmTransaction(); }; handleConfirmTransaction = async () => { - const { transactionDetails } = this.props.navigation.state.params; + const { + callback, + transactionDetails: { + dappName, + displayDetails, + payload: { method, params }, + peerId, + requestId, + }, + } = this.props.navigation.state.params; - const txPayload = get(transactionDetails, 'payload.params[0]'); - let { gasLimit } = txPayload; + const sendInsteadOfSign = method === SEND_TRANSACTION; + const txPayload = get(params, '[0]'); + let { gasLimit, gasPrice } = txPayload; + + if (isNil(gasPrice)) { + const { gasPrices } = this.props; + const rawGasPrice = get(gasPrices, `${gasUtils.NORMAL}.value.amount`); + if (rawGasPrice) { + gasPrice = toHex(rawGasPrice); + } + } if (isNil(gasLimit)) { try { @@ -57,102 +89,133 @@ class TransactionConfirmationScreenWithData extends PureComponent { console.log('error estimating gas', error); } } + const web3TxnCount = await getTransactionCount(txPayload.from); - const maxTxnCount = Math.max(this.props.transactionCountNonce, web3TxnCount); + const maxTxnCount = Math.max( + this.props.transactionCountNonce, + web3TxnCount + ); const nonce = ethers.utils.hexlify(maxTxnCount); - let txPayloadLatestNonce = { ...txPayload, nonce }; + let txPayloadLatestNonce = { ...txPayload, gasLimit, gasPrice, nonce }; txPayloadLatestNonce = omit(txPayloadLatestNonce, 'from'); - const transactionHash = await sendTransaction({ - transaction: txPayloadLatestNonce, - }); - - if (transactionHash) { - this.props.updateTransactionCountNonce(maxTxnCount + 1); - const txDetails = { - amount: get(transactionDetails, 'displayDetails.payload.value'), - asset: get(transactionDetails, 'displayDetails.payload.asset'), - dappName: get(transactionDetails, 'dappName'), - from: get(transactionDetails, 'displayDetails.payload.from'), - gasLimit: get(transactionDetails, 'displayDetails.payload.gasLimit'), - gasPrice: get(transactionDetails, 'displayDetails.payload.gasPrice'), - hash: transactionHash, - nonce: get(transactionDetails, 'displayDetails.payload.nonce'), - to: get(transactionDetails, 'displayDetails.payload.to'), - }; - this.props.dataAddNewTransaction(txDetails); - this.props.removeRequest(transactionDetails.requestId); - try { - await this.props.walletConnectSendStatus(transactionDetails.peerId, transactionDetails.requestId, transactionHash); - } catch (error) { + let result = null; + if (sendInsteadOfSign) { + result = await sendTransaction({ + transaction: txPayloadLatestNonce, + }); + } else { + result = await signTransaction({ + transaction: txPayloadLatestNonce, + }); + } + + if (result) { + if (callback) { + callback({ result }); + } + if (sendInsteadOfSign) { + this.props.updateTransactionCountNonce(maxTxnCount + 1); + const txDetails = { + amount: get(displayDetails, 'request.value'), + asset: get(displayDetails, 'request.asset'), + dappName, + from: get(displayDetails, 'request.from'), + gasLimit, + gasPrice, + hash: result, + nonce, + to: get(displayDetails, 'request.to'), + }; + this.props.dataAddNewTransaction(txDetails); } analytics.track('Approved WalletConnect transaction request'); + if (requestId) { + this.props.removeRequest(requestId); + await this.props.walletConnectSendStatus(peerId, requestId, result); + } this.closeScreen(); } else { await this.handleCancelRequest(); } }; - handleSignMessage = async (requestType) => { - const { transactionDetails } = this.props.navigation.state.params; + handleSignMessage = async () => { + const { + callback, + transactionDetails: { + payload: { method, params }, + peerId, + requestId, + }, + } = this.props.navigation.state.params; let message = null; let flatFormatSignature = null; - if (requestType === 'message') { - message = get(transactionDetails, 'payload.params[1]'); - flatFormatSignature = await signMessage(message); - } else if (requestType === 'messagePersonal') { - message = get(transactionDetails, 'payload.params[0]'); + if (isSignFirstParamType(method)) { + message = get(params, '[0]'); flatFormatSignature = await signPersonalMessage(message); + } else if (isSignSecondParamType(method)) { + message = get(params, '[1]'); + flatFormatSignature = await signMessage(message); } if (flatFormatSignature) { - this.props.removeRequest(transactionDetails.requestId); - await this.props.walletConnectSendStatus(transactionDetails.peerId, transactionDetails.requestId, flatFormatSignature); analytics.track('Approved WalletConnect signature request'); + if (requestId) { + this.props.removeRequest(requestId); + await this.props.walletConnectSendStatus( + peerId, + requestId, + flatFormatSignature + ); + } + if (callback) { + callback({ sig: flatFormatSignature }); + } this.closeScreen(); } else { await this.handleCancelRequest(); } }; - sendFailedTransactionStatus = async () => { - try { - this.closeScreen(); - const { transactionDetails } = this.props.navigation.state.params; - await this.props.walletConnectSendStatus(transactionDetails.peerId, transactionDetails.requestId, null); - } catch (error) { - this.closeScreen(); - Alert.alert(lang.t('wallet.transaction.alert.cancelled_transaction')); - } - } - handleCancelRequest = async () => { try { - await this.sendFailedTransactionStatus(); - const { transactionDetails } = this.props.navigation.state.params; - const { requestId, displayDetails: { requestType } } = transactionDetails; - this.props.removeRequest(requestId); - const rejectionType = requestType === 'message' ? 'signature' : 'transaction'; + this.closeScreen(); + const { + callback, + transactionDetails: { + payload: { method }, + peerId, + requestId, + }, + } = this.props.navigation.state.params; + if (callback) { + callback({ error: 'User cancelled the request' }); + } + if (requestId) { + await this.props.walletConnectSendStatus(peerId, requestId, null); + this.props.removeRequest(requestId); + } + const rejectionType = + method === SEND_TRANSACTION ? 'transaction' : 'signature'; analytics.track(`Rejected WalletConnect ${rejectionType} request`); } catch (error) { + console.log('error while handling cancel request', error); this.closeScreen(); - Alert.alert('Failed to send rejected transaction status'); + Alert.alert(lang.t('wallet.transaction.alert.cancelled_transaction')); } - } + }; closeScreen = () => { - StatusBar.setBarStyle('dark-content', true); this.props.navigation.popToTop(); - } + }; render = () => { const { transactionDetails: { dappName, imageUrl, - displayDetails: { - type, - payload, - }, + displayDetails: { request }, + payload: { method }, }, } = this.props.navigation.state.params; @@ -160,16 +223,17 @@ class TransactionConfirmationScreenWithData extends PureComponent { ); - } + }; } export default compose( + withGas, withNavigationFocus, - withTransactionConfirmationScreen, + withTransactionConfirmationScreen )(TransactionConfirmationScreenWithData); diff --git a/src/screens/WalletConnectConfirmationModal.js b/src/screens/WalletConnectConfirmationModal.js index fe86b85c5dd..e7afc75486b 100644 --- a/src/screens/WalletConnectConfirmationModal.js +++ b/src/screens/WalletConnectConfirmationModal.js @@ -25,15 +25,13 @@ const WalletConnectConfirmationModal = ({ peerMeta, }) => ( - + {get(peerMeta, 'name', 'Unknown dapp')} - wants to connect to your wallet. + + + wants to connect to your wallet. + @@ -43,11 +41,9 @@ const WalletConnectConfirmationModal = ({ ); WalletConnectConfirmationModal.propTypes = { - navigation: PropTypes.object.isRequired, onApprove: PropTypes.func.isRequired, onCloseModal: PropTypes.func.isRequired, onReject: PropTypes.func.isRequired, - peerId: PropTypes.string.isRequired, peerMeta: PropTypes.object.isRequired, }; @@ -59,7 +55,11 @@ export default compose( })), withHandlers({ onCloseModal: ({ navigation }) => () => navigation.goBack() }), withHandlers({ - onApprove: ({ onCloseModal, peerId, walletConnectApproveSession }) => () => { + onApprove: ({ + onCloseModal, + peerId, + walletConnectApproveSession, + }) => () => { walletConnectApproveSession(peerId); return onCloseModal(); }, @@ -67,5 +67,5 @@ export default compose( walletConnectRejectSession(peerId); onCloseModal(); }, - }), + }) )(WalletConnectConfirmationModal); diff --git a/src/screens/WalletScreen.js b/src/screens/WalletScreen.js index 8826396106a..1c9f30fd423 100644 --- a/src/screens/WalletScreen.js +++ b/src/screens/WalletScreen.js @@ -1,18 +1,10 @@ import { withSafeTimeout } from '@hocs/safe-timers'; -import analytics from '@segment/analytics-react-native'; import PropTypes from 'prop-types'; import React, { Component } from 'react'; import Animated from 'react-native-reanimated'; -import { withNavigation, withNavigationFocus } from 'react-navigation'; -import { - compose, - withHandlers, - withProps, - withState, -} from 'recompact'; -import { FadeInAnimation } from '../components/animations'; +import { withNavigation } from 'react-navigation'; +import { compose, withProps } from 'recompact'; import { AssetList } from '../components/asset-list'; -import BlurOverlay from '../components/BlurOverlay'; import { FabWrapper } from '../components/fab'; import { CameraHeaderButton, @@ -21,98 +13,73 @@ import { } from '../components/header'; import { Page } from '../components/layout'; import buildWalletSectionsSelector from '../helpers/buildWalletSections'; -import { - getShowShitcoinsSetting, - updateShowShitcoinsSetting, -} from '../handlers/commonStorage'; import { withAccountData, withAccountSettings, - withBlurTransitionProps, withDataInit, withIsWalletEmpty, withIsWalletEthZero, - withUniqueTokens, withStatusBarStyle, - withUniswapLiquidity, + withUniqueTokens, + withUniswapLiquidityTokenInfo, + withKeyboardHeight, } from '../hoc'; import { position } from '../styles'; -import { isNewValueForPath } from '../utils'; +import { isNewValueForObjectPaths } from '../utils'; +import { getKeyboardHeight } from '../handlers/localstorage/globalSettings'; class WalletScreen extends Component { static propTypes = { + accountAddress: PropTypes.string, allAssetsCount: PropTypes.number, assets: PropTypes.array, assetsTotal: PropTypes.object, - blurOpacity: PropTypes.object, initializeWallet: PropTypes.func, isEmpty: PropTypes.bool.isRequired, isFocused: PropTypes.bool, isWalletEthZero: PropTypes.bool.isRequired, navigation: PropTypes.object, + network: PropTypes.string, refreshAccountData: PropTypes.func, scrollViewTracker: PropTypes.object, sections: PropTypes.array, + setKeyboardHeight: PropTypes.func, setSafeTimeout: PropTypes.func, - showBlur: PropTypes.bool, - toggleShowShitcoins: PropTypes.func, uniqueTokens: PropTypes.array, - } + }; componentDidMount = async () => { try { await this.props.initializeWallet(); - const showShitcoins = await getShowShitcoinsSetting(); - if (showShitcoins !== null) { - this.props.toggleShowShitcoins(showShitcoins); + const keyboardheight = await getKeyboardHeight(); + if (keyboardheight) { + this.props.setKeyboardHeight(keyboardheight); } } catch (error) { - // TODO + // TODO error state } - } + }; - shouldComponentUpdate = (nextProps) => { - const isNewBlurOpacity = isNewValueForPath(this.props, nextProps, 'blurOpacity'); - const isNewCurrency = isNewValueForPath(this.props, nextProps, 'nativeCurrency'); - const isNewFetchingAssets = isNewValueForPath(this.props, nextProps, 'fetchingAssets'); - const isNewFetchingUniqueTokens = isNewValueForPath(this.props, nextProps, 'fetchingUniqueTokens'); - const isNewIsWalletEmpty = isNewValueForPath(this.props, nextProps, 'isEmpty'); - const isNewIsWalletEthZero = isNewValueForPath(this.props, nextProps, 'isWalletEthZero'); - const isNewLanguage = isNewValueForPath(this.props, nextProps, 'language'); - const isNewSections = isNewValueForPath(this.props, nextProps, 'sections'); - const isNewShowBlur = isNewValueForPath(this.props, nextProps, 'showBlur'); - const isNewShowShitcoins = isNewValueForPath(this.props, nextProps, 'showShitcoins'); - const isNewTransitionProps = isNewValueForPath(this.props, nextProps, 'transitionProps'); - - if (!nextProps.isFocused && !nextProps.showBlur) { - return isNewBlurOpacity - || isNewShowBlur - || isNewTransitionProps; - } - - return isNewFetchingAssets - || isNewFetchingUniqueTokens - || isNewIsWalletEmpty - || isNewIsWalletEthZero - || isNewLanguage - || isNewCurrency - || isNewBlurOpacity - || isNewSections - || isNewShowShitcoins - || isNewTransitionProps - || isNewShowBlur; - } + shouldComponentUpdate = nextProps => + nextProps.navigation.isFocused() && + isNewValueForObjectPaths(this.props, nextProps, [ + 'fetchingAssets', + 'fetchingUniqueTokens', + 'isEmpty', + 'isWalletEthZero', + 'language', + 'nativeCurrency', + 'sections', + ]); render = () => { const { - blurOpacity, isEmpty, isWalletEthZero, navigation, refreshAccountData, scrollViewTracker, sections, - showBlur, } = this.props; return ( @@ -125,7 +92,7 @@ class WalletScreen extends Component { scrollViewTracker={scrollViewTracker} sections={sections} > -
+
@@ -137,14 +104,9 @@ class WalletScreen extends Component { sections={sections} /> - {showBlur && ( - - - - )} ); - } + }; } export default compose( @@ -152,30 +114,13 @@ export default compose( withUniqueTokens, withAccountSettings, withDataInit, - withUniswapLiquidity, + withUniswapLiquidityTokenInfo, withSafeTimeout, withNavigation, - withNavigationFocus, - withBlurTransitionProps, withIsWalletEmpty, withIsWalletEthZero, + withKeyboardHeight, withStatusBarStyle('dark-content'), - withState('showShitcoins', 'toggleShowShitcoins', true), - withHandlers({ - onToggleShowShitcoins: ({ showShitcoins, toggleShowShitcoins }) => (index) => { - if (index === 0) { - const updatedShowShitcoinsSetting = !showShitcoins; - toggleShowShitcoins(updatedShowShitcoinsSetting); - updateShowShitcoinsSetting(updatedShowShitcoinsSetting); - - if (updatedShowShitcoinsSetting) { - analytics.track('Showed shitcoins'); - } else { - analytics.track('Hid shitcoins'); - } - } - }, - }), withProps(buildWalletSectionsSelector), - withProps({ scrollViewTracker: new Animated.Value(0) }), + withProps({ scrollViewTracker: new Animated.Value(0) }) )(WalletScreen); diff --git a/src/styles/animations.js b/src/styles/animations.js index afa9eb140b4..94a28484b19 100644 --- a/src/styles/animations.js +++ b/src/styles/animations.js @@ -29,14 +29,13 @@ const buildSpring = ({ to, useNativeDriver = true, value, -}) => ( +}) => Animated.spring(value, { ...spring.default, toValue: isActive ? to : from, useNativeDriver, ...config, - }) -); + }); export default { buildSpring, diff --git a/src/styles/borders.js b/src/styles/borders.js index 11e451fc284..3cf431f30a0 100644 --- a/src/styles/borders.js +++ b/src/styles/borders.js @@ -5,7 +5,7 @@ import position from './position'; const border = {}; -border.color = colors.lightGrey; +border.color = colors.lighterGrey; border.radius = 6; border.width = 1; diff --git a/src/styles/buildLayoutStyles.js b/src/styles/buildLayoutStyles.js index 334fe7e7eee..cb4f813596b 100644 --- a/src/styles/buildLayoutStyles.js +++ b/src/styles/buildLayoutStyles.js @@ -14,10 +14,12 @@ export default (values, type, shouldReturnCss) => { top: values[0], }; - return shouldReturnCss ? css` + return shouldReturnCss + ? css` ${type}${separator}bottom: ${coordinates.bottom}; ${type}${separator}left: ${coordinates.left}; ${type}${separator}right: ${coordinates.right}; ${type}${separator}top: ${coordinates.top}; - ` : coordinates; + ` + : coordinates; }; diff --git a/src/styles/buildTextStyles.js b/src/styles/buildTextStyles.js index a03210361ef..f5429e74ecc 100644 --- a/src/styles/buildTextStyles.js +++ b/src/styles/buildTextStyles.js @@ -3,28 +3,17 @@ import colors from './colors'; import fonts from './fonts'; export default css` - ${({ align }) => ( - align - ? `text-align: ${align};` - : '' - )} - ${({ letterSpacing }) => ( + ${({ align }) => (align ? `text-align: ${align};` : '')} + ${({ letterSpacing }) => letterSpacing ? `letter-spacing: ${fonts.letterSpacing[letterSpacing]};` - : '' - )} - ${({ lineHeight }) => ( - lineHeight - ? `line-height: ${fonts.lineHeight[lineHeight]};` - : '' - )} - ${({ uppercase }) => ( - uppercase - ? 'text-transform: uppercase;' - : '' - )} - color: ${({ color }) => (colors.get(color) || colors.dark)} - font-family: ${({ family }) => fonts.family[family || 'SFProText']}; + : ''} + ${({ lineHeight }) => + lineHeight ? `line-height: ${fonts.lineHeight[lineHeight]};` : ''} + ${({ uppercase }) => (uppercase ? 'text-transform: uppercase;' : '')} + color: ${({ color }) => colors.get(color) || colors.dark} + font-family: ${({ family = 'SFProText', mono }) => + fonts.family[mono ? 'SFMono' : family]}; font-size: ${({ size }) => fonts.size[size || 'medium']}; font-weight: ${({ weight }) => fonts.weight[weight || 'regular']}; `; diff --git a/src/styles/colors.js b/src/styles/colors.js index 5a6b98f15ce..14e2681684a 100644 --- a/src/styles/colors.js +++ b/src/styles/colors.js @@ -1,25 +1,35 @@ import chroma from 'chroma-js'; +import { toLower } from 'lodash'; import PropTypes from 'prop-types'; const base = { appleBlue: '#0E76FD', // 14, 118, 253 + backgroundGrey: '#141414', // 20, 20, 20 black: '#000000', // '0, 0, 0' blueGreyDark: '#3C4252', // '60, 66, 82' blueGreyDarker: '#0F0F11', // '15, 15, 17' blueGreyLight: '#A1A5AC', - blueGreyLightest: '#8A8E97', // '138, 142, 151' - blueGreyLigter: '#666A73', // '102, 106, 115' + blueGreyLighter: '#666A73', // '102, 106, 115' + blueGreyLightest: '#888D96', // '136, 141, 150' blueGreyMedium: '#636875', // '99, 104, 117' blueGreyMediumLight: '#7b7f8a', // '123, 127, 138' + brightOrange: '#FFB624', // '255, 182, 36' + brightRed: '#FF4B19', // '255, 75, 25' dark: '#25292E', // '37, 41, 46' darkGrey: '#71778a', // '113, 119, 138' + dodgerBlue: '#575CFF', // '87, 92, 255' green: '#00994d', // '0, 153, 77' grey: '#a9adb9', // '169, 173, 185' - highlightBackground: '#F0F7FF', // '240, 247, 255' + grey20: '#333333', // '51, 51, 51' + headerTitle: '#aaafbd', // '170, 175, 189' + lightBlue: '#c5f2ff', // '197, 242, 255' + lightBlueGrey: '#F3F5F7', // '243, 245, 247' + lighterGrey: '#f7f7f8', // '247, 247, 248' lightestGrey: '#E9EBEF', // '238, 233, 232' - lightGrey: '#f7f7f8', // '247, 247, 248' + lightGrey: '#CDCFD4', // '205, 207, 212' limeGreen: '#3FCC18', // '58, 166, 134' mediumGrey: '#a1a5b3', // '161, 165, 179' + orangeLight: '#FEBE44', // '254, 190, 68' orangeMedium: '#FCA247', // '252, 162, 71' paleBlue: '#579DFF', placeholder: '#C4C6CB', // 196, 198, 203 @@ -34,6 +44,18 @@ const base = { white: '#ffffff', // '255, 255, 255' }; +const avatarColor = [ + '#ff494a', // '255, 73, 74' + '#02d3ff', // '2, 211, 255' + '#fb60c4', // '251, 96, 196' + '#3f6aff', // '63, 106, 255' + '#fada3d', // '250, 218, 61' + '#b140ff', // '177, 64, 255' + '#40ebc1', // '64, 235, 193' + '#f46e38', // '244, 110, 56' + '#6d7e8f', // '109, 126, 143' +]; + const assetIcon = { blue: '#7dabf0', // '125, 171, 240' orange: '#f2bb3a', // '242, 187, 58' @@ -61,24 +83,23 @@ const vendor = { const buildRgba = (color, alpha) => `rgba(${chroma(color).rgb()}, ${alpha})`; -const isColorLight = targetColor => (chroma(targetColor || base.white).luminance() > 0.5); +const isColorLight = targetColor => + chroma(targetColor || base.white).luminance() > 0.5; -const isHex = (color = '') => ((color.length >= 3) && (color.charAt(0) === '#')); -const isRGB = (color = '') => (color.toLowerCase().substring(0, 3) === 'rgb'); +const isHex = (color = '') => color.length >= 3 && color.charAt(0) === '#'; +const isRGB = (color = '') => toLower(color).substring(0, 3) === 'rgb'; const getTextColorForBackground = (targetColor, textColors = {}) => { - const { - dark = base.black, - light = base.white, - } = textColors; + const { dark = base.black, light = base.white } = textColors; return isColorLight(targetColor) ? dark : light; }; -const getFallbackTextColor = bg => colors.getTextColorForBackground(bg, { - dark: colors.blueGreyLight, - light: colors.white, -}); +const getFallbackTextColor = bg => + colors.getTextColorForBackground(bg, { + dark: colors.blueGreyLight, + light: colors.white, + }); const transparent = { blueGreyDarkTransparent: buildRgba(base.blueGreyDark, 0.6), @@ -89,6 +110,7 @@ const transparent = { const colors = { alpha: buildRgba, assetIcon, + avatarColor, getFallbackTextColor, getTextColorForBackground, isColorLight, @@ -108,8 +130,5 @@ const getColorForString = (colorString = '') => { export default { ...colors, get: getColorForString, - propType: PropTypes.oneOf([ - ...Object.keys(colors), - ...Object.values(colors), - ]), + propType: PropTypes.oneOf([...Object.keys(colors), ...Object.values(colors)]), }; diff --git a/src/styles/fonts.js b/src/styles/fonts.js index 8908805bc32..72d97c29fa5 100644 --- a/src/styles/fonts.js +++ b/src/styles/fonts.js @@ -1,3 +1,4 @@ +/* eslint-disable sort-keys */ const font = {}; font.family = { @@ -8,7 +9,7 @@ font.family = { }; font.letterSpacing = { - /* eslint-disable sort-keys */ + tightest: -0.3, tighter: -0.2, tight: -0.1, loose: 0.15, @@ -16,17 +17,15 @@ font.letterSpacing = { }; font.lineHeight = { - /* eslint-disable sort-keys */ none: 0, tight: 16, normal: 20, loose: 21, - looser: 25, + looser: 26, loosest: 28, }; font.size = { - /* eslint-disable sort-keys */ micro: '9px', tiny: '11px', smaller: '12px', @@ -40,6 +39,7 @@ font.size = { blarge: '21px', big: '22px', bigger: '26px', + biggest: '27px', h1: '42px', h2: '30px', h3: '24px', @@ -50,7 +50,6 @@ font.size = { // react-native requires font weights to be defined as strings font.weight = { - /* eslint-disable sort-keys */ thin: '100', ultraLight: '200', light: '300', diff --git a/src/styles/shadow.js b/src/styles/shadow.js index dec92d36441..5f692cb5f99 100644 --- a/src/styles/shadow.js +++ b/src/styles/shadow.js @@ -1,20 +1,24 @@ import { isNumber } from 'lodash'; import colors from './colors'; -const addUnitToNumberValues = value => ( - isNumber(value) ? `${value}px` : value -); +const addUnitToNumberValues = value => (isNumber(value) ? `${value}px` : value); const shadow = {}; shadow.color = colors.black; shadow.opacity = 0.4; -shadow.build = (x, y, radius, color = shadow.color, opacity = shadow.opacity) => ` +shadow.build = ( + x, + y, + radius, + color = shadow.color, + opacity = shadow.opacity +) => ` shadow-color: ${color}; shadow-offset: ${addUnitToNumberValues(x)} ${addUnitToNumberValues(y)}; shadow-opacity: ${opacity}; - shadow-radius: ${addUnitToNumberValues(radius)}; + shadow-radius: ${addUnitToNumberValues(radius / 2)}; `; export default shadow; diff --git a/src/utils/__tests__/contract.test.js b/src/utils/__tests__/contract.test.js new file mode 100644 index 00000000000..3026c60c0b0 --- /dev/null +++ b/src/utils/__tests__/contract.test.js @@ -0,0 +1,43 @@ +import { greaterThan } from '../../helpers/utilities'; +import Contract from '../contract'; + +const { getAllowance } = Contract; + +const accountAddress = '0x1492004547FF0eFd778CC2c14E794B26B4701105'; + +it('getAllowanceZrx', async () => { + const exchangeAddress = '0xaE76c84C9262Cdb9abc0C2c8888e62Db8E22A0bF'; + const tokenAddress = '0xe41d2489571d322189246dafa5ebde1f4699f498'; + const allowance = await getAllowance( + accountAddress, + { address: tokenAddress, decimals: 18 }, + exchangeAddress + ); + const result = greaterThan(allowance, 0); + expect(result).toBeTruthy(); +}); + +it('getAllowanceMkr', async () => { + const exchangeAddress = '0x2C4Bd064b998838076fa341A83d007FC2FA50957'; + const tokenAddress = '0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2'; + const allowance = await getAllowance( + accountAddress, + { address: tokenAddress, decimals: 18 }, + exchangeAddress + ); + const result = greaterThan(allowance, 0); + expect(result).toBeTruthy(); +}); + +// TODO +xit('getAllowanceBatNotApproved', async () => { + const exchangeAddress = '0x2E642b8D59B45a1D8c5aEf716A84FF44ea665914'; + const tokenAddress = '0x0d8775f648430679a709e98d2b0cb6250d2887ef'; + const allowance = await getAllowance( + accountAddress, + { address: tokenAddress, decimals: 18 }, + exchangeAddress + ); + const result = greaterThan(allowance, 0); + expect(result).toBeFalsy(); +}); diff --git a/src/utils/__tests__/ethereumUtils.test.js b/src/utils/__tests__/ethereumUtils.test.js new file mode 100644 index 00000000000..639c4002b75 --- /dev/null +++ b/src/utils/__tests__/ethereumUtils.test.js @@ -0,0 +1,36 @@ +import ethereumUtils from '../ethereumUtils'; + +const gasPrice = { + txFee: { + value: { + amount: 21000, + }, + }, +}; + +it('getBalanceAmountEth', () => { + const selected = { + address: 'eth', + balance: { amount: '1' }, + }; + const updatedBalance = ethereumUtils.getBalanceAmount(gasPrice, selected); + expect(updatedBalance).toBe('0.999999999999979'); +}); + +it('getBalanceAmountInsufficientEth', () => { + const selected = { + address: 'eth', + balance: { amount: '0.00000000000000001' }, + }; + const updatedBalance = ethereumUtils.getBalanceAmount(gasPrice, selected); + expect(updatedBalance).toBe('0'); +}); + +it('getBalanceAmountToken', () => { + const selected = { + address: '0x12345', + balance: { amount: '1' }, + }; + const updatedBalance = ethereumUtils.getBalanceAmount(gasPrice, selected); + expect(updatedBalance).toBe('1'); +}); diff --git a/src/utils/__tests__/search.test.js b/src/utils/__tests__/search.test.js new file mode 100644 index 00000000000..e8e3a282c5b --- /dev/null +++ b/src/utils/__tests__/search.test.js @@ -0,0 +1,18 @@ +import { filterList } from '../search'; + +it('filterListSimpleArray', () => { + const list = ['a dog', 'black cat']; + const searchPhrase = 'cat'; + const result = filterList(list, searchPhrase); + expect(result.length).toBe(1); +}); + +it('filterListWithParameter', () => { + const list = [ + { name: 'Ethereum', symbol: 'ETH' }, + { name: '0x Protocol Token', symbol: 'ZRX' }, + ]; + const searchPhrase = 'eth'; + const result = filterList(list, searchPhrase, 'name'); + expect(result.length).toBe(1); +}); diff --git a/src/utils/abbreviations.js b/src/utils/abbreviations.js index 1da2093ce3c..14c77e10452 100644 --- a/src/utils/abbreviations.js +++ b/src/utils/abbreviations.js @@ -12,7 +12,10 @@ export function address(currentAddress, truncationLength, firstSectionLength) { } export function isAddress(currentAddress) { - return (currentAddress || '').substring(0, 2) === '0x' && (currentAddress || '').indexOf('...') > -1; + return ( + (currentAddress || '').substring(0, 2) === '0x' && + (currentAddress || '').indexOf('...') > -1 + ); } export default { diff --git a/src/utils/address.js b/src/utils/address.js index 82e0c3cbf00..020188fb931 100644 --- a/src/utils/address.js +++ b/src/utils/address.js @@ -1,19 +1,19 @@ -import { isValidAddress } from '../helpers/validators'; +import { checkIsValidAddress } from '../helpers/validators'; /** * @desc get ethereum address from raw QR Code data * @param {String} data - qr code data * @return {String} address - ethereum address */ -export const getEthereumAddressFromQRCodeData = async (data) => { +export const getEthereumAddressFromQRCodeData = async data => { if (!data) return null; const parts = data.split(':'); - if (parts[0] === 'ethereum' && await isValidAddress(parts[1])) { + if (parts[0] === 'ethereum' && (await checkIsValidAddress(parts[1]))) { return parts[1]; } - if (await isValidAddress(parts[0])) { + if (await checkIsValidAddress(parts[0])) { return parts[0]; } diff --git a/src/utils/contract.js b/src/utils/contract.js new file mode 100644 index 00000000000..c28581917f2 --- /dev/null +++ b/src/utils/contract.js @@ -0,0 +1,59 @@ +import { ethers } from 'ethers'; +import { toHex, web3Provider } from '../handlers/web3'; +import { convertRawAmountToDecimalFormat } from '../helpers/utilities'; +import { loadWallet } from '../model/wallet'; +import erc20ABI from '../references/erc20-abi.json'; + +const estimateApproveWithExchange = async (spender, exchange) => { + try { + const gasLimit = await exchange.estimate.approve( + spender, + ethers.constants.MaxUint256 + ); + return gasLimit ? gasLimit.toString() : null; + } catch (error) { + console.log('error estimating approval', error); + return null; + } +}; + +const estimateApprove = (tokenAddress, spender) => { + const exchange = new ethers.Contract(tokenAddress, erc20ABI, web3Provider); + return estimateApproveWithExchange(spender, exchange); +}; + +const approve = async (tokenAddress, spender, gasLimit, gasPrice) => { + const wallet = await loadWallet(); + if (!wallet) return null; + const exchange = new ethers.Contract(tokenAddress, erc20ABI, wallet); + const creationTimestamp = Date.now(); + const approval = await exchange.approve( + spender, + ethers.constants.MaxUint256, + { + gasLimit: gasLimit ? toHex(gasLimit) : undefined, + gasPrice: gasPrice ? toHex(gasPrice) : undefined, + } + ); + return { + approval, + creationTimestamp, + }; +}; + +const getAllowance = async (owner, token, spender) => { + const { address: tokenAddress, decimals } = token; + const tokenContract = new ethers.Contract( + tokenAddress, + erc20ABI, + web3Provider + ); + const allowance = await tokenContract.allowance(owner, spender); + return convertRawAmountToDecimalFormat(allowance.toString(), decimals); +}; + +export default { + approve, + estimateApprove, + getAllowance, +}; diff --git a/src/utils/deviceUtils.js b/src/utils/deviceUtils.js index e9abf291a0c..c79d9a9197c 100644 --- a/src/utils/deviceUtils.js +++ b/src/utils/deviceUtils.js @@ -1,7 +1,6 @@ -import { pick } from 'lodash'; import { Dimensions } from 'react-native'; -const { height, width } = pick(Dimensions.get('window'), ['height', 'width']); +const { height, width } = Dimensions.get('window'); const deviceUtils = {}; diff --git a/src/utils/directionPropType.js b/src/utils/directionPropType.js index 1eb4530d6e8..b09bc5b224e 100644 --- a/src/utils/directionPropType.js +++ b/src/utils/directionPropType.js @@ -1,8 +1,3 @@ import PropTypes from 'prop-types'; -export default PropTypes.oneOf([ - 'down', - 'left', - 'right', - 'up', -]); +export default PropTypes.oneOf(['down', 'left', 'right', 'up']); diff --git a/src/utils/ethereumUtils.js b/src/utils/ethereumUtils.js index 4d397b84a50..f72c5957a84 100644 --- a/src/utils/ethereumUtils.js +++ b/src/utils/ethereumUtils.js @@ -1,19 +1,41 @@ -import { find, get } from 'lodash'; +import { find, get, replace, toLower } from 'lodash'; import chains from '../references/chains.json'; import { add, convertNumberToString, fromWei, + greaterThan, + subtract, } from '../helpers/utilities'; -export const getAsset = (assets, address = 'eth') => find(assets, asset => asset.address === address); +const getEthPriceUnit = assets => { + const ethAsset = getAsset(assets); + return get(ethAsset, 'price.value', 0); +}; + +const getBalanceAmount = (selectedGasPrice, selected) => { + let amount = ''; + if (selected.address === 'eth') { + const balanceAmount = get(selected, 'balance.amount', 0); + const txFeeRaw = get(selectedGasPrice, 'txFee.value.amount'); + const txFeeAmount = fromWei(txFeeRaw); + const remaining = subtract(balanceAmount, txFeeAmount); + amount = convertNumberToString(greaterThan(remaining, 0) ? remaining : 0); + } else { + amount = get(selected, 'balance.amount', 0); + } + return amount; +}; + +const getAsset = (assets, address = 'eth') => + find(assets, asset => asset.address === address); /** * @desc remove hex prefix * @param {String} hex * @return {String} */ -export const removeHexPrefix = hex => hex.toLowerCase().replace('0x', ''); +const removeHexPrefix = hex => replace(toLower(hex), '0x', ''); /** * @desc pad string to specific width and padding @@ -22,7 +44,7 @@ export const removeHexPrefix = hex => hex.toLowerCase().replace('0x', ''); * @param {String} z * @return {String} */ -export const padLeft = (n, width, z) => { +const padLeft = (n, width, z) => { z = z || '0'; n = n + ''; return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n; @@ -34,7 +56,7 @@ export const padLeft = (n, width, z) => { * @param {Array} arrVals * @return {String} */ -export const getDataString = (func, arrVals) => { +const getDataString = (func, arrVals) => { let val = ''; for (let i = 0; i < arrVals.length; i++) val += padLeft(arrVals[i], 64); const data = func + val; @@ -45,7 +67,7 @@ export const getDataString = (func, arrVals) => { * @desc get network string from chainId * @param {Number} chainId */ -export const getNetworkFromChainId = (chainId) => { +const getNetworkFromChainId = chainId => { const networkData = find(chains, ['chain_id', chainId]); return get(networkData, 'network', 'mainnet'); }; @@ -54,7 +76,7 @@ export const getNetworkFromChainId = (chainId) => { * @desc get chainId from network string * @param {String} network */ -export const getChainIdFromNetwork = (network) => { +const getChainIdFromNetwork = network => { const chainData = find(chains, ['network', network]); return get(chainData, 'chain_id', 1); }; @@ -66,7 +88,7 @@ export const getChainIdFromNetwork = (network) => { * @param {String} gasPrice * @return {Object} ethereum, balanceAmount, balance, requestedAmount, txFeeAmount, txFee, amountWithFees */ -export const transactionData = (assets, assetAmount, gasPrice) => { +const transactionData = (assets, assetAmount, gasPrice) => { const ethereum = getAsset(assets); const balance = get(ethereum, 'balance.amount', 0); const requestedAmount = convertNumberToString(assetAmount); @@ -84,8 +106,10 @@ export const transactionData = (assets, assetAmount, gasPrice) => { export default { getAsset, + getBalanceAmount, getChainIdFromNetwork, getDataString, + getEthPriceUnit, getNetworkFromChainId, removeHexPrefix, transactionData, diff --git a/src/utils/formatters.js b/src/utils/formatters.js index b1b2be1925c..f337aff7a9c 100644 --- a/src/utils/formatters.js +++ b/src/utils/formatters.js @@ -1,19 +1,33 @@ import { isString } from 'lodash'; +import GraphemeSplitter from 'grapheme-splitter'; + +const grapheme = new GraphemeSplitter(); const firstCharacterOfString = n => n.charAt(0); -export const initials = (string) => ( - (!string || !isString(string)) +export const getFirstGrapheme = string => grapheme.splitGraphemes(string)[0]; + +export const initials = string => + !string || !isString(string) ? '?' - : string.split(' ').map(firstCharacterOfString).join('') -); + : string + .split(' ') + .map(firstCharacterOfString) + .join(''); export function removeLeadingZeros(value = '') { - if (value.length > 1 && value.substring(0, 1) === '0' && value.substring(1, 2) !== '.') { + if ( + value.length > 1 && + value.substring(0, 1) === '0' && + value.substring(1, 2) !== '.' + ) { return removeLeadingZeros(value.substring(1)); } - if (value.substring(value.length - 1, value.length) === '.' && value.indexOf('.') !== value.length - 1) { + if ( + value.substring(value.length - 1, value.length) === '.' && + value.indexOf('.') !== value.length - 1 + ) { return value.substring(0, value.length - 1); } @@ -25,6 +39,7 @@ export function removeLeadingZeros(value = '') { } export default { + getFirstGrapheme, initials, removeLeadingZeros, }; diff --git a/src/utils/gas.js b/src/utils/gas.js new file mode 100644 index 00000000000..9ad5e261d07 --- /dev/null +++ b/src/utils/gas.js @@ -0,0 +1,72 @@ +import analytics from '@segment/analytics-react-native'; +import { + get, + indexOf, + isFunction, + map, + property, + sortBy, + upperFirst, +} from 'lodash'; +import { showActionSheetWithOptions } from './actionsheet'; + +const FAST = 'fast'; +const NORMAL = 'normal'; +const SLOW = 'slow'; + +const GasSpeedOrder = [SLOW, NORMAL, FAST]; + +const showTransactionSpeedOptions = ( + gasPrices, + txFees, + updateGasOption, + onSuccess +) => { + const options = [ + { label: 'Cancel' }, + ...formatGasSpeedItems(gasPrices, txFees), + ]; + + showActionSheetWithOptions( + { + cancelButtonIndex: 0, + options: options.map(property('label')), + }, + buttonIndex => { + if (buttonIndex > 0) { + const selectedGasPriceItem = options[buttonIndex]; + updateGasOption(selectedGasPriceItem.speed); + analytics.track('Updated Gas Price', { + gasPrice: selectedGasPriceItem.gweiValue, + }); + } + + if (isFunction(onSuccess)) { + onSuccess(); + } + } + ); +}; + +const formatGasSpeedItems = (gasPrices, txFees) => { + const gasItems = map(GasSpeedOrder, speed => { + const cost = get(txFees, `[${speed}].txFee.native.value.display`); + const gwei = get(gasPrices, `[${speed}].value.display`); + const time = get(gasPrices, `[${speed}].estimatedTime.display`); + + return { + gweiValue: gwei, + label: `${upperFirst(speed)}: ${cost} ~${time}`, + speed, + }; + }); + return sortBy(gasItems, ({ speed }) => indexOf(GasSpeedOrder, speed)); +}; + +export default { + FAST, + GasSpeedOrder, + NORMAL, + showTransactionSpeedOptions, + SLOW, +}; diff --git a/src/utils/haptics.js b/src/utils/haptics.js new file mode 100644 index 00000000000..50bcdda95da --- /dev/null +++ b/src/utils/haptics.js @@ -0,0 +1,23 @@ +import { keys, map } from 'lodash'; +import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; +import reduceArrayToObject from './reduceArrayToObject'; + +export const HapticFeedbackTypes = { + impactHeavy: 'impactHeavy', + impactLight: 'impactLight', + impactMedium: 'impactMedium', + notificationError: 'notificationError', + notificationSuccess: 'notificationSuccess', + notificationWarning: 'notificationWarning', + selection: 'selection', +}; + +const hapticToTrigger = haptic => ({ + [haptic]: () => ReactNativeHapticFeedback.trigger(haptic), +}); + +const haptics = reduceArrayToObject( + map(keys(HapticFeedbackTypes), hapticToTrigger) +); + +export default haptics; diff --git a/src/utils/index.js b/src/utils/index.js index 0840a93573d..a89fef6f8df 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -1,13 +1,20 @@ export { default as abbreviations } from './abbreviations'; export { default as addressUtils } from './address'; +export { default as contractUtils } from './contract'; export { default as deviceUtils } from './deviceUtils'; export { default as dimensionsPropType } from './dimensionsPropType'; export { default as directionPropType } from './directionPropType'; export { default as ethereumUtils } from './ethereumUtils'; -export { initials, removeLeadingZeros } from './formatters'; +export { default as gasUtils } from './gas'; +export { default as haptics } from './haptics'; +export { getFirstGrapheme, initials, removeLeadingZeros } from './formatters'; export { default as isLowerCaseMatch } from './isLowerCaseMatch'; +export { default as isNewValueForObjectPaths } from './isNewValueForObjectPaths'; export { default as isNewValueForPath } from './isNewValueForPath'; +export { default as parseObjectToUrlQueryString } from './parseObjectToUrlQueryString'; export { default as parseQueryParams } from './parseQueryParams'; +export { default as promiseUtils } from './promise'; export { default as reduceArrayToObject } from './reduceArrayToObject'; export { default as safeAreaInsetValues } from './safeAreaInsetValues'; +export { default as sentryUtils } from './sentry'; export { default as statusBar } from './statusBar'; diff --git a/src/utils/isLowerCaseMatch.js b/src/utils/isLowerCaseMatch.js index ac142257e7b..96f92ba1ba7 100644 --- a/src/utils/isLowerCaseMatch.js +++ b/src/utils/isLowerCaseMatch.js @@ -1,5 +1,5 @@ +import { toLower } from 'lodash'; + export default function isLowerCaseMatch(a, b) { - const _a = a || ''; - const _b = b || ''; - return _a.toLowerCase() === _b.toLowerCase(); + return toLower(a) === toLower(b); } diff --git a/src/utils/isNewValueForObjectPaths.js b/src/utils/isNewValueForObjectPaths.js new file mode 100644 index 00000000000..6b0d330e82c --- /dev/null +++ b/src/utils/isNewValueForObjectPaths.js @@ -0,0 +1,6 @@ +import { pick } from 'lodash'; +import isEqual from 'react-fast-compare'; + +export default function isNewValueForObjectPaths(a, b, paths) { + return !isEqual(pick(a, paths), pick(b, paths)); +} diff --git a/src/utils/parseObjectToUrlQueryString.js b/src/utils/parseObjectToUrlQueryString.js new file mode 100644 index 00000000000..937bd3344dd --- /dev/null +++ b/src/utils/parseObjectToUrlQueryString.js @@ -0,0 +1,10 @@ +import { keys } from 'lodash'; + +export default params => + keys(params) + .map(key => { + const encodedKey = encodeURIComponent(key); + const encodedValue = encodeURIComponent(params[key]); + return `${encodedKey}=${encodedValue}`; + }) + .join('&'); diff --git a/src/utils/parseQueryParams.js b/src/utils/parseQueryParams.js index 59e809347f1..d2fffb2705e 100644 --- a/src/utils/parseQueryParams.js +++ b/src/utils/parseQueryParams.js @@ -11,10 +11,9 @@ export default queryString => { const valueArr = pairs[i].match(/=.+/i) || []; if (keyArr[0]) { result[decodeURIComponent(keyArr[0])] = decodeURIComponent( - valueArr[0].substr(1), + valueArr[0].substr(1) ); } } - return result; }; diff --git a/src/utils/promise.js b/src/utils/promise.js new file mode 100644 index 00000000000..8f590a40ca1 --- /dev/null +++ b/src/utils/promise.js @@ -0,0 +1,10 @@ +const PromiseAllWithFails = async promises => + Promise.all( + promises.map(promise => + promise && promise.catch ? promise.catch(error => error) : promise + ) + ); + +export default { + PromiseAllWithFails, +}; diff --git a/src/utils/reduceArrayToObject.js b/src/utils/reduceArrayToObject.js index 2b18a0371ae..4abbeef6564 100644 --- a/src/utils/reduceArrayToObject.js +++ b/src/utils/reduceArrayToObject.js @@ -2,8 +2,5 @@ import { compact } from 'lodash'; const reduceArrayToObject = (item, culm) => Object.assign(culm, item); -export default array => ( - Array.isArray(array) - ? compact(array).reduce(reduceArrayToObject, {}) - : array -); +export default array => + Array.isArray(array) ? compact(array).reduce(reduceArrayToObject, {}) : array; diff --git a/src/utils/search.js b/src/utils/search.js new file mode 100644 index 00000000000..b2f124fd13c --- /dev/null +++ b/src/utils/search.js @@ -0,0 +1,7 @@ +import matchSorter from 'match-sorter'; + +export const filterList = (list, searchQuery, searchListByKey) => { + return matchSorter(list, searchQuery, { + keys: searchListByKey ? [searchListByKey] : null, + }); +}; diff --git a/src/utils/sentry.js b/src/utils/sentry.js new file mode 100644 index 00000000000..0e18d493a7e --- /dev/null +++ b/src/utils/sentry.js @@ -0,0 +1,11 @@ +import { addBreadcrumb } from '@sentry/react-native'; + +const addInfoBreadcrumb = message => + addBreadcrumb({ + level: 'info', + message, + }); + +export default { + addInfoBreadcrumb, +}; diff --git a/src/utils/signingMethods.js b/src/utils/signingMethods.js new file mode 100644 index 00000000000..c3ca0d31772 --- /dev/null +++ b/src/utils/signingMethods.js @@ -0,0 +1,31 @@ +import { concat, includes } from 'lodash'; + +export const PERSONAL_SIGN = 'personal_sign'; +export const SEND_TRANSACTION = 'eth_sendTransaction'; +export const SIGN = 'eth_sign'; +export const SIGN_TRANSACTION = 'eth_signTransaction'; +export const SIGN_TYPED = 'eth_signTypedData'; +export const SIGN_TYPED_V3 = 'eth_signTypedData_v3'; + +const displayTypes = { + message: [PERSONAL_SIGN, SIGN, SIGN_TYPED, SIGN_TYPED_V3], + transaction: [SEND_TRANSACTION, SIGN_TRANSACTION], +}; +const firstParamSigning = [PERSONAL_SIGN]; +const secondParamSigning = [SIGN, SIGN_TYPED, SIGN_TYPED_V3]; + +const allTypes = concat(displayTypes.message, ...displayTypes.transaction); + +export const isSigningMethod = method => includes(allTypes, method); + +export const isMessageDisplayType = method => + includes(displayTypes.message, method); + +export const isTransactionDisplayType = method => + includes(displayTypes.transaction, method); + +export const isSignSecondParamType = method => + includes(secondParamSigning, method); + +export const isSignFirstParamType = method => + includes(firstParamSigning, method); diff --git a/yarn.lock b/yarn.lock index 1e4a415a0f5..2e0fd043868 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,13 +2,6 @@ # yarn lockfile v1 -"@babel/code-frame@7.0.0-beta.44": - version "7.0.0-beta.44" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-beta.44.tgz#2a02643368de80916162be70865c97774f3adbd9" - integrity sha512-cuAuTTIQ9RqcFRJ/Y8PvTh+paepNcaGxwQwjIDRWPXmzzyAeCO4KqS9ikMvq0MCbRk6GlYKwfzStrcP3/jSL8g== - dependencies: - "@babel/highlight" "7.0.0-beta.44" - "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" @@ -16,19 +9,19 @@ dependencies: "@babel/highlight" "^7.0.0" -"@babel/core@>=7.2.2", "@babel/core@^7.0.0", "@babel/core@^7.1.0", "@babel/core@^7.4.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.5.5.tgz#17b2686ef0d6bc58f963dddd68ab669755582c30" - integrity sha512-i4qoSr2KTtce0DmkuuQBV4AuQgGPUcPXMr9L5MyYAtk06z068lQ10a4O009fe5OB/DfNV+h+qqT7ddNV8UnRjg== +"@babel/core@>=7.2.2", "@babel/core@^7.0.0", "@babel/core@^7.1.0", "@babel/core@^7.4.5", "@babel/core@^7.7.2": + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.7.tgz#ee155d2e12300bcc0cff6a8ad46f2af5063803e9" + integrity sha512-jlSjuj/7z138NLZALxVgrx13AOtqip42ATZP7+kYl53GvDV6+4dCek1mVUo8z8c8Xnw/mx2q3d9HWh3griuesQ== dependencies: "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.5.5" - "@babel/helpers" "^7.5.5" - "@babel/parser" "^7.5.5" - "@babel/template" "^7.4.4" - "@babel/traverse" "^7.5.5" - "@babel/types" "^7.5.5" - convert-source-map "^1.1.0" + "@babel/generator" "^7.7.7" + "@babel/helpers" "^7.7.4" + "@babel/parser" "^7.7.7" + "@babel/template" "^7.7.4" + "@babel/traverse" "^7.7.4" + "@babel/types" "^7.7.4" + convert-source-map "^1.7.0" debug "^4.1.0" json5 "^2.1.0" lodash "^4.17.13" @@ -36,160 +29,140 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@7.0.0-beta.44": - version "7.0.0-beta.44" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.0.0-beta.44.tgz#c7e67b9b5284afcf69b309b50d7d37f3e5033d42" - integrity sha512-5xVb7hlhjGcdkKpMXgicAVgx8syK5VJz193k0i/0sLP6DzE6lRrU1K3B/rFefgdo9LPGMAOOOAWW4jycj07ShQ== +"@babel/generator@^7.0.0", "@babel/generator@^7.4.0", "@babel/generator@^7.7.4", "@babel/generator@^7.7.7": + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.7.tgz#859ac733c44c74148e1a72980a64ec84b85f4f45" + integrity sha512-/AOIBpHh/JU1l0ZFS4kiRCBnLi6OTHzh0RPk3h9isBxkkqELtQNFi1Vr/tiG9p1yfoUdKVwISuXWQR+hwwM4VQ== dependencies: - "@babel/types" "7.0.0-beta.44" - jsesc "^2.5.1" - lodash "^4.2.0" - source-map "^0.5.0" - trim-right "^1.0.1" - -"@babel/generator@^7.0.0", "@babel/generator@^7.4.0", "@babel/generator@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.5.5.tgz#873a7f936a3c89491b43536d12245b626664e3cf" - integrity sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ== - dependencies: - "@babel/types" "^7.5.5" + "@babel/types" "^7.7.4" jsesc "^2.5.1" lodash "^4.17.13" source-map "^0.5.0" - trim-right "^1.0.1" -"@babel/helper-annotate-as-pure@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz#323d39dd0b50e10c7c06ca7d7638e6864d8c5c32" - integrity sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q== +"@babel/helper-annotate-as-pure@^7.0.0", "@babel/helper-annotate-as-pure@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.7.4.tgz#bb3faf1e74b74bd547e867e48f551fa6b098b6ce" + integrity sha512-2BQmQgECKzYKFPpiycoF9tlb5HA4lrVyAmLLVK177EcQAqjVLciUb2/R+n1boQ9y5ENV3uz2ZqiNw7QMBBw1Og== dependencies: - "@babel/types" "^7.0.0" + "@babel/types" "^7.7.4" -"@babel/helper-builder-binary-assignment-operator-visitor@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz#6b69628dfe4087798e0c4ed98e3d4a6b2fbd2f5f" - integrity sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w== +"@babel/helper-builder-binary-assignment-operator-visitor@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.7.4.tgz#5f73f2b28580e224b5b9bd03146a4015d6217f5f" + integrity sha512-Biq/d/WtvfftWZ9Uf39hbPBYDUo986m5Bb4zhkeYDGUllF43D+nUe5M6Vuo6/8JDK/0YX/uBdeoQpyaNhNugZQ== dependencies: - "@babel/helper-explode-assignable-expression" "^7.1.0" - "@babel/types" "^7.0.0" + "@babel/helper-explode-assignable-expression" "^7.7.4" + "@babel/types" "^7.7.4" -"@babel/helper-builder-react-jsx@^7.3.0": - version "7.3.0" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.3.0.tgz#a1ac95a5d2b3e88ae5e54846bf462eeb81b318a4" - integrity sha512-MjA9KgwCuPEkQd9ncSXvSyJ5y+j2sICHyrI0M3L+6fnS4wMSNDc1ARXsbTfbb2cXHn17VisSnU/sHFTCxVxSMw== +"@babel/helper-builder-react-jsx@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.7.4.tgz#da188d247508b65375b2c30cf59de187be6b0c66" + integrity sha512-kvbfHJNN9dg4rkEM4xn1s8d1/h6TYNvajy9L1wx4qLn9HFg0IkTsQi4rfBe92nxrPUFcMsHoMV+8rU7MJb3fCA== dependencies: - "@babel/types" "^7.3.0" + "@babel/types" "^7.7.4" esutils "^2.0.0" -"@babel/helper-call-delegate@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.4.4.tgz#87c1f8ca19ad552a736a7a27b1c1fcf8b1ff1f43" - integrity sha512-l79boDFJ8S1c5hvQvG+rc+wHw6IuH7YldmRKsYtpbawsxURu/paVy57FZMomGK22/JckepaikOkY0MoAmdyOlQ== +"@babel/helper-call-delegate@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.7.4.tgz#621b83e596722b50c0066f9dc37d3232e461b801" + integrity sha512-8JH9/B7J7tCYJ2PpWVpw9JhPuEVHztagNVuQAFBVFYluRMlpG7F1CgKEgGeL6KFqcsIa92ZYVj6DSc0XwmN1ZA== dependencies: - "@babel/helper-hoist-variables" "^7.4.4" - "@babel/traverse" "^7.4.4" - "@babel/types" "^7.4.4" + "@babel/helper-hoist-variables" "^7.7.4" + "@babel/traverse" "^7.7.4" + "@babel/types" "^7.7.4" -"@babel/helper-create-class-features-plugin@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.5.5.tgz#401f302c8ddbc0edd36f7c6b2887d8fa1122e5a4" - integrity sha512-ZsxkyYiRA7Bg+ZTRpPvB6AbOFKTFFK4LrvTet8lInm0V468MWCaSYJE+I7v2z2r8KNLtYiV+K5kTCnR7dvyZjg== +"@babel/helper-create-class-features-plugin@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.7.4.tgz#fce60939fd50618610942320a8d951b3b639da2d" + integrity sha512-l+OnKACG4uiDHQ/aJT8dwpR+LhCJALxL0mJ6nzjB25e5IPwqV1VOsY7ah6UB1DG+VOXAIMtuC54rFJGiHkxjgA== dependencies: - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-member-expression-to-functions" "^7.5.5" - "@babel/helper-optimise-call-expression" "^7.0.0" + "@babel/helper-function-name" "^7.7.4" + "@babel/helper-member-expression-to-functions" "^7.7.4" + "@babel/helper-optimise-call-expression" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.5.5" - "@babel/helper-split-export-declaration" "^7.4.4" + "@babel/helper-replace-supers" "^7.7.4" + "@babel/helper-split-export-declaration" "^7.7.4" -"@babel/helper-define-map@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.5.5.tgz#3dec32c2046f37e09b28c93eb0b103fd2a25d369" - integrity sha512-fTfxx7i0B5NJqvUOBBGREnrqbTxRh7zinBANpZXAVDlsZxYdclDp467G1sQ8VZYMnAURY3RpBUAgOYT9GfzHBg== - dependencies: - "@babel/helper-function-name" "^7.1.0" - "@babel/types" "^7.5.5" - lodash "^4.17.13" - -"@babel/helper-explode-assignable-expression@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz#537fa13f6f1674df745b0c00ec8fe4e99681c8f6" - integrity sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA== +"@babel/helper-create-regexp-features-plugin@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.7.4.tgz#6d5762359fd34f4da1500e4cff9955b5299aaf59" + integrity sha512-Mt+jBKaxL0zfOIWrfQpnfYCN7/rS6GKx6CCCfuoqVVd+17R8zNDlzVYmIi9qyb2wOk002NsmSTDymkIygDUH7A== dependencies: - "@babel/traverse" "^7.1.0" - "@babel/types" "^7.0.0" + "@babel/helper-regex" "^7.4.4" + regexpu-core "^4.6.0" -"@babel/helper-function-name@7.0.0-beta.44": - version "7.0.0-beta.44" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.44.tgz#e18552aaae2231100a6e485e03854bc3532d44dd" - integrity sha512-MHRG2qZMKMFaBavX0LWpfZ2e+hLloT++N7rfM3DYOMUOGCD8cVjqZpwiL8a0bOX3IYcQev1ruciT0gdFFRTxzg== +"@babel/helper-define-map@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.7.4.tgz#2841bf92eb8bd9c906851546fe6b9d45e162f176" + integrity sha512-v5LorqOa0nVQUvAUTUF3KPastvUt/HzByXNamKQ6RdJRTV7j8rLL+WB5C/MzzWAwOomxDhYFb1wLLxHqox86lg== dependencies: - "@babel/helper-get-function-arity" "7.0.0-beta.44" - "@babel/template" "7.0.0-beta.44" - "@babel/types" "7.0.0-beta.44" + "@babel/helper-function-name" "^7.7.4" + "@babel/types" "^7.7.4" + lodash "^4.17.13" -"@babel/helper-function-name@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz#a0ceb01685f73355d4360c1247f582bfafc8ff53" - integrity sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw== +"@babel/helper-explode-assignable-expression@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.7.4.tgz#fa700878e008d85dc51ba43e9fb835cddfe05c84" + integrity sha512-2/SicuFrNSXsZNBxe5UGdLr+HZg+raWBLE9vC98bdYOKX/U6PY0mdGlYUJdtTDPSU0Lw0PNbKKDpwYHJLn2jLg== dependencies: - "@babel/helper-get-function-arity" "^7.0.0" - "@babel/template" "^7.1.0" - "@babel/types" "^7.0.0" + "@babel/traverse" "^7.7.4" + "@babel/types" "^7.7.4" -"@babel/helper-get-function-arity@7.0.0-beta.44": - version "7.0.0-beta.44" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.44.tgz#d03ca6dd2b9f7b0b1e6b32c56c72836140db3a15" - integrity sha512-w0YjWVwrM2HwP6/H3sEgrSQdkCaxppqFeJtAnB23pRiJB5E/O9Yp7JAAeWBl+gGEgmBFinnTyOv2RN7rcSmMiw== +"@babel/helper-function-name@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz#ab6e041e7135d436d8f0a3eca15de5b67a341a2e" + integrity sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ== dependencies: - "@babel/types" "7.0.0-beta.44" + "@babel/helper-get-function-arity" "^7.7.4" + "@babel/template" "^7.7.4" + "@babel/types" "^7.7.4" -"@babel/helper-get-function-arity@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3" - integrity sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ== +"@babel/helper-get-function-arity@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz#cb46348d2f8808e632f0ab048172130e636005f0" + integrity sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA== dependencies: - "@babel/types" "^7.0.0" + "@babel/types" "^7.7.4" -"@babel/helper-hoist-variables@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz#0298b5f25c8c09c53102d52ac4a98f773eb2850a" - integrity sha512-VYk2/H/BnYbZDDg39hr3t2kKyifAm1W6zHRfhx8jGjIHpQEBv9dry7oQ2f3+J703TLu69nYdxsovl0XYfcnK4w== +"@babel/helper-hoist-variables@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.7.4.tgz#612384e3d823fdfaaf9fce31550fe5d4db0f3d12" + integrity sha512-wQC4xyvc1Jo/FnLirL6CEgPgPCa8M74tOdjWpRhQYapz5JC7u3NYU1zCVoVAGCE3EaIP9T1A3iW0WLJ+reZlpQ== dependencies: - "@babel/types" "^7.4.4" + "@babel/types" "^7.7.4" -"@babel/helper-member-expression-to-functions@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.5.5.tgz#1fb5b8ec4453a93c439ee9fe3aeea4a84b76b590" - integrity sha512-5qZ3D1uMclSNqYcXqiHoA0meVdv+xUEex9em2fqMnrk/scphGlGgg66zjMrPJESPwrFJ6sbfFQYUSa0Mz7FabA== +"@babel/helper-member-expression-to-functions@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.7.4.tgz#356438e2569df7321a8326644d4b790d2122cb74" + integrity sha512-9KcA1X2E3OjXl/ykfMMInBK+uVdfIVakVe7W7Lg3wfXUNyS3Q1HWLFRwZIjhqiCGbslummPDnmb7vIekS0C1vw== dependencies: - "@babel/types" "^7.5.5" + "@babel/types" "^7.7.4" -"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.0.0-beta.49": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d" - integrity sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A== +"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.0.0-beta.49", "@babel/helper-module-imports@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.7.4.tgz#e5a92529f8888bf319a6376abfbd1cebc491ad91" + integrity sha512-dGcrX6K9l8258WFjyDLJwuVKxR4XZfU0/vTUgOQYWEnRD8mgr+p4d6fCUMq/ys0h4CCt/S5JhbvtyErjWouAUQ== dependencies: - "@babel/types" "^7.0.0" + "@babel/types" "^7.7.4" -"@babel/helper-module-transforms@^7.4.4": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz#f84ff8a09038dcbca1fd4355661a500937165b4a" - integrity sha512-jBeCvETKuJqeiaCdyaheF40aXnnU1+wkSiUs/IQg3tB85up1LyL8x77ClY8qJpuRJUcXQo+ZtdNESmZl4j56Pw== +"@babel/helper-module-transforms@^7.7.5": + version "7.7.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.7.5.tgz#d044da7ffd91ec967db25cd6748f704b6b244835" + integrity sha512-A7pSxyJf1gN5qXVcidwLWydjftUN878VkalhXX5iQDuGyiGK3sOrrKKHF4/A4fwHtnsotv/NipwAeLzY4KQPvw== dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@babel/helper-simple-access" "^7.1.0" - "@babel/helper-split-export-declaration" "^7.4.4" - "@babel/template" "^7.4.4" - "@babel/types" "^7.5.5" + "@babel/helper-module-imports" "^7.7.4" + "@babel/helper-simple-access" "^7.7.4" + "@babel/helper-split-export-declaration" "^7.7.4" + "@babel/template" "^7.7.4" + "@babel/types" "^7.7.4" lodash "^4.17.13" -"@babel/helper-optimise-call-expression@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz#a2920c5702b073c15de51106200aa8cad20497d5" - integrity sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g== +"@babel/helper-optimise-call-expression@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.7.4.tgz#034af31370d2995242aa4df402c3b7794b2dcdf2" + integrity sha512-VB7gWZ2fDkSuqW6b1AKXkJWO5NyNI3bFL/kK79/30moK57blr6NbH8xcl2XcKCwOmJosftWunZqfO84IGq3ZZg== dependencies: - "@babel/types" "^7.0.0" + "@babel/types" "^7.7.4" "@babel/helper-plugin-utils@^7.0.0": version "7.0.0" @@ -203,76 +176,60 @@ dependencies: lodash "^4.17.13" -"@babel/helper-remap-async-to-generator@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz#361d80821b6f38da75bd3f0785ece20a88c5fe7f" - integrity sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.0.0" - "@babel/helper-wrap-function" "^7.1.0" - "@babel/template" "^7.1.0" - "@babel/traverse" "^7.1.0" - "@babel/types" "^7.0.0" - -"@babel/helper-replace-supers@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.5.5.tgz#f84ce43df031222d2bad068d2626cb5799c34bc2" - integrity sha512-XvRFWrNnlsow2u7jXDuH4jDDctkxbS7gXssrP4q2nUD606ukXHRvydj346wmNg+zAgpFx4MWf4+usfC93bElJg== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.5.5" - "@babel/helper-optimise-call-expression" "^7.0.0" - "@babel/traverse" "^7.5.5" - "@babel/types" "^7.5.5" - -"@babel/helper-simple-access@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz#65eeb954c8c245beaa4e859da6188f39d71e585c" - integrity sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w== - dependencies: - "@babel/template" "^7.1.0" - "@babel/types" "^7.0.0" - -"@babel/helper-split-export-declaration@7.0.0-beta.44": - version "7.0.0-beta.44" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.44.tgz#c0b351735e0fbcb3822c8ad8db4e583b05ebd9dc" - integrity sha512-aQ7QowtkgKKzPGf0j6u77kBMdUFVBKNHw2p/3HX/POt5/oz8ec5cs0GwlgM8Hz7ui5EwJnzyfRmkNF1Nx1N7aA== - dependencies: - "@babel/types" "7.0.0-beta.44" - -"@babel/helper-split-export-declaration@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz#ff94894a340be78f53f06af038b205c49d993677" - integrity sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q== - dependencies: - "@babel/types" "^7.4.4" - -"@babel/helper-wrap-function@^7.1.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz#c4e0012445769e2815b55296ead43a958549f6fa" - integrity sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ== - dependencies: - "@babel/helper-function-name" "^7.1.0" - "@babel/template" "^7.1.0" - "@babel/traverse" "^7.1.0" - "@babel/types" "^7.2.0" - -"@babel/helpers@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.5.5.tgz#63908d2a73942229d1e6685bc2a0e730dde3b75e" - integrity sha512-nRq2BUhxZFnfEn/ciJuhklHvFOqjJUD5wpx+1bxUF2axL9C+v4DE/dmp5sT2dKnpOs4orZWzpAZqlCy8QqE/7g== - dependencies: - "@babel/template" "^7.4.4" - "@babel/traverse" "^7.5.5" - "@babel/types" "^7.5.5" - -"@babel/highlight@7.0.0-beta.44": - version "7.0.0-beta.44" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0-beta.44.tgz#18c94ce543916a80553edcdcf681890b200747d5" - integrity sha512-Il19yJvy7vMFm8AVAh6OZzaFoAd0hbkeMZiX3P5HGD+z7dyI7RzndHB0dg6Urh/VAFfHtpOIzDUSxmY6coyZWQ== - dependencies: - chalk "^2.0.0" - esutils "^2.0.2" - js-tokens "^3.0.0" +"@babel/helper-remap-async-to-generator@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.7.4.tgz#c68c2407350d9af0e061ed6726afb4fff16d0234" + integrity sha512-Sk4xmtVdM9sA/jCI80f+KS+Md+ZHIpjuqmYPk1M7F/upHou5e4ReYmExAiu6PVe65BhJPZA2CY9x9k4BqE5klw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.7.4" + "@babel/helper-wrap-function" "^7.7.4" + "@babel/template" "^7.7.4" + "@babel/traverse" "^7.7.4" + "@babel/types" "^7.7.4" + +"@babel/helper-replace-supers@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.7.4.tgz#3c881a6a6a7571275a72d82e6107126ec9e2cdd2" + integrity sha512-pP0tfgg9hsZWo5ZboYGuBn/bbYT/hdLPVSS4NMmiRJdwWhP0IznPwN9AE1JwyGsjSPLC364I0Qh5p+EPkGPNpg== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.7.4" + "@babel/helper-optimise-call-expression" "^7.7.4" + "@babel/traverse" "^7.7.4" + "@babel/types" "^7.7.4" + +"@babel/helper-simple-access@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.7.4.tgz#a169a0adb1b5f418cfc19f22586b2ebf58a9a294" + integrity sha512-zK7THeEXfan7UlWsG2A6CI/L9jVnI5+xxKZOdej39Y0YtDYKx9raHk5F2EtK9K8DHRTihYwg20ADt9S36GR78A== + dependencies: + "@babel/template" "^7.7.4" + "@babel/types" "^7.7.4" + +"@babel/helper-split-export-declaration@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz#57292af60443c4a3622cf74040ddc28e68336fd8" + integrity sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug== + dependencies: + "@babel/types" "^7.7.4" + +"@babel/helper-wrap-function@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.7.4.tgz#37ab7fed5150e22d9d7266e830072c0cdd8baace" + integrity sha512-VsfzZt6wmsocOaVU0OokwrIytHND55yvyT4BPB9AIIgwr8+x7617hetdJTsuGwygN5RC6mxA9EJztTjuwm2ofg== + dependencies: + "@babel/helper-function-name" "^7.7.4" + "@babel/template" "^7.7.4" + "@babel/traverse" "^7.7.4" + "@babel/types" "^7.7.4" + +"@babel/helpers@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.7.4.tgz#62c215b9e6c712dadc15a9a0dcab76c92a940302" + integrity sha512-ak5NGZGJ6LV85Q1Zc9gn2n+ayXOizryhjSUBTdu5ih1tlVCJeuQENzc4ItyCVhINVXvIT/ZQ4mheGIsfBkpskg== + dependencies: + "@babel/template" "^7.7.4" + "@babel/traverse" "^7.7.4" + "@babel/types" "^7.7.4" "@babel/highlight@^7.0.0": version "7.5.0" @@ -283,456 +240,426 @@ esutils "^2.0.2" js-tokens "^4.0.0" -"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.4.4", "@babel/parser@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.5.5.tgz#02f077ac8817d3df4a832ef59de67565e71cca4b" - integrity sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g== +"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.7.4", "@babel/parser@^7.7.7": + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.7.tgz#1b886595419cf92d811316d5b715a53ff38b4937" + integrity sha512-WtTZMZAZLbeymhkd/sEaPD8IQyGAhmuTuvTzLiCFM7iXiVdY0gc0IaI+cW0fh1BnSMbJSzXX6/fHllgHKwHhXw== "@babel/plugin-external-helpers@^7.0.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-external-helpers/-/plugin-external-helpers-7.2.0.tgz#7f4cb7dee651cd380d2034847d914288467a6be4" - integrity sha512-QFmtcCShFkyAsNtdCM3lJPmRe1iB+vPZymlB4LnDIKEBj2yKQLQKtoxXxJ8ePT5fwMl4QGg303p4mB0UsSI2/g== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-external-helpers/-/plugin-external-helpers-7.7.4.tgz#8aa7aa402f0e2ecb924611cbf30942a497dfd17e" + integrity sha512-RVGNajLaFlknbZLutaP/uv7Q+xmVs2LMlEWFXbcjLnwtBdPqAVpV3nzYIAJqri/VjJCUrhG5nALijtg0aND+XA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-proposal-class-properties@^7.0.0": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.5.5.tgz#a974cfae1e37c3110e71f3c6a2e48b8e71958cd4" - integrity sha512-AF79FsnWFxjlaosgdi421vmYG6/jg79bVD0dpD44QdgobzHKuLZ6S3vl8la9qIeSwGi8i1fS0O1mfuDAAdo1/A== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.7.4.tgz#2f964f0cb18b948450362742e33e15211e77c2ba" + integrity sha512-EcuXeV4Hv1X3+Q1TsuOmyyxeTRiSqurGJ26+I/FW1WbymmRRapVORm6x1Zl3iDIHyRxEs+VXWp6qnlcfcJSbbw== dependencies: - "@babel/helper-create-class-features-plugin" "^7.5.5" + "@babel/helper-create-class-features-plugin" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-proposal-export-default-from@^7.0.0": - version "7.5.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.5.2.tgz#2c0ac2dcc36e3b2443fead2c3c5fc796fb1b5145" - integrity sha512-wr9Itk05L1/wyyZKVEmXWCdcsp/e185WUNl6AfYZeEKYaUPPvHXRDqO5K1VH7/UamYqGJowFRuCv30aDYZawsg== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.7.4.tgz#890de3c0c475374638292df31f6582160b54d639" + integrity sha512-1t6dh7BHYUz4zD1m4pozYYEZy/3m8dgOr9owx3r0mPPI3iGKRUKUbIxfYmcJ4hwljs/dhd0qOTr1ZDUp43ix+w== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-export-default-from" "^7.2.0" + "@babel/plugin-syntax-export-default-from" "^7.7.4" "@babel/plugin-proposal-nullish-coalescing-operator@^7.0.0": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.4.4.tgz#41c360d59481d88e0ce3a3f837df10121a769b39" - integrity sha512-Amph7Epui1Dh/xxUxS2+K22/MUi6+6JVTvy3P58tja3B6yKTSjwwx0/d83rF7551D6PVSSoplQb8GCwqec7HRw== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.7.4.tgz#7db302c83bc30caa89e38fee935635ef6bd11c28" + integrity sha512-TbYHmr1Gl1UC7Vo2HVuj/Naci5BEGNZ0AJhzqD2Vpr6QPFWpUmBRLrIDjedzx7/CShq0bRDS2gI4FIs77VHLVQ== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.2.0" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.7.4" "@babel/plugin-proposal-object-rest-spread@^7.0.0": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.5.5.tgz#61939744f71ba76a3ae46b5eea18a54c16d22e58" - integrity sha512-F2DxJJSQ7f64FyTVl5cw/9MWn6naXGdk3Q3UhDbFEEHv+EilCPoeRD3Zh/Utx1CJz4uyKlQ4uH+bJPbEhMV7Zw== + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.7.7.tgz#9f27075004ab99be08c5c1bd653a2985813cb370" + integrity sha512-3qp9I8lelgzNedI3hrhkvhaEYree6+WHnyA/q4Dza9z7iEIs1eyhWyJnetk3jJ69RT0AT4G0UhEGwyGFJ7GUuQ== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-object-rest-spread" "^7.2.0" + "@babel/plugin-syntax-object-rest-spread" "^7.7.4" "@babel/plugin-proposal-optional-catch-binding@^7.0.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz#135d81edb68a081e55e56ec48541ece8065c38f5" - integrity sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.7.4.tgz#ec21e8aeb09ec6711bc0a39ca49520abee1de379" + integrity sha512-DyM7U2bnsQerCQ+sejcTNZh8KQEUuC3ufzdnVnSiUv/qoGJp2Z3hanKL18KDhsBT5Wj6a7CMT5mdyCNJsEaA9w== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.7.4" "@babel/plugin-proposal-optional-chaining@^7.0.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.2.0.tgz#ae454f4c21c6c2ce8cb2397dc332ae8b420c5441" - integrity sha512-ea3Q6edZC/55wEBVZAEz42v528VulyO0eir+7uky/sT4XRcdkWJcFi1aPtitTlwUzGnECWJNExWww1SStt+yWw== + version "7.7.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.7.5.tgz#f0835f044cef85b31071a924010a2a390add11d4" + integrity sha512-sOwFqT8JSchtJeDD+CjmWCaiFoLxY4Ps7NjvwHC/U7l4e9i5pTRNt8nDMIFSOUL+ncFbYSwruHM8WknYItWdXw== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-optional-chaining" "^7.2.0" + "@babel/plugin-syntax-optional-chaining" "^7.7.4" "@babel/plugin-syntax-class-properties@^7.0.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.2.0.tgz#23b3b7b9bcdabd73672a9149f728cd3be6214812" - integrity sha512-UxYaGXYQ7rrKJS/PxIKRkv3exi05oH7rokBAsmCSsCxz1sVPZ7Fu6FzKoGgUvmY+0YgSkYHgUoCh5R5bCNBQlw== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.7.4.tgz#6048c129ea908a432a1ff85f1dc794dc62ddaa5e" + integrity sha512-JH3v5ZOeKT0qqdJ9BeBcZTFQiJOMax8RopSr1bH6ASkZKo2qWsvBML7W1mp89sszBRDBBRO8snqcByGdrMTdMg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-dynamic-import@^7.0.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz#69c159ffaf4998122161ad8ebc5e6d1f55df8612" - integrity sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.7.4.tgz#29ca3b4415abfe4a5ec381e903862ad1a54c3aec" + integrity sha512-jHQW0vbRGvwQNgyVxwDh4yuXu4bH1f5/EICJLAhl1SblLs2CDhrsmCk+v5XLdE9wxtAFRyxx+P//Iw+a5L/tTg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-export-default-from@^7.0.0", "@babel/plugin-syntax-export-default-from@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.2.0.tgz#edd83b7adc2e0d059e2467ca96c650ab6d2f3820" - integrity sha512-c7nqUnNST97BWPtoe+Ssi+fJukc9P9/JMZ71IOMNQWza2E+Psrd46N6AEvtw6pqK+gt7ChjXyrw4SPDO79f3Lw== +"@babel/plugin-syntax-export-default-from@^7.0.0", "@babel/plugin-syntax-export-default-from@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.7.4.tgz#897f05808298060b52873fa804ff853540790ea1" + integrity sha512-j888jpjATLEzOWhKawq46UrpXnCRDbdhBd5io4jgwjJ3+CHHGCRb6PNAVEgs+BXIb+dNRAmnkv36zfB992PRVw== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-flow@^7.0.0", "@babel/plugin-syntax-flow@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.2.0.tgz#a765f061f803bc48f240c26f8747faf97c26bf7c" - integrity sha512-r6YMuZDWLtLlu0kqIim5o/3TNRAlWb073HwT3e2nKf9I8IIvOggPrnILYPsrrKilmn/mYEMCf/Z07w3yQJF6dg== +"@babel/plugin-syntax-flow@^7.0.0", "@babel/plugin-syntax-flow@^7.2.0", "@babel/plugin-syntax-flow@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.7.4.tgz#6d91b59e1a0e4c17f36af2e10dd64ef220919d7b" + integrity sha512-2AMAWl5PsmM5KPkB22cvOkUyWk6MjUaqhHNU5nSPUl/ns3j5qLfw2SuYP5RbVZ0tfLvePr4zUScbICtDP2CUNw== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-jsx@^7.0.0", "@babel/plugin-syntax-jsx@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.2.0.tgz#0b85a3b4bc7cdf4cc4b8bf236335b907ca22e7c7" - integrity sha512-VyN4QANJkRW6lDBmENzRszvZf3/4AXaj9YR7GwrWeeN9tEBPuXbmDYVU9bYBN0D70zCWVwUy0HWq2553VCb6Hw== +"@babel/plugin-syntax-jsx@^7.0.0", "@babel/plugin-syntax-jsx@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.7.4.tgz#dab2b56a36fb6c3c222a1fbc71f7bf97f327a9ec" + integrity sha512-wuy6fiMe9y7HeZBWXYCGt2RGxZOj0BImZ9EyXJVnVGBKO/Br592rbR3rtIQn0eQhAk9vqaKP5n8tVqEFBQMfLg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-nullish-coalescing-operator@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.2.0.tgz#f75083dfd5ade73e783db729bbd87e7b9efb7624" - integrity sha512-lRCEaKE+LTxDQtgbYajI04ddt6WW0WJq57xqkAZ+s11h4YgfRHhVA/Y2VhfPzzFD4qeLHWg32DMp9HooY4Kqlg== +"@babel/plugin-syntax-nullish-coalescing-operator@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.7.4.tgz#e53b751d0c3061b1ba3089242524b65a7a9da12b" + integrity sha512-XKh/yIRPiQTOeBg0QJjEus5qiSKucKAiApNtO1psqG7D17xmE+X2i5ZqBEuSvo0HRuyPaKaSN/Gy+Ha9KFQolw== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-object-rest-spread@^7.0.0", "@babel/plugin-syntax-object-rest-spread@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz#3b7a3e733510c57e820b9142a6579ac8b0dfad2e" - integrity sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA== +"@babel/plugin-syntax-object-rest-spread@^7.0.0", "@babel/plugin-syntax-object-rest-spread@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.7.4.tgz#47cf220d19d6d0d7b154304701f468fc1cc6ff46" + integrity sha512-mObR+r+KZq0XhRVS2BrBKBpr5jqrqzlPvS9C9vuOf5ilSwzloAl7RPWLrgKdWS6IreaVrjHxTjtyqFiOisaCwg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-optional-catch-binding@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz#a94013d6eda8908dfe6a477e7f9eda85656ecf5c" - integrity sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w== +"@babel/plugin-syntax-optional-catch-binding@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.7.4.tgz#a3e38f59f4b6233867b4a92dcb0ee05b2c334aa6" + integrity sha512-4ZSuzWgFxqHRE31Glu+fEr/MirNZOMYmD/0BhBWyLyOOQz/gTAl7QmWm2hX1QxEIXsr2vkdlwxIzTyiYRC4xcQ== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-optional-chaining@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.2.0.tgz#a59d6ae8c167e7608eaa443fda9fa8fa6bf21dff" - integrity sha512-HtGCtvp5Uq/jH/WNUPkK6b7rufnCPLLlDAFN7cmACoIjaOOiXxUt3SswU5loHqrhtqTsa/WoLQ1OQ1AGuZqaWA== +"@babel/plugin-syntax-optional-chaining@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.7.4.tgz#c91fdde6de85d2eb8906daea7b21944c3610c901" + integrity sha512-2MqYD5WjZSbJdUagnJvIdSfkb/ucOC9/1fRJxm7GAxY6YQLWlUvkfxoNbUPcPLHJyetKUDQ4+yyuUyAoc0HriA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-typescript@^7.2.0": - version "7.3.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.3.3.tgz#a7cc3f66119a9f7ebe2de5383cce193473d65991" - integrity sha512-dGwbSMA1YhVS8+31CnPR7LB4pcbrzcV99wQzby4uAfrkZPYZlQ7ImwdpzLqi6Z6IL02b8IAL379CaMwo0x5Lag== +"@babel/plugin-syntax-typescript@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.7.4.tgz#5d037ffa10f3b25a16f32570ebbe7a8c2efa304b" + integrity sha512-77blgY18Hud4NM1ggTA8xVT/dBENQf17OpiToSa2jSmEY3fWXD2jwrdVlO4kq5yzUTeF15WSQ6b4fByNvJcjpQ== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-arrow-functions@^7.0.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz#9aeafbe4d6ffc6563bf8f8372091628f00779550" - integrity sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.7.4.tgz#76309bd578addd8aee3b379d809c802305a98a12" + integrity sha512-zUXy3e8jBNPiffmqkHRNDdZM2r8DWhCB7HhcoyZjiK1TxYEluLHAvQuYnTT+ARqRpabWqy/NHkO6e3MsYB5YfA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-async-to-generator@^7.0.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.5.0.tgz#89a3848a0166623b5bc481164b5936ab947e887e" - integrity sha512-mqvkzwIGkq0bEF1zLRRiTdjfomZJDV33AH3oQzHVGkI2VzEmXLpKKOBvEVaFZBJdN0XTyH38s9j/Kiqr68dggg== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.7.4.tgz#694cbeae6d613a34ef0292713fa42fb45c4470ba" + integrity sha512-zpUTZphp5nHokuy8yLlyafxCJ0rSlFoSHypTUWgpdwoDXWQcseaect7cJ8Ppk6nunOM6+5rPMkod4OYKPR5MUg== dependencies: - "@babel/helper-module-imports" "^7.0.0" + "@babel/helper-module-imports" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-remap-async-to-generator" "^7.1.0" + "@babel/helper-remap-async-to-generator" "^7.7.4" "@babel/plugin-transform-block-scoped-functions@^7.0.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz#5d3cc11e8d5ddd752aa64c9148d0db6cb79fd190" - integrity sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.7.4.tgz#d0d9d5c269c78eaea76227ace214b8d01e4d837b" + integrity sha512-kqtQzwtKcpPclHYjLK//3lH8OFsCDuDJBaFhVwf8kqdnF6MN4l618UDlcA7TfRs3FayrHj+svYnSX8MC9zmUyQ== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-block-scoping@^7.0.0": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.5.5.tgz#a35f395e5402822f10d2119f6f8e045e3639a2ce" - integrity sha512-82A3CLRRdYubkG85lKwhZB0WZoHxLGsJdux/cOVaJCJpvYFl1LVzAIFyRsa7CvXqW8rBM4Zf3Bfn8PHt5DP0Sg== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.7.4.tgz#200aad0dcd6bb80372f94d9e628ea062c58bf224" + integrity sha512-2VBe9u0G+fDt9B5OV5DQH4KBf5DoiNkwFKOz0TCvBWvdAN2rOykCTkrL+jTLxfCAm76l9Qo5OqL7HBOx2dWggg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" lodash "^4.17.13" "@babel/plugin-transform-classes@^7.0.0": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.5.5.tgz#d094299d9bd680a14a2a0edae38305ad60fb4de9" - integrity sha512-U2htCNK/6e9K7jGyJ++1p5XRU+LJjrwtoiVn9SzRlDT2KubcZ11OOwy3s24TjHxPgxNwonCYP7U2K51uVYCMDg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.0.0" - "@babel/helper-define-map" "^7.5.5" - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-optimise-call-expression" "^7.0.0" + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.7.4.tgz#c92c14be0a1399e15df72667067a8f510c9400ec" + integrity sha512-sK1mjWat7K+buWRuImEzjNf68qrKcrddtpQo3swi9j7dUcG6y6R6+Di039QN2bD1dykeswlagupEmpOatFHHUg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.7.4" + "@babel/helper-define-map" "^7.7.4" + "@babel/helper-function-name" "^7.7.4" + "@babel/helper-optimise-call-expression" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.5.5" - "@babel/helper-split-export-declaration" "^7.4.4" + "@babel/helper-replace-supers" "^7.7.4" + "@babel/helper-split-export-declaration" "^7.7.4" globals "^11.1.0" "@babel/plugin-transform-computed-properties@^7.0.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz#83a7df6a658865b1c8f641d510c6f3af220216da" - integrity sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.7.4.tgz#e856c1628d3238ffe12d668eb42559f79a81910d" + integrity sha512-bSNsOsZnlpLLyQew35rl4Fma3yKWqK3ImWMSC/Nc+6nGjC9s5NFWAer1YQ899/6s9HxO2zQC1WoFNfkOqRkqRQ== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-destructuring@^7.0.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.5.0.tgz#f6c09fdfe3f94516ff074fe877db7bc9ef05855a" - integrity sha512-YbYgbd3TryYYLGyC7ZR+Tq8H/+bCmwoaxHfJHupom5ECstzbRLTch6gOQbhEY9Z4hiCNHEURgq06ykFv9JZ/QQ== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.7.4.tgz#2b713729e5054a1135097b6a67da1b6fe8789267" + integrity sha512-4jFMXI1Cu2aXbcXXl8Lr6YubCn6Oc7k9lLsu8v61TZh+1jny2BWmdtvY9zSUlLdGUvcy9DMAWyZEOqjsbeg/wA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-exponentiation-operator@^7.0.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz#a63868289e5b4007f7054d46491af51435766008" - integrity sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.7.4.tgz#dd30c0191e3a1ba19bcc7e389bdfddc0729d5db9" + integrity sha512-MCqiLfCKm6KEA1dglf6Uqq1ElDIZwFuzz1WH5mTf8k2uQSxEJMbOIEh7IZv7uichr7PMfi5YVSrr1vz+ipp7AQ== dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.1.0" + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-flow-strip-types@^7.0.0": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.4.4.tgz#d267a081f49a8705fc9146de0768c6b58dccd8f7" - integrity sha512-WyVedfeEIILYEaWGAUWzVNyqG4sfsNooMhXWsu/YzOvVGcsnPb5PguysjJqI3t3qiaYj0BR8T2f5njdjTGe44Q== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.7.4.tgz#cc73f85944782df1d77d80977bc097920a8bf31a" + integrity sha512-w9dRNlHY5ElNimyMYy0oQowvQpwt/PRHI0QS98ZJCTZU2bvSnKXo5zEiD5u76FBPigTm8TkqzmnUTg16T7qbkA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-flow" "^7.2.0" + "@babel/plugin-syntax-flow" "^7.7.4" "@babel/plugin-transform-for-of@^7.0.0": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz#0267fc735e24c808ba173866c6c4d1440fc3c556" - integrity sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.7.4.tgz#248800e3a5e507b1f103d8b4ca998e77c63932bc" + integrity sha512-zZ1fD1B8keYtEcKF+M1TROfeHTKnijcVQm0yO/Yu1f7qoDoxEIc/+GX6Go430Bg84eM/xwPFp0+h4EbZg7epAA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-function-name@^7.0.0": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz#e1436116abb0610c2259094848754ac5230922ad" - integrity sha512-iU9pv7U+2jC9ANQkKeNF6DrPy4GBa4NWQtl6dHB4Pb3izX2JOEvDTFarlNsBj/63ZEzNNIAMs3Qw4fNCcSOXJA== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.7.4.tgz#75a6d3303d50db638ff8b5385d12451c865025b1" + integrity sha512-E/x09TvjHNhsULs2IusN+aJNRV5zKwxu1cpirZyRPw+FyyIKEHPXTsadj48bVpc1R5Qq1B5ZkzumuFLytnbT6g== dependencies: - "@babel/helper-function-name" "^7.1.0" + "@babel/helper-function-name" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-literals@^7.0.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz#690353e81f9267dad4fd8cfd77eafa86aba53ea1" - integrity sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.7.4.tgz#27fe87d2b5017a2a5a34d1c41a6b9f6a6262643e" + integrity sha512-X2MSV7LfJFm4aZfxd0yLVFrEXAgPqYoDG53Br/tCKiKYfX0MjVjQeWPIhPHHsCqzwQANq+FLN786fF5rgLS+gw== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-member-expression-literals@^7.0.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz#fa10aa5c58a2cb6afcf2c9ffa8cb4d8b3d489a2d" - integrity sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.7.4.tgz#aee127f2f3339fc34ce5e3055d7ffbf7aa26f19a" + integrity sha512-9VMwMO7i69LHTesL0RdGy93JU6a+qOPuvB4F4d0kR0zyVjJRVJRaoaGjhtki6SzQUu8yen/vxPKN6CWnCUw6bA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-modules-commonjs@^7.0.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.5.0.tgz#425127e6045231360858eeaa47a71d75eded7a74" - integrity sha512-xmHq0B+ytyrWJvQTc5OWAC4ii6Dhr0s22STOoydokG51JjWhyYo5mRPXoi+ZmtHQhZZwuXNN+GG5jy5UZZJxIQ== + version "7.7.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.7.5.tgz#1d27f5eb0bcf7543e774950e5b2fa782e637b345" + integrity sha512-9Cq4zTFExwFhQI6MT1aFxgqhIsMWQWDVwOgLzl7PTWJHsNaqFvklAU+Oz6AQLAS0dJKTwZSOCo20INwktxpi3Q== dependencies: - "@babel/helper-module-transforms" "^7.4.4" + "@babel/helper-module-transforms" "^7.7.5" "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-simple-access" "^7.1.0" + "@babel/helper-simple-access" "^7.7.4" babel-plugin-dynamic-import-node "^2.3.0" "@babel/plugin-transform-object-assign@^7.0.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.2.0.tgz#6fdeea42be17040f119e38e23ea0f49f31968bde" - integrity sha512-nmE55cZBPFgUktbF2OuoZgPRadfxosLOpSgzEPYotKSls9J4pEPcembi8r78RU37Rph6UApCpNmsQA4QMWK9Ng== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.7.4.tgz#a31b70c434a00a078b2d4d10dbd59992fa70afca" + integrity sha512-0TpeUlnhQDwKxPLTIckdaWt46L2s61c/5w5snw1OUod5ehOJywZD98Ha3dFHVjeqkfOFtOTH7cqxddjxUuvcmg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-object-super@^7.0.0": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz#c70021df834073c65eb613b8679cc4a381d1a9f9" - integrity sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.7.4.tgz#48488937a2d586c0148451bf51af9d7dda567262" + integrity sha512-ho+dAEhC2aRnff2JCA0SAK7V2R62zJd/7dmtoe7MHcso4C2mS+vZjn1Pb1pCVZvJs1mgsvv5+7sT+m3Bysb6eg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.5.5" + "@babel/helper-replace-supers" "^7.7.4" "@babel/plugin-transform-parameters@^7.0.0": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz#7556cf03f318bd2719fe4c922d2d808be5571e16" - integrity sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw== + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.7.7.tgz#7a884b2460164dc5f194f668332736584c760007" + integrity sha512-OhGSrf9ZBrr1fw84oFXj5hgi8Nmg+E2w5L7NhnG0lPvpDtqd7dbyilM2/vR8CKbJ907RyxPh2kj6sBCSSfI9Ew== dependencies: - "@babel/helper-call-delegate" "^7.4.4" - "@babel/helper-get-function-arity" "^7.0.0" + "@babel/helper-call-delegate" "^7.7.4" + "@babel/helper-get-function-arity" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-property-literals@^7.0.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz#03e33f653f5b25c4eb572c98b9485055b389e905" - integrity sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.7.4.tgz#2388d6505ef89b266103f450f9167e6bd73f98c2" + integrity sha512-MatJhlC4iHsIskWYyawl53KuHrt+kALSADLQQ/HkhTjX954fkxIEh4q5slL4oRAnsm/eDoZ4q0CIZpcqBuxhJQ== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-react-display-name@^7.0.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.2.0.tgz#ebfaed87834ce8dc4279609a4f0c324c156e3eb0" - integrity sha512-Htf/tPa5haZvRMiNSQSFifK12gtr/8vwfr+A9y69uF0QcU77AVu4K7MiHEkTxF7lQoHOL0F9ErqgfNEAKgXj7A== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.7.4.tgz#9f2b80b14ebc97eef4a9b29b612c58ed9c0d10dd" + integrity sha512-sBbIvqYkthai0X0vkD2xsAwluBp+LtNHH+/V4a5ydifmTtb8KOVOlrMIk/MYmIc4uTYDnjZUHQildYNo36SRJw== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-react-jsx-source@^7.0.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.5.0.tgz#583b10c49cf057e237085bcbd8cc960bd83bd96b" - integrity sha512-58Q+Jsy4IDCZx7kqEZuSDdam/1oW8OdDX8f+Loo6xyxdfg1yF0GE2XNJQSTZCaMol93+FBzpWiPEwtbMloAcPg== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.7.4.tgz#8994b1bf6014b133f5a46d3b7d1ee5f5e3e72c10" + integrity sha512-5ZU9FnPhqtHsOXxutRtXZAzoEJwDaP32QcobbMP1/qt7NYcsCNK8XgzJcJfoEr/ZnzVvUNInNjIW22Z6I8p9mg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-jsx" "^7.2.0" + "@babel/plugin-syntax-jsx" "^7.7.4" "@babel/plugin-transform-react-jsx@^7.0.0": - version "7.3.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.3.0.tgz#f2cab99026631c767e2745a5368b331cfe8f5290" - integrity sha512-a/+aRb7R06WcKvQLOu4/TpjKOdvVEKRLWFpKcNuHhiREPgGRB4TQJxq07+EZLS8LFVYpfq1a5lDUnuMdcCpBKg== + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.7.7.tgz#5cbaa7445b4a09f774029f3cc7bb448ff3122a5d" + integrity sha512-SlPjWPbva2+7/ZJbGcoqjl4LsQaLpKEzxW9hcxU7675s24JmdotJOSJ4cgAbV82W3FcZpHIGmRZIlUL8ayMvjw== dependencies: - "@babel/helper-builder-react-jsx" "^7.3.0" + "@babel/helper-builder-react-jsx" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-jsx" "^7.2.0" + "@babel/plugin-syntax-jsx" "^7.7.4" "@babel/plugin-transform-regenerator@^7.0.0": - version "7.4.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz#629dc82512c55cee01341fb27bdfcb210354680f" - integrity sha512-gBKRh5qAaCWntnd09S8QC7r3auLCqq5DI6O0DlfoyDjslSBVqBibrMdsqO+Uhmx3+BlOmE/Kw1HFxmGbv0N9dA== + version "7.7.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.7.5.tgz#3a8757ee1a2780f390e89f246065ecf59c26fce9" + integrity sha512-/8I8tPvX2FkuEyWbjRCt4qTAgZK0DVy8QRguhA524UH48RfGJy94On2ri+dCuwOpcerPRl9O4ebQkRcVzIaGBw== dependencies: regenerator-transform "^0.14.0" "@babel/plugin-transform-runtime@^7.0.0": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.5.5.tgz#a6331afbfc59189d2135b2e09474457a8e3d28bc" - integrity sha512-6Xmeidsun5rkwnGfMOp6/z9nSzWpHFNVr2Jx7kwoq4mVatQfQx5S56drBgEHF+XQbKOdIaOiMIINvp/kAwMN+w== + version "7.7.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.7.6.tgz#4f2b548c88922fb98ec1c242afd4733ee3e12f61" + integrity sha512-tajQY+YmXR7JjTwRvwL4HePqoL3DYxpYXIHKVvrOIvJmeHe2y1w4tz5qz9ObUDC9m76rCzIMPyn4eERuwA4a4A== dependencies: - "@babel/helper-module-imports" "^7.0.0" + "@babel/helper-module-imports" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" resolve "^1.8.1" semver "^5.5.1" "@babel/plugin-transform-shorthand-properties@^7.0.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz#6333aee2f8d6ee7e28615457298934a3b46198f0" - integrity sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.7.4.tgz#74a0a9b2f6d67a684c6fbfd5f0458eb7ba99891e" + integrity sha512-q+suddWRfIcnyG5YiDP58sT65AJDZSUhXQDZE3r04AuqD6d/XLaQPPXSBzP2zGerkgBivqtQm9XKGLuHqBID6Q== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-spread@^7.0.0": - version "7.2.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz#3103a9abe22f742b6d406ecd3cd49b774919b406" - integrity sha512-KWfky/58vubwtS0hLqEnrWJjsMGaOeSBn90Ezn5Jeg9Z8KKHmELbP1yGylMlm5N6TPKeY9A2+UaSYLdxahg01w== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.7.4.tgz#aa673b356fe6b7e70d69b6e33a17fef641008578" + integrity sha512-8OSs0FLe5/80cndziPlg4R0K6HcWSM0zyNhHhLsmw/Nc5MaA49cAsnoJ/t/YZf8qkG7fD+UjTRaApVDB526d7Q== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-sticky-regex@^7.0.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz#a1e454b5995560a9c1e0d537dfc15061fd2687e1" - integrity sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.7.4.tgz#ffb68c05090c30732076b1285dc1401b404a123c" + integrity sha512-Ls2NASyL6qtVe1H1hXts9yuEeONV2TJZmplLONkMPUG158CtmnrzW5Q5teibM5UVOFjG0D3IC5mzXR6pPpUY7A== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-regex" "^7.0.0" "@babel/plugin-transform-template-literals@^7.0.0": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz#9d28fea7bbce637fb7612a0750989d8321d4bcb0" - integrity sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.7.4.tgz#1eb6411736dd3fe87dbd20cc6668e5121c17d604" + integrity sha512-sA+KxLwF3QwGj5abMHkHgshp9+rRz+oY9uoRil4CyLtgEuE/88dpkeWgNk5qKVsJE9iSfly3nvHapdRiIS2wnQ== dependencies: - "@babel/helper-annotate-as-pure" "^7.0.0" + "@babel/helper-annotate-as-pure" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-typescript@^7.0.0": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.5.5.tgz#6d862766f09b2da1cb1f7d505fe2aedab6b7d4b8" - integrity sha512-pehKf4m640myZu5B2ZviLaiBlxMCjSZ1qTEO459AXKX5GnPueyulJeCqZFs1nz/Ya2dDzXQ1NxZ/kKNWyD4h6w== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.7.4.tgz#2974fd05f4e85c695acaf497f432342de9fc0636" + integrity sha512-X8e3tcPEKnwwPVG+vP/vSqEShkwODOEeyQGod82qrIuidwIrfnsGn11qPM1jBLF4MqguTXXYzm58d0dY+/wdpg== dependencies: - "@babel/helper-create-class-features-plugin" "^7.5.5" + "@babel/helper-create-class-features-plugin" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-typescript" "^7.2.0" + "@babel/plugin-syntax-typescript" "^7.7.4" "@babel/plugin-transform-unicode-regex@^7.0.0": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz#ab4634bb4f14d36728bf5978322b35587787970f" - integrity sha512-il+/XdNw01i93+M9J9u4T7/e/Ue/vWfNZE4IRUQjplu2Mqb/AFTDimkw2tdEdSH50wuQXZAbXSql0UphQke+vA== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.7.4.tgz#a3c0f65b117c4c81c5b6484f2a5e7b95346b83ae" + integrity sha512-N77UUIV+WCvE+5yHw+oks3m18/umd7y392Zv7mYTpFqHtkpcc+QUz+gLJNTWVlWROIWeLqY0f3OjZxV5TcXnRw== dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.7.4" "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-regex" "^7.4.4" - regexpu-core "^4.5.4" "@babel/register@^7.0.0": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.5.5.tgz#40fe0d474c8c8587b28d6ae18a03eddad3dac3c1" - integrity sha512-pdd5nNR+g2qDkXZlW1yRCWFlNrAn2PPdnZUB72zjX4l1Vv4fMRRLwyf+n/idFCLI1UgVGboUU8oVziwTBiyNKQ== + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.7.7.tgz#46910c4d1926b9c6096421b23d1f9e159c1dcee1" + integrity sha512-S2mv9a5dc2pcpg/ConlKZx/6wXaEwHeqfo7x/QbXsdCAZm+WJC1ekVvL1TVxNsedTs5y/gG63MhJTEsmwmjtiA== dependencies: - core-js "^3.0.0" find-cache-dir "^2.0.0" lodash "^4.17.13" - mkdirp "^0.5.1" + make-dir "^2.1.0" pirates "^4.0.0" - source-map-support "^0.5.9" + source-map-support "^0.5.16" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.5.5.tgz#74fba56d35efbeca444091c7850ccd494fd2f132" - integrity sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ== +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2": + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.7.7.tgz#194769ca8d6d7790ec23605af9ee3e42a0aa79cf" + integrity sha512-uCnC2JEVAu8AKB5do1WRIsvrdJ0flYx/A/9f/6chdacnEZ7LmavjdsDXr5ksYBegxtuTPR5Va9/+13QF/kFkCA== dependencies: regenerator-runtime "^0.13.2" -"@babel/template@7.0.0-beta.44": - version "7.0.0-beta.44" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.44.tgz#f8832f4fdcee5d59bf515e595fc5106c529b394f" - integrity sha512-w750Sloq0UNifLx1rUqwfbnC6uSUk0mfwwgGRfdLiaUzfAOiH0tHJE6ILQIUi3KYkjiCDTskoIsnfqZvWLBDng== - dependencies: - "@babel/code-frame" "7.0.0-beta.44" - "@babel/types" "7.0.0-beta.44" - babylon "7.0.0-beta.44" - lodash "^4.2.0" - -"@babel/template@^7.0.0", "@babel/template@^7.1.0", "@babel/template@^7.4.0", "@babel/template@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.4.4.tgz#f4b88d1225689a08f5bc3a17483545be9e4ed237" - integrity sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw== +"@babel/template@^7.0.0", "@babel/template@^7.4.0", "@babel/template@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.4.tgz#428a7d9eecffe27deac0a98e23bf8e3675d2a77b" + integrity sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw== dependencies: "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.4.4" - "@babel/types" "^7.4.4" - -"@babel/traverse@7.0.0-beta.44": - version "7.0.0-beta.44" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.0.0-beta.44.tgz#a970a2c45477ad18017e2e465a0606feee0d2966" - integrity sha512-UHuDz8ukQkJCDASKHf+oDt3FVUzFd+QYfuBIsiNu/4+/ix6pP/C+uQZJ6K1oEfbCMv/IKWbgDEh7fcsnIE5AtA== - dependencies: - "@babel/code-frame" "7.0.0-beta.44" - "@babel/generator" "7.0.0-beta.44" - "@babel/helper-function-name" "7.0.0-beta.44" - "@babel/helper-split-export-declaration" "7.0.0-beta.44" - "@babel/types" "7.0.0-beta.44" - babylon "7.0.0-beta.44" - debug "^3.1.0" - globals "^11.1.0" - invariant "^2.2.0" - lodash "^4.2.0" + "@babel/parser" "^7.7.4" + "@babel/types" "^7.7.4" -"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.4.4", "@babel/traverse@^7.4.5", "@babel/traverse@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.5.5.tgz#f664f8f368ed32988cd648da9f72d5ca70f165bb" - integrity sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ== +"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.4.5", "@babel/traverse@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.4.tgz#9c1e7c60fb679fe4fcfaa42500833333c2058558" + integrity sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw== dependencies: "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.5.5" - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-split-export-declaration" "^7.4.4" - "@babel/parser" "^7.5.5" - "@babel/types" "^7.5.5" + "@babel/generator" "^7.7.4" + "@babel/helper-function-name" "^7.7.4" + "@babel/helper-split-export-declaration" "^7.7.4" + "@babel/parser" "^7.7.4" + "@babel/types" "^7.7.4" debug "^4.1.0" globals "^11.1.0" lodash "^4.17.13" -"@babel/types@7.0.0-beta.44": - version "7.0.0-beta.44" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.44.tgz#6b1b164591f77dec0a0342aca995f2d046b3a757" - integrity sha512-5eTV4WRmqbaFM3v9gHAIljEQJU4Ssc6fxL61JN+Oe2ga/BwyjzjamwkCVVAQjHGuAX8i0BWo42dshL8eO5KfLQ== +"@babel/types@^7.0.0", "@babel/types@^7.0.0-beta.49", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.4.tgz#516570d539e44ddf308c07569c258ff94fde9193" + integrity sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA== dependencies: esutils "^2.0.2" - lodash "^4.2.0" + lodash "^4.17.13" to-fast-properties "^2.0.0" -"@babel/types@^7.0.0", "@babel/types@^7.0.0-beta.49", "@babel/types@^7.2.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.5.5.tgz#97b9f728e182785909aa4ab56264f090a028d18a" - integrity sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw== +"@bankify/react-native-animate-number@^0.2.1": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@bankify/react-native-animate-number/-/react-native-animate-number-0.2.1.tgz#80b2d700d0556b2d57ec1757a37454fcfbd968b8" + integrity sha512-rBIiZZWAU6Nfr7bqJ6Dc0vAqk8Xf0LU3otrad9jbrJQOUJRUSUf9nWttQVLW4/alKTYq1kXkGYJ1l4dsTQbLmA== dependencies: - esutils "^2.0.2" - lodash "^4.17.13" - to-fast-properties "^2.0.0" + babel-plugin-syntax-async-functions "^6.8.0" "@cnakazawa/watch@^1.0.3": version "1.0.3" @@ -742,148 +669,131 @@ exec-sh "^0.3.2" minimist "^1.2.0" -"@emotion/is-prop-valid@^0.7.3": - version "0.7.3" - resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.7.3.tgz#a6bf4fa5387cbba59d44e698a4680f481a8da6cc" - integrity sha512-uxJqm/sqwXw3YPA5GXX365OBcJGFtxUVkB6WyezqFHlNe9jqUWH5ur2O2M8dGBz61kn1g3ZBlzUunFQXQIClhA== - dependencies: - "@emotion/memoize" "0.7.1" - "@emotion/is-prop-valid@^0.8.1": - version "0.8.2" - resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.2.tgz#b9692080da79041683021fcc32f96b40c54c59dc" - integrity sha512-ZQIMAA2kLUWiUeMZNJDTeCwYRx1l8SQL0kHktze4COT22occKpDML1GDUXP5/sxhOMrZO8vZw773ni4H5Snrsg== + version "0.8.6" + resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.6.tgz#4757646f0a58e9dec614c47c838e7147d88c263c" + integrity sha512-mnZMho3Sq8BfzkYYRVc8ilQTnc8U02Ytp6J1AwM6taQStZ3AhsEJBX2LzhA/LJirNCwM2VtHL3VFIZ+sNJUgUQ== dependencies: - "@emotion/memoize" "0.7.2" + "@emotion/memoize" "0.7.4" -"@emotion/memoize@0.7.1": - version "0.7.1" - resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.1.tgz#e93c13942592cf5ef01aa8297444dc192beee52f" - integrity sha512-Qv4LTqO11jepd5Qmlp3M1YEjBumoTHcHFdgPTQ+sFlIL5myi/7xu/POwP7IRu6odBdmLXdtIs1D6TuW6kbwbbg== - -"@emotion/memoize@0.7.2": - version "0.7.2" - resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.2.tgz#7f4c71b7654068dfcccad29553520f984cc66b30" - integrity sha512-hnHhwQzvPCW1QjBWFyBtsETdllOM92BfrKWbUTmh9aeOlcVOiXvlPsK4104xH8NsaKfg86PTFsWkueQeUfMA/w== +"@emotion/memoize@0.7.4": + version "0.7.4" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb" + integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw== "@emotion/stylis@^0.8.3": - version "0.8.4" - resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.4.tgz#6c51afdf1dd0d73666ba09d2eb6c25c220d6fe4c" - integrity sha512-TLmkCVm8f8gH0oLv+HWKiu7e8xmBIaokhxcEKPh1m8pXiV/akCiq50FvYgOwY42rjejck8nsdQxZlXZ7pmyBUQ== + version "0.8.5" + resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.5.tgz#deacb389bd6ee77d1e7fcaccce9e16c5c7e78e04" + integrity sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ== "@emotion/unitless@^0.7.0": - version "0.7.4" - resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.4.tgz#a87b4b04e5ae14a88d48ebef15015f6b7d1f5677" - integrity sha512-kBa+cDHOR9jpRJ+kcGMsysrls0leukrm68DmFQoMIWQcXdr2cZvyvypWuGYT7U+9kAExUE7+T7r6G3C3A6L8MQ== + version "0.7.5" + resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" + integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== "@ethersproject/address@^5.0.0-beta.125": - version "5.0.0-beta.125" - resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.0.0-beta.125.tgz#0e75562d0fd493d73f23d31844521ef6556e1bc1" - integrity sha512-X742o0xmcpnv9X5pXKdzTmPfFdmMjQ21iu7LT3Hua2vPa/o6Ve0GQI295PhxUh/YoWdyH95FO4dK9KkAtl2r3Q== - dependencies: - "@ethersproject/bignumber" ">5.0.0-beta.0" - "@ethersproject/bytes" ">5.0.0-beta.0" - "@ethersproject/errors" ">5.0.0-beta.0" - "@ethersproject/keccak256" ">5.0.0-beta.0" - "@ethersproject/rlp" ">5.0.0-beta.0" + version "5.0.0-beta.133" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.0.0-beta.133.tgz#b6bf2c298da5701c61038e4cdfac2e0038b884ce" + integrity sha512-7SjGhZ3xClqlmzqNNzESKlHbBeEzDWXIeKUBbSzK3Ce9PgK6uboiNe53fgqzhrRVOMhD1J4Q+oIm4DsTv37FWg== + dependencies: + "@ethersproject/bignumber" ">=5.0.0-beta.130" + "@ethersproject/bytes" ">=5.0.0-beta.129" + "@ethersproject/keccak256" ">=5.0.0-beta.127" + "@ethersproject/logger" ">=5.0.0-beta.129" + "@ethersproject/rlp" ">=5.0.0-beta.126" bn.js "^4.4.0" -"@ethersproject/bignumber@>5.0.0-beta.0": - version "5.0.0-beta.127" - resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.0.0-beta.127.tgz#9fb1df7979b81c77a22ce4a2ca7e049d1c7f52e9" - integrity sha512-nt8lKya8dECXJH6DTQHL0H6HbfKbGCatPLzptAFt53ODgbb1on3Cr//5l4XvCZO6ZWn+DSa38PigY+ntooe8QA== +"@ethersproject/bignumber@>=5.0.0-beta.130": + version "5.0.0-beta.135" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.0.0-beta.135.tgz#9d464df8967f5d314d109497e4f25ab82314c098" + integrity sha512-7Tw2NgHzK7o+70bwyoaIZCbRycz+saWNU0sLOYnis3qYXwYsdTL+Rm0PMGA2v4jyHJt7BPS2pxGww+akVXbX+w== dependencies: - "@ethersproject/bytes" ">5.0.0-beta.0" - "@ethersproject/errors" ">5.0.0-beta.0" - "@ethersproject/properties" ">5.0.0-beta.0" + "@ethersproject/bytes" ">=5.0.0-beta.129" + "@ethersproject/logger" ">=5.0.0-beta.129" + "@ethersproject/properties" ">=5.0.0-beta.131" bn.js "^4.4.0" -"@ethersproject/bytes@>5.0.0-beta.0", "@ethersproject/bytes@^5.0.0-beta.126": - version "5.0.0-beta.126" - resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.0.0-beta.126.tgz#17992dfbf4e1b8e972ad1caf04780d7d8ddc4ca6" - integrity sha512-MWBM1F2uypiDb3ROUJjBRtR0DGYvjAHqlOoaGBsTqq2DgF3swASF6Pfbqj+dS0zpY6XoO3w41e4+RCdjiAr0Jw== +"@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@^5.0.0-beta.126": + version "5.0.0-beta.134" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.0.0-beta.134.tgz#eb6b9a200be02d6d539f90086fbfad26ec63d0d5" + integrity sha512-2BULy5x0BuHPRzuGjEYWndJieDaRAaZUbMk53fZjH4yjhKMHDGADQQOtaSD4wN+H183YOXMGdtlCrRGJ1N+uNg== dependencies: - "@ethersproject/errors" ">5.0.0-beta.0" + "@ethersproject/logger" ">=5.0.0-beta.129" -"@ethersproject/constants@>5.0.0-beta.0": - version "5.0.0-beta.126" - resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.0.0-beta.126.tgz#cc3bab8269f085d0032730493433595ea0989bfd" - integrity sha512-wU1KhoSxxhCESX6JRVks/NAaB/WdIeMmEKDVu4tSsTG/IBogjxQY/jmVRhqKOw7eLvqOf6eTxcQ+11w/kU6HHg== +"@ethersproject/constants@>=5.0.0-beta.128": + version "5.0.0-beta.132" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.0.0-beta.132.tgz#068cc97493fbc1543299bda79e0e726310e129a4" + integrity sha512-ioO7Ez8Xatk5z3lVzzEhRjXng1le1sTzfuD3v8gUozrzgLXyl0X81Go1Nadj7qPgo68HziIFcm5kRFp4SdJa0A== dependencies: - "@ethersproject/bignumber" ">5.0.0-beta.0" + "@ethersproject/bignumber" ">=5.0.0-beta.130" -"@ethersproject/errors@>5.0.0-beta.0": - version "5.0.0-beta.126" - resolved "https://registry.yarnpkg.com/@ethersproject/errors/-/errors-5.0.0-beta.126.tgz#bddabff53cb0a6fd544e1168ce3990a095f2b593" - integrity sha512-Rfc+rLaykgKaYgdc/5FuTNqlQNKzm6h9w9HNhkpGT8gE5Dh1xjtWrv8pKdUCbBjy6RCzMeVcmJ8COqLmsxPS6g== - -"@ethersproject/keccak256@>5.0.0-beta.0": - version "5.0.0-beta.125" - resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.0.0-beta.125.tgz#ac2bd7d20a411ebcddddcfc686ebd426960eb112" - integrity sha512-Vzood4ptHvWk64yqE5DMef7qLivEm3qH3S/60l66kWSAMmf5ISuSxeO+8Ss3o+p86zEGIhyipjpenb2LD6+/xA== +"@ethersproject/keccak256@>=5.0.0-beta.127": + version "5.0.0-beta.131" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.0.0-beta.131.tgz#b5778723ee75208065b9b9ad30c71d480f41bb31" + integrity sha512-KQnqMwGV0IMOjAr/UTFO8DuLrmN1uaMvcV3zh9hiXhh3rCuY+WXdeUh49w1VQ94kBKmaP0qfGb7z4SdhUWUHjw== dependencies: - "@ethersproject/bytes" ">5.0.0-beta.0" + "@ethersproject/bytes" ">=5.0.0-beta.129" js-sha3 "0.5.7" -"@ethersproject/properties@>5.0.0-beta.0": - version "5.0.0-beta.128" - resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.0.0-beta.128.tgz#26e8a4cb95f0d048531f0a8da39773b16b4633b4" - integrity sha512-4ABgX2WmpQLlmbyR6EwxoT5YTRYxV6fGRtK+1nt48dvG2Y8FSkg33JvCfei3w432RjEEHEN5IOmTf+nTr9n6VA== +"@ethersproject/logger@>=5.0.0-beta.129": + version "5.0.0-beta.133" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.0.0-beta.133.tgz#2d62d495ed413c7045054d4f99a0fb4920079b2e" + integrity sha512-1ISf7rFKFbMHlEB37JS7Oy3FgFlvzF2Ze2uFZMJHGKp9xgDvFy1VHNMBM1KrJPK4AqCZXww0//e2keLsN3g/Cw== + +"@ethersproject/properties@>=5.0.0-beta.131": + version "5.0.0-beta.135" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.0.0-beta.135.tgz#51a0a5d72ca034b5ae845d43ed409eb3576a3ca7" + integrity sha512-R4ROFaFh86n09eE+MWMPzaB87V5OSgqu0gtQ7LjUvkFF3eqdpdvLVD4N93hvCKNZcjGHI4WmazDUlpuXZVgDkA== dependencies: - "@ethersproject/errors" ">5.0.0-beta.0" + "@ethersproject/logger" ">=5.0.0-beta.129" -"@ethersproject/rlp@>5.0.0-beta.0": - version "5.0.0-beta.124" - resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.0.0-beta.124.tgz#ca333bf52b03fac56ce94b90a701604bda526465" - integrity sha512-XRjIyOflY6VzSy62iBplESUWgRVJh9ImUwxILpMXLRxtTa7IGtu2Poe1L+O8LEm6gXvTOFd1uzrk/mXnkBoyHQ== +"@ethersproject/rlp@>=5.0.0-beta.126": + version "5.0.0-beta.131" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.0.0-beta.131.tgz#4a0c0c314e26ed7f01be6bca16308d629a8022d2" + integrity sha512-sUJUGbywlnuk2frkSWzWiGenTrwOnrKQaNKJqjCGmK35x0WIzcR4/1gC6jWa0hpWJT6Seq6J6SCT5CS+ZWCFNw== dependencies: - "@ethersproject/bytes" ">5.0.0-beta.0" + "@ethersproject/bytes" ">=5.0.0-beta.129" "@ethersproject/strings@^5.0.0-beta.125": - version "5.0.0-beta.127" - resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.0.0-beta.127.tgz#e07848b92cb1b615a11d7289449312c069a234e9" - integrity sha512-FKQDBKgcX7Bc0J45TIwwT4PTnE1TvtDRka3dAkH1VX4odnj6DzpZ99QdkhX4mBL2J+6/XK+trA7m/HTDx+5YqA== + version "5.0.0-beta.135" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.0.0-beta.135.tgz#7754a805831383bf1838cd097d26c6135e96a745" + integrity sha512-MiZSJPhAQggXb3XA/XS4jmwmj5CsknMXk/XIzNZB7eYqEGA2i7sQV7+o6DOE+3lq5k5BhB8OaDziogNCOGAouA== dependencies: - "@ethersproject/bytes" ">5.0.0-beta.0" - "@ethersproject/constants" ">5.0.0-beta.0" - "@ethersproject/errors" ">5.0.0-beta.0" + "@ethersproject/bytes" ">=5.0.0-beta.129" + "@ethersproject/constants" ">=5.0.0-beta.128" + "@ethersproject/logger" ">=5.0.0-beta.129" "@hapi/address@2.x.x": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.0.0.tgz#9f05469c88cb2fd3dcd624776b54ee95c312126a" - integrity sha512-mV6T0IYqb0xL1UALPFplXYQmR0twnXG0M6jUswpquqT2sD12BOiCiLy3EvMp/Fy7s3DZElC4/aPjEjo2jeZpvw== + version "2.1.4" + resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.1.4.tgz#5d67ed43f3fd41a69d4b9ff7b56e7c0d1d0a81e5" + integrity sha512-QD1PhQk+s31P1ixsX0H0Suoupp3VMXzIVMSwobR3F3MSUO2YCV0B7xqLcUw/Bh8yuvd3LhpyqLQWTNcRmp6IdQ== -"@hapi/hoek@6.x.x": - version "6.2.4" - resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-6.2.4.tgz#4b95fbaccbfba90185690890bdf1a2fbbda10595" - integrity sha512-HOJ20Kc93DkDVvjwHyHawPwPkX44sIrbXazAUDiUXaY2R9JwQGo2PhFfnQtdrsIe4igjG2fPgMra7NYw7qhy0A== +"@hapi/bourne@1.x.x": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@hapi/bourne/-/bourne-1.3.2.tgz#0a7095adea067243ce3283e1b56b8a8f453b242a" + integrity sha512-1dVNHT76Uu5N3eJNTYcvxee+jzX4Z9lfciqRRHCU27ihbUcYi+iSc2iml5Ke1LXe1SyJCLA0+14Jh4tXJgOppA== -"@hapi/hoek@8.x.x": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-8.1.0.tgz#8f7627b23ed9bf67088fc7f9669e48c63ad421bd" - integrity sha512-b1J4jxYnW+n6lC91V6Pqg9imP9BZq0HNCeM+3sbXg05rQsE9cGYrKFpZjyztVesGmNRE6R+QaEoWGATeIiUVjA== +"@hapi/hoek@8.x.x", "@hapi/hoek@^8.3.0": + version "8.5.0" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-8.5.0.tgz#2f9ce301c8898e1c3248b0a8564696b24d1a9a5a" + integrity sha512-7XYT10CZfPsH7j9F1Jmg1+d0ezOux2oM2GfArAzLwWe4mE2Dr3hVjsAL6+TFY49RRJlCdJDMw3nJsLFroTc8Kw== "@hapi/joi@^15.0.3": - version "15.1.0" - resolved "https://registry.yarnpkg.com/@hapi/joi/-/joi-15.1.0.tgz#940cb749b5c55c26ab3b34ce362e82b6162c8e7a" - integrity sha512-n6kaRQO8S+kepUTbXL9O/UOL788Odqs38/VOfoCrATDtTvyfiO3fgjlSRaNkHabpTLgM7qru9ifqXlXbXk8SeQ== + version "15.1.1" + resolved "https://registry.yarnpkg.com/@hapi/joi/-/joi-15.1.1.tgz#c675b8a71296f02833f8d6d243b34c57b8ce19d7" + integrity sha512-entf8ZMOK8sc+8YfeOlM8pCfg3b5+WZIKBfUaaJT8UsjAAPjartzxIYm3TIbjvA4u+u++KbcXD38k682nVHDAQ== dependencies: "@hapi/address" "2.x.x" - "@hapi/hoek" "6.x.x" - "@hapi/marker" "1.x.x" + "@hapi/bourne" "1.x.x" + "@hapi/hoek" "8.x.x" "@hapi/topo" "3.x.x" -"@hapi/marker@1.x.x": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@hapi/marker/-/marker-1.0.0.tgz#65b0b2b01d1be06304886ce9b4b77b1bfb21a769" - integrity sha512-JOfdekTXnJexfE8PyhZFyHvHjt81rBFSAbTIRAhF2vv/2Y1JzoKsGqxH/GpZJoF7aEfYok8JVcAHmSz1gkBieA== - "@hapi/topo@3.x.x": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-3.1.2.tgz#57cc1317be1a8c5f47c124f9b0e3c49cd78424d2" - integrity sha512-r+aumOqJ5QbD6aLPJWqVjMAPsx5pZKz+F5yPqXZ/WWG9JTtHbQqlzrJoknJ0iJxLj9vlXtmpSdjlkszseeG8OA== + version "3.1.6" + resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-3.1.6.tgz#68d935fa3eae7fdd5ab0d7f953f3205d8b2bfc29" + integrity sha512-tAag0jEcjwH+P2quUfipd7liWCNX2F8NvYjQp2wtInsZxnMlypdw0FtAOLxtvvkO+GSRRbmNi8m/5y42PQJYCQ== dependencies: - "@hapi/hoek" "8.x.x" + "@hapi/hoek" "^8.3.0" "@hocs/omit-props@^0.4.0": version "0.4.0" @@ -907,76 +817,77 @@ dependencies: react-display-name "^0.2.4" -"@jest/console@^24.7.1": - version "24.7.1" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-24.7.1.tgz#32a9e42535a97aedfe037e725bd67e954b459545" - integrity sha512-iNhtIy2M8bXlAOULWVTUxmnelTLFneTNEkHCgPmgd+zNwy9zVddJ6oS5rZ9iwoscNdT5mMwUd0C51v/fSlzItg== +"@jest/console@^24.7.1", "@jest/console@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-24.9.0.tgz#79b1bc06fb74a8cfb01cbdedf945584b1b9707f0" + integrity sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ== dependencies: - "@jest/source-map" "^24.3.0" + "@jest/source-map" "^24.9.0" chalk "^2.0.1" slash "^2.0.0" -"@jest/core@^24.8.0": - version "24.8.0" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-24.8.0.tgz#fbbdcd42a41d0d39cddbc9f520c8bab0c33eed5b" - integrity sha512-R9rhAJwCBQzaRnrRgAdVfnglUuATXdwTRsYqs6NMdVcAl5euG8LtWDe+fVkN27YfKVBW61IojVsXKaOmSnqd/A== +"@jest/core@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-24.9.0.tgz#2ceccd0b93181f9c4850e74f2a9ad43d351369c4" + integrity sha512-Fogg3s4wlAr1VX7q+rhV9RVnUv5tD7VuWfYy1+whMiWUrvl7U3QJSJyWcDio9Lq2prqYsZaeTv2Rz24pWGkJ2A== dependencies: "@jest/console" "^24.7.1" - "@jest/reporters" "^24.8.0" - "@jest/test-result" "^24.8.0" - "@jest/transform" "^24.8.0" - "@jest/types" "^24.8.0" + "@jest/reporters" "^24.9.0" + "@jest/test-result" "^24.9.0" + "@jest/transform" "^24.9.0" + "@jest/types" "^24.9.0" ansi-escapes "^3.0.0" chalk "^2.0.1" exit "^0.1.2" graceful-fs "^4.1.15" - jest-changed-files "^24.8.0" - jest-config "^24.8.0" - jest-haste-map "^24.8.0" - jest-message-util "^24.8.0" + jest-changed-files "^24.9.0" + jest-config "^24.9.0" + jest-haste-map "^24.9.0" + jest-message-util "^24.9.0" jest-regex-util "^24.3.0" - jest-resolve-dependencies "^24.8.0" - jest-runner "^24.8.0" - jest-runtime "^24.8.0" - jest-snapshot "^24.8.0" - jest-util "^24.8.0" - jest-validate "^24.8.0" - jest-watcher "^24.8.0" + jest-resolve "^24.9.0" + jest-resolve-dependencies "^24.9.0" + jest-runner "^24.9.0" + jest-runtime "^24.9.0" + jest-snapshot "^24.9.0" + jest-util "^24.9.0" + jest-validate "^24.9.0" + jest-watcher "^24.9.0" micromatch "^3.1.10" p-each-series "^1.0.0" - pirates "^4.0.1" realpath-native "^1.1.0" rimraf "^2.5.4" + slash "^2.0.0" strip-ansi "^5.0.0" -"@jest/environment@^24.8.0": - version "24.8.0" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-24.8.0.tgz#0342261383c776bdd652168f68065ef144af0eac" - integrity sha512-vlGt2HLg7qM+vtBrSkjDxk9K0YtRBi7HfRFaDxoRtyi+DyVChzhF20duvpdAnKVBV6W5tym8jm0U9EfXbDk1tw== - dependencies: - "@jest/fake-timers" "^24.8.0" - "@jest/transform" "^24.8.0" - "@jest/types" "^24.8.0" - jest-mock "^24.8.0" - -"@jest/fake-timers@^24.8.0": - version "24.8.0" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-24.8.0.tgz#2e5b80a4f78f284bcb4bd5714b8e10dd36a8d3d1" - integrity sha512-2M4d5MufVXwi6VzZhJ9f5S/wU4ud2ck0kxPof1Iz3zWx6Y+V2eJrES9jEktB6O3o/oEyk+il/uNu9PvASjWXQw== - dependencies: - "@jest/types" "^24.8.0" - jest-message-util "^24.8.0" - jest-mock "^24.8.0" - -"@jest/reporters@^24.8.0": - version "24.8.0" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-24.8.0.tgz#075169cd029bddec54b8f2c0fc489fd0b9e05729" - integrity sha512-eZ9TyUYpyIIXfYCrw0UHUWUvE35vx5I92HGMgS93Pv7du+GHIzl+/vh8Qj9MCWFK/4TqyttVBPakWMOfZRIfxw== - dependencies: - "@jest/environment" "^24.8.0" - "@jest/test-result" "^24.8.0" - "@jest/transform" "^24.8.0" - "@jest/types" "^24.8.0" +"@jest/environment@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-24.9.0.tgz#21e3afa2d65c0586cbd6cbefe208bafade44ab18" + integrity sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ== + dependencies: + "@jest/fake-timers" "^24.9.0" + "@jest/transform" "^24.9.0" + "@jest/types" "^24.9.0" + jest-mock "^24.9.0" + +"@jest/fake-timers@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-24.9.0.tgz#ba3e6bf0eecd09a636049896434d306636540c93" + integrity sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A== + dependencies: + "@jest/types" "^24.9.0" + jest-message-util "^24.9.0" + jest-mock "^24.9.0" + +"@jest/reporters@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-24.9.0.tgz#86660eff8e2b9661d042a8e98a028b8d631a5b43" + integrity sha512-mu4X0yjaHrffOsWmVLzitKmmmWSQ3GGuefgNscUSWNiUNcEOSEQk9k3pERKEQVBb0Cnn88+UESIsZEMH3o88Gw== + dependencies: + "@jest/environment" "^24.9.0" + "@jest/test-result" "^24.9.0" + "@jest/transform" "^24.9.0" + "@jest/types" "^24.9.0" chalk "^2.0.1" exit "^0.1.2" glob "^7.1.2" @@ -984,74 +895,75 @@ istanbul-lib-instrument "^3.0.1" istanbul-lib-report "^2.0.4" istanbul-lib-source-maps "^3.0.1" - istanbul-reports "^2.1.1" - jest-haste-map "^24.8.0" - jest-resolve "^24.8.0" - jest-runtime "^24.8.0" - jest-util "^24.8.0" + istanbul-reports "^2.2.6" + jest-haste-map "^24.9.0" + jest-resolve "^24.9.0" + jest-runtime "^24.9.0" + jest-util "^24.9.0" jest-worker "^24.6.0" - node-notifier "^5.2.1" + node-notifier "^5.4.2" slash "^2.0.0" source-map "^0.6.0" string-length "^2.0.0" -"@jest/source-map@^24.3.0": - version "24.3.0" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-24.3.0.tgz#563be3aa4d224caf65ff77edc95cd1ca4da67f28" - integrity sha512-zALZt1t2ou8le/crCeeiRYzvdnTzaIlpOWaet45lNSqNJUnXbppUUFR4ZUAlzgDmKee4Q5P/tKXypI1RiHwgag== +"@jest/source-map@^24.3.0", "@jest/source-map@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-24.9.0.tgz#0e263a94430be4b41da683ccc1e6bffe2a191714" + integrity sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg== dependencies: callsites "^3.0.0" graceful-fs "^4.1.15" source-map "^0.6.0" -"@jest/test-result@^24.8.0": - version "24.8.0" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-24.8.0.tgz#7675d0aaf9d2484caa65e048d9b467d160f8e9d3" - integrity sha512-+YdLlxwizlfqkFDh7Mc7ONPQAhA4YylU1s529vVM1rsf67vGZH/2GGm5uO8QzPeVyaVMobCQ7FTxl38QrKRlng== +"@jest/test-result@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-24.9.0.tgz#11796e8aa9dbf88ea025757b3152595ad06ba0ca" + integrity sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA== dependencies: - "@jest/console" "^24.7.1" - "@jest/types" "^24.8.0" + "@jest/console" "^24.9.0" + "@jest/types" "^24.9.0" "@types/istanbul-lib-coverage" "^2.0.0" -"@jest/test-sequencer@^24.8.0": - version "24.8.0" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-24.8.0.tgz#2f993bcf6ef5eb4e65e8233a95a3320248cf994b" - integrity sha512-OzL/2yHyPdCHXEzhoBuq37CE99nkme15eHkAzXRVqthreWZamEMA0WoetwstsQBCXABhczpK03JNbc4L01vvLg== +"@jest/test-sequencer@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-24.9.0.tgz#f8f334f35b625a4f2f355f2fe7e6036dad2e6b31" + integrity sha512-6qqsU4o0kW1dvA95qfNog8v8gkRN9ph6Lz7r96IvZpHdNipP2cBcb07J1Z45mz/VIS01OHJ3pY8T5fUY38tg4A== dependencies: - "@jest/test-result" "^24.8.0" - jest-haste-map "^24.8.0" - jest-runner "^24.8.0" - jest-runtime "^24.8.0" + "@jest/test-result" "^24.9.0" + jest-haste-map "^24.9.0" + jest-runner "^24.9.0" + jest-runtime "^24.9.0" -"@jest/transform@^24.8.0": - version "24.8.0" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-24.8.0.tgz#628fb99dce4f9d254c6fd9341e3eea262e06fef5" - integrity sha512-xBMfFUP7TortCs0O+Xtez2W7Zu1PLH9bvJgtraN1CDST6LBM/eTOZ9SfwS/lvV8yOfcDpFmwf9bq5cYbXvqsvA== +"@jest/transform@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-24.9.0.tgz#4ae2768b296553fadab09e9ec119543c90b16c56" + integrity sha512-TcQUmyNRxV94S0QpMOnZl0++6RMiqpbH/ZMccFB/amku6Uwvyb1cjYX7xkp5nGNkbX4QPH/FcB6q1HBTHynLmQ== dependencies: "@babel/core" "^7.1.0" - "@jest/types" "^24.8.0" + "@jest/types" "^24.9.0" babel-plugin-istanbul "^5.1.0" chalk "^2.0.1" convert-source-map "^1.4.0" fast-json-stable-stringify "^2.0.0" graceful-fs "^4.1.15" - jest-haste-map "^24.8.0" - jest-regex-util "^24.3.0" - jest-util "^24.8.0" + jest-haste-map "^24.9.0" + jest-regex-util "^24.9.0" + jest-util "^24.9.0" micromatch "^3.1.10" + pirates "^4.0.1" realpath-native "^1.1.0" slash "^2.0.0" source-map "^0.6.1" write-file-atomic "2.4.1" -"@jest/types@^24.8.0": - version "24.8.0" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.8.0.tgz#f31e25948c58f0abd8c845ae26fcea1491dea7ad" - integrity sha512-g17UxVr2YfBtaMUxn9u/4+siG1ptg9IGYAYwvpwn61nBg779RXnjE/m7CxYcIzEt0AbHZZAHSEZNhkE2WxURVg== +"@jest/types@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.9.0.tgz#63cb26cb7500d069e5a389441a7c6ab5e909fc59" + integrity sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw== dependencies: "@types/istanbul-lib-coverage" "^2.0.0" "@types/istanbul-reports" "^1.1.1" - "@types/yargs" "^12.0.9" + "@types/yargs" "^13.0.0" "@mrmlnc/readdir-enhanced@^2.2.1": version "2.2.1" @@ -1066,60 +978,73 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== -"@react-native-community/async-storage@1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@react-native-community/async-storage/-/async-storage-1.5.0.tgz#647ffcd832272068b0be57332e08d73036ed391f" - integrity sha512-2yE4RzQ5IL+UTPhuMY0ykNRKHf1m90jOnmp8fcDPUun5U97cXlorjI4p66ovDgF0FuOv8ZpiUKvunGy3qqBxwg== +"@react-native-community/async-storage@1.6.2": + version "1.6.2" + resolved "https://registry.yarnpkg.com/@react-native-community/async-storage/-/async-storage-1.6.2.tgz#a19ca7149c4dfe8216f2330e6b1ebfe2d075ef92" + integrity sha512-EJGsbrHubK1mGxPjWB74AaHAd5m9I+Gg2RRPZzMK6org7QOU9WOBnIMFqoeVto3hKOaEPlk8NV74H6G34/2pZQ== -"@react-native-community/blur@^3.3.1": - version "3.3.1" - resolved "https://registry.yarnpkg.com/@react-native-community/blur/-/blur-3.3.1.tgz#bc9ecd6d85d89739d8180138716535ac7cfa4680" - integrity sha512-UfH2ut/l4GpZHeq/TGx3BrmyXSCSBBwBCVx1DhPodP3k959zJ2ajgXa3PiU/qjutftTUw6KH9Frsh2U0ax9dMQ== +"@react-native-community/blur@^3.4.1": + version "3.4.1" + resolved "https://registry.yarnpkg.com/@react-native-community/blur/-/blur-3.4.1.tgz#dec04c7d60dd6a4fa7e3af3506feefec804728d0" + integrity sha512-XhbS230J7BGuoEamjPFZ5jUWDOW16y+vD0Soyq9Iv1qL8R47esGl54bnfUSMH10WhNXrQzvPxkMzap+ONHpE2w== dependencies: prop-types "^15.5.10" -"@react-native-community/cli-platform-android@^2.0.0-rc.2": - version "2.7.0" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-2.7.0.tgz#511d1db12c52d29cb87b6e4e84d63030ffa2c38d" - integrity sha512-hO/gYqzLCeCFnLIgYiGlZhiQMAnMuTxNS6rCbC8leMnlGARzrarnWsepHhvottOKeSctVh0wzchLCLCBcw4zVA== +"@react-native-community/cli-debugger-ui@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-3.0.0.tgz#d01d08d1e5ddc1633d82c7d84d48fff07bd39416" + integrity sha512-m3X+iWLsK/H7/b7PpbNO33eQayR/+M26la4ZbYe1KRke5Umg4PIWsvg21O8Tw4uJcY8LA5hsP+rBi/syBkBf0g== dependencies: - "@react-native-community/cli-tools" "^2.7.0" + serve-static "^1.13.1" + +"@react-native-community/cli-platform-android@^3.0.0": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-3.0.3.tgz#e652abce79a7c1e3a8280228123e99df2c4b97b6" + integrity sha512-rNO9DmRiVhB6aP2DVUjEJv7ecriTARDZND88ny3xNVUkrD1Y+zwF6aZu3eoT52VXOxLCSLiJzz19OiyGmfqxYg== + dependencies: + "@react-native-community/cli-tools" "^3.0.0" chalk "^2.4.2" execa "^1.0.0" jetifier "^1.6.2" - logkitty "^0.5.0" - slash "^2.0.0" - xmldoc "^0.4.0" + logkitty "^0.6.0" + slash "^3.0.0" + xmldoc "^1.1.2" -"@react-native-community/cli-platform-ios@^2.0.0-rc.2": - version "2.8.0" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-2.8.0.tgz#95cea3e8feab4d9525a96a9dcf56bd0d62633158" - integrity sha512-a6DD4fnfJij8FicQ/5+4zgsqxRO92o6unt2XKZexIM8bqH3i8U5pvUsccOhRnsaIjXUFMbLU5knozRrFSaJBoQ== +"@react-native-community/cli-platform-ios@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-3.0.0.tgz#3a48a449c0c33af3b0b3d19d3256de99388fe15f" + integrity sha512-QoNVlDj8eMXRZk9uktPFsctHurQpv9jKmiu6mQii4NEtT2npE7g1hbWpRNojutBsfgmCdQGDHd9uB54eeCnYgg== dependencies: - "@react-native-community/cli-tools" "^2.7.0" + "@react-native-community/cli-tools" "^3.0.0" chalk "^2.4.2" + js-yaml "^3.13.1" xcode "^2.0.0" -"@react-native-community/cli-tools@^2.0.0-rc.2", "@react-native-community/cli-tools@^2.7.0": - version "2.7.0" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-2.7.0.tgz#b468ce74cb5ebf5789731d4d330740801679cf81" - integrity sha512-9rNoGiokyMkbQ97gAvQde4mpAw2M/GhPBtrQJb4WglgVoJhfj4kpe+qMCWNsOepCrID5JY2Y1nTDEq/v+ETyNA== +"@react-native-community/cli-tools@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-3.0.0.tgz#fe48b80822ed7e49b8af051f9fe41e22a2a710b1" + integrity sha512-8IhQKZdf3E4CR8T7HhkPGgorot/cLkRDgneJFDSWk/wCYZAuUh4NEAdumQV7N0jLSMWX7xxiWUPi94lOBxVY9g== dependencies: chalk "^2.4.2" lodash "^4.17.5" mime "^2.4.1" node-fetch "^2.5.0" -"@react-native-community/cli@2.0.0-rc.2": - version "2.0.0-rc.2" - resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-2.0.0-rc.2.tgz#8bb3c07a58056b0af5474782bedc457184b42595" - integrity sha512-G0NrMfJ6bcXfJKLijQmxuTV4S22pXfp8c5XI7L1i+b5Vu34IvR6xvKVPT9leYEEI/bg/ZuyguDZuVecycJb63A== +"@react-native-community/cli-types@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-3.0.0.tgz#488d46605cb05e88537e030f38da236eeda74652" + integrity sha512-ng6Tm537E/M42GjE4TRUxQyL8sRfClcL7bQWblOCoxPZzJ2J3bdALsjeG3vDnVCIfI/R0AeFalN9KjMt0+Z/Zg== + +"@react-native-community/cli@3.0.4", "@react-native-community/cli@^3.0.0": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-3.0.4.tgz#a9dba1bc77855a6e45fccaabb017360645d936bb" + integrity sha512-kt+ENtC+eRUSfWPbbpx3r7fAQDcFwgM03VW/lBdVAUjkNxffPFT2GGdK23CJSBOXTjRSiGuwhvwH4Z28PdrlRA== dependencies: "@hapi/joi" "^15.0.3" - "@react-native-community/cli-platform-android" "^2.0.0-rc.2" - "@react-native-community/cli-platform-ios" "^2.0.0-rc.2" - "@react-native-community/cli-tools" "^2.0.0-rc.2" - chalk "^1.1.1" + "@react-native-community/cli-debugger-ui" "^3.0.0" + "@react-native-community/cli-tools" "^3.0.0" + "@react-native-community/cli-types" "^3.0.0" + chalk "^2.4.2" command-exists "^1.2.8" commander "^2.19.0" compression "^1.7.1" @@ -1129,15 +1054,16 @@ envinfo "^7.1.0" errorhandler "^1.5.0" execa "^1.0.0" + find-up "^4.1.0" fs-extra "^7.0.1" glob "^7.1.1" graceful-fs "^4.1.3" inquirer "^3.0.6" lodash "^4.17.5" - metro "^0.54.1" - metro-config "^0.54.1" - metro-core "^0.54.1" - metro-react-native-babel-transformer "^0.54.1" + metro "^0.56.0" + metro-config "^0.56.0" + metro-core "^0.56.0" + metro-react-native-babel-transformer "^0.56.0" minimist "^1.2.0" mkdirp "^0.5.1" morgan "^1.9.0" @@ -1145,101 +1071,181 @@ open "^6.2.0" ora "^3.4.0" plist "^3.0.0" - semver "^5.0.3" + semver "^6.3.0" serve-static "^1.13.1" shell-quote "1.6.1" + strip-ansi "^5.2.0" + sudo-prompt "^9.0.0" + wcwidth "^1.0.1" ws "^1.1.0" -"@react-native-community/cli@^1.2.1": - version "1.11.2" - resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-1.11.2.tgz#b14967f24a389f5a16889a747345cf0e5757a2f1" - integrity sha512-5NuYd30f5PCTrGUbZLnusZKv5nfTWvTDTRa/3Q4vwdMnUQrhm9sZXWGQ5CnFoQ7cE58EAqhj6/ShXeJF3DZ9uQ== +"@react-native-community/masked-view@^0.1.5": + version "0.1.5" + resolved "https://registry.yarnpkg.com/@react-native-community/masked-view/-/masked-view-0.1.5.tgz#25421be6cd943a4b1660b62cfbcd45be8891462c" + integrity sha512-Lj1DzfCmW0f4HnmHtEuX8Yy2f7cnUA8r5KGGUuDDGtQt1so6QJkKeUmsnLo2zYDtsF8due6hvIL06Vdo5xxuLQ== + +"@react-native-community/netinfo@^5.0.0": + version "5.3.2" + resolved "https://registry.yarnpkg.com/@react-native-community/netinfo/-/netinfo-5.3.2.tgz#7b6ee417c2a905663e10de176c00eeab09bdd14c" + integrity sha512-npNcLAz6iWzwRNh+0tSFMlR+xkpSz9NWzX+5AxW40KE6qEZGWdE3dtGBKsezMdWD2Fh+6Je6P6hgUEF8xuZrbA== + +"@react-native-community/push-notification-ios@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@react-native-community/push-notification-ios/-/push-notification-ios-1.0.3.tgz#cd2c7f29aeeb431942eda0bd729738fd2b444ae9" + integrity sha512-f+Y3lFLt5OBWHDtGHE+PiZH4aLeS8w2D47c0G/S5XpzeGoEeggOiALtou/r6raiVLP+D5CrLkIBMs2U2+LGJhw== dependencies: - chalk "^1.1.1" - commander "^2.19.0" - compression "^1.7.1" - connect "^3.6.5" - denodeify "^1.2.1" - envinfo "^5.7.0" - errorhandler "^1.5.0" - escape-string-regexp "^1.0.5" - execa "^1.0.0" - fs-extra "^7.0.1" - glob "^7.1.1" - graceful-fs "^4.1.3" - inquirer "^3.0.6" - lodash "^4.17.5" - metro "^0.51.0" - metro-config "^0.51.0" - metro-core "^0.51.0" - metro-memory-fs "^0.51.0" - metro-react-native-babel-transformer "^0.51.0" - mime "^1.3.4" - minimist "^1.2.0" - mkdirp "^0.5.1" - morgan "^1.9.0" - node-fetch "^2.2.0" - node-notifier "^5.2.1" - opn "^3.0.2" - plist "^3.0.0" - semver "^5.0.3" - serve-static "^1.13.1" - shell-quote "1.6.1" - slash "^2.0.0" - ws "^1.1.0" - xcode "^2.0.0" - xmldoc "^0.4.0" + invariant "^2.2.4" -"@react-native-community/eslint-config@^0.0.5": - version "0.0.5" - resolved "https://registry.yarnpkg.com/@react-native-community/eslint-config/-/eslint-config-0.0.5.tgz#584f6493258202a57efc22e7be66966e43832795" - integrity sha512-jwO2tnKaTPTLX5XYXMHGEnFdf543SU7jz98/OF5mDH3b7lP+BOaCD+jVfqqHoDRkcqyPlYiR1CgwVGWpi0vMWg== +"@react-native-firebase/app-types@6.2.0": + version "6.2.0" + resolved "https://registry.yarnpkg.com/@react-native-firebase/app-types/-/app-types-6.2.0.tgz#4d3c0e7fa4e4f00061c52b1a32d76e85e5db9f2c" + integrity sha512-3UW3cuCgY/JMp+7n6bLeRXKDS/JcXwnHwL0RUIUHg2NhlNAXmIUQbbl0gZbW10YHRnW7D3+JE60Mpm9atTzh9g== + +"@react-native-firebase/app@^6.2.0": + version "6.2.0" + resolved "https://registry.yarnpkg.com/@react-native-firebase/app/-/app-6.2.0.tgz#2d4327399f5e8021d7bad264624f1a29f0741f6c" + integrity sha512-LlYvml2hhqE28T9rU0SpwcKvlrwp0QyY90HTV0tvEEfGaCahd9xlIj7IFQCXNUNYICFi7Vn2YjxAZNF8KgKpmQ== dependencies: - "@typescript-eslint/eslint-plugin" "^1.5.0" - "@typescript-eslint/parser" "^1.5.0" - babel-eslint "10.0.1" - eslint-plugin-eslint-comments "^3.1.1" - eslint-plugin-flowtype "2.50.3" - eslint-plugin-jest "22.4.1" - eslint-plugin-prettier "2.6.2" - eslint-plugin-react "7.12.4" - eslint-plugin-react-hooks "^1.5.1" - eslint-plugin-react-native "3.6.0" - prettier "1.16.4" - -"@react-native-community/masked-view@^0.1.1": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@react-native-community/masked-view/-/masked-view-0.1.1.tgz#dbcfc5ec08efbb02d4142dd9426c8d7a396829d7" - integrity sha512-EyJVSbarZkOPYq+zCZLx9apMcpwkX9HvH6R+6CeVL29q88kEFemnLO/IhmE4YX/0MfalsduI8eTi7fuQh/5VeA== + "@react-native-firebase/app-types" "6.2.0" + opencollective-postinstall "^2.0.1" + superstruct "^0.6.2" -"@react-native-community/netinfo@^3.2.1": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@react-native-community/netinfo/-/netinfo-3.2.1.tgz#cd073b81a4b978f7f55f1a960a0b56c462813e02" - integrity sha512-A2qANOnlRDVe+8kMbKMwy3/0bOlOA2+y8DyWg2Rv2KHICIfin+oxixbG0ewAOLQdLkSEyyumZXRmIVl7VI/KJg== +"@react-native-firebase/crashlytics@^6.2.0": + version "6.2.0" + resolved "https://registry.yarnpkg.com/@react-native-firebase/crashlytics/-/crashlytics-6.2.0.tgz#7c2add9857f1f26d6d317590dc2c301144ea1e50" + integrity sha512-yk25Uu2F/moeoa3DFtt88SA5jqib5wXff7MhAX9vkvcDqWwEaZtT0Clk/+ObMHs/rL6LUtLhHwo6qfYzknVEfQ== + dependencies: + stacktrace-js "^2.0.0" + +"@react-native-firebase/messaging@^6.2.0": + version "6.2.0" + resolved "https://registry.yarnpkg.com/@react-native-firebase/messaging/-/messaging-6.2.0.tgz#d882e650f9b21aff54482f9cedfa677cef85ccfb" + integrity sha512-RqgpUkiDqp/aIgMoQUOAfMtVB9bWnii8Ii4jrQQQ10dAPUW6+HmqxFIQlzi6blsbltAc5ESGk29Tl2SUbISIQA== -"@react-navigation/core@~3.4.1": - version "3.4.2" - resolved "https://registry.yarnpkg.com/@react-navigation/core/-/core-3.4.2.tgz#bec563e94fde40fbab3730cdc97f22afbb2a1498" - integrity sha512-7G+iDzLSTeOUU4vVZeRZKJ+Bd7ds7ZxYNqZcB8i0KlBeQEQfR74Ounfu/p0KIEq2RiNnaE3QT7WVP3C87sebzw== +"@react-navigation/core@^3.5.1": + version "3.5.1" + resolved "https://registry.yarnpkg.com/@react-navigation/core/-/core-3.5.1.tgz#7a2339fca3496979305fb3a8ab88c2ca8d8c214d" + integrity sha512-q7NyhWVYOhVIWqL2GZKa6G78YarXaVTTtOlSDkvy4ZIggo40wZzamlnrJRvsaQX46gsgw45FAWb5SriHh8o7eA== dependencies: hoist-non-react-statics "^3.3.0" path-to-regexp "^1.7.0" query-string "^6.4.2" react-is "^16.8.6" -"@react-navigation/native@~3.5.0": - version "3.5.0" - resolved "https://registry.yarnpkg.com/@react-navigation/native/-/native-3.5.0.tgz#f5d16e0845ac26d1147d1caa481f18a00740e7ae" - integrity sha512-TmGOis++ejEXG3sqNJhCSKqB0/qLu3FQgDtO959qpqif36R/diR8SQwJqeSdofoEiK3CepdhFlTCeHdS1/+MsQ== +"@react-navigation/native@^3.6.2": + version "3.6.2" + resolved "https://registry.yarnpkg.com/@react-navigation/native/-/native-3.6.2.tgz#3634697b6350cc5189657ae4551f2d52b57fbbf0" + integrity sha512-Cybeou6N82ZeRmgnGlu+wzlV3z5BZQR2dmYaNFV1TNLUGHqtvv8E7oNw9uYcz9Ox5LFbiX+FdNTn2d6ZPlK0kg== dependencies: hoist-non-react-statics "^3.0.1" react-native-safe-area-view "^0.14.1" react-native-screens "^1.0.0 || ^1.0.0-alpha" "@segment/analytics-react-native@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@segment/analytics-react-native/-/analytics-react-native-1.0.1.tgz#7e974ae3a4b28bd4a4d760d0ec752512912a8ce7" - integrity sha512-872ojMYhRZSBGHRngSpNkRCE5SkD+pD4cVB9QoLyGVssune4jeqVaPwuXji/J9wuQ/u871n7Qt1MqtD500Jv7A== + version "1.1.0" + resolved "https://registry.yarnpkg.com/@segment/analytics-react-native/-/analytics-react-native-1.1.0.tgz#209c28a7b6f60c80bdce8e7c66bfb26aaeef9ed6" + integrity sha512-9a4/uvsP+MebvoLDpUAjeeflgDVQjYaPEYp22JpAZiMlr0Tmsrrbwud/FE/bHeMX6HeLfgeCghhK4GvfeZsc9g== + +"@sentry/browser@^5.10.0": + version "5.10.2" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.10.2.tgz#0bbb05505c58ea998c833cffec3f922fe4b4fa58" + integrity sha512-r3eyBu2ln7odvWtXARCZPzpuGrKsD6U9F3gKTu4xdFkA0swSLUvS7AC2FUksj/1BE23y+eB/zzPT+RYJ58tidA== + dependencies: + "@sentry/core" "5.10.2" + "@sentry/types" "5.10.0" + "@sentry/utils" "5.10.2" + tslib "^1.9.3" + +"@sentry/cli@^1.48.0": + version "1.49.0" + resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-1.49.0.tgz#174152978acbe6023986a8fb0b247cf58b4653d8" + integrity sha512-Augz7c42Cxz/xWQ/NOVjUGePKVA370quvskWbCICMUwxcTvKnCLI+7KDdzEoCexj4MSuxFfBzLnrrn4w2+c9TQ== + dependencies: + fs-copy-file-sync "^1.1.1" + https-proxy-agent "^3.0.0" + mkdirp "^0.5.1" + node-fetch "^2.1.2" + progress "2.0.0" + proxy-from-env "^1.0.0" + +"@sentry/core@5.10.2", "@sentry/core@^5.10.0": + version "5.10.2" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.10.2.tgz#1cb64489e6f8363c3249415b49d3f1289814825f" + integrity sha512-sKVeFH3v8K8xw2vM5MKMnnyAAwih+JSE3pbNL0CcCCA+/SwX+3jeAo2BhgXev2SAR/TjWW+wmeC9TdIW7KyYbg== + dependencies: + "@sentry/hub" "5.10.2" + "@sentry/minimal" "5.10.2" + "@sentry/types" "5.10.0" + "@sentry/utils" "5.10.2" + tslib "^1.9.3" + +"@sentry/hub@5.10.2": + version "5.10.2" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.10.2.tgz#25d9f36b8f7c5cb65cf486737fa61dc9bf69b7e3" + integrity sha512-hSlZIiu3hcR/I5yEhlpN9C0nip+U7hiRzRzUQaBiHO4YG4TC58NqnOPR89D/ekiuHIXzFpjW9OQmqtAMRoSUYA== + dependencies: + "@sentry/types" "5.10.0" + "@sentry/utils" "5.10.2" + tslib "^1.9.3" + +"@sentry/integrations@^5.10.0": + version "5.10.2" + resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-5.10.2.tgz#44f5c55d1619d816c0f20208a3727bb07abb98c8" + integrity sha512-yvIJ6aXpzWlwD1WGTxvaeCm7JmNs4flWXKLlPWm2CEwgWBfjyaWjW7PqlA0jUOnLGCeYzgFD3AdUPlpgCsFXXA== + dependencies: + "@sentry/types" "5.10.0" + "@sentry/utils" "5.10.2" + tslib "^1.9.3" + +"@sentry/minimal@5.10.2": + version "5.10.2" + resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.10.2.tgz#267c2f3aa6877a0fe7a86971942e83f3ee616580" + integrity sha512-GalixiM9sckYfompH5HHTp9XT2BcjawBkcl1DMEKUBEi37+kUq0bivOBmnN1G/I4/wWOUdnAI/kagDWaWpbZPg== + dependencies: + "@sentry/hub" "5.10.2" + "@sentry/types" "5.10.0" + tslib "^1.9.3" + +"@sentry/react-native@^1.2.0": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@sentry/react-native/-/react-native-1.2.1.tgz#a015ed280ffa8afde3f775b91d173ad7c884e169" + integrity sha512-JE2B/pMvd7+3TFdzs03+DOdrALAHd8bAphJ8tk+nWjX7oQVJNgVn/IvnJfKxasHHBXQ2z+42Xy9n2Fqam/Gq0w== + dependencies: + "@sentry/browser" "^5.10.0" + "@sentry/core" "^5.10.0" + "@sentry/integrations" "^5.10.0" + "@sentry/types" "^5.10.0" + "@sentry/utils" "^5.10.0" + "@sentry/wizard" "^1.0.2" + +"@sentry/types@5.10.0", "@sentry/types@^5.10.0": + version "5.10.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.10.0.tgz#4f0ba31b6e4d5371112c38279f11f66c73b43746" + integrity sha512-TW20GzkCWsP6uAxR2JIpIkiitCKyIOfkyDsKBeLqYj4SaZjfvBPnzgNCcYR0L0UsP1/Es6oHooZfIGSkp6GGxQ== + +"@sentry/utils@5.10.2", "@sentry/utils@^5.10.0": + version "5.10.2" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.10.2.tgz#261f575079d30aaf604e59f5f4de0aa21db22252" + integrity sha512-UcbbaFpYrGSV448lQ16Cr+W/MPuKUflQQUdrMCt5vgaf5+M7kpozlcji4GGGZUCXIA7oRP93ABoXj55s1OM9zw== + dependencies: + "@sentry/types" "5.10.0" + tslib "^1.9.3" + +"@sentry/wizard@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@sentry/wizard/-/wizard-1.0.2.tgz#346d1ecbeef7b765120ec8627053443456660f0d" + integrity sha512-/mS9SWcgc8uqrOhiwyGqusGnWXf4hvIiYpUGJGw4vxL8gZ3k+UMSKaEw46p+ND1X8y2RRgFJh7h7q2dtXa8QvQ== + dependencies: + "@sentry/cli" "^1.48.0" + chalk "^2.4.1" + glob "^7.1.3" + inquirer "^6.2.0" + lodash "^4.17.15" + opn "^5.4.0" + r2 "^2.0.1" + read-env "^1.3.0" + xcode "2.0.0" + yargs "^12.0.2" "@staltz/react-native-tcp@^3.3.1": version "3.3.1" @@ -1274,10 +1280,10 @@ resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-4.2.0.tgz#310ec0775de808a6a2e4fd4268c245fd734c1165" integrity sha512-U9m870Kqm0ko8beHawRXLGLvSi/ZMrl89gJ5BNcT452fAjtF2p4uRzXkdzvGJJJYBgx7BmqlDjBN/eCp5AAX2w== -"@svgr/babel-plugin-svg-dynamic-title@^4.3.1": - version "4.3.1" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-4.3.1.tgz#646c2f5b5770c2fe318d6e51492344c3d62ddb63" - integrity sha512-p6z6JJroP989jHWcuraeWpzdejehTmLUpyC9smhTBWyPN0VVGe2phbYxpPTV7Vh8XzmFrcG55idrnfWn/2oQEw== +"@svgr/babel-plugin-svg-dynamic-title@^4.3.3": + version "4.3.3" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-4.3.3.tgz#2cdedd747e5b1b29ed4c241e46256aac8110dd93" + integrity sha512-w3Be6xUNdwgParsvxkkeZb545VhXEwjGMwExMVBIdPQJeyMQHqm9Msnb2a1teHBqUYL66qtwfhNkbj1iarCG7w== "@svgr/babel-plugin-svg-em-dimensions@^4.2.0": version "4.2.0" @@ -1294,27 +1300,27 @@ resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-4.2.0.tgz#5f1e2f886b2c85c67e76da42f0f6be1b1767b697" integrity sha512-hYfYuZhQPCBVotABsXKSCfel2slf/yvJY8heTVX1PCTaq/IgASq1IyxPPKJ0chWREEKewIU/JMSsIGBtK1KKxw== -"@svgr/babel-preset@^4.3.1": - version "4.3.1" - resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-4.3.1.tgz#62ffcb85d756580e8ce608e9d2ac3b9063be9e28" - integrity sha512-rPFKLmyhlh6oeBv3j2vEAj2nd2QbWqpoJLKzBLjwQVt+d9aeXajVaPNEqrES2spjXKR4OxfgSs7U0NtmAEkr0Q== +"@svgr/babel-preset@^4.3.3": + version "4.3.3" + resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-4.3.3.tgz#a75d8c2f202ac0e5774e6bfc165d028b39a1316c" + integrity sha512-6PG80tdz4eAlYUN3g5GZiUjg2FMcp+Wn6rtnz5WJG9ITGEF1pmFdzq02597Hn0OmnQuCVaBYQE1OVFAnwOl+0A== dependencies: "@svgr/babel-plugin-add-jsx-attribute" "^4.2.0" "@svgr/babel-plugin-remove-jsx-attribute" "^4.2.0" "@svgr/babel-plugin-remove-jsx-empty-expression" "^4.2.0" "@svgr/babel-plugin-replace-jsx-attribute-value" "^4.2.0" - "@svgr/babel-plugin-svg-dynamic-title" "^4.3.1" + "@svgr/babel-plugin-svg-dynamic-title" "^4.3.3" "@svgr/babel-plugin-svg-em-dimensions" "^4.2.0" "@svgr/babel-plugin-transform-react-native-svg" "^4.2.0" "@svgr/babel-plugin-transform-svg-component" "^4.2.0" "@svgr/cli@^4.3.0": - version "4.3.2" - resolved "https://registry.yarnpkg.com/@svgr/cli/-/cli-4.3.2.tgz#fb20fd33429f0d0dfc6c7178e8bfc1e86006e9de" - integrity sha512-QdYzVgsowOWpOwkX+3+EK6zxlttADc2v6t0Baj2xETAdhBcpFAf/nZ0xw6b5zxdbGk8fm3nxJyPUddYuBkgzpg== + version "4.3.3" + resolved "https://registry.yarnpkg.com/@svgr/cli/-/cli-4.3.3.tgz#90b3acd1e1067b73a4dd6a768eea86d0dccf975c" + integrity sha512-FHsb9+2zMy9XZgEBFEh+1iofE0TBQn7OnJ9JF/2YimdyE93u2/j1p1K71+rJQ0GWKy96aSSbFWkRVR1i3zATOQ== dependencies: - "@svgr/core" "^4.3.2" - "@svgr/plugin-jsx" "^4.3.2" + "@svgr/core" "^4.3.3" + "@svgr/plugin-jsx" "^4.3.3" "@svgr/plugin-prettier" "^4.3.2" "@svgr/plugin-svgo" "^4.3.1" camelcase "^5.3.1" @@ -1325,12 +1331,12 @@ output-file-sync "^2.0.1" recursive-readdir "^2.2.2" -"@svgr/core@^4.3.2": - version "4.3.2" - resolved "https://registry.yarnpkg.com/@svgr/core/-/core-4.3.2.tgz#939c89be670ad79b762f4c063f213f0e02535f2e" - integrity sha512-N+tP5CLFd1hP9RpO83QJPZY3NL8AtrdqNbuhRgBkjE/49RnMrrRsFm1wY8pueUfAGvzn6tSXUq29o6ah8RuR5w== +"@svgr/core@^4.3.3": + version "4.3.3" + resolved "https://registry.yarnpkg.com/@svgr/core/-/core-4.3.3.tgz#b37b89d5b757dc66e8c74156d00c368338d24293" + integrity sha512-qNuGF1QON1626UCaZamWt5yedpgOytvLj5BQZe2j1k1B8DUG4OyugZyfEwBeXozCUwhLEpsrgPrE+eCu4fY17w== dependencies: - "@svgr/plugin-jsx" "^4.3.2" + "@svgr/plugin-jsx" "^4.3.3" camelcase "^5.3.1" cosmiconfig "^5.2.1" @@ -1341,13 +1347,13 @@ dependencies: "@babel/types" "^7.4.4" -"@svgr/plugin-jsx@^4.3.2": - version "4.3.2" - resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-4.3.2.tgz#ce9ddafc8cdd74da884c9f7af014afcf37f93d3c" - integrity sha512-+1GW32RvmNmCsOkMoclA/TppNjHPLMnNZG3/Ecscxawp051XJ2MkO09Hn11VcotdC2EPrDfT8pELGRo+kbZ1Eg== +"@svgr/plugin-jsx@^4.3.3": + version "4.3.3" + resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-4.3.3.tgz#e2ba913dbdfbe85252a34db101abc7ebd50992fa" + integrity sha512-cLOCSpNWQnDB1/v+SUENHH7a0XY09bfuMKdq9+gYvtuwzC2rU4I0wKGFEp1i24holdQdwodCtDQdFtJiTCWc+w== dependencies: "@babel/core" "^7.4.5" - "@svgr/babel-preset" "^4.3.1" + "@svgr/babel-preset" "^4.3.3" "@svgr/hast-util-to-babel-ast" "^4.3.2" svg-parser "^2.0.0" @@ -1377,9 +1383,9 @@ inherits "~2.0.1" "@types/babel__core@^7.1.0": - version "7.1.2" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.2.tgz#608c74f55928033fce18b99b213c16be4b3d114f" - integrity sha512-cfCCrFmiGY/yq0NuKNxIQvZFy9kY/1immpSpTngOnyIbD4+eJOG5mxphhHDv3CHL9GltO4GcKr54kGBg3RNdbg== + version "7.1.3" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.3.tgz#e441ea7df63cd080dfcd02ab199e6d16a735fc30" + integrity sha512-8fBo0UR2CcwWxeX7WIIgJ7lXjasFxoYgRnFHUj+hRvKkpiBJbxhdAPTCY6/ZKM0uxANFVzt4yObSLuTiTnazDA== dependencies: "@babel/parser" "^7.1.0" "@babel/types" "^7.0.0" @@ -1388,9 +1394,9 @@ "@types/babel__traverse" "*" "@types/babel__generator@*": - version "7.0.2" - resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.0.2.tgz#d2112a6b21fad600d7674274293c85dce0cb47fc" - integrity sha512-NHcOfab3Zw4q5sEE2COkpfXjoE7o+PmqD9DQW4koUT3roNxwziUdXGnRndMat/LJNUtePwn1TlP4do3uoe3KZQ== + version "7.6.1" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.1.tgz#4901767b397e8711aeb99df8d396d7ba7b7f0e04" + integrity sha512-bBKm+2VPJcMRVwNhxKu8W+5/zT7pwNEqeokFOmbvVSqGzFneNxYcEBro9Ac7/N9tlsaPYnZLK8J1LWKkMsLAew== dependencies: "@babel/types" "^7.0.0" @@ -1403,12 +1409,17 @@ "@babel/types" "^7.0.0" "@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": - version "7.0.7" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.7.tgz#2496e9ff56196cc1429c72034e07eab6121b6f3f" - integrity sha512-CeBpmX1J8kWLcDEnI3Cl2Eo6RfbGvzUctA+CjZUhOKDFbLfcr7fc4usEqLNWetrlJd7RhAkyYe2czXop4fICpw== + version "7.0.8" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.8.tgz#479a4ee3e291a403a1096106013ec22cf9b64012" + integrity sha512-yGeB2dHEdvxjP0y4UbRtQaSkXJ9649fYCmIdRoul5kfAoGCwxuCbMhag0k3RPfnuh9kPGm8x89btcfDEXdVWGw== dependencies: "@babel/types" "^7.3.0" +"@types/color-name@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" + integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== + "@types/eslint-visitor-keys@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" @@ -1449,9 +1460,9 @@ "@types/istanbul-lib-report" "*" "@types/json-schema@^7.0.3": - version "7.0.3" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.3.tgz#bdfd69d61e464dcc81b25159c270d75a73c1a636" - integrity sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A== + version "7.0.4" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339" + integrity sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA== "@types/minimatch@*": version "3.0.3" @@ -1459,19 +1470,14 @@ integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== "@types/node@*": - version "12.6.8" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.6.8.tgz#e469b4bf9d1c9832aee4907ba8a051494357c12c" - integrity sha512-aX+gFgA5GHcDi89KG5keey2zf0WfZk/HAQotEamsK2kbey+8yGKcson0hbK8E+v0NArlCJQCqMP161YhV6ZXLg== - -"@types/node@^10.3.2": - version "10.14.13" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.13.tgz#ac786d623860adf39a3f51d629480aacd6a6eec7" - integrity sha512-yN/FNNW1UYsRR1wwAoyOwqvDuLDtVXnaJTZ898XIw/Q5cCaeVAlVwvsmXLX5PuiScBYwZsZU4JYSHB3TvfdwvQ== + version "13.1.4" + resolved "https://registry.yarnpkg.com/@types/node/-/node-13.1.4.tgz#4cfd90175a200ee9b02bd6b1cd19bc349741607e" + integrity sha512-Lue/mlp2egZJoHXZr4LndxDAd7i/7SQYhV0EjWfb/a4/OZ6tuVwMCVPiwkU5nsEipxEf7hmkSU7Em5VQ8P5NGA== -"@types/node@^8.0.7": - version "8.10.51" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.51.tgz#80600857c0a47a8e8bafc2dae6daed6db58e3627" - integrity sha512-cArrlJp3Yv6IyFT/DYe+rlO8o3SIHraALbBW/+CcCYW/a9QucpLI+n2p4sRxAvl2O35TiecpX2heSZtJjvEO+Q== +"@types/normalize-package-data@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" + integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA== "@types/q@^1.5.1": version "1.5.2" @@ -1483,18 +1489,17 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw== -"@types/unist@*", "@types/unist@^2.0.0": +"@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2": version "2.0.3" resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e" integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ== "@types/vfile-message@*": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@types/vfile-message/-/vfile-message-1.0.1.tgz#e1e9895cc6b36c462d4244e64e6d0b6eaf65355a" - integrity sha512-mlGER3Aqmq7bqR1tTTIVHq8KSAFFRyGbrxuM8C/H82g6k7r2fS+IMEkIu3D7JHzG10NvPdR8DNx0jr0pwpp4dA== + version "2.0.0" + resolved "https://registry.yarnpkg.com/@types/vfile-message/-/vfile-message-2.0.0.tgz#690e46af0fdfc1f9faae00cd049cc888957927d5" + integrity sha512-GpTIuDpb9u4zIO165fUy9+fXcULdD8HFRNli04GehoMVbeNq7D6OBnqSmg3lxZnC+UvgUhEWKxdKiwYUkGltIw== dependencies: - "@types/node" "*" - "@types/unist" "*" + vfile-message "*" "@types/vfile@^3.0.0": version "3.0.2" @@ -1505,12 +1510,19 @@ "@types/unist" "*" "@types/vfile-message" "*" -"@types/yargs@^12.0.2", "@types/yargs@^12.0.9": - version "12.0.12" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-12.0.12.tgz#45dd1d0638e8c8f153e87d296907659296873916" - integrity sha512-SOhuU4wNBxhhTHxYaiG5NY4HBhDIDnJF60GU+2LqHAdKKer86//e4yg69aENCtQ04n0ovz+tq2YPME5t5yp4pw== +"@types/yargs-parser@*": + version "13.1.0" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-13.1.0.tgz#c563aa192f39350a1d18da36c5a8da382bbd8228" + integrity sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg== + +"@types/yargs@^13.0.0": + version "13.0.4" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.4.tgz#53d231cebe1a540e7e13727fc1f0d13ad4a9ba3b" + integrity sha512-Ke1WmBbIkVM8bpvsNEcGgQM70XcEh/nbpxQhW7FhrsbCsXSY9BmLB1+LHtD7r9zrsOcFlLiF+a/UeJsdfw3C5A== + dependencies: + "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^1.5.0": +"@typescript-eslint/eslint-plugin@^1.6.0": version "1.13.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-1.13.0.tgz#22fed9b16ddfeb402fd7bcde56307820f6ebc49f" integrity sha512-WQHCozMnuNADiqMtsNzp96FNox5sOVpU8Xt4meaT4em8lOG1SrOv92/mUbEHQVh90sldKSfcOc/I0FOb/14G1g== @@ -1521,7 +1533,7 @@ regexpp "^2.0.1" tsutils "^3.7.0" -"@typescript-eslint/experimental-utils@1.13.0": +"@typescript-eslint/experimental-utils@1.13.0", "@typescript-eslint/experimental-utils@^1.13.0": version "1.13.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-1.13.0.tgz#b08c60d780c0067de2fb44b04b432f540138301e" integrity sha512-zmpS6SyqG4ZF64ffaJ6uah6tWWWgZ8m+c54XXgwFtUv0jNz8aJAVx8chMCvnk7yl6xwn8d+d96+tWp7fXzTuDg== @@ -1530,7 +1542,7 @@ "@typescript-eslint/typescript-estree" "1.13.0" eslint-scope "^4.0.0" -"@typescript-eslint/parser@^1.5.0": +"@typescript-eslint/parser@^1.6.0": version "1.13.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-1.13.0.tgz#61ac7811ea52791c47dc9fd4dd4a184fae9ac355" integrity sha512-ITMBs52PCPgLb2nGPoeT4iU3HdQZHcPaZVw+7CsFagRJHUhyeTgorEwHXhFf3e7Evzi8oujKNpHc8TONth8AdQ== @@ -1548,37 +1560,46 @@ lodash.unescape "4.0.1" semver "5.5.0" -"@walletconnect/core@^1.0.0-beta.31": - version "1.0.0-beta.31" - resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-1.0.0-beta.31.tgz#ce9257c13a0da7a52a61829b66c45a9686cedca9" - integrity sha512-EggZFGdQ0EMjWZrtqAn6PJslLDlc5suyPBWfp4PP0247tYorcXXz/7OSiek0XWBVQ7dakCqeJAOteuc/FaQ+hw== +"@uniswap/sdk@^1.0.0-beta.4": + version "1.0.0-beta.4" + resolved "https://registry.yarnpkg.com/@uniswap/sdk/-/sdk-1.0.0-beta.4.tgz#d14a0ddc15e8de9173f3d97075e7ebbaa2570f1a" + integrity sha512-a2GnlZrmg0Qxr4HFIBPCKygLFxu5f/hhIOKYVm12hG8vzsCVh72DEqZkpaOSFH3o6LDez4p2KnPvmwZkWVUnRg== dependencies: - "@walletconnect/types" "^1.0.0-beta.31" - "@walletconnect/utils" "^1.0.0-beta.31" + bignumber.js "^9.0.0" + ethers "^4.0.28" + lodash.clonedeepwith "^4.5.0" + +"@walletconnect/core@^1.0.0-beta.42": + version "1.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-1.0.0-beta.42.tgz#cb9b098590255577571a90b9bda83a0f920020d8" + integrity sha512-Q7pDpTj2/bm7rkAbI+5/mf7SdurLXDfznjvE6jZGg8o23wsYamnkwLnqVMkqeFyUjY7bpHxWqakY813wmmlrZw== + dependencies: + "@walletconnect/types" "^1.0.0-beta.42" + "@walletconnect/utils" "^1.0.0-beta.42" "@walletconnect/react-native@^1.0.0-beta.29": - version "1.0.0-beta.31" - resolved "https://registry.yarnpkg.com/@walletconnect/react-native/-/react-native-1.0.0-beta.31.tgz#097af6bf635bf4917e4fc6cc0cbd39609aed64f6" - integrity sha512-zscEiCUshvMfV9/yU+UL5gKZ/0WD+UH+Ar0XBdWA/BVu306maCoqNUWTV3Txj7gl+1L/hwIchbrT8np9dgK1tQ== + version "1.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@walletconnect/react-native/-/react-native-1.0.0-beta.42.tgz#3e703a62d80db6f10470ecdd443a3c4025973e3f" + integrity sha512-pcgIx+d4LFjXAgI8+n60fqh5YN/YiVtGhcqdVC/9dadcV/9C0YkFYQiYAXNqXPx/FzaA0+4X8PSyEZY4P61A7g== dependencies: - "@walletconnect/core" "^1.0.0-beta.31" - "@walletconnect/types" "^1.0.0-beta.31" - "@walletconnect/utils" "^1.0.0-beta.31" + "@walletconnect/core" "^1.0.0-beta.42" + "@walletconnect/types" "^1.0.0-beta.42" + "@walletconnect/utils" "^1.0.0-beta.42" -"@walletconnect/types@^1.0.0-beta.31": - version "1.0.0-beta.31" - resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-1.0.0-beta.31.tgz#a35049a719042bda819759e4cd77591c5315a6a6" - integrity sha512-C6W4K+YWoAl69xDvbbhjBtQ02Xx2eBsfLyezSvs8eFw4toKkkJ5Uw5dp9C6qmUBDrKIIcmP2004F1MniLnnk3Q== +"@walletconnect/types@^1.0.0-beta.42": + version "1.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-1.0.0-beta.42.tgz#1a0db31b37b7765985f78e2b0f2942407685cdcf" + integrity sha512-YBpcYdYGEacOob5VF0/8LRGz/uGynFcwoj9RIEOkDl9JqGQMaXhlZ1M48AfEp8NVQvXRF+cSc3moPDwu3+9USw== -"@walletconnect/utils@^1.0.0-beta.31": - version "1.0.0-beta.31" - resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-1.0.0-beta.31.tgz#a73ea81325750208b5298680bf3f82208f0d4f37" - integrity sha512-cTZu+EzoEdvbkT36o+4VqBsD7ro5pXrOu9sswgcWkZ2xVFfRSnNctJkUdeK3JOu1wPnG25/QaRr3fQx4ZoIBrQ== +"@walletconnect/utils@^1.0.0-beta.36", "@walletconnect/utils@^1.0.0-beta.42": + version "1.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-1.0.0-beta.42.tgz#60304d0ed902a532ac9e535905b5a1c4c8063069" + integrity sha512-/eLcm+tEcvqlYaEaG/L7c+3uNrugZs3a30bwYUbNvlmzYWTNBzU/EV18CGavlZLc/Pb2XtPXevGtDsLlvtR7/Q== dependencies: "@ethersproject/address" "^5.0.0-beta.125" "@ethersproject/bytes" "^5.0.0-beta.126" "@ethersproject/strings" "^5.0.0-beta.125" - "@walletconnect/types" "^1.0.0-beta.31" + "@walletconnect/types" "^1.0.0-beta.42" bignumber.js "^8.1.1" "@yarnpkg/lockfile@^1.0.0", "@yarnpkg/lockfile@^1.1.0": @@ -1592,14 +1613,16 @@ Base64@~0.2.0: integrity sha1-ujpCMHCOGGcFBl5mur3Uw1z2ACg= abab@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.0.tgz#aba0ab4c5eee2d4c79d3487d85450fb2376ebb0f" - integrity sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w== + version "2.0.3" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a" + integrity sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg== -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" abs-svg-path@^0.1.1: version "0.1.1" @@ -1634,17 +1657,17 @@ accepts@~1.3.5, accepts@~1.3.7: negotiator "0.6.2" acorn-globals@^4.1.0: - version "4.3.2" - resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.2.tgz#4e2c2313a597fd589720395f6354b41cd5ec8006" - integrity sha512-BbzvZhVtZP+Bs1J1HcwrQe8ycfO0wStkSGxuul3He3GkHOIZ6eTqOkPuw9IP1X3+IkOo4wiJmwkobzXYz4wewQ== + version "4.3.4" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.4.tgz#9fa1926addc11c97308c4e66d7add0d40c3272e7" + integrity sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A== dependencies: acorn "^6.0.1" acorn-walk "^6.0.1" -acorn-jsx@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.1.tgz#32a064fd925429216a09b141102bfdd185fae40e" - integrity sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg== +acorn-jsx@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.1.0.tgz#294adb71b57398b0680015f0a38c563ee1db5384" + integrity sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw== acorn-walk@^6.0.1: version "6.2.0" @@ -1656,10 +1679,15 @@ acorn@^5.5.3: resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== -acorn@^6.0.1, acorn@^6.0.7: - version "6.2.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.2.1.tgz#3ed8422d6dec09e6121cc7a843ca86a330a86b51" - integrity sha512-JD0xT5FCRDNyjDda3Lrg/IxFscp9q4tiYtxE1/nOzlKCk7hIRuYjhq1kCNkbPjMRMZuFq20HNQn1I9k8Oj0E+Q== +acorn@^6.0.1: + version "6.4.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.0.tgz#b659d2ffbafa24baf5db1cdbb2c94a983ecd2784" + integrity sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw== + +acorn@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.0.tgz#949d36f2c292535da602283586c2477c57eb2d6c" + integrity sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ== aes-js@3.0.0: version "3.0.0" @@ -1685,7 +1713,7 @@ agent-base@~4.2.1: dependencies: es6-promisify "^5.0.0" -ajv@^6.10.2, ajv@^6.5.5, ajv@^6.9.1: +ajv@^6.10.0, ajv@^6.10.2, ajv@^6.5.5: version "6.10.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52" integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw== @@ -1703,6 +1731,11 @@ animated@^0.2.2: invariant "^2.2.0" normalize-css-color "^1.0.1" +anser@^1.4.9: + version "1.4.9" + resolved "https://registry.yarnpkg.com/anser/-/anser-1.4.9.tgz#1f85423a5dcf8da4631a341665ff675b96845760" + integrity sha512-AI+BjTeGt2+WFk4eWcqbQ7snZpDBt8SaLlj0RT2h5xfdWaiy51OjYvqwMrNzJLGy8iOAL6nKDITWO+rd4MkYEA== + ansi-align@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f" @@ -1739,6 +1772,13 @@ ansi-escapes@^3.0.0, ansi-escapes@^3.2.0: resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== +ansi-escapes@^4.2.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.0.tgz#a4ce2b33d6b214b7950d8595c212f12ac9cc569d" + integrity sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg== + dependencies: + type-fest "^0.8.1" + ansi-fragments@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/ansi-fragments/-/ansi-fragments-0.2.1.tgz#24409c56c4cc37817c3d7caa99d8969e2de5a05e" @@ -1777,6 +1817,11 @@ ansi-regex@^4.0.0, ansi-regex@^4.1.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" @@ -1789,16 +1834,19 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" + integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== + dependencies: + "@types/color-name" "^1.1.1" + color-convert "^2.0.1" + ansi-wrap@0.1.0, ansi-wrap@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768= -ansi@^0.3.0, ansi@~0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/ansi/-/ansi-0.3.1.tgz#0c42d4fb17160d5a9af1e484bace1c66922c1b21" - integrity sha1-DELU+xcWDVqa8eSEus4cZpIsGyE= - anymatch@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" @@ -1807,19 +1855,6 @@ anymatch@^2.0.0: micromatch "^3.1.4" normalize-path "^2.1.1" -aproba@^1.0.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== - -are-we-there-yet@~1.1.2: - version "1.1.5" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -1840,13 +1875,6 @@ arr-diff@^1.0.1: arr-flatten "^1.0.1" array-slice "^0.2.3" -arr-diff@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" - integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8= - dependencies: - arr-flatten "^1.0.1" - arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" @@ -1883,12 +1911,13 @@ array-find-index@^1.0.1: integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= array-includes@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.0.3.tgz#184b48f62d92d7452bb31b323165c7f8bd02266d" - integrity sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0= + version "3.1.1" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.1.tgz#cdd67e6852bdf9c1215460786732255ed2459348" + integrity sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ== dependencies: - define-properties "^1.1.2" - es-abstract "^1.7.0" + define-properties "^1.1.3" + es-abstract "^1.17.0" + is-string "^1.0.5" array-map@~0.0.0: version "0.0.0" @@ -1917,11 +1946,6 @@ array-uniq@^1.0.1: resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= -array-unique@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" - integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM= - array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" @@ -1937,11 +1961,6 @@ arrify@^1.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= -art@^0.10.0: - version "0.10.3" - resolved "https://registry.yarnpkg.com/art/-/art-0.10.3.tgz#b01d84a968ccce6208df55a733838c96caeeaea2" - integrity sha512-HXwbdofRTiJT6qZX/FnchtldzJjS3vkLJxQilc3Xj+ma2MXjY4UAyQ0ls1XZYVnDvVIBiFZbC6QsvtW86TD6tQ== - asap@~2.0.3: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" @@ -1992,9 +2011,9 @@ astral-regex@^1.0.0: integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== async-limiter@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" - integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg== + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" + integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== async@^2.4.0: version "2.6.3" @@ -2019,23 +2038,23 @@ asyncstorage-down@^4.2.0: ltgt "^2.1.3" tiny-queue "0.2.0" -atob@^2.1.1: +atob@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== autoprefixer@^9.5.1: - version "9.6.1" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.6.1.tgz#51967a02d2d2300bb01866c1611ec8348d355a47" - integrity sha512-aVo5WxR3VyvyJxcJC3h4FKfwCQvQWb1tSI5VHNibddCVWrcD1NvlxEweg3TSgiPztMnWfjpy2FURKA2kvDE+Tw== + version "9.7.3" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.7.3.tgz#fd42ed03f53de9beb4ca0d61fb4f7268a9bb50b4" + integrity sha512-8T5Y1C5Iyj6PgkPSFd0ODvK9DIleuPKUPYniNxybS47g2k2wFgLZ46lGQHlBuGKIAEV8fbCDfKCCRS1tvOgc3Q== dependencies: - browserslist "^4.6.3" - caniuse-lite "^1.0.30000980" + browserslist "^4.8.0" + caniuse-lite "^1.0.30001012" chalk "^2.4.2" normalize-range "^0.1.2" num2fraction "^1.2.2" - postcss "^7.0.17" - postcss-value-parser "^4.0.0" + postcss "^7.0.23" + postcss-value-parser "^4.0.2" aws-sign2@~0.7.0: version "0.7.0" @@ -2043,9 +2062,9 @@ aws-sign2@~0.7.0: integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= aws4@^1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" - integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== + version "1.9.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.0.tgz#24390e6ad61386b0a747265754d2a17219de862c" + integrity sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A== axios@^0.19.0: version "0.19.0" @@ -2060,40 +2079,28 @@ babel-core@7.0.0-bridge.0: resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece" integrity sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg== -babel-eslint@10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.0.1.tgz#919681dc099614cd7d31d45c8908695092a1faed" - integrity sha512-z7OT1iNV+TjOwHNLLyJk+HN+YVWX+CLE6fPD2SymJZOZQBs+QIexFjhm4keGTm8MW9xr4EC9Q0PbaLB24V5GoQ== +babel-eslint@^10.0.1, babel-eslint@^10.0.3: + version "10.0.3" + resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.0.3.tgz#81a2c669be0f205e19462fed2482d33e4687a88a" + integrity sha512-z3U7eMY6r/3f3/JB9mTsLjyxrv0Yb1zb8PCWCLpguxfCzBIZUwy23R1t/XKewP+8mEN2Ck8Dtr4q20z6ce6SoA== dependencies: "@babel/code-frame" "^7.0.0" "@babel/parser" "^7.0.0" "@babel/traverse" "^7.0.0" "@babel/types" "^7.0.0" - eslint-scope "3.7.1" eslint-visitor-keys "^1.0.0" + resolve "^1.12.0" -babel-eslint@^8.2.2: - version "8.2.6" - resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-8.2.6.tgz#6270d0c73205628067c0f7ae1693a9e797acefd9" - integrity sha512-aCdHjhzcILdP8c9lej7hvXKvQieyRt20SF102SIGyY4cUIiw6UaAtK4j2o3dXX74jEmy0TJ0CEhv4fTIM3SzcA== +babel-jest@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.9.0.tgz#3fc327cb8467b89d14d7bc70e315104a783ccd54" + integrity sha512-ntuddfyiN+EhMw58PTNL1ph4C9rECiQXjI4nMMBKBaNjXvqLdkXpPRcMSr4iyBrJg/+wz9brFUD6RhOAT6r4Iw== dependencies: - "@babel/code-frame" "7.0.0-beta.44" - "@babel/traverse" "7.0.0-beta.44" - "@babel/types" "7.0.0-beta.44" - babylon "7.0.0-beta.44" - eslint-scope "3.7.1" - eslint-visitor-keys "^1.0.0" - -babel-jest@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.8.0.tgz#5c15ff2b28e20b0f45df43fe6b7f2aae93dba589" - integrity sha512-+5/kaZt4I9efoXzPlZASyK/lN9qdRKmmUav9smVc0ruPQD7IsfucQ87gpOE8mn2jbDuS6M/YOW6n3v9ZoIfgnw== - dependencies: - "@jest/transform" "^24.8.0" - "@jest/types" "^24.8.0" + "@jest/transform" "^24.9.0" + "@jest/types" "^24.9.0" "@types/babel__core" "^7.1.0" babel-plugin-istanbul "^5.1.0" - babel-preset-jest "^24.6.0" + babel-preset-jest "^24.9.0" chalk "^2.4.2" slash "^2.0.0" @@ -2128,10 +2135,10 @@ babel-plugin-istanbul@^5.1.0: istanbul-lib-instrument "^3.3.0" test-exclude "^5.2.3" -babel-plugin-jest-hoist@^24.6.0: - version "24.6.0" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.6.0.tgz#f7f7f7ad150ee96d7a5e8e2c5da8319579e78019" - integrity sha512-3pKNH6hMt9SbOv0F3WVmy5CWQ4uogS3k0GY5XLyQHJ9EGpAT9XWkFd2ZiXXtkwFHdAHa5j7w7kfxSP5lAIwu7w== +babel-plugin-jest-hoist@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.9.0.tgz#4f837091eb407e01447c8843cbec546d0002d756" + integrity sha512-2EMA2P8Vp7lG0RAzr4HXqtYwacfMErOuv1U3wrvxHX6rD1sV6xS3WXG3r8TRQ2r6w8OhvSdWt+z41hQNwNm3Xw== dependencies: "@types/babel__traverse" "^7.0.6" @@ -2161,6 +2168,11 @@ babel-plugin-rewire@^1.2.0: babel-plugin-syntax-jsx "^6.18.0" lodash "^4.17.11" +babel-plugin-syntax-async-functions@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" + integrity sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU= + babel-plugin-syntax-jsx@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" @@ -2185,10 +2197,10 @@ babel-polyfill@6.23.0: core-js "^2.4.0" regenerator-runtime "^0.10.0" -babel-preset-fbjs@^3.0.1, babel-preset-fbjs@^3.1.2, babel-preset-fbjs@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/babel-preset-fbjs/-/babel-preset-fbjs-3.2.0.tgz#c0e6347d3e0379ed84b3c2434d3467567aa05297" - integrity sha512-5Jo+JeWiVz2wHUUyAlvb/sSYnXNig9r+HqGAOSfh5Fzxp7SnAaR/tEGRJ1ZX7C77kfk82658w6R5Z+uPATTD9g== +babel-preset-fbjs@^3.1.2, babel-preset-fbjs@^3.2.0, babel-preset-fbjs@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/babel-preset-fbjs/-/babel-preset-fbjs-3.3.0.tgz#a6024764ea86c8e06a22d794ca8b69534d263541" + integrity sha512-7QTLTCd2gwB2qGoi5epSULMHugSVgpcVt5YAeiFO9ABLrutDQzKfGwzxgZHLpugq8qMdg/DhRZDZ5CLKxBkEbw== dependencies: "@babel/plugin-proposal-class-properties" "^7.0.0" "@babel/plugin-proposal-object-rest-spread" "^7.0.0" @@ -2218,13 +2230,13 @@ babel-preset-fbjs@^3.0.1, babel-preset-fbjs@^3.1.2, babel-preset-fbjs@^3.2.0: "@babel/plugin-transform-template-literals" "^7.0.0" babel-plugin-syntax-trailing-function-commas "^7.0.0-beta.0" -babel-preset-jest@^24.6.0: - version "24.6.0" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-24.6.0.tgz#66f06136eefce87797539c0d63f1769cc3915984" - integrity sha512-pdZqLEdmy1ZK5kyRUfvBb2IfTPb2BUvIJczlPspS8fWmBQslNNDBqVfh7BW5leOVJMDZKzjD8XEyABTk6gQ5yw== +babel-preset-jest@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-24.9.0.tgz#192b521e2217fb1d1f67cf73f70c336650ad3cdc" + integrity sha512-izTUuhE4TMfTRPF92fFwD2QfdXaZW08qvWTFCI51V8rW5x00UuPgc3ajRoWofXOuxjfcOM5zzSYsQS3H8KGCAg== dependencies: "@babel/plugin-syntax-object-rest-spread" "^7.0.0" - babel-plugin-jest-hoist "^24.6.0" + babel-plugin-jest-hoist "^24.9.0" babel-runtime@^6.22.0: version "6.26.0" @@ -2234,11 +2246,6 @@ babel-runtime@^6.22.0: core-js "^2.4.0" regenerator-runtime "^0.11.0" -babylon@7.0.0-beta.44: - version "7.0.0-beta.44" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.44.tgz#89159e15e6e30c5096e22d738d8c0af8a0e8ca1d" - integrity sha512-5Hlm13BJVAioCHpImtFqNOF2H3ieTOHd0fmFGMxOJ9jgeFqeAwsv3u5P5cR7CSeFrkgHsT19DgFJkHV0/Mcd8g== - backo2@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" @@ -2270,9 +2277,9 @@ base64-js@1.1.2: integrity sha1-1kAMrBxMZgl22Q0HoENR2JOV9eg= base64-js@^1.0.2, base64-js@^1.1.2, base64-js@^1.2.3: - version "1.3.0" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" - integrity sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw== + version "1.3.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" + integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== base@^0.11.1: version "0.11.2" @@ -2308,10 +2315,10 @@ better-assert@~1.0.0: dependencies: callsite "1.0.0" -big-integer@^1.6.7: - version "1.6.44" - resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.44.tgz#4ee9ae5f5839fc11ade338fea216b4513454a539" - integrity sha512-7MzElZPTyJ2fNvBkPxtFQ2fWIkVmuzw41+BZHSzpEq3ymB2MfeKp1+yXl/tS75xCx+WnyV+yb0kp+K1C3UNwmQ== +big-integer@^1.6.44, big-integer@^1.6.7: + version "1.6.48" + resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.48.tgz#8fd88bd1632cba4a1c8c3e3d7159f08bb95b4b9e" + integrity sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w== bignumber.js@^8.1.1: version "8.1.1" @@ -2323,6 +2330,13 @@ bignumber.js@^9.0.0: resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.0.tgz#805880f84a329b5eac6e7cb6f8274b6d82bdf075" integrity sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A== +bindings@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + bl@~0.8.1: version "0.8.2" resolved "https://registry.yarnpkg.com/bl/-/bl-0.8.2.tgz#c9b6bca08d1bc2ea00fc8afb4f1a5fd1e1c66e4e" @@ -2370,6 +2384,13 @@ bplist-creator@0.0.7: dependencies: stream-buffers "~2.2.0" +bplist-creator@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/bplist-creator/-/bplist-creator-0.0.8.tgz#56b2a6e79e9aec3fc33bf831d09347d73794e79c" + integrity sha512-Za9JKzD6fjLC16oX2wsXfc+qBEhJBJB1YPInoAQpMLhDuj5aVOv1baGeIQSq1Fr3OCqzvsoQcSBSwGId/Ja2PA== + dependencies: + stream-buffers "~2.2.0" + bplist-parser@0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.1.1.tgz#d60d5dcc20cba6dc7e1f299b35d3e1f95dafbae6" @@ -2377,6 +2398,13 @@ bplist-parser@0.1.1: dependencies: big-integer "^1.6.7" +bplist-parser@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.2.0.tgz#43a9d183e5bf9d545200ceac3e712f79ebbe8d0e" + integrity sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw== + dependencies: + big-integer "^1.6.44" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -2385,15 +2413,6 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^1.8.2: - version "1.8.5" - resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" - integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc= - dependencies: - expand-range "^1.8.1" - preserve "^0.2.0" - repeat-element "^1.1.2" - braces@^2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" @@ -2498,28 +2517,51 @@ browserify-zlib@^0.1.4: dependencies: pako "~0.2.0" -browserslist@^4.6.3: - version "4.6.6" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.6.6.tgz#6e4bf467cde520bc9dbdf3747dafa03531cec453" - integrity sha512-D2Nk3W9JL9Fp/gIcWei8LrERCS+eXu9AM5cfXA8WEZ84lFks+ARnZ0q/R69m2SV3Wjma83QDDPxsNKXUwdIsyA== +browserslist@^4.8.0: + version "4.8.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.8.3.tgz#65802fcd77177c878e015f0e3189f2c4f627ba44" + integrity sha512-iU43cMMknxG1ClEZ2MDKeonKE1CCrFVkQK2AqO2YWFmvIrx4JWrvQ4w4hQez6EpVI8rHTtqh/ruHHDHSOKxvUg== dependencies: - caniuse-lite "^1.0.30000984" - electron-to-chromium "^1.3.191" - node-releases "^1.1.25" + caniuse-lite "^1.0.30001017" + electron-to-chromium "^1.3.322" + node-releases "^1.1.44" -bser@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.0.tgz#65fc784bf7f87c009b973c12db6546902fa9c7b5" - integrity sha512-8zsjWrQkkBoLK6uxASk1nJ2SKv97ltiGDo6A3wA0/yRPz+CwmEyDo0hUrhIuukG2JHpAl3bvFIixw2/3Hi0DOg== +bser@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== dependencies: node-int64 "^0.4.0" +btoa@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/btoa/-/btoa-1.2.1.tgz#01a9909f8b2c93f6bf680ba26131eb30f7fa3d73" + integrity sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g== + +buffer-alloc-unsafe@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" + integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== + +buffer-alloc@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" + integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== + dependencies: + buffer-alloc-unsafe "^1.1.0" + buffer-fill "^1.0.0" + buffer-crc32@^0.2.13, buffer-crc32@~0.2.3: version "0.2.13" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= -buffer-from@^1.0.0: +buffer-fill@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" + integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= + +buffer-from@^1.0.0, buffer-from@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== @@ -2530,18 +2572,18 @@ buffer-xor@^1.0.3: integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= buffer@^4.9.1: - version "4.9.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" - integrity sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg= + version "4.9.2" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" + integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== dependencies: base64-js "^1.0.2" ieee754 "^1.1.4" isarray "^1.0.0" -buffer@^5.0.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.2.1.tgz#dd57fa0f109ac59c602479044dca7b8b3d0b71d6" - integrity sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg== +buffer@^5.0.0, buffer@^5.4.3: + version "5.4.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.4.3.tgz#3fbc9c69eb713d323e3fc1a895eee0710c072115" + integrity sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A== dependencies: base64-js "^1.0.2" ieee754 "^1.1.4" @@ -2632,6 +2674,11 @@ camelcase-keys@^4.0.0: map-obj "^2.0.0" quick-lru "^1.0.0" +camelcase@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.0.0.tgz#03295527d58bd3cd4aa75363f35b2e8d97be2f42" + integrity sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA== + camelcase@^4.0.0, camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" @@ -2647,17 +2694,10 @@ camelize@^1.0.0: resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.0.tgz#164a5483e630fa4321e5af07020e531831b2609b" integrity sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs= -caniuse-lite@^1.0.30000980, caniuse-lite@^1.0.30000984: - version "1.0.30000987" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000987.tgz#bc6b47217afd8226a2b1964635c6bff62cdf5738" - integrity sha512-O3VrjtRMTxoU5Cn5/QSmXeIR1gkVps4j9jqfIm4FLaQ5JzqBlVjMUG1xWnoYFv8N+H3Lp++aa05TekyIbjHL7g== - -capture-exit@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-1.2.0.tgz#1c5fcc489fd0ab00d4f1ac7ae1072e3173fbab6f" - integrity sha1-HF/MSJ/QqwDU8ax64QcuMXP7q28= - dependencies: - rsvp "^3.3.3" +caniuse-lite@^1.0.30001012, caniuse-lite@^1.0.30001017: + version "1.0.30001019" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001019.tgz#857e3fccaad2b2feb3f1f6d8a8f62d747ea648e1" + integrity sha512-6ljkLtF1KM5fQ+5ZN0wuyVvvebJxgJPTmScOMaFuQN2QuOzvRJnWSKfzQskQU5IOU4Gap3zasYPIinzwUjoj/g== capture-exit@^2.0.0: version "2.0.0" @@ -2671,7 +2711,7 @@ capture-stack-trace@^1.0.0: resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz#a6c0bbe1f38f3aa0b92238ecb6ff42c344d4135d" integrity sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw== -caseless@~0.12.0: +caseless@^0.12.0, caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= @@ -2681,7 +2721,7 @@ ccount@^1.0.0: resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.0.4.tgz#9cf2de494ca84060a2a8d2854edd6dfb0445f386" integrity sha512-fpZ81yYfzentuieinmGnphk0pLkOTMm6MZdVqwd77ROvhko6iujLNGrHH5E7utq3ygWklwfmwuG+A7P+NpqT6w== -chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.1: +chalk@1.1.3, chalk@^1.0.0: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= @@ -2701,6 +2741,14 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + change-emitter@^0.1.2: version "0.1.6" resolved "https://registry.yarnpkg.com/change-emitter/-/change-emitter-0.1.6.tgz#e8b2fe3d7f1ab7d69a32199aff91ea6931409515" @@ -2745,15 +2793,12 @@ child-process-promise@^2.2.0: node-version "^1.0.0" promise-polyfill "^6.0.1" -chownr@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.2.tgz#a18f1e0b269c8a6a5d3c86eb298beb14c3dd7bf6" - integrity sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A== - -chroma-js@^1.3.7: - version "1.4.1" - resolved "https://registry.yarnpkg.com/chroma-js/-/chroma-js-1.4.1.tgz#eb2d9c4d1ff24616be84b35119f4d26f8205f134" - integrity sha512-jTwQiT859RTFN/vIf7s+Vl/Z2LcMrvMv3WUFmd/4u76AdlFC0NTNgqEEFPcRiHmAswPsMiQEDZLM8vX8qXpZNQ== +chroma-js@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/chroma-js/-/chroma-js-2.1.0.tgz#c0be48a21fe797ef8965608c1c4f911ef2da49d5" + integrity sha512-uiRdh4ZZy+UTPSrAdp8hqEdVb1EllLtTHOt5TMaOjJUvi+O54/83Fc5K2ld1P+TJX+dw5B+8/sCgzI6eaur/lg== + dependencies: + cross-env "^6.0.3" ci-info@^1.5.0: version "1.6.0" @@ -2802,6 +2847,13 @@ cli-cursor@^2.1.0: dependencies: restore-cursor "^2.0.0" +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + cli-spinners@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.2.0.tgz#e8b988d9206c692302d8ee834e7a85c0144d8f77" @@ -2839,6 +2891,15 @@ cliui@^5.0.0: strip-ansi "^5.2.0" wrap-ansi "^5.1.0" +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + clone-deep@^0.2.4: version "0.2.4" resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-0.2.4.tgz#4e73dd09e9fb971cc38670c5dced9c1896481cc6" @@ -2850,6 +2911,16 @@ clone-deep@^0.2.4: lazy-cache "^1.0.3" shallow-clone "^0.1.2" +clone-deep@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-2.0.2.tgz#00db3a1e173656730d1188c3d6aced6d7ea97713" + integrity sha512-SZegPTKjCgpQH63E+eN6mVEEPdQBOUzjyJm5Pora4lrwWRFS8I0QAxV/KD6vV/i0WuijHZWQC1fMsPEdxfdVCQ== + dependencies: + for-own "^1.0.0" + is-plain-object "^2.0.4" + kind-of "^6.0.0" + shallow-clone "^1.0.0" + clone-regexp@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/clone-regexp/-/clone-regexp-2.2.0.tgz#7d65e00885cd8796405c35a737e7a86b7429e36f" @@ -2886,7 +2957,7 @@ code-point-at@^1.0.0: resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= -code-push@^2.0.6, code-push@^2.0.7: +code-push@^2.0.6: version "2.0.7" resolved "https://registry.yarnpkg.com/code-push/-/code-push-2.0.7.tgz#aa2303376552a15ea3c2092ff2f19e4d6666ab9e" integrity sha512-8cEO60OYPiDj4vaSBxRAySzShYrKLi8GXdxcbJhTJ25PAvMUkf9rC/IQxgRK01EqWcGwKvIAGvz+Xk9YJcMM+A== @@ -2898,6 +2969,16 @@ code-push@^2.0.6, code-push@^2.0.7: superagent-proxy "^2.0.0" yazl "^2.4.1" +code-push@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/code-push/-/code-push-3.1.0.tgz#02b43b8f8cae1d8d281437aa5635c288399a48ca" + integrity sha512-SwEWx/MLEkRh/oXw4kvi8AIVzR7R2HFWKjsZwX3BWMLEudus3kekwuO2ufk9nYxHcDBZjUfao0G3HIkV9P2Cbw== + dependencies: + q "^1.4.1" + recursive-fs "^1.1.2" + slash "^3.0.0" + yazl "^2.4.1" + collapse-white-space@^1.0.2: version "1.0.5" resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.5.tgz#c2495b699ab1ed380d29a1091e01063e75dbbe3a" @@ -2918,11 +2999,23 @@ color-convert@^1.9.0: dependencies: color-name "1.1.3" +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + color-support@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" @@ -2934,11 +3027,11 @@ colorette@^1.0.7: integrity sha512-6S062WDQUXi6hOfkO/sBPVwE5ASXY4G2+b4atvhJfSsuUUhIaUKlkjLe9692Ipyt5/a+IPF5aVTu3V5gvXq5cg== colors@^1.0.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.3.tgz#39e005d546afe01e01f9c4ca8fa50f686a01205d" - integrity sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg== + version "1.4.0" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" + integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== -combined-stream@^1.0.6, combined-stream@~1.0.6: +combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== @@ -2950,10 +3043,10 @@ command-exists@^1.2.8: resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.8.tgz#715acefdd1223b9c9b37110a149c6392c2852291" integrity sha512-PM54PkseWbiiD/mMsbvW351/u+dafwTJ0ye2qB60G1aGQP9j3xK2gmMDc+R34L3nDtx4qMCitXT75mkbkGJDLw== -commander@^2.19.0, commander@^2.20.0, commander@^2.9.0, commander@~2.20.0: - version "2.20.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" - integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== +commander@^2.19.0, commander@^2.20.0, commander@~2.20.3: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== commander@~2.13.0: version "2.13.0" @@ -2986,11 +3079,11 @@ component-inherit@0.0.3: integrity sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM= compressible@~2.0.16: - version "2.0.17" - resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.17.tgz#6e8c108a16ad58384a977f3a482ca20bff2f38c1" - integrity sha512-BGHeLCK1GV7j1bSmQQAi26X+GgWcTjLr/0tzSvMCl3LH1w1IJ4PFSPoV5316b30cneTziC+B1a+3OjoSUcQYmw== + version "2.0.18" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" + integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== dependencies: - mime-db ">= 1.40.0 < 2" + mime-db ">= 1.43.0 < 2" compression@^1.7.1: version "1.7.4" @@ -3032,11 +3125,6 @@ configstore@^3.0.0: write-file-atomic "^2.0.0" xdg-basedir "^3.0.0" -confusing-browser-globals@^1.0.5: - version "1.0.7" - resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.7.tgz#5ae852bd541a910e7ffb2dbb864a2d21a36ad29b" - integrity sha512-cgHI1azax5ATrZ8rJ+ODDML9Fvu67PimB6aNxBrc/QwSaDaM9eTfIEUHx3bBLJJ82ioSb+/5zfsMCCEJax3ByQ== - connect@^3.6.5: version "3.7.0" resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8" @@ -3048,16 +3136,9 @@ connect@^3.6.5: utils-merge "1.0.1" console-browserify@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" - integrity sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA= - dependencies: - date-now "^0.1.4" - -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + version "1.2.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" + integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== constants-browserify@^1.0.0: version "1.0.0" @@ -3069,10 +3150,10 @@ contains-path@^0.1.0: resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= -convert-source-map@^1.1.0, convert-source-map@^1.4.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" - integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A== +convert-source-map@^1.4.0, convert-source-map@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" + integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== dependencies: safe-buffer "~5.1.1" @@ -3092,14 +3173,9 @@ core-js@^1.0.0: integrity sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY= core-js@^2.2.2, core-js@^2.4.0, core-js@^2.4.1: - version "2.6.9" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2" - integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A== - -core-js@^3.0.0: - version "3.1.4" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.1.4.tgz#3a2837fc48e582e1ae25907afcd6cf03b0cc7a07" - integrity sha512-YNZN8lt82XIMLnLirj9MhKDFZHalwzzrL9YLt6eb0T5D0EDl4IQ90IGkua8mHbnxNrkj1d8hbdizMc0Qmg1WnQ== + version "2.6.11" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" + integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" @@ -3163,6 +3239,13 @@ create-react-class@^15.6.3: loose-envify "^1.3.1" object-assign "^4.1.1" +cross-env@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-6.0.3.tgz#4256b71e49b3a40637a0ce70768a6ef5c72ae941" + integrity sha512-+KqxF6LCvfhWvADcDPqo64yVIB31gv/jQulX2NGzKS/g3GEVz6/pt4wjHFtFWsHMddebWD/sDthJemzM4MaAag== + dependencies: + cross-spawn "^7.0.0" + cross-spawn@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41" @@ -3191,6 +3274,15 @@ cross-spawn@^6.0.0, cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" +cross-spawn@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.1.tgz#0ab56286e0f7c24e153d04cc2aa027e43a9a5d14" + integrity sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + crypto-random-string@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" @@ -3206,52 +3298,52 @@ css-select-base-adapter@^0.1.1: resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w== -css-select@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.0.2.tgz#ab4386cec9e1f668855564b17c3733b43b2a5ede" - integrity sha512-dSpYaDVoWaELjvZ3mS6IKZM/y2PMPa/XYoEfYNZePL4U/XgyxZNroHEHReDx/d+VgXh9VbCTtFqLkFbmeqeaRQ== +css-select@^2.0.0, css-select@^2.0.2: + version "2.1.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.1.0.tgz#6a34653356635934a81baca68d0255432105dbef" + integrity sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ== dependencies: boolbase "^1.0.0" - css-what "^2.1.2" + css-what "^3.2.1" domutils "^1.7.0" nth-check "^1.0.2" css-to-react-native@^2.2.2: - version "2.3.1" - resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-2.3.1.tgz#cf0f61e0514846e2d4dc188b0886e29d8bef64a2" - integrity sha512-yO+oEx1Lf+hDKasqQRVrAvzMCz825Huh1VMlEEDlRWyAhFb/FWb6I0KpEF1PkyKQ7NEdcx9d5M2ZEWgJAsgPvQ== + version "2.3.2" + resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-2.3.2.tgz#e75e2f8f7aa385b4c3611c52b074b70a002f2e7d" + integrity sha512-VOFaeZA053BqvvvqIA8c9n0+9vFppVBAHCp6JgFTtTMU3Mzi+XnelJ9XC9ul3BqFzZyQ5N+H0SnwsWT2Ebchxw== dependencies: camelize "^1.0.0" css-color-keywords "^1.0.0" postcss-value-parser "^3.3.0" -css-tree@1.0.0-alpha.29: - version "1.0.0-alpha.29" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.29.tgz#3fa9d4ef3142cbd1c301e7664c1f352bd82f5a39" - integrity sha512-sRNb1XydwkW9IOci6iB2xmy8IGCj6r/fr+JWitvJ2JxQRPzN3T4AGGVWCMlVmVwM1gtgALJRmGIlWv5ppnGGkg== +css-tree@1.0.0-alpha.37: + version "1.0.0-alpha.37" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.37.tgz#98bebd62c4c1d9f960ec340cf9f7522e30709a22" + integrity sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg== dependencies: - mdn-data "~1.1.0" - source-map "^0.5.3" + mdn-data "2.0.4" + source-map "^0.6.1" -css-tree@1.0.0-alpha.33: - version "1.0.0-alpha.33" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.33.tgz#970e20e5a91f7a378ddd0fc58d0b6c8d4f3be93e" - integrity sha512-SPt57bh5nQnpsTBsx/IXbO14sRc9xXu5MtMAVuo0BaQQmyf0NupNPPSoMaqiAF5tDFafYsTkfeH4Q/HCKXkg4w== +css-tree@^1.0.0-alpha.37: + version "1.0.0-alpha.39" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.39.tgz#2bff3ffe1bb3f776cf7eefd91ee5cba77a149eeb" + integrity sha512-7UvkEYgBAHRG9Nt980lYxjsTrCyHFN53ky3wVsDkiMdVqylqRt+Zc+jm5qw7/qyOvN2dHSYtX0e4MbCCExSvnA== dependencies: - mdn-data "2.0.4" - source-map "^0.5.3" + mdn-data "2.0.6" + source-map "^0.6.1" -css-what@^2.1.2: - version "2.1.3" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" - integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== +css-what@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.2.1.tgz#f4a8f12421064621b456755e34a03a2c22df5da1" + integrity sha512-WwOrosiQTvyms+Ti5ZC5vGEK0Vod3FTt1ca+payZqvKuGJF+dq7bG63DstxtN0dpm6FxY27a/zS3Wten+gEtGw== -csso@^3.5.1: - version "3.5.1" - resolved "https://registry.yarnpkg.com/csso/-/csso-3.5.1.tgz#7b9eb8be61628973c1b261e169d2f024008e758b" - integrity sha512-vrqULLffYU1Q2tLdJvaCYbONStnfkfimRxXNaGjxMldI0C7JPBC4rB1RyjhfdZ4m1frm8pM9uRPKH3d2knZ8gg== +csso@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/csso/-/csso-4.0.2.tgz#e5f81ab3a56b8eefb7f0092ce7279329f454de3d" + integrity sha512-kS7/oeNVXkHWxby5tHVxlhjizRCSv8QdU7hB2FpdAibDU8FjTAolhNjKNTiLzXtUrKT6HwClE81yXwEk1309wg== dependencies: - css-tree "1.0.0-alpha.29" + css-tree "1.0.0-alpha.37" cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0": version "0.3.8" @@ -3277,6 +3369,14 @@ d64@^1.0.0: resolved "https://registry.yarnpkg.com/d64/-/d64-1.0.0.tgz#4002a87e850cbfc9f9d9706b60fca613a3336e90" integrity sha1-QAKofoUMv8n52XBrYPymE6MzbpA= +d@1, d@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" + integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== + dependencies: + es5-ext "^0.10.50" + type "^1.0.1" + dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" @@ -3289,12 +3389,10 @@ dashify@^2.0.0: resolved "https://registry.yarnpkg.com/dashify/-/dashify-2.0.0.tgz#fff270ca2868ca427fee571de35691d6e437a648" integrity sha512-hpA5C/YrPjucXypHPPc0oJ1l9Hf6wWbiOL7Ik42cxnsUOhWiCB/fylKbKqqJalW9FgkNQCw16YO8uW9Hs0Iy1A== -data-uri-to-buffer@2: - version "2.0.1" - resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-2.0.1.tgz#ca8f56fe38b1fd329473e9d1b4a9afcd8ce1c045" - integrity sha512-OkVVLrerfAKZlW2ZZ3Ve2y65jgiWqBKsTfUIAFbn8nVbPcCZg6l6gikKlEYv0kXcmzqGm6mFq/Jf2vriuEkv8A== - dependencies: - "@types/node" "^8.0.7" +data-uri-to-buffer@1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz#77163ea9c20d8641b4707e8f18abdf9a78f34835" + integrity sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ== data-urls@^1.0.0: version "1.1.0" @@ -3310,17 +3408,17 @@ date-fns@^1.30.1: resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw== -date-now@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" - integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs= +dayjs@^1.8.15: + version "1.8.19" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.8.19.tgz#5117dc390d8f8e586d53891dbff3fa308f51abfe" + integrity sha512-7kqOoj3oQSmqbvtvGFLU5iYqies+SqUiEGNT0UtUPPxcPYgY1BrkXR0Cq2R9HYSimBXN+xHkEN4Hi399W+Ovlg== debounce@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.0.tgz#44a540abc0ea9943018dc0eaa95cce87f65cd131" integrity sha512-mYtLl1xfZLi1m4RtQYlZgJUNQjl4ZxVnHzIR8nLLgi4q1YT8o/WM+MK/f8yfcc9s5Ir5zRaPZyZU6xs1Syoocg== -debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: +debug@2, debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -3334,14 +3432,14 @@ debug@3.1.0, debug@=3.1.0, debug@~3.1.0: dependencies: ms "2.0.0" -debug@3.2.6, debug@^3.1.0, debug@^3.2.6: +debug@3.2.6, debug@^3.1.0: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== dependencies: ms "^2.1.1" -debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: +debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@~4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== @@ -3367,9 +3465,16 @@ decode-uri-component@^0.2.0: integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= deep-equal@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" - integrity sha1-9dJgKStmDghO/0zbyfCK0yR0SLU= + version "1.1.1" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" + integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== + dependencies: + is-arguments "^1.0.4" + is-date-object "^1.0.1" + is-regex "^1.0.4" + object-is "^1.0.1" + object-keys "^1.1.1" + regexp.prototype.flags "^1.2.0" deep-extend@^0.6.0: version "0.6.0" @@ -3448,11 +3553,6 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= - denodeify@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/denodeify/-/denodeify-1.2.1.tgz#3a36287f5034e699e7577901052c2e6c94251631" @@ -3464,9 +3564,9 @@ depd@~1.1.2: integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= des.js@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" - integrity sha1-wHTS4qpqipoH29YfmhXCzYPsjsw= + version "1.0.1" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" + integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== dependencies: inherits "^2.0.1" minimalistic-assert "^1.0.0" @@ -3476,11 +3576,6 @@ destroy@~1.0.4: resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= -detect-libc@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= - detect-newline@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" @@ -3512,10 +3607,10 @@ detox@^12.8.0: yargs "^13.0.0" yargs-parser "^13.0.0" -diff-sequences@^24.3.0: - version "24.3.0" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.3.0.tgz#0f20e8a1df1abddaf4d9c226680952e64118b975" - integrity sha512-xLqpez+Zj9GKSnPWS0WZw1igGocZ+uua8+y+5dDNTT934N3QuY1sp2LkHzwiaYQGz60hMq0pjAshdeXm5VUOEw== +diff-sequences@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.9.0.tgz#5715d6244e2aa65f48bba0bc972db0b0b11e95b5" + integrity sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew== diff@3.5.0: version "3.5.0" @@ -3571,12 +3666,12 @@ doctrine@^3.0.0: esutils "^2.0.2" dom-serializer@0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.1.tgz#1ec4059e284babed36eec2941d4a970a189ce7c0" - integrity sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA== + version "0.2.2" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" + integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== dependencies: - domelementtype "^1.3.0" - entities "^1.1.1" + domelementtype "^2.0.1" + entities "^2.0.0" dom-walk@^0.1.0: version "0.1.1" @@ -3588,11 +3683,16 @@ domain-browser@^1.2.0: resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== -domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1: +domelementtype@1, domelementtype@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== +domelementtype@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" + integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ== + domexception@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" @@ -3628,11 +3728,11 @@ dotenv@^2.0.0: integrity sha1-vXWcNXqqcDZeAclrewvsCKbg2Uk= dtrace-provider@~0.8: - version "0.8.7" - resolved "https://registry.yarnpkg.com/dtrace-provider/-/dtrace-provider-0.8.7.tgz#dc939b4d3e0620cfe0c1cd803d0d2d7ed04ffd04" - integrity sha1-3JObTT4GIM/gwc2APQ0tftBP/QQ= + version "0.8.8" + resolved "https://registry.yarnpkg.com/dtrace-provider/-/dtrace-provider-0.8.8.tgz#2996d5490c37e1347be263b423ed7b297fb0d97e" + integrity sha512-b7Z7cNtHPhH9EJhNNbbeqTcXB8LGFFZhq1PGgEvpeHlzd36bhbdTWoE/Ba/YguqpBSlAPKnARWhVlhunCMwfxg== dependencies: - nan "^2.10.0" + nan "^2.14.0" duplexer3@^0.1.4: version "0.1.4" @@ -3652,25 +3752,20 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= -electron-to-chromium@^1.3.191: - version "1.3.205" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.205.tgz#084835a5ecca0765a805acb50a0fddc23d8d530e" - integrity sha512-VV+f2FVeFI5D/slUD7A3V1lTMDkQTUGWYH2dZGAijIutN5Aga4Fn/Hv4Gc+60OpXFVLYIq5HpXb2cG6NrGGQaA== +ejs@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.0.1.tgz#30c8f6ee9948502cc32e85c37a3f8b39b5a614a5" + integrity sha512-cuIMtJwxvzumSAkqaaoGY/L6Fc/t6YvoP9/VIaK0V/CyqKLEQ8sqODmYfy/cjXEdZ9+OOL8TecbJu+1RsofGDw== -elliptic@6.3.3: - version "6.3.3" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.3.3.tgz#5482d9646d54bcb89fd7d994fc9e2e9568876e3f" - integrity sha1-VILZZG1UvLif19mU/J4ulWiHbj8= - dependencies: - bn.js "^4.4.0" - brorand "^1.0.1" - hash.js "^1.0.0" - inherits "^2.0.1" +electron-to-chromium@^1.3.322: + version "1.3.327" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.327.tgz#516f28b4271727004362b4ac814494ae64d9dde7" + integrity sha512-DNMd91VtKt44LIkFtpICxAWu/GSGFLUMDM/kFINJ3Oe47OimSnbMvO3ChkUCdUyit+pRdhdCcM3+i5bpli5gqg== -elliptic@^6.0.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.0.tgz#2b8ed4c891b7de3200e14412a5b8248c7af505ca" - integrity sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg== +elliptic@6.5.2, elliptic@^6.0.0: + version "6.5.2" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.2.tgz#05c5678d7173c049d8ca433552224a495d0e3762" + integrity sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw== dependencies: bn.js "^4.4.0" brorand "^1.0.1" @@ -3703,21 +3798,21 @@ encoding@^0.1.11: iconv-lite "~0.4.13" end-of-stream@^1.1.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" - integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== dependencies: once "^1.4.0" -engine.io-client@~3.3.1: - version "3.3.2" - resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.3.2.tgz#04e068798d75beda14375a264bb3d742d7bc33aa" - integrity sha512-y0CPINnhMvPuwtqXfsGuWE8BB66+B6wTtCofQDRecMQPYX3MYUZXFNKDhdrSe3EVjgOu4V3rxdeqN/Tr91IgbQ== +engine.io-client@~3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.4.0.tgz#82a642b42862a9b3f7a188f41776b2deab643700" + integrity sha512-a4J5QO2k99CM2a0b12IznnyQndoEvtA4UAldhGzKqnHf42I3Qs2W5SPnDvatZRcMaNZs4IevVicBPayxYt6FwA== dependencies: component-emitter "1.2.1" component-inherit "0.0.3" - debug "~3.1.0" - engine.io-parser "~2.1.1" + debug "~4.1.0" + engine.io-parser "~2.2.0" has-cors "1.1.0" indexof "0.0.1" parseqs "0.0.5" @@ -3726,10 +3821,10 @@ engine.io-client@~3.3.1: xmlhttprequest-ssl "~1.5.4" yeast "0.1.2" -engine.io-parser@~2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.1.3.tgz#757ab970fbf2dfb32c7b74b033216d5739ef79a6" - integrity sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA== +engine.io-parser@~2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.2.0.tgz#312c4894f57d52a02b420868da7b5c1c84af80ed" + integrity sha512-6I3qD9iUxotsC5HEMuuGsKA0cXerGz+4uGcXQEkfBidgKf0amsjrrtwcbwK/nzpZBxclXlV7gGl9dgWvu4LF6w== dependencies: after "0.8.2" arraybuffer.slice "~0.0.7" @@ -3742,15 +3837,15 @@ entities@^1.1.1: resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== -envinfo@^5.7.0: - version "5.12.1" - resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-5.12.1.tgz#83068c33e0972eb657d6bc69a6df30badefb46ef" - integrity sha512-pwdo0/G3CIkQ0y6PCXq4RdkvId2elvtPCJMG0konqlrfkWQbf1DWeH9K2b/cvu2YgGvPPTOnonZxXM1gikFu1w== +entities@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" + integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== envinfo@^7.1.0: - version "7.3.1" - resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.3.1.tgz#892e42f7bf858b3446d9414ad240dbaf8da52f09" - integrity sha512-GvXiDTqLYrORVSCuJCsWHPXF5BFvoWMQA9xX4YVjPT1jyS3aZEHUBwjzxU/6LTPF9ReHgVEbX7IEN5UvSXHw/A== + version "7.5.0" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.5.0.tgz#91410bb6db262fb4f1409bd506e9ff57e91023f4" + integrity sha512-jDgnJaF/Btomk+m3PZDTTCb5XIIIX3zYItnCRfF73zVgvinLoRomuhi75Y4su0PtQxWz4v66XnLLckyvyJTOIQ== errno@^0.1.1, errno@~0.1.1: version "0.1.7" @@ -3766,6 +3861,13 @@ error-ex@^1.2.0, error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" +error-stack-parser@^2.0.4: + version "2.0.6" + resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.0.6.tgz#5a99a707bd7a4c58a797902d48d82803ede6aad8" + integrity sha512-d51brTeqC+BHlwF0BhPtcYgF5nlzf9ZZ0ZIUQNZpc9ZB9qw5IJ2diTrBY9jlCJkTLITYPjmiX6OWCwH+fuyNgQ== + dependencies: + stackframe "^1.1.1" + errorhandler@^1.5.0: version "1.5.1" resolved "https://registry.yarnpkg.com/errorhandler/-/errorhandler-1.5.1.tgz#b9ba5d17cf90744cd1e851357a6e75bf806a9a91" @@ -3774,27 +3876,50 @@ errorhandler@^1.5.0: accepts "~1.3.7" escape-html "~1.0.3" -es-abstract@^1.11.0, es-abstract@^1.12.0, es-abstract@^1.5.1, es-abstract@^1.7.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" - integrity sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg== +es-abstract@^1.17.0, es-abstract@^1.17.0-next.1: + version "1.17.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.0.tgz#f42a517d0036a5591dbb2c463591dc8bb50309b1" + integrity sha512-yYkE07YF+6SIBmg1MsJ9dlub5L48Ek7X0qz+c/CPCHS9EBXfESorzng4cJQjJW5/pB6vDF41u7F8vUhLVDqIug== dependencies: - es-to-primitive "^1.2.0" + es-to-primitive "^1.2.1" function-bind "^1.1.1" has "^1.0.3" - is-callable "^1.1.4" - is-regex "^1.0.4" - object-keys "^1.0.12" + has-symbols "^1.0.1" + is-callable "^1.1.5" + is-regex "^1.0.5" + object-inspect "^1.7.0" + object-keys "^1.1.1" + object.assign "^4.1.0" + string.prototype.trimleft "^2.1.1" + string.prototype.trimright "^2.1.1" -es-to-primitive@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" - integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== dependencies: is-callable "^1.1.4" is-date-object "^1.0.1" is-symbol "^1.0.2" +es5-ext@^0.10.35, es5-ext@^0.10.50: + version "0.10.53" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1" + integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q== + dependencies: + es6-iterator "~2.0.3" + es6-symbol "~3.1.3" + next-tick "~1.0.0" + +es6-iterator@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + es6-promise@^4.0.3: version "4.2.8" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" @@ -3807,7 +3932,15 @@ es6-promisify@^5.0.0: dependencies: es6-promise "^4.0.3" -escape-html@~1.0.3: +es6-symbol@^3, es6-symbol@^3.1.1, es6-symbol@~3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" + integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== + dependencies: + d "^1.0.1" + ext "^1.1.2" + +escape-html@^1.0.3, escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= @@ -3818,9 +3951,9 @@ escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1 integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= escodegen@1.x.x, escodegen@^1.9.1: - version "1.11.1" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.11.1.tgz#c485ff8d6b4cdb89e27f4a856e91f118401ca510" - integrity sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw== + version "1.12.1" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.12.1.tgz#08770602a74ac34c7a90ca9229e7d51e379abc76" + integrity sha512-Q8t2YZ+0e0pc7NRVj3B4tSQ9rim1oi4Fh46k2xhJ2qOiEwhQfdjyEQddWdj7ZFaKmU+5104vn1qrcjEPWq+bgQ== dependencies: esprima "^3.1.3" estraverse "^4.2.0" @@ -3829,16 +3962,35 @@ escodegen@1.x.x, escodegen@^1.9.1: optionalDependencies: source-map "~0.6.1" -eslint-config-airbnb-base@^13.1.0: - version "13.2.0" - resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-13.2.0.tgz#f6ea81459ff4dec2dda200c35f1d8f7419d57943" - integrity sha512-1mg/7eoB4AUeB0X1c/ho4vb2gYkNH8Trr/EgCT/aGmKhhG+F6vF5s8+iRBlWAzFIAphxIdp3YfEKgEl0f9Xg+w== +eslint-config-prettier@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-4.3.0.tgz#c55c1fcac8ce4518aeb77906984e134d9eb5a4f0" + integrity sha512-sZwhSTHVVz78+kYD3t5pCWSYEdVSBR0PXnwjDRsUs8ytIrK8PLXw+6FKp8r3Z7rx4ZszdetWlXYKOHoUrrwPlA== dependencies: - confusing-browser-globals "^1.0.5" - object.assign "^4.1.0" - object.entries "^1.1.0" + get-stdin "^6.0.0" -eslint-import-resolver-node@^0.3.1, eslint-import-resolver-node@^0.3.2: +eslint-config-satya164@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/eslint-config-satya164/-/eslint-config-satya164-2.4.1.tgz#139909a590d4503197d501051deef9aa67768990" + integrity sha512-i9fqMDq4XywgRrcYdaPwmv/i+FtGI1FTXz9yKb4JktlWnU555cxmryFDknNJJj9cL06RR5a/O5hnJSoLksGWbQ== + dependencies: + "@typescript-eslint/eslint-plugin" "^1.6.0" + "@typescript-eslint/parser" "^1.6.0" + babel-eslint "^10.0.1" + eslint-config-prettier "^4.1.0" + eslint-plugin-babel "^5.3.0" + eslint-plugin-eslint-comments "^3.1.1" + eslint-plugin-flowtype "^3.6.1" + eslint-plugin-import "^2.16.0" + eslint-plugin-jest "^22.4.1" + eslint-plugin-json "^1.4.0" + eslint-plugin-markdown "^1.0.0" + eslint-plugin-prettier "^3.0.1" + eslint-plugin-react "^7.12.4" + eslint-plugin-react-hooks "^1.6.0" + eslint-plugin-react-native "^3.6.0" + +eslint-import-resolver-node@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a" integrity sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q== @@ -3846,14 +3998,21 @@ eslint-import-resolver-node@^0.3.1, eslint-import-resolver-node@^0.3.2: debug "^2.6.9" resolve "^1.5.0" -eslint-module-utils@^2.2.0, eslint-module-utils@^2.4.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.4.1.tgz#7b4675875bf96b0dbf1b21977456e5bb1f5e018c" - integrity sha512-H6DOj+ejw7Tesdgbfs4jeS4YMFrT8uI8xwd1gtQqXssaR0EQ26L+2O/w6wkYFy2MymON0fTwHmXBvvfLNZVZEw== +eslint-module-utils@^2.2.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.5.0.tgz#cdf0b40d623032274ccd2abd7e64c4e524d6e19c" + integrity sha512-kCo8pZaNz2dsAW7nCUjuVoI11EBXXpIzfNxmaoLhXoRDOnqXLC4iSGVRdZPhOitfbdEfMEfKOiENaK6wDPZEGw== dependencies: - debug "^2.6.8" + debug "^2.6.9" pkg-dir "^2.0.0" +eslint-plugin-babel@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-babel/-/eslint-plugin-babel-5.3.0.tgz#2e7f251ccc249326da760c1a4c948a91c32d0023" + integrity sha512-HPuNzSPE75O+SnxHIafbW5QB45r2w78fxqwK3HmjqIUoPfPzVrq6rD+CINU3yzoDSzEhUkX07VUphbF73Lth/w== + dependencies: + eslint-rule-composer "^0.3.0" + eslint-plugin-eslint-comments@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-3.1.2.tgz#4ef6c488dbe06aa1627fea107b3e5d059fc8a395" @@ -3862,14 +4021,19 @@ eslint-plugin-eslint-comments@^3.1.1: escape-string-regexp "^1.0.5" ignore "^5.0.5" -eslint-plugin-flowtype@2.50.3: - version "2.50.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.50.3.tgz#61379d6dce1d010370acd6681740fd913d68175f" - integrity sha512-X+AoKVOr7Re0ko/yEXyM5SSZ0tazc6ffdIOocp2fFUlWoDt7DV0Bz99mngOkAFLOAWjqRA5jPwqUCbrx13XoxQ== +eslint-plugin-eslint-plugin@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-eslint-plugin/-/eslint-plugin-eslint-plugin-2.1.0.tgz#a7a00f15a886957d855feacaafee264f039e62d5" + integrity sha512-kT3A/ZJftt28gbl/Cv04qezb/NQ1dwYIbi8lyf806XMxkus7DvOVCLIfTXMrorp322Pnoez7+zabXH29tADIDg== + +eslint-plugin-flowtype@^3.6.1: + version "3.13.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-3.13.0.tgz#e241ebd39c0ce519345a3f074ec1ebde4cf80f2c" + integrity sha512-bhewp36P+t7cEV0b6OdmoRWJCBYRiHFlqPZAG1oS3SF+Y0LQkeDvFSM4oxoxvczD1OdONCXMlJfQFiWLcV9urw== dependencies: - lodash "^4.17.10" + lodash "^4.17.15" -eslint-plugin-import@2.14.0: +eslint-plugin-import@2.14.0, eslint-plugin-import@^2.16.0: version "2.14.0" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz#6b17626d2e3e6ad52cfce8807a845d15e22111a8" integrity sha512-FpuRtniD/AY6sXByma2Wr0TXvXJ4nA/2/04VPlfpmUDPOpOY264x+ILiwnrk/k4RINgDAyFZByxqPUbSQ5YE7g== @@ -3885,102 +4049,82 @@ eslint-plugin-import@2.14.0: read-pkg-up "^2.0.0" resolve "^1.6.0" -eslint-plugin-import@^2.14.0: - version "2.18.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz#02f1180b90b077b33d447a17a2326ceb400aceb6" - integrity sha512-5ohpsHAiUBRNaBWAF08izwUGlbrJoJJ+W9/TBwsGoR1MnlgfwMIKrFeSjWbt6moabiXW9xNvtFz+97KHRfI4HQ== +eslint-plugin-jest@^22.4.1: + version "22.21.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-22.21.0.tgz#8137294645866636160487d9764224b9a43e2eb1" + integrity sha512-OaqnSS7uBgcGiqXUiEnjoqxPNKvR4JWG5mSRkzVoR6+vDwlqqp11beeql1hYs0HTbdhiwrxWLxbX0Vx7roG3Ew== dependencies: - array-includes "^3.0.3" - contains-path "^0.1.0" - debug "^2.6.9" - doctrine "1.5.0" - eslint-import-resolver-node "^0.3.2" - eslint-module-utils "^2.4.0" - has "^1.0.3" - minimatch "^3.0.4" - object.values "^1.1.0" - read-pkg-up "^2.0.0" - resolve "^1.11.0" + "@typescript-eslint/experimental-utils" "^1.13.0" -eslint-plugin-jest@22.4.1: - version "22.4.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-22.4.1.tgz#a5fd6f7a2a41388d16f527073b778013c5189a9c" - integrity sha512-gcLfn6P2PrFAVx3AobaOzlIEevpAEf9chTpFZz7bYfc7pz8XRv7vuKTIE4hxPKZSha6XWKKplDQ0x9Pq8xX2mg== +eslint-plugin-json@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-json/-/eslint-plugin-json-1.4.0.tgz#4d29f3a4c08d412df739bd65049ce23636515af8" + integrity sha512-CECvgRAWtUzuepdlPWd+VA7fhyF9HT183pZnl8wQw5x699Mk/MbME/q8xtULBfooi3LUbj6fToieNmsvUcDxWA== + dependencies: + vscode-json-languageservice "^3.2.1" -eslint-plugin-prettier@2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-2.6.2.tgz#71998c60aedfa2141f7bfcbf9d1c459bf98b4fad" - integrity sha512-tGek5clmW5swrAx1mdPYM8oThrBE83ePh7LeseZHBWfHVGrHPhKn7Y5zgRMbU/9D5Td9K4CEmUPjGxA7iw98Og== +eslint-plugin-markdown@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-markdown/-/eslint-plugin-markdown-1.0.1.tgz#9705786310f84dad9cf800bea1eb5c4acafcc13a" + integrity sha512-nAUURNHJGPooBMZMP23FmTbh3LTdgoSqeFBv9FA3fYrJ+vDUJxrp6nKiQF4iDNAmnWQnmnrDvV61BmIF4X9QAQ== dependencies: - fast-diff "^1.1.1" - jest-docblock "^21.0.0" + object-assign "^4.0.1" + remark-parse "^5.0.0" + unified "^6.1.2" -eslint-plugin-react-hooks@^1.5.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-1.6.1.tgz#3c66a5515ea3e0a221ffc5d4e75c971c217b1a4c" - integrity sha512-wHhmGJyVuijnYIJXZJHDUF2WM+rJYTjulUTqF9k61d3BTk8etydz+M4dXUVH7M76ZRS85rqBTCx0Es/lLsrjnA== +eslint-plugin-prettier@^3.0.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.2.tgz#432e5a667666ab84ce72f945c72f77d996a5c9ba" + integrity sha512-GlolCC9y3XZfv3RQfwGew7NnuFDKsfI4lbvRK+PIIo23SFH+LemGs4cKwzAaRa+Mdb+lQO/STaIayno8T5sJJA== + dependencies: + prettier-linter-helpers "^1.0.0" -eslint-plugin-react-native-animation-linter@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-native-animation-linter/-/eslint-plugin-react-native-animation-linter-0.1.2.tgz#07edd97544f5db7e04c640480d3683e99d264ff1" - integrity sha512-BYIzn3/CP95Wm7pMS6+hJjFZpWwFR4qzOwCdGZaAAQqdbGhQWX2GnsaWQwWKq/FKOhZHdQ4cpmEaFcwzoEamqA== +eslint-plugin-react-hooks@^1.6.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-1.7.0.tgz#6210b6d5a37205f0b92858f895a4e827020a7d04" + integrity sha512-iXTCFcOmlWvw4+TOE8CLWj6yX1GwzT0Y6cUfHHZqWnSk144VmVIRcVGtUAzrLES7C798lmvnt02C7rxaOX1HNA== eslint-plugin-react-native-globals@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/eslint-plugin-react-native-globals/-/eslint-plugin-react-native-globals-0.1.2.tgz#ee1348bc2ceb912303ce6bdbd22e2f045ea86ea2" integrity sha512-9aEPf1JEpiTjcFAmmyw8eiIXmcNZOqaZyHO77wgm0/dWfT/oxC1SrIq8ET38pMxHYrcB6Uew+TzUVsBeczF88g== -eslint-plugin-react-native@3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-native/-/eslint-plugin-react-native-3.6.0.tgz#7cad3b7c6159df6d26fe3252c6c5417a17f27b4b" - integrity sha512-BEQcHZ06hZSBYWFVuNEq0xuui5VEsWpHDsZGBtfadHfCRqRMUrkYPgdDb3bpc60qShHE83kqIv59uKdinEg91Q== +eslint-plugin-react-native@^3.6.0: + version "3.8.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-native/-/eslint-plugin-react-native-3.8.1.tgz#92811e37191ecb0d29c0f0a0c9e5c943ee573821" + integrity sha512-6Z4s4nvgFRdda/1s1+uu4a6EMZwEjjJ9Bk/1yBImv0fd9U2CsGu2cUakAtV83cZKhizbWhSouXoaK4JtlScdFg== dependencies: eslint-plugin-react-native-globals "^0.1.1" -eslint-plugin-react-native@^3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-native/-/eslint-plugin-react-native-3.7.0.tgz#7e2cc1f3cf24919c4c0ea7fac13301e7444e105f" - integrity sha512-krLtQmGih/uJDPxF8DBpnU8J3kRUsDm/Dey5yEhOO8LN1I3Wesbk4PGCg8Zah57azKFU+9YtGooFjJcDJWUs+g== - dependencies: - eslint-plugin-react-native-globals "^0.1.1" - -eslint-plugin-react@7.12.4: - version "7.12.4" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.12.4.tgz#b1ecf26479d61aee650da612e425c53a99f48c8c" - integrity sha512-1puHJkXJY+oS1t467MjbqjvX53uQ05HXwjqDgdbGBqf5j9eeydI54G3KwiJmWciQ0HTBacIKw2jgwSBSH3yfgQ== - dependencies: - array-includes "^3.0.3" - doctrine "^2.1.0" - has "^1.0.3" - jsx-ast-utils "^2.0.1" - object.fromentries "^2.0.0" - prop-types "^15.6.2" - resolve "^1.9.0" - -eslint-plugin-react@^7.13.0: - version "7.14.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.14.3.tgz#911030dd7e98ba49e1b2208599571846a66bdf13" - integrity sha512-EzdyyBWC4Uz2hPYBiEJrKCUi2Fn+BJ9B/pJQcjw5X+x/H2Nm59S4MJIvL4O5NEE0+WbnQwEBxWY03oUk+Bc3FA== +eslint-plugin-react@^7.12.4: + version "7.17.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.17.0.tgz#a31b3e134b76046abe3cd278e7482bd35a1d12d7" + integrity sha512-ODB7yg6lxhBVMeiH1c7E95FLD4E/TwmFjltiU+ethv7KPdCwgiFuOZg9zNRHyufStTDLl/dEFqI2Q1VPmCd78A== dependencies: array-includes "^3.0.3" doctrine "^2.1.0" + eslint-plugin-eslint-plugin "^2.1.0" has "^1.0.3" - jsx-ast-utils "^2.1.0" + jsx-ast-utils "^2.2.3" object.entries "^1.1.0" - object.fromentries "^2.0.0" + object.fromentries "^2.0.1" object.values "^1.1.0" prop-types "^15.7.2" - resolve "^1.10.1" + resolve "^1.13.1" -eslint-scope@3.7.1: - version "3.7.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8" - integrity sha1-PWPD7f2gLgbgGkUq2IyqzHzctug= +eslint-plugin-relay@1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-relay/-/eslint-plugin-relay-1.4.1.tgz#5af2ac13e24bd01ad17b6a4014204918d65021cd" + integrity sha512-yb+p+4AxZTi2gXN7cZRfXMBFlRa5j6TtiVeq3yHXyy+tlgYNpxi/dDrP1+tcUTNP9vdaJovnfGZ5jp6kMiH9eg== dependencies: - esrecurse "^4.1.0" - estraverse "^4.1.1" + graphql "^14.0.0" + +eslint-rule-composer@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz#79320c927b0c5c0d3d3d2b76c8b4a488f25bbaf9" + integrity sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg== -eslint-scope@^4.0.0, eslint-scope@^4.0.3: +eslint-scope@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== @@ -3988,68 +4132,77 @@ eslint-scope@^4.0.0, eslint-scope@^4.0.3: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-utils@^1.3.1: - version "1.4.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.0.tgz#e2c3c8dba768425f897cf0f9e51fe2e241485d4c" - integrity sha512-7ehnzPaP5IIEh1r1tkjuIrxqhNkzUJa9z3R92tLJdZIVdWaczEhr3EbhGtsMrVxi1KeR8qA7Off6SWc5WNQqyQ== +eslint-scope@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9" + integrity sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw== dependencies: - eslint-visitor-keys "^1.0.0" + esrecurse "^4.1.0" + estraverse "^4.1.1" -eslint-visitor-keys@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" - integrity sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ== +eslint-utils@^1.3.1, eslint-utils@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" + integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== + dependencies: + eslint-visitor-keys "^1.1.0" + +eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" + integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== -eslint@^5.16.0: - version "5.16.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" - integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg== +eslint@^6.6.0: + version "6.8.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb" + integrity sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig== dependencies: "@babel/code-frame" "^7.0.0" - ajv "^6.9.1" + ajv "^6.10.0" chalk "^2.1.0" cross-spawn "^6.0.5" debug "^4.0.1" doctrine "^3.0.0" - eslint-scope "^4.0.3" - eslint-utils "^1.3.1" - eslint-visitor-keys "^1.0.0" - espree "^5.0.1" + eslint-scope "^5.0.0" + eslint-utils "^1.4.3" + eslint-visitor-keys "^1.1.0" + espree "^6.1.2" esquery "^1.0.1" esutils "^2.0.2" file-entry-cache "^5.0.1" functional-red-black-tree "^1.0.1" - glob "^7.1.2" - globals "^11.7.0" + glob-parent "^5.0.0" + globals "^12.1.0" ignore "^4.0.6" import-fresh "^3.0.0" imurmurhash "^0.1.4" - inquirer "^6.2.2" - js-yaml "^3.13.0" + inquirer "^7.0.0" + is-glob "^4.0.0" + js-yaml "^3.13.1" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.3.0" - lodash "^4.17.11" + lodash "^4.17.14" minimatch "^3.0.4" mkdirp "^0.5.1" natural-compare "^1.4.0" - optionator "^0.8.2" - path-is-inside "^1.0.2" + optionator "^0.8.3" progress "^2.0.0" regexpp "^2.0.1" - semver "^5.5.1" - strip-ansi "^4.0.0" - strip-json-comments "^2.0.1" + semver "^6.1.2" + strip-ansi "^5.2.0" + strip-json-comments "^3.0.1" table "^5.2.3" text-table "^0.2.0" + v8-compile-cache "^2.0.3" -espree@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a" - integrity sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A== +espree@^6.1.2: + version "6.1.2" + resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.2.tgz#6c272650932b4f91c3714e5e7b5f5e2ecf47262d" + integrity sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA== dependencies: - acorn "^6.0.7" - acorn-jsx "^5.0.0" - eslint-visitor-keys "^1.0.0" + acorn "^7.1.0" + acorn-jsx "^5.1.0" + eslint-visitor-keys "^1.1.0" esprima@3.x.x, esprima@^3.1.3: version "3.1.3" @@ -4076,34 +4229,33 @@ esrecurse@^4.1.0: estraverse "^4.1.0" estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" - integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== esutils@^2.0.0, esutils@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" - integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs= + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= -eth-contract-metadata@^1.9.2: - version "1.9.2" - resolved "https://registry.yarnpkg.com/eth-contract-metadata/-/eth-contract-metadata-1.9.2.tgz#6c23383e35de1014c1c00f2c8c787cd48d54ae20" - integrity sha512-2ycmqRQ9u4Tbpir7hwEKZ8Qjy1bc3KaiRBd/jkL8Xye9wqnYMpgaUK4UHPm1uTnCZZ+KoN0Mxg6kL9JILrYdhA== +eth-contract-metadata@^1.9.3: + version "1.11.0" + resolved "https://registry.yarnpkg.com/eth-contract-metadata/-/eth-contract-metadata-1.11.0.tgz#4d23a8208d5d53be9d4c0696ed8492b505c6bca1" + integrity sha512-Bbvio71M+lH+qXd8XXddpTc8hhjL9m4fNPOxmZFIX8z0/VooUdwV8YmmDAbkU5WVioZi+Jp1XaoO7VwzXnDboA== -ethers@^4.0.33: - version "4.0.33" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.33.tgz#f7b88d2419d731a39aefc37843a3f293e396f918" - integrity sha512-lAHkSPzBe0Vj+JrhmkEHLtUEKEheVktIjGDyE9gbzF4zf1vibjYgB57LraDHu4/ItqWVkztgsm8GWqcDMN+6vQ== +ethers@^4.0.28, ethers@^4.0.39: + version "4.0.42" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.42.tgz#7def83a1f770b84d44cf1c2dfc58b7fd29d1d45d" + integrity sha512-2gmmt5x683Xz4QwGDBVJhrdXevVAEr5fnXPGDPou2AKB+zklrirGpl0w1SHBn7Wa9hbL2z6MvP3n7k8Yss2MFg== dependencies: - "@types/node" "^10.3.2" aes-js "3.0.0" bn.js "^4.4.0" - elliptic "6.3.3" + elliptic "6.5.2" hash.js "1.1.3" js-sha3 "0.5.7" scrypt-js "2.0.4" @@ -4111,10 +4263,10 @@ ethers@^4.0.33: uuid "2.0.1" xmlhttprequest "1.8.0" -event-target-shim@^1.0.5: - version "1.1.1" - resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-1.1.1.tgz#a86e5ee6bdaa16054475da797ccddf0c55698491" - integrity sha1-qG5e5r2qFgVEddp5fM3fDFVphJE= +event-target-shim@^5.0.0, event-target-shim@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== eventemitter3@^3.0.0: version "3.1.2" @@ -4141,17 +4293,10 @@ exception-formatter@^1.0.4: dependencies: colors "^1.0.3" -exec-sh@^0.2.0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.2.2.tgz#2a5e7ffcbd7d0ba2755bdecb16e5a427dfbdec36" - integrity sha512-FIUCJz1RbuS0FKTdaAafAByGS0CPvU3R0MeHxgtl+djzCc//F8HakL8GzmVNZanasTbTAY/3DRFA0KpVqj/eAw== - dependencies: - merge "^1.2.0" - exec-sh@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.2.tgz#6738de2eb7c8e671d0366aea0b0db8c6f7d7391b" - integrity sha512-9sLAvzhI5nc8TpuQUh4ahMdCrWT00wPWz7j47/emR5+2qEfoZP5zzUXvx+vdx+H6ohhnsYC31iX04QLYJK8zTg== + version "0.3.4" + resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.4.tgz#3a018ceb526cc6f6df2bb504b2bfe8e3a4934ec5" + integrity sha512-sEFIkc61v75sWeOe72qyrqg2Qg0OuLESziUDk/O/z2qgS15y2gWVFrI6f2Qn/qw/0/NCfCEsmNA4zOjkwEZT1A== execa@^0.7.0: version "0.7.0" @@ -4179,6 +4324,22 @@ execa@^1.0.0: signal-exit "^3.0.0" strip-eof "^1.0.0" +execa@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-3.4.0.tgz#c08ed4550ef65d858fac269ffc8572446f37eb89" + integrity sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g== + dependencies: + cross-spawn "^7.0.0" + get-stream "^5.0.0" + human-signals "^1.1.1" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.0" + onetime "^5.1.0" + p-finally "^2.0.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" + execall@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/execall/-/execall-2.0.0.tgz#16a06b5fe5099df7d00be5d9c06eecded1663b45" @@ -4196,13 +4357,6 @@ exit@^0.1.2: resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= -expand-brackets@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" - integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s= - dependencies: - is-posix-bracket "^0.1.0" - expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" @@ -4216,24 +4370,24 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -expand-range@^1.8.1: - version "1.8.2" - resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" - integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc= +expect@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-24.9.0.tgz#b75165b4817074fa4a157794f46fe9f1ba15b6ca" + integrity sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q== dependencies: - fill-range "^2.1.0" + "@jest/types" "^24.9.0" + ansi-styles "^3.2.0" + jest-get-type "^24.9.0" + jest-matcher-utils "^24.9.0" + jest-message-util "^24.9.0" + jest-regex-util "^24.9.0" -expect@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-24.8.0.tgz#471f8ec256b7b6129ca2524b2a62f030df38718d" - integrity sha512-/zYvP8iMDrzaaxHVa724eJBCKqSHmO0FA7EDkBiRHxg6OipmMn1fN+C8T9L9K8yr7UONkOifu6+LLH+z76CnaA== +ext@^1.1.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.4.0.tgz#89ae7a07158f79d35517882904324077e4379244" + integrity sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A== dependencies: - "@jest/types" "^24.8.0" - ansi-styles "^3.2.0" - jest-get-type "^24.8.0" - jest-matcher-utils "^24.8.0" - jest-message-util "^24.8.0" - jest-regex-util "^24.3.0" + type "^2.0.0" extend-shallow@^1.1.2: version "1.1.4" @@ -4289,13 +4443,6 @@ external-editor@^3.0.3: iconv-lite "^0.4.24" tmp "^0.0.33" -extglob@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" - integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE= - dependencies: - is-extglob "^1.0.0" - extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" @@ -4335,7 +4482,7 @@ fast-deep-equal@^2.0.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= -fast-diff@^1.1.1: +fast-diff@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== @@ -4353,33 +4500,33 @@ fast-glob@^2.2.6: micromatch "^3.1.10" fast-json-stable-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fast-levenshtein@~2.0.4: +fast-levenshtein@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= -fast-safe-stringify@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.6.tgz#04b26106cc56681f51a044cfc0d76cf0008ac2c2" - integrity sha512-q8BZ89jjc+mz08rSxROs8VsrBBcn1SIw1kq9NjolL509tkABRk9io01RAjSaEv1Xb2uFLt8VtRiZbGp5H8iDtg== +fast-safe-stringify@^2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz#124aa885899261f68aedb42a7c080de9da608743" + integrity sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA== fb-watchman@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58" - integrity sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg= + version "2.0.1" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" + integrity sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg== dependencies: - bser "^2.0.0" + bser "2.1.1" fbjs-css-vars@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz#216551136ae02fe255932c3ec8775f18e2c078b8" integrity sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ== -fbjs-scripts@^1.0.0: +fbjs-scripts@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/fbjs-scripts/-/fbjs-scripts-1.2.0.tgz#069a0c0634242d10031c6460ef1fccefcdae8b27" integrity sha512-5krZ8T0Bf8uky0abPoCLrfa7Orxd8UH4Qq8hRUF2RZYNMu+FmEOrBc7Ib3YVONmxTXTlLAvyrrdrVmksDb2OqQ== @@ -4437,6 +4584,13 @@ figures@^2.0.0: dependencies: escape-string-regexp "^1.0.5" +figures@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-3.1.0.tgz#4b198dd07d8d71530642864af2d45dd9e459c4ec" + integrity sha512-ravh8VRXqHuMvZt/d8GblBeqDMkdJMBdv/2KntFH+ra5MXkO7nxNKpzQ3n6QD/2da1kH0aWmNISdvhM7gl2gVg== + dependencies: + escape-string-regexp "^1.0.5" + file-entry-cache@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" @@ -4444,27 +4598,11 @@ file-entry-cache@^5.0.1: dependencies: flat-cache "^2.0.1" -file-uri-to-path@1: +file-uri-to-path@1, file-uri-to-path@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== -filename-regex@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" - integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY= - -fill-range@^2.1.0: - version "2.2.4" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" - integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q== - dependencies: - is-number "^2.1.0" - isobject "^2.0.0" - randomatic "^3.0.0" - repeat-element "^1.1.2" - repeat-string "^1.5.2" - fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" @@ -4518,6 +4656,14 @@ find-up@^2.0.0, find-up@^2.1.0: dependencies: locate-path "^2.0.0" +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + find-yarn-workspace-root@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz#40eb8e6e7c2502ddfaa2577c176f221422f860db" @@ -4569,13 +4715,20 @@ for-in@^1.0.1, for-in@^1.0.2: resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= -for-own@^0.1.3, for-own@^0.1.4: +for-own@^0.1.3: version "0.1.5" resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4= dependencies: for-in "^1.0.1" +for-own@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-1.0.0.tgz#c63332f415cedc4b04dbfe70cf836494c53cb44b" + integrity sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs= + dependencies: + for-in "^1.0.1" + foreach@~2.0.1: version "2.0.5" resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" @@ -4586,13 +4739,13 @@ forever-agent@~0.6.1: resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= -form-data@^2.3.3: - version "2.5.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.0.tgz#094ec359dc4b55e7d62e0db4acd76e89fe874d37" - integrity sha512-WXieX3G/8side6VIqx44ablyULoGruSde5PNTxoUyo5CeyAMX6nVWUd0rgist/EuX655cjhUhTo1Fo3tRYqbcA== +form-data@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.0.tgz#31b7e39c85f1355b7139ee0c647cf0de7f83c682" + integrity sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg== dependencies: asynckit "^0.4.0" - combined-stream "^1.0.6" + combined-stream "^1.0.8" mime-types "^2.1.12" form-data@~2.3.2: @@ -4621,6 +4774,11 @@ fresh@0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= +fs-copy-file-sync@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/fs-copy-file-sync/-/fs-copy-file-sync-1.1.1.tgz#11bf32c096c10d126e5f6b36d06eece776062918" + integrity sha512-2QY5eeqVv4m2PfyMiEuy9adxNP+ajf+8AR05cEi+OAzPcOj90hvFImeZhTmKLBgSd9EvG33jsD7ZRxsx9dThkQ== + fs-extra@^0.22.1: version "0.22.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.22.1.tgz#5fd6f8049dc976ca19eb2355d658173cabcce056" @@ -4657,25 +4815,18 @@ fs-extra@^7.0.1: jsonfile "^4.0.0" universalify "^0.1.0" -fs-minipass@^1.2.5: - version "1.2.6" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.6.tgz#2c5cc30ded81282bfe8a0d7c7c1853ddeb102c07" - integrity sha512-crhvyXcMejjv3Z5d2Fa9sf5xLYVCF5O1c71QxbVnbLsmYMBEvDAftewesN/HhY03YRoA7zOMxjNGrF5svGaaeQ== - dependencies: - minipass "^2.2.1" - fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= -fsevents@^1.2.3, fsevents@^1.2.7: - version "1.2.9" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.9.tgz#3f5ed66583ccd6f400b5a00db6f7e861363e388f" - integrity sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw== +fsevents@^1.2.7: + version "1.2.11" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.11.tgz#67bf57f4758f02ede88fb2a1712fef4d15358be3" + integrity sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw== dependencies: + bindings "^1.5.0" nan "^2.12.1" - node-pre-gyp "^0.12.0" ftp@~0.3.10: version "0.3.10" @@ -4707,31 +4858,6 @@ fwd-stream@^1.0.4: dependencies: readable-stream "~1.0.26-4" -gauge@~1.2.5: - version "1.2.7" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-1.2.7.tgz#e9cec5483d3d4ee0ef44b60a7d99e4935e136d93" - integrity sha1-6c7FSD09TuDvRLYKfZnkk14TbZM= - dependencies: - ansi "^0.3.0" - has-unicode "^2.0.0" - lodash.pad "^4.1.0" - lodash.padend "^4.1.0" - lodash.padstart "^4.1.0" - -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - get-caller-file@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" @@ -4749,6 +4875,11 @@ get-port@^2.1.0: dependencies: pinkie-promise "^2.0.0" +get-stdin@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" + integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== + get-stdin@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-7.0.0.tgz#8d5de98f15171a125c5e516643c7a6d0ea8a96f6" @@ -4766,17 +4897,24 @@ get-stream@^4.0.0: dependencies: pump "^3.0.0" +get-stream@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9" + integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw== + dependencies: + pump "^3.0.0" + get-uri@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-2.0.3.tgz#fa13352269781d75162c6fc813c9e905323fbab5" - integrity sha512-x5j6Ks7FOgLD/GlvjKwgu7wdmMR55iuRHhn8hj/+gA+eSbxQvZ+AEomq+3MgVEZj1vpi738QahGbCCSIDtXtkw== + version "2.0.4" + resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-2.0.4.tgz#d4937ab819e218d4cb5ae18e4f5962bef169cc6a" + integrity sha512-v7LT/s8kVjs+Tx0ykk1I+H/rbpzkHvuIq87LmeXptcf5sNWm9uQiwjNAt94SJPA1zOlCntmnOlJvVWKmzsxG8Q== dependencies: - data-uri-to-buffer "2" - debug "4" + data-uri-to-buffer "1" + debug "2" extend "~3.0.2" file-uri-to-path "1" ftp "~0.3.10" - readable-stream "3" + readable-stream "2" get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" @@ -4790,21 +4928,6 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" -glob-base@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" - integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q= - dependencies: - glob-parent "^2.0.0" - is-glob "^2.0.0" - -glob-parent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" - integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg= - dependencies: - is-glob "^2.0.0" - glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" @@ -4813,6 +4936,13 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" +glob-parent@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2" + integrity sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw== + dependencies: + is-glob "^4.0.1" + glob-to-regexp@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" @@ -4852,10 +4982,10 @@ glob@^6.0.1: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4: - version "7.1.4" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" - integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== +glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -4887,7 +5017,7 @@ global-prefix@^3.0.0: kind-of "^6.0.2" which "^1.3.1" -global@^4.3.0, global@^4.3.2: +global@^4.3.2: version "4.4.0" resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406" integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w== @@ -4895,11 +5025,18 @@ global@^4.3.0, global@^4.3.2: min-document "^2.19.0" process "^0.11.10" -globals@^11.1.0, globals@^11.7.0: +globals@^11.1.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== +globals@^12.1.0: + version "12.3.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-12.3.0.tgz#1e564ee5c4dded2ab098b0f88f24702a3c56be13" + integrity sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw== + dependencies: + type-fest "^0.8.1" + globby@^9.2.0: version "9.2.0" resolved "https://registry.yarnpkg.com/globby/-/globby-9.2.0.tgz#fd029a706c703d29bdd170f4b6db3a3f7a7cb63d" @@ -4944,9 +5081,21 @@ got@^6.7.1: url-parse-lax "^1.0.0" graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.1.9: - version "4.2.0" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.0.tgz#8d8fdc73977cb04104721cb53666c1ca64cd328b" - integrity sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg== + version "4.2.3" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" + integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== + +grapheme-splitter@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" + integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== + +graphql@^14.0.0: + version "14.5.8" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.5.8.tgz#504f3d3114cb9a0a3f359bbbcf38d9e5bf6a6b3c" + integrity sha512-MMwmi0zlVLQKLdGiMfWkgQD7dY/TUKt4L+zgJ/aR0Howebod3aNgP5JkgvAULiR2HPVZaP2VEElqtdidHweLkg== + dependencies: + iterall "^1.2.2" growl@1.10.5: version "1.10.5" @@ -4958,10 +5107,15 @@ growly@^1.3.0: resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= +hammerjs@^2.0.8: + version "2.0.8" + resolved "https://registry.yarnpkg.com/hammerjs/-/hammerjs-2.0.8.tgz#04ef77862cff2bb79d30f7692095930222bf60f1" + integrity sha1-BO93hiz/K7edMPdpIJWTAiK/YPE= + handlebars@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.2.tgz#b6b37c1ced0306b221e094fc7aca3ec23b131b67" - integrity sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw== + version "4.5.3" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.5.3.tgz#5cf75bd8714f7605713511a56be7c349becb0482" + integrity sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA== dependencies: neo-async "^2.6.0" optimist "^0.6.1" @@ -5006,15 +5160,15 @@ has-flag@^3.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= -has-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" - integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= +has-symbols@^1.0.0, has-symbols@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" + integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== has-value@^0.3.1: version "0.3.1" @@ -5083,6 +5237,11 @@ he@1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== +hermes-engine@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/hermes-engine/-/hermes-engine-0.3.0.tgz#c03ded211102eef775045a5f55e286783db8ad48" + integrity sha512-Xl21n/FohkoeQyz/9AeisoePhXaLvXRyT41xkYHOrqoNr+pkLUGc1xIo486ctIxSp5SN4BkN6T3YFWOdD0ntaQ== + hmac-drbg@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -5097,17 +5256,17 @@ hoist-non-react-statics@^2.3.1, hoist-non-react-statics@^2.5.0: resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47" integrity sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw== -hoist-non-react-statics@^3.0.1, hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz#b09178f0122184fb95acf525daaecb4d8f45958b" - integrity sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA== +hoist-non-react-statics@^3.0.1, hoist-non-react-statics@^3.3.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#101685d3aff3b23ea213163f6e8e12f4f111e19f" + integrity sha512-wbg3bpgA/ZqWrZuMOeJi8+SKMhr7X9TesL/rXMjTzh0p0JUBo3II8DHboYbuIXWRlttrUFxwcu/5kygrCw8fJw== dependencies: react-is "^16.7.0" hosted-git-info@^2.1.4: - version "2.7.1" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" - integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w== + version "2.8.5" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.5.tgz#759cfcf2c4d156ade59b0b2dfabddc42a6b9c70c" + integrity sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg== html-encoding-sniffer@^1.0.2: version "1.0.2" @@ -5117,9 +5276,9 @@ html-encoding-sniffer@^1.0.2: whatwg-encoding "^1.0.1" html-tags@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.0.0.tgz#41f57708c9e6b7b46a00a22317d614c4a2bab166" - integrity sha512-xiXEBjihaNI+VZ2mKEoI5ZPxqUsevTKM+aeeJ/W4KAg2deGE35minmCJMn51BvwJZmiHaeAxrb2LAS0yZJxuuA== + version "3.1.0" + resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140" + integrity sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg== htmlparser2@^3.10.0: version "3.10.1" @@ -5166,27 +5325,48 @@ https-browserify@0.0.1: resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-0.0.1.tgz#3f91365cabe60b77ed0ebba24b454e3e09d95a82" integrity sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI= -https-proxy-agent@^2.2.1: - version "2.2.2" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.2.tgz#271ea8e90f836ac9f119daccd39c19ff7dfb0793" - integrity sha512-c8Ndjc9Bkpfx/vCJueCPy0jlP4ccCCSNDp8xwCZzPjKJUm+B+u9WX2x98Qx4n1PiMNTWo3D7KK5ifNV/yJyRzg== +https-proxy-agent@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-3.0.1.tgz#b8c286433e87602311b01c8ea34413d856a4af81" + integrity sha512-+ML2Rbh6DAuee7d07tYGEKOEi2voWPUGan+ExdPbPW6Z3svq+JCqr0v8WmKPOkz1vOVykPCBSuobe7G8GJUtVg== dependencies: agent-base "^4.3.0" debug "^3.1.0" +human-signals@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" + integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== + +husky@^2.4.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/husky/-/husky-2.7.0.tgz#c0a9a6a3b51146224e11bba0b46bba546e461d05" + integrity sha512-LIi8zzT6PyFpcYKdvWRCn/8X+6SuG2TgYYMrM6ckEYhlp44UcEduVymZGIZNLiwOUjrEud+78w/AsAiqJA/kRg== + dependencies: + cosmiconfig "^5.2.0" + execa "^1.0.0" + find-up "^3.0.0" + get-stdin "^7.0.0" + is-ci "^2.0.0" + pkg-dir "^4.1.0" + please-upgrade-node "^3.1.1" + read-pkg "^5.1.1" + run-node "^1.0.0" + slash "^3.0.0" + i18n-js@^3.0.11: - version "3.3.0" - resolved "https://registry.yarnpkg.com/i18n-js/-/i18n-js-3.3.0.tgz#05512f7184b5117c087ab597be649720a834c068" - integrity sha512-+m8jh84IIWlFwEJgwrWCkeIwIES9ilJKBOj5qx8ZTLLmlPz7bjKnCdxf254wRf6M4pkQHtgXGT9r9lGk0e9aug== + version "3.5.1" + resolved "https://registry.yarnpkg.com/i18n-js/-/i18n-js-3.5.1.tgz#9787450894059bec1af791123231e59898eb97c1" + integrity sha512-nJgbE5Vj9qzOQfjdVd/uoMoO8ppVaB/3LB6KOmMfD8IQ1vNNh307iHyQLK8ZnLYWkAszfPvVpYmUt1Le/RuHMQ== i18next@^17.0.3: - version "17.0.7" - resolved "https://registry.yarnpkg.com/i18next/-/i18next-17.0.7.tgz#aae8591634b109c0ecec755b46c6414b0d743e07" - integrity sha512-fQn+gcyDaHb3qXIeahjCnGMsCeHaKveSORclang55stBjOL13oK7ZYxXVz1AaFV6p3SzOSu/KW+tgZcUuDdf6Q== + version "17.3.1" + resolved "https://registry.yarnpkg.com/i18next/-/i18next-17.3.1.tgz#5fe75e054aae39a6f38f1a79f7ab49184c6dc7a1" + integrity sha512-4nY+yaENaoZKmpbiDXPzucVHCN3hN9Z9Zk7LyQXVOKVIpnYOJ3L/yxHJlBPtJDq3PGgjFwA0QBFm/26Z0iDT5A== dependencies: "@babel/runtime" "^7.3.1" -iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: +iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@~0.4.13: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -5198,32 +5378,25 @@ ieee754@^1.1.4: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== -ignore-walk@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" - integrity sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ== - dependencies: - minimatch "^3.0.4" - ignore@^4.0.3, ignore@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== ignore@^5.0.5, ignore@^5.0.6: - version "5.1.2" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.2.tgz#e28e584d43ad7e92f96995019cc43b9e1ac49558" - integrity sha512-vdqWBp7MyzdmHkkRWV5nY+PfGRbYbahfuvsBCh277tq+w9zyNi7h5CYJCK0kmzti9kU+O/cB7sE8HvKv6aXAKQ== + version "5.1.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.4.tgz#84b7b3dbe64552b6ef0eca99f6743dbec6d97adf" + integrity sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A== image-size@^0.6.0: version "0.6.3" resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.6.3.tgz#e7e5c65bb534bd7cdcedd6cb5166272a85f75fb2" integrity sha512-47xSUiQioGaB96nqtp5/q55m0aBQSQdyIloMOc/x+QVTDZLNmXE892IIDrJ0hM1A5vcNUDD5tDffkSP5lCaIIA== -immer@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/immer/-/immer-3.1.3.tgz#59bc742b2aab6e2c676445edb653e588a23c70fc" - integrity sha512-HG5SXTXTTVy9lGNwS075cNhQoV375jHsIJO3UtMjuUWJOuwlMr0u42FlsKTJcppt5AzsFAsmj9r4kHvsSHh3hQ== +immer@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/immer/-/immer-5.1.0.tgz#38d9eba40dbb0389b7ae7b8b99e4661df0cf89e3" + integrity sha512-t6gyFtTcokCuI0tX9KQZJQAkIjSqo/nTeJnwojfty69EzrorZbywwhZ8qNNlF+faajHeRnhOvM2F40KHLFCghQ== import-fresh@^2.0.0: version "2.0.0" @@ -5234,9 +5407,9 @@ import-fresh@^2.0.0: resolve-from "^3.0.0" import-fresh@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.1.0.tgz#6d33fa1dcef6df930fae003446f33415af905118" - integrity sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ== + version "3.2.1" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66" + integrity sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ== dependencies: parent-module "^1.0.0" resolve-from "^4.0.0" @@ -5366,10 +5539,10 @@ inquirer@^3.0.6: strip-ansi "^4.0.0" through "^2.3.6" -inquirer@^6.2.2: - version "6.5.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.0.tgz#2303317efc9a4ea7ec2e2df6f86569b734accf42" - integrity sha512-scfHejeG/lVZSpvCXpsB4j/wQNPM5JC8kiElOI0OUTwmc1RTpXr4H32/HOlQHcZiYl2z2VElwuCVDRG8vFmbnA== +inquirer@^6.2.0: + version "6.5.2" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" + integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ== dependencies: ansi-escapes "^3.2.0" chalk "^2.4.2" @@ -5385,7 +5558,26 @@ inquirer@^6.2.2: strip-ansi "^5.1.0" through "^2.3.6" -invariant@^2.2.0, invariant@^2.2.2, invariant@^2.2.4: +inquirer@^7.0.0: + version "7.0.2" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.0.2.tgz#b39b205b95c9424839a1fd991d60426cf9bbc0e9" + integrity sha512-cZGvHaHwcR9E3xK9EGO5pHKELU+yaeJO7l2qGKIbqk4bCuDuAn15LCoUTS2nSkfv9JybFlnAGrOcVpCDZZOLhw== + dependencies: + ansi-escapes "^4.2.1" + chalk "^2.4.2" + cli-cursor "^3.1.0" + cli-width "^2.0.0" + external-editor "^3.0.3" + figures "^3.0.0" + lodash "^4.17.15" + mute-stream "0.0.8" + run-async "^2.2.0" + rxjs "^6.5.3" + string-width "^4.1.0" + strip-ansi "^5.1.0" + through "^2.3.6" + +invariant@^2.2.0, 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== @@ -5407,7 +5599,7 @@ ip-regex@^1.0.3: resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-1.0.3.tgz#dc589076f659f419c222039a33316f1c7387effd" integrity sha1-3FiQdvZZ9BnCIgOaMzFvHHOH7/0= -ip@^1.1.5: +ip@1.1.5, ip@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= @@ -5444,25 +5636,30 @@ is-alphanumerical@^1.0.0: is-alphabetical "^1.0.0" is-decimal "^1.0.0" +is-arguments@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.0.4.tgz#3faf966c7cba0ff437fb31f6250082fcf0448cf3" + integrity sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA== + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= -is-buffer@^1.0.2, is-buffer@^1.1.5: +is-buffer@^1.0.2, is-buffer@^1.1.4, is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== is-buffer@^2.0.0, is-buffer@^2.0.2, is-buffer@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725" - integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw== + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" + integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A== -is-callable@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" - integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== +is-callable@^1.1.4, is-callable@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" + integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== is-ci@^1.0.10: version "1.2.1" @@ -5493,9 +5690,9 @@ is-data-descriptor@^1.0.0: kind-of "^6.0.0" is-date-object@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" - integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" + integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== is-decimal@^1.0.0: version "1.0.3" @@ -5525,18 +5722,6 @@ is-directory@^0.3.1: resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= -is-dotfile@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" - integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE= - -is-equal-shallow@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" - integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ= - dependencies: - is-primitive "^2.0.0" - is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" @@ -5549,11 +5734,6 @@ is-extendable@^1.0.0, is-extendable@^1.0.1: dependencies: is-plain-object "^2.0.4" -is-extglob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" - integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA= - is-extglob@^2.1.0, is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -5581,13 +5761,6 @@ is-generator-fn@^2.0.0: resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== -is-glob@^2.0.0, is-glob@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" - integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM= - dependencies: - is-extglob "^1.0.0" - is-glob@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" @@ -5595,7 +5768,7 @@ is-glob@^3.1.0: dependencies: is-extglob "^2.1.0" -is-glob@^4.0.0: +is-glob@^4.0.0, is-glob@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== @@ -5620,13 +5793,6 @@ is-npm@^1.0.0: resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4" integrity sha1-8vtjpl5JBbQGyGBydloaTceTufQ= -is-number@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" - integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8= - dependencies: - kind-of "^3.0.2" - is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" @@ -5634,11 +5800,6 @@ is-number@^3.0.0: dependencies: kind-of "^3.0.2" -is-number@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" - integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== - is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" @@ -5673,16 +5834,6 @@ is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" -is-posix-bracket@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" - integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q= - -is-primitive@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" - integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU= - is-promise@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" @@ -5693,12 +5844,12 @@ is-redirect@^1.0.0: resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" integrity sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ= -is-regex@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" - integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= +is-regex@^1.0.4, is-regex@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae" + integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ== dependencies: - has "^1.0.1" + has "^1.0.3" is-regexp@^2.0.0: version "2.1.0" @@ -5706,31 +5857,41 @@ is-regexp@^2.0.0: integrity sha512-OZ4IlER3zmRIoB9AqNhEggVxqIH4ofDns5nRrPS6yQxXE1TPCUpFznBfRQmQa8uC+pXqjMnukiJBxCisIxiLGA== is-retry-allowed@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" - integrity sha1-EaBgVotnM5REAz0BJaYaINVk+zQ= + version "1.2.0" + resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4" + integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg== is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= +is-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" + integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== + +is-string@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" + integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ== + is-symbol@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" - integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" + integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ== dependencies: - has-symbols "^1.0.0" + has-symbols "^1.0.1" -is-typedarray@~1.0.0: +is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= -is-what@^3.2.4: - version "3.2.4" - resolved "https://registry.yarnpkg.com/is-what/-/is-what-3.2.4.tgz#da528659017bdd4b07892dfe4fd60da6ac500e98" - integrity sha512-0awkPsfVd85bYStP99EqLxKvhc5SiE70hSZCPxJN2SYZ5d+IkX+r1Ri0qnPWPnuRVFrqrEnI3JgFN3yrGtjXaw== +is-what@^3.3.1: + version "3.5.0" + resolved "https://registry.yarnpkg.com/is-what/-/is-what-3.5.0.tgz#c50b0e8f3021e0b39410c159bea43a5510d99027" + integrity sha512-00pwt/Jf7IaRh5m2Dp93Iw8LG2cd3OpDj3NrD1XPNUpAWVxPvBP296p4IiGmIU4Ur0f3f56IoIM+fS2pFYF+tQ== is-whitespace-character@^1.0.0: version "1.0.3" @@ -5752,6 +5913,11 @@ is-wsl@^1.1.0: resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= +is-wsl@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.1.1.tgz#4a1c152d429df3d441669498e2486d3596ebaf1d" + integrity sha512-umZHcSrwlDHo2TGMXv0DZ8dIUGunZ2Iv68YZnrmCiBPkZ4aaOhtv7pXJKeki9k3qJ3RJr0cDyitcl5wEH3AYog== + is@~0.2.6: version "0.2.7" resolved "https://registry.yarnpkg.com/is/-/is-0.2.7.tgz#3b34a2c48f359972f35042849193ae7264b63562" @@ -5845,339 +6011,323 @@ istanbul-lib-source-maps@^3.0.1: rimraf "^2.6.3" source-map "^0.6.1" -istanbul-reports@^2.1.1: +istanbul-reports@^2.2.6: version "2.2.6" resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.2.6.tgz#7b4f2660d82b29303a8fe6091f8ca4bf058da1af" integrity sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA== dependencies: handlebars "^4.1.2" -jest-changed-files@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-24.8.0.tgz#7e7eb21cf687587a85e50f3d249d1327e15b157b" - integrity sha512-qgANC1Yrivsq+UrLXsvJefBKVoCsKB0Hv+mBb6NMjjZ90wwxCDmU3hsCXBya30cH+LnPYjwgcU65i6yJ5Nfuug== +iterall@^1.2.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.3.0.tgz#afcb08492e2915cbd8a0884eb93a8c94d0d72fea" + integrity sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg== + +jest-changed-files@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-24.9.0.tgz#08d8c15eb79a7fa3fc98269bc14b451ee82f8039" + integrity sha512-6aTWpe2mHF0DhL28WjdkO8LyGjs3zItPET4bMSeXU6T3ub4FPMw+mcOcbdGXQOAfmLcxofD23/5Bl9Z4AkFwqg== dependencies: - "@jest/types" "^24.8.0" + "@jest/types" "^24.9.0" execa "^1.0.0" throat "^4.0.0" -jest-cli@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-24.8.0.tgz#b075ac914492ed114fa338ade7362a301693e989" - integrity sha512-+p6J00jSMPQ116ZLlHJJvdf8wbjNbZdeSX9ptfHX06/MSNaXmKihQzx5vQcw0q2G6JsdVkUIdWbOWtSnaYs3yA== +jest-cli@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-24.9.0.tgz#ad2de62d07472d419c6abc301fc432b98b10d2af" + integrity sha512-+VLRKyitT3BWoMeSUIHRxV/2g8y9gw91Jh5z2UmXZzkZKpbC08CSehVxgHUwTpy+HwGcns/tqafQDJW7imYvGg== dependencies: - "@jest/core" "^24.8.0" - "@jest/test-result" "^24.8.0" - "@jest/types" "^24.8.0" + "@jest/core" "^24.9.0" + "@jest/test-result" "^24.9.0" + "@jest/types" "^24.9.0" chalk "^2.0.1" exit "^0.1.2" import-local "^2.0.0" is-ci "^2.0.0" - jest-config "^24.8.0" - jest-util "^24.8.0" - jest-validate "^24.8.0" + jest-config "^24.9.0" + jest-util "^24.9.0" + jest-validate "^24.9.0" prompts "^2.0.1" realpath-native "^1.1.0" - yargs "^12.0.2" + yargs "^13.3.0" -jest-config@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-24.8.0.tgz#77db3d265a6f726294687cbbccc36f8a76ee0f4f" - integrity sha512-Czl3Nn2uEzVGsOeaewGWoDPD8GStxCpAe0zOYs2x2l0fZAgPbCr3uwUkgNKV3LwE13VXythM946cd5rdGkkBZw== +jest-config@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-24.9.0.tgz#fb1bbc60c73a46af03590719efa4825e6e4dd1b5" + integrity sha512-RATtQJtVYQrp7fvWg6f5y3pEFj9I+H8sWw4aKxnDZ96mob5i5SD6ZEGWgMLXQ4LE8UurrjbdlLWdUeo+28QpfQ== dependencies: "@babel/core" "^7.1.0" - "@jest/test-sequencer" "^24.8.0" - "@jest/types" "^24.8.0" - babel-jest "^24.8.0" + "@jest/test-sequencer" "^24.9.0" + "@jest/types" "^24.9.0" + babel-jest "^24.9.0" chalk "^2.0.1" glob "^7.1.1" - jest-environment-jsdom "^24.8.0" - jest-environment-node "^24.8.0" - jest-get-type "^24.8.0" - jest-jasmine2 "^24.8.0" + jest-environment-jsdom "^24.9.0" + jest-environment-node "^24.9.0" + jest-get-type "^24.9.0" + jest-jasmine2 "^24.9.0" jest-regex-util "^24.3.0" - jest-resolve "^24.8.0" - jest-util "^24.8.0" - jest-validate "^24.8.0" + jest-resolve "^24.9.0" + jest-util "^24.9.0" + jest-validate "^24.9.0" micromatch "^3.1.10" - pretty-format "^24.8.0" + pretty-format "^24.9.0" realpath-native "^1.1.0" -jest-diff@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.8.0.tgz#146435e7d1e3ffdf293d53ff97e193f1d1546172" - integrity sha512-wxetCEl49zUpJ/bvUmIFjd/o52J+yWcoc5ZyPq4/W1LUKGEhRYDIbP1KcF6t+PvqNrGAFk4/JhtxDq/Nnzs66g== +jest-diff@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.9.0.tgz#931b7d0d5778a1baf7452cb816e325e3724055da" + integrity sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ== dependencies: chalk "^2.0.1" - diff-sequences "^24.3.0" - jest-get-type "^24.8.0" - pretty-format "^24.8.0" - -jest-docblock@^21.0.0: - version "21.2.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414" - integrity sha512-5IZ7sY9dBAYSV+YjQ0Ovb540Ku7AO9Z5o2Cg789xj167iQuZ2cG+z0f3Uct6WeYLbU6aQiM2pCs7sZ+4dotydw== + diff-sequences "^24.9.0" + jest-get-type "^24.9.0" + pretty-format "^24.9.0" jest-docblock@^24.3.0: - version "24.3.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-24.3.0.tgz#b9c32dac70f72e4464520d2ba4aec02ab14db5dd" - integrity sha512-nlANmF9Yq1dufhFlKG9rasfQlrY7wINJbo3q01tu56Jv5eBU5jirylhF2O5ZBnLxzOVBGRDz/9NAwNyBtG4Nyg== + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-24.9.0.tgz#7970201802ba560e1c4092cc25cbedf5af5a8ce2" + integrity sha512-F1DjdpDMJMA1cN6He0FNYNZlo3yYmOtRUnktrT9Q37njYzC5WEaDdmbynIgy0L/IvXvvgsG8OsqhLPXTpfmZAA== dependencies: detect-newline "^2.1.0" -jest-each@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-24.8.0.tgz#a05fd2bf94ddc0b1da66c6d13ec2457f35e52775" - integrity sha512-NrwK9gaL5+XgrgoCsd9svsoWdVkK4gnvyhcpzd6m487tXHqIdYeykgq3MKI1u4I+5Zf0tofr70at9dWJDeb+BA== +jest-each@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-24.9.0.tgz#eb2da602e2a610898dbc5f1f6df3ba86b55f8b05" + integrity sha512-ONi0R4BvW45cw8s2Lrx8YgbeXL1oCQ/wIDwmsM3CqM/nlblNCPmnC3IPQlMbRFZu3wKdQ2U8BqM6lh3LJ5Bsog== dependencies: - "@jest/types" "^24.8.0" + "@jest/types" "^24.9.0" chalk "^2.0.1" - jest-get-type "^24.8.0" - jest-util "^24.8.0" - pretty-format "^24.8.0" - -jest-environment-jsdom@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-24.8.0.tgz#300f6949a146cabe1c9357ad9e9ecf9f43f38857" - integrity sha512-qbvgLmR7PpwjoFjM/sbuqHJt/NCkviuq9vus9NBn/76hhSidO+Z6Bn9tU8friecegbJL8gzZQEMZBQlFWDCwAQ== - dependencies: - "@jest/environment" "^24.8.0" - "@jest/fake-timers" "^24.8.0" - "@jest/types" "^24.8.0" - jest-mock "^24.8.0" - jest-util "^24.8.0" + jest-get-type "^24.9.0" + jest-util "^24.9.0" + pretty-format "^24.9.0" + +jest-environment-jsdom@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-24.9.0.tgz#4b0806c7fc94f95edb369a69cc2778eec2b7375b" + integrity sha512-Zv9FV9NBRzLuALXjvRijO2351DRQeLYXtpD4xNvfoVFw21IOKNhZAEUKcbiEtjTkm2GsJ3boMVgkaR7rN8qetA== + dependencies: + "@jest/environment" "^24.9.0" + "@jest/fake-timers" "^24.9.0" + "@jest/types" "^24.9.0" + jest-mock "^24.9.0" + jest-util "^24.9.0" jsdom "^11.5.1" -jest-environment-node@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-24.8.0.tgz#d3f726ba8bc53087a60e7a84ca08883a4c892231" - integrity sha512-vIGUEScd1cdDgR6sqn2M08sJTRLQp6Dk/eIkCeO4PFHxZMOgy+uYLPMC4ix3PEfM5Au/x3uQ/5Tl0DpXXZsJ/Q== +jest-environment-node@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-24.9.0.tgz#333d2d2796f9687f2aeebf0742b519f33c1cbfd3" + integrity sha512-6d4V2f4nxzIzwendo27Tr0aFm+IXWa0XEUnaH6nU0FMaozxovt+sfRvh4J47wL1OvF83I3SSTu0XK+i4Bqe7uA== dependencies: - "@jest/environment" "^24.8.0" - "@jest/fake-timers" "^24.8.0" - "@jest/types" "^24.8.0" - jest-mock "^24.8.0" - jest-util "^24.8.0" + "@jest/environment" "^24.9.0" + "@jest/fake-timers" "^24.9.0" + "@jest/types" "^24.9.0" + jest-mock "^24.9.0" + jest-util "^24.9.0" -jest-get-type@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.8.0.tgz#a7440de30b651f5a70ea3ed7ff073a32dfe646fc" - integrity sha512-RR4fo8jEmMD9zSz2nLbs2j0zvPpk/KCEz3a62jJWbd2ayNo0cb+KFRxPHVhE4ZmgGJEQp0fosmNz84IfqM8cMQ== - -jest-haste-map@24.0.0-alpha.6: - version "24.0.0-alpha.6" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.0.0-alpha.6.tgz#fb2c785080f391b923db51846b86840d0d773076" - integrity sha512-+NO2HMbjvrG8BC39ieLukdpFrcPhhjCJGhpbHodHNZygH1Tt06WrlNYGpZtWKx/zpf533tCtMQXO/q59JenjNw== - dependencies: - fb-watchman "^2.0.0" - graceful-fs "^4.1.11" - invariant "^2.2.4" - jest-serializer "^24.0.0-alpha.6" - jest-worker "^24.0.0-alpha.6" - micromatch "^2.3.11" - sane "^3.0.0" +jest-get-type@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.9.0.tgz#1684a0c8a50f2e4901b6644ae861f579eed2ef0e" + integrity sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q== -jest-haste-map@^24.7.1, jest-haste-map@^24.8.0: - version "24.8.1" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.8.1.tgz#f39cc1d2b1d907e014165b4bd5a957afcb992982" - integrity sha512-SwaxMGVdAZk3ernAx2Uv2sorA7jm3Kx+lR0grp6rMmnY06Kn/urtKx1LPN2mGTea4fCT38impYT28FfcLUhX0g== +jest-haste-map@^24.7.1, jest-haste-map@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.9.0.tgz#b38a5d64274934e21fa417ae9a9fbeb77ceaac7d" + integrity sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ== dependencies: - "@jest/types" "^24.8.0" + "@jest/types" "^24.9.0" anymatch "^2.0.0" fb-watchman "^2.0.0" graceful-fs "^4.1.15" invariant "^2.2.4" - jest-serializer "^24.4.0" - jest-util "^24.8.0" - jest-worker "^24.6.0" + jest-serializer "^24.9.0" + jest-util "^24.9.0" + jest-worker "^24.9.0" micromatch "^3.1.10" sane "^4.0.3" walker "^1.0.7" optionalDependencies: fsevents "^1.2.7" -jest-jasmine2@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-24.8.0.tgz#a9c7e14c83dd77d8b15e820549ce8987cc8cd898" - integrity sha512-cEky88npEE5LKd5jPpTdDCLvKkdyklnaRycBXL6GNmpxe41F0WN44+i7lpQKa/hcbXaQ+rc9RMaM4dsebrYong== +jest-jasmine2@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-24.9.0.tgz#1f7b1bd3242c1774e62acabb3646d96afc3be6a0" + integrity sha512-Cq7vkAgaYKp+PsX+2/JbTarrk0DmNhsEtqBXNwUHkdlbrTBLtMJINADf2mf5FkowNsq8evbPc07/qFO0AdKTzw== dependencies: "@babel/traverse" "^7.1.0" - "@jest/environment" "^24.8.0" - "@jest/test-result" "^24.8.0" - "@jest/types" "^24.8.0" + "@jest/environment" "^24.9.0" + "@jest/test-result" "^24.9.0" + "@jest/types" "^24.9.0" chalk "^2.0.1" co "^4.6.0" - expect "^24.8.0" + expect "^24.9.0" is-generator-fn "^2.0.0" - jest-each "^24.8.0" - jest-matcher-utils "^24.8.0" - jest-message-util "^24.8.0" - jest-runtime "^24.8.0" - jest-snapshot "^24.8.0" - jest-util "^24.8.0" - pretty-format "^24.8.0" + jest-each "^24.9.0" + jest-matcher-utils "^24.9.0" + jest-message-util "^24.9.0" + jest-runtime "^24.9.0" + jest-snapshot "^24.9.0" + jest-util "^24.9.0" + pretty-format "^24.9.0" throat "^4.0.0" -jest-leak-detector@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-24.8.0.tgz#c0086384e1f650c2d8348095df769f29b48e6980" - integrity sha512-cG0yRSK8A831LN8lIHxI3AblB40uhv0z+SsQdW3GoMMVcK+sJwrIIyax5tu3eHHNJ8Fu6IMDpnLda2jhn2pD/g== +jest-leak-detector@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-24.9.0.tgz#b665dea7c77100c5c4f7dfcb153b65cf07dcf96a" + integrity sha512-tYkFIDsiKTGwb2FG1w8hX9V0aUb2ot8zY/2nFg087dUageonw1zrLMP4W6zsRO59dPkTSKie+D4rhMuP9nRmrA== dependencies: - pretty-format "^24.8.0" + jest-get-type "^24.9.0" + pretty-format "^24.9.0" -jest-matcher-utils@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.8.0.tgz#2bce42204c9af12bde46f83dc839efe8be832495" - integrity sha512-lex1yASY51FvUuHgm0GOVj7DCYEouWSlIYmCW7APSqB9v8mXmKSn5+sWVF0MhuASG0bnYY106/49JU1FZNl5hw== +jest-matcher-utils@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz#f5b3661d5e628dffe6dd65251dfdae0e87c3a073" + integrity sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA== dependencies: chalk "^2.0.1" - jest-diff "^24.8.0" - jest-get-type "^24.8.0" - pretty-format "^24.8.0" + jest-diff "^24.9.0" + jest-get-type "^24.9.0" + pretty-format "^24.9.0" -jest-message-util@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.8.0.tgz#0d6891e72a4beacc0292b638685df42e28d6218b" - integrity sha512-p2k71rf/b6ns8btdB0uVdljWo9h0ovpnEe05ZKWceQGfXYr4KkzgKo3PBi8wdnd9OtNh46VpNIJynUn/3MKm1g== +jest-message-util@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.9.0.tgz#527f54a1e380f5e202a8d1149b0ec872f43119e3" + integrity sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw== dependencies: "@babel/code-frame" "^7.0.0" - "@jest/test-result" "^24.8.0" - "@jest/types" "^24.8.0" + "@jest/test-result" "^24.9.0" + "@jest/types" "^24.9.0" "@types/stack-utils" "^1.0.1" chalk "^2.0.1" micromatch "^3.1.10" slash "^2.0.0" stack-utils "^1.0.1" -jest-mock@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.8.0.tgz#2f9d14d37699e863f1febf4e4d5a33b7fdbbde56" - integrity sha512-6kWugwjGjJw+ZkK4mDa0Df3sDlUTsV47MSrT0nGQ0RBWJbpODDQ8MHDVtGtUYBne3IwZUhtB7elxHspU79WH3A== +jest-mock@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.9.0.tgz#c22835541ee379b908673ad51087a2185c13f1c6" + integrity sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w== dependencies: - "@jest/types" "^24.8.0" + "@jest/types" "^24.9.0" jest-pnp-resolver@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz#ecdae604c077a7fbc70defb6d517c3c1c898923a" integrity sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ== -jest-regex-util@^24.3.0: - version "24.3.0" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-24.3.0.tgz#d5a65f60be1ae3e310d5214a0307581995227b36" - integrity sha512-tXQR1NEOyGlfylyEjg1ImtScwMq8Oh3iJbGTjN7p0J23EuVX1MA8rwU69K4sLbCmwzgCUbVkm0FkSF9TdzOhtg== +jest-regex-util@^24.3.0, jest-regex-util@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-24.9.0.tgz#c13fb3380bde22bf6575432c493ea8fe37965636" + integrity sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA== -jest-resolve-dependencies@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-24.8.0.tgz#19eec3241f2045d3f990dba331d0d7526acff8e0" - integrity sha512-hyK1qfIf/krV+fSNyhyJeq3elVMhK9Eijlwy+j5jqmZ9QsxwKBiP6qukQxaHtK8k6zql/KYWwCTQ+fDGTIJauw== +jest-resolve-dependencies@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-24.9.0.tgz#ad055198959c4cfba8a4f066c673a3f0786507ab" + integrity sha512-Fm7b6AlWnYhT0BXy4hXpactHIqER7erNgIsIozDXWl5dVm+k8XdGVe1oTg1JyaFnOxarMEbax3wyRJqGP2Pq+g== dependencies: - "@jest/types" "^24.8.0" + "@jest/types" "^24.9.0" jest-regex-util "^24.3.0" - jest-snapshot "^24.8.0" + jest-snapshot "^24.9.0" -jest-resolve@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-24.8.0.tgz#84b8e5408c1f6a11539793e2b5feb1b6e722439f" - integrity sha512-+hjSzi1PoRvnuOICoYd5V/KpIQmkAsfjFO71458hQ2Whi/yf1GDeBOFj8Gxw4LrApHsVJvn5fmjcPdmoUHaVKw== +jest-resolve@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-24.9.0.tgz#dff04c7687af34c4dd7e524892d9cf77e5d17321" + integrity sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ== dependencies: - "@jest/types" "^24.8.0" + "@jest/types" "^24.9.0" browser-resolve "^1.11.3" chalk "^2.0.1" jest-pnp-resolver "^1.2.1" realpath-native "^1.1.0" -jest-runner@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-24.8.0.tgz#4f9ae07b767db27b740d7deffad0cf67ccb4c5bb" - integrity sha512-utFqC5BaA3JmznbissSs95X1ZF+d+4WuOWwpM9+Ak356YtMhHE/GXUondZdcyAAOTBEsRGAgH/0TwLzfI9h7ow== +jest-runner@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-24.9.0.tgz#574fafdbd54455c2b34b4bdf4365a23857fcdf42" + integrity sha512-KksJQyI3/0mhcfspnxxEOBueGrd5E4vV7ADQLT9ESaCzz02WnbdbKWIf5Mkaucoaj7obQckYPVX6JJhgUcoWWg== dependencies: "@jest/console" "^24.7.1" - "@jest/environment" "^24.8.0" - "@jest/test-result" "^24.8.0" - "@jest/types" "^24.8.0" + "@jest/environment" "^24.9.0" + "@jest/test-result" "^24.9.0" + "@jest/types" "^24.9.0" chalk "^2.4.2" exit "^0.1.2" graceful-fs "^4.1.15" - jest-config "^24.8.0" + jest-config "^24.9.0" jest-docblock "^24.3.0" - jest-haste-map "^24.8.0" - jest-jasmine2 "^24.8.0" - jest-leak-detector "^24.8.0" - jest-message-util "^24.8.0" - jest-resolve "^24.8.0" - jest-runtime "^24.8.0" - jest-util "^24.8.0" + jest-haste-map "^24.9.0" + jest-jasmine2 "^24.9.0" + jest-leak-detector "^24.9.0" + jest-message-util "^24.9.0" + jest-resolve "^24.9.0" + jest-runtime "^24.9.0" + jest-util "^24.9.0" jest-worker "^24.6.0" source-map-support "^0.5.6" throat "^4.0.0" -jest-runtime@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-24.8.0.tgz#05f94d5b05c21f6dc54e427cd2e4980923350620" - integrity sha512-Mq0aIXhvO/3bX44ccT+czU1/57IgOMyy80oM0XR/nyD5zgBcesF84BPabZi39pJVA6UXw+fY2Q1N+4BiVUBWOA== +jest-runtime@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-24.9.0.tgz#9f14583af6a4f7314a6a9d9f0226e1a781c8e4ac" + integrity sha512-8oNqgnmF3v2J6PVRM2Jfuj8oX3syKmaynlDMMKQ4iyzbQzIG6th5ub/lM2bCMTmoTKM3ykcUYI2Pw9xwNtjMnw== dependencies: "@jest/console" "^24.7.1" - "@jest/environment" "^24.8.0" + "@jest/environment" "^24.9.0" "@jest/source-map" "^24.3.0" - "@jest/transform" "^24.8.0" - "@jest/types" "^24.8.0" - "@types/yargs" "^12.0.2" + "@jest/transform" "^24.9.0" + "@jest/types" "^24.9.0" + "@types/yargs" "^13.0.0" chalk "^2.0.1" exit "^0.1.2" glob "^7.1.3" graceful-fs "^4.1.15" - jest-config "^24.8.0" - jest-haste-map "^24.8.0" - jest-message-util "^24.8.0" - jest-mock "^24.8.0" + jest-config "^24.9.0" + jest-haste-map "^24.9.0" + jest-message-util "^24.9.0" + jest-mock "^24.9.0" jest-regex-util "^24.3.0" - jest-resolve "^24.8.0" - jest-snapshot "^24.8.0" - jest-util "^24.8.0" - jest-validate "^24.8.0" + jest-resolve "^24.9.0" + jest-snapshot "^24.9.0" + jest-util "^24.9.0" + jest-validate "^24.9.0" realpath-native "^1.1.0" slash "^2.0.0" strip-bom "^3.0.0" - yargs "^12.0.2" + yargs "^13.3.0" -jest-serializer@24.0.0-alpha.6: - version "24.0.0-alpha.6" - resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-24.0.0-alpha.6.tgz#27d2fee4b1a85698717a30c3ec2ab80767312597" - integrity sha512-IPA5T6/GhlE6dedSk7Cd7YfuORnYjN0VD5iJVFn1Q81RJjpj++Hen5kJbKcg547vXsQ1TddV15qOA/zeIfOCLw== +jest-serializer@^24.4.0, jest-serializer@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-24.9.0.tgz#e6d7d7ef96d31e8b9079a714754c5d5c58288e73" + integrity sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ== -jest-serializer@^24.0.0-alpha.6, jest-serializer@^24.4.0: - version "24.4.0" - resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-24.4.0.tgz#f70c5918c8ea9235ccb1276d232e459080588db3" - integrity sha512-k//0DtglVstc1fv+GY/VHDIjrtNjdYvYjMlbLUed4kxrE92sIUewOi5Hj3vrpB8CXfkJntRPDRjCrCvUhBdL8Q== - -jest-snapshot@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-24.8.0.tgz#3bec6a59da2ff7bc7d097a853fb67f9d415cb7c6" - integrity sha512-5ehtWoc8oU9/cAPe6fez6QofVJLBKyqkY2+TlKTOf0VllBB/mqUNdARdcjlZrs9F1Cv+/HKoCS/BknT0+tmfPg== +jest-snapshot@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-24.9.0.tgz#ec8e9ca4f2ec0c5c87ae8f925cf97497b0e951ba" + integrity sha512-uI/rszGSs73xCM0l+up7O7a40o90cnrk429LOiK3aeTvfC0HHmldbd81/B7Ix81KSFe1lwkbl7GnBGG4UfuDew== dependencies: "@babel/types" "^7.0.0" - "@jest/types" "^24.8.0" + "@jest/types" "^24.9.0" chalk "^2.0.1" - expect "^24.8.0" - jest-diff "^24.8.0" - jest-matcher-utils "^24.8.0" - jest-message-util "^24.8.0" - jest-resolve "^24.8.0" + expect "^24.9.0" + jest-diff "^24.9.0" + jest-get-type "^24.9.0" + jest-matcher-utils "^24.9.0" + jest-message-util "^24.9.0" + jest-resolve "^24.9.0" mkdirp "^0.5.1" natural-compare "^1.4.0" - pretty-format "^24.8.0" - semver "^5.5.0" - -jest-util@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-24.8.0.tgz#41f0e945da11df44cc76d64ffb915d0716f46cd1" - integrity sha512-DYZeE+XyAnbNt0BG1OQqKy/4GVLPtzwGx5tsnDrFcax36rVE3lTA5fbvgmbVPUZf9w77AJ8otqR4VBbfFJkUZA== - dependencies: - "@jest/console" "^24.7.1" - "@jest/fake-timers" "^24.8.0" - "@jest/source-map" "^24.3.0" - "@jest/test-result" "^24.8.0" - "@jest/types" "^24.8.0" + pretty-format "^24.9.0" + semver "^6.2.0" + +jest-util@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-24.9.0.tgz#7396814e48536d2e85a37de3e4c431d7cb140162" + integrity sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg== + dependencies: + "@jest/console" "^24.9.0" + "@jest/fake-timers" "^24.9.0" + "@jest/source-map" "^24.9.0" + "@jest/test-result" "^24.9.0" + "@jest/types" "^24.9.0" callsites "^3.0.0" chalk "^2.0.1" graceful-fs "^4.1.15" @@ -6186,75 +6336,63 @@ jest-util@^24.8.0: slash "^2.0.0" source-map "^0.6.0" -jest-validate@^24.7.0, jest-validate@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-24.8.0.tgz#624c41533e6dfe356ffadc6e2423a35c2d3b4849" - integrity sha512-+/N7VOEMW1Vzsrk3UWBDYTExTPwf68tavEPKDnJzrC6UlHtUDU/fuEdXqFoHzv9XnQ+zW6X3qMZhJ3YexfeLDA== +jest-validate@^24.7.0, jest-validate@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-24.9.0.tgz#0775c55360d173cd854e40180756d4ff52def8ab" + integrity sha512-HPIt6C5ACwiqSiwi+OfSSHbK8sG7akG8eATl+IPKaeIjtPOeBUd/g3J7DghugzxrGjI93qS/+RPKe1H6PqvhRQ== dependencies: - "@jest/types" "^24.8.0" - camelcase "^5.0.0" + "@jest/types" "^24.9.0" + camelcase "^5.3.1" chalk "^2.0.1" - jest-get-type "^24.8.0" - leven "^2.1.0" - pretty-format "^24.8.0" - -jest-watcher@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-24.8.0.tgz#58d49915ceddd2de85e238f6213cef1c93715de4" - integrity sha512-SBjwHt5NedQoVu54M5GEx7cl7IGEFFznvd/HNT8ier7cCAx/Qgu9ZMlaTQkvK22G1YOpcWBLQPFSImmxdn3DAw== - dependencies: - "@jest/test-result" "^24.8.0" - "@jest/types" "^24.8.0" - "@types/yargs" "^12.0.9" + jest-get-type "^24.9.0" + leven "^3.1.0" + pretty-format "^24.9.0" + +jest-watcher@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-24.9.0.tgz#4b56e5d1ceff005f5b88e528dc9afc8dd4ed2b3b" + integrity sha512-+/fLOfKPXXYJDYlks62/4R4GoT+GU1tYZed99JSCOsmzkkF7727RqKrjNAxtfO4YpGv11wybgRvCjR73lK2GZw== + dependencies: + "@jest/test-result" "^24.9.0" + "@jest/types" "^24.9.0" + "@types/yargs" "^13.0.0" ansi-escapes "^3.0.0" chalk "^2.0.1" - jest-util "^24.8.0" + jest-util "^24.9.0" string-length "^2.0.0" -jest-worker@24.0.0-alpha.6: - version "24.0.0-alpha.6" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.0.0-alpha.6.tgz#463681b92c117c57107135c14b9b9d6cd51d80ce" - integrity sha512-iXtH7MR9bjWlNnlnRBcrBRrb4cSVxML96La5vsnmBvDI+mJnkP5uEt6Fgpo5Y8f3z9y2Rd7wuPnKRxqQsiU/dA== - dependencies: - merge-stream "^1.0.1" - -jest-worker@^24.0.0-alpha.6, jest-worker@^24.6.0: - version "24.6.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.6.0.tgz#7f81ceae34b7cde0c9827a6980c35b7cdc0161b3" - integrity sha512-jDwgW5W9qGNvpI1tNnvajh0a5IE/PuGLFmHk6aR/BZFz8tSgGw17GsDPXAJ6p91IvYDjOw8GpFbvvZGAK+DPQQ== +jest-worker@^24.6.0, jest-worker@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.9.0.tgz#5dbfdb5b2d322e98567898238a9697bcce67b3e5" + integrity sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw== dependencies: - merge-stream "^1.0.1" + merge-stream "^2.0.0" supports-color "^6.1.0" -jest@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest/-/jest-24.8.0.tgz#d5dff1984d0d1002196e9b7f12f75af1b2809081" - integrity sha512-o0HM90RKFRNWmAWvlyV8i5jGZ97pFwkeVoGvPW1EtLTgJc2+jcuqcbbqcSZLE/3f2S5pt0y2ZBETuhpWNl1Reg== +jest@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-24.9.0.tgz#987d290c05a08b52c56188c1002e368edb007171" + integrity sha512-YvkBL1Zm7d2B1+h5fHEOdyjCG+sGMz4f8D86/0HiqJ6MB4MnDc8FgP5vdWsGnemOQro7lnYo8UakZ3+5A0jxGw== dependencies: import-local "^2.0.0" - jest-cli "^24.8.0" + jest-cli "^24.9.0" jetifier@^1.6.2: - version "1.6.3" - resolved "https://registry.yarnpkg.com/jetifier/-/jetifier-1.6.3.tgz#61a95b29aefddfe3b6d81ee956f5e99f8b9cba19" - integrity sha512-i0rb2nHVPZDPzFhgs9+yYxEDMh2z0iSHRD3vBQmvn98wlgWKwhmU2F3MUEEXfK+MLnKwLKqsCTvlcS1+CpDTUg== + version "1.6.5" + resolved "https://registry.yarnpkg.com/jetifier/-/jetifier-1.6.5.tgz#ea87324a4230bef20a9651178ecab978ee54a8cb" + integrity sha512-T7yzBSu9PR+DqjYt+I0KVO1XTb1QhAfHnXV5Nd3xpbXM6Xg4e3vP60Q4qkNU8Fh6PHC2PivPUNN3rY7G2MxcDQ== js-sha3@0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" integrity sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc= -js-tokens@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= - "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@3.13.1, js-yaml@^3.13.0, js-yaml@^3.13.1: +js-yaml@3.13.1, js-yaml@^3.13.1: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== @@ -6267,6 +6405,11 @@ jsbn@~0.1.0: resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= +jsc-android@^245459.0.0: + version "245459.0.0" + resolved "https://registry.yarnpkg.com/jsc-android/-/jsc-android-245459.0.0.tgz#e584258dd0b04c9159a27fb104cd5d491fd202c9" + integrity sha512-wkjURqwaB1daNkDi2OYYbsLnIdC/lUM2nPXQKRs5pqEU9chDg435bjvo+LSaHotDENygHQDHe+ntUkkw2gwMtg== + jsdom@^11.5.1: version "11.12.0" resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-11.12.0.tgz#1a80d40ddd378a1de59656e9e6dc5a3ba8657bc8" @@ -6342,12 +6485,17 @@ json-stringify-safe@~5.0.1: integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= json5@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.0.tgz#e7a0c62c48285c628d20a10b85c89bb807c32850" - integrity sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ== + version "2.1.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.1.tgz#81b6cb04e9ba496f1c7005d07b4368a2638f90b6" + integrity sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ== dependencies: minimist "^1.2.0" +jsonc-parser@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.2.0.tgz#f206f87f9d49d644b7502052c04e82dd6392e9ef" + integrity sha512-4fLQxW1j/5fWj6p78vAlAafoCKtuBm6ghv+Ij5W2DrDx0qE+ZdEl2c6Ko1mgJNF5ftX1iEWQQ4Ap7+3GlhjkOA== + jsonfile@^2.1.0: version "2.4.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" @@ -6377,10 +6525,10 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" -jsx-ast-utils@^2.0.1, jsx-ast-utils@^2.1.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.2.1.tgz#4d4973ebf8b9d2837ee91a8208cc66f3a2776cfb" - integrity sha512-v3FxCcAf20DayI+uxnCuw795+oOIkVu6EnJ1+kSzhqqTZHNkTZ7B66ZgLp4oLJ/gbA64cI0B7WRoHZMSRdyVRQ== +jsx-ast-utils@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.2.3.tgz#8a9364e402448a3ce7f14d357738310d9248054f" + integrity sha512-EdIHFMm+1BPynpKOpdPqiOsvnIrInRGJD7bzPZdPkjitQEqpdpUuFpq4T0npZFKTiB3RhWFdGN+oqOJIdhDhQA== dependencies: array-includes "^3.0.3" object.assign "^4.1.0" @@ -6421,7 +6569,7 @@ kind-of@^5.0.0: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== -kind-of@^6.0.0, kind-of@^6.0.2: +kind-of@^6.0.0, kind-of@^6.0.1, kind-of@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== @@ -6440,7 +6588,7 @@ klaw@^1.0.0: optionalDependencies: graceful-fs "^4.1.9" -kleur@^3.0.2: +kleur@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== @@ -6559,11 +6707,6 @@ levelup@^0.18.2: semver "~2.3.1" xtend "~3.0.0" -leven@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" - integrity sha1-wuep93IJTe6dNCAq6KzORoeHVYA= - leven@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" @@ -6577,6 +6720,11 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +lines-and-columns@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" + integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= + load-json-file@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" @@ -6613,26 +6761,23 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +lodash.clonedeepwith@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clonedeepwith/-/lodash.clonedeepwith-4.5.0.tgz#6ee30573a03a1a60d670a62ef33c10cf1afdbdd4" + integrity sha1-buMFc6A6GmDWcKYu8zwQzxr9vdQ= + lodash.debounce@4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= -lodash.pad@^4.1.0: - version "4.5.1" - resolved "https://registry.yarnpkg.com/lodash.pad/-/lodash.pad-4.5.1.tgz#4330949a833a7c8da22cc20f6a26c4d59debba70" - integrity sha1-QzCUmoM6fI2iLMIPaibE1Z3runA= - -lodash.padend@^4.1.0: - version "4.6.1" - resolved "https://registry.yarnpkg.com/lodash.padend/-/lodash.padend-4.6.1.tgz#53ccba047d06e158d311f45da625f4e49e6f166e" - integrity sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4= - -lodash.padstart@^4.1.0: - version "4.6.1" - resolved "https://registry.yarnpkg.com/lodash.padstart/-/lodash.padstart-4.6.1.tgz#d2e3eebff0d9d39ad50f5cbd1b52a7bce6bb611b" - integrity sha1-0uPuv/DZ05rVD1y9G1KnvOa7YRs= - lodash.snakecase@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz#39d714a35357147837aefd64b5dcbb16becd8f8d" @@ -6658,7 +6803,7 @@ lodash.unescape@4.0.1: resolved "https://registry.yarnpkg.com/lodash.unescape/-/lodash.unescape-4.0.1.tgz#bf2249886ce514cda112fae9218cdc065211fc9c" integrity sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw= -lodash@4.x.x, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.6.1: +lodash@4.x.x, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== @@ -6677,12 +6822,13 @@ log-symbols@^3.0.0: dependencies: chalk "^2.4.2" -logkitty@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/logkitty/-/logkitty-0.5.0.tgz#5a348c2049551aa02da69543c3b5c44e28c7c24f" - integrity sha512-UA06TmPaSPiHxMBlo5uxL3ZvjJ2Gx/rEECrqowHsIsNoAoSB8aBSP553Fr2FJhOp3it2ulLsd520DZWS1IaYOw== +logkitty@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/logkitty/-/logkitty-0.6.1.tgz#fe29209669d261539cbd6bb998a136fc92a1a05c" + integrity sha512-cHuXN8qUZuzX/7kB6VyS7kB4xyD24e8gyHXIFNhIv+fjW3P+jEXNUhj0o/7qWJtv7UZpbnPgUqzu/AZQ8RAqxQ== dependencies: ansi-fragments "^0.2.1" + dayjs "^1.8.15" yargs "^12.0.5" longest-streak@^2.0.1: @@ -6710,7 +6856,7 @@ lowercase-keys@^1.0.0: resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== -lru-cache@^4.0.1, lru-cache@^4.1.2: +lru-cache@^4.0.1: version "4.1.5" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== @@ -6718,6 +6864,13 @@ lru-cache@^4.0.1, lru-cache@^4.1.2: pseudomap "^1.0.2" yallist "^2.1.2" +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + ltgt@^2.1.3: version "2.2.1" resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" @@ -6784,10 +6937,13 @@ markdown-table@^1.1.0: resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.3.tgz#9fcb69bcfdb8717bfd0398c6ec2d93036ef8de60" integrity sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q== -math-random@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c" - integrity sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A== +match-sorter@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/match-sorter/-/match-sorter-4.0.2.tgz#1b451e8bc7112e5a41ebe3a977b7e19f167c3215" + integrity sha512-5EcCLEmPgfvq2hg1DAgAG7zqqS9bnZmRXzLR3md0xRi3Q1oGnnze6HuY+4bDRtm+X2lTsVZL8oG9FOkALFT4vw== + dependencies: + "@babel/runtime" "^7.5.5" + remove-accents "0.4.2" mathml-tag-names@^2.1.0: version "2.1.1" @@ -6804,9 +6960,9 @@ md5.js@^1.3.4: safe-buffer "^5.1.2" mdast-util-compact@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/mdast-util-compact/-/mdast-util-compact-1.0.3.tgz#98a25cc8a7865761a41477b3a87d1dcef0b1e79d" - integrity sha512-nRiU5GpNy62rZppDKbLwhhtw5DXoFMqw9UNZFmlPsNaQCZ//WLjGKUwWMdJrUH+Se7UvtO2gXtAMe0g/N+eI5w== + version "1.0.4" + resolved "https://registry.yarnpkg.com/mdast-util-compact/-/mdast-util-compact-1.0.4.tgz#d531bb7667b5123abf20859be086c4d06c894593" + integrity sha512-3YDMQHI5vRiS2uygEFYaqckibpJtKq5Sj2c8JioeOQBU6INpKbdWzfyLqFFnDwEcEnRFIdMsguzs5pC1Jp4Isg== dependencies: unist-util-visit "^1.1.0" @@ -6815,10 +6971,10 @@ mdn-data@2.0.4: resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA== -mdn-data@~1.1.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-1.1.4.tgz#50b5d4ffc4575276573c4eedb8780812a8419f01" - integrity sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA== +mdn-data@2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.6.tgz#852dc60fcaa5daa2e8cf6c9189c440ed3e042978" + integrity sha512-rQvjv71olwNHgiTbfPZFkJtjNMciWgswYeciZhtvWLO8bmX3TnhyA62I6sTWOyZssWHJJjY6/KiWwqQsWWsqOA== mem@^1.1.0: version "1.1.0" @@ -6837,9 +6993,9 @@ mem@^4.0.0: p-is-promise "^2.0.0" memoize-one@^5.0.0: - version "5.0.5" - resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.0.5.tgz#8cd3809555723a07684afafcd6f756072ac75d7e" - integrity sha512-ey6EpYv0tEaIbM/nTDOpHciXUvd+ackQrJgEzBwemhZZIWZjcyodqEcrmqDy2BKRTM3a65kKBV4WtLXJDt26SQ== + version "5.1.1" + resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.1.1.tgz#047b6e3199b508eaec03504de71229b8eb1d75c0" + integrity sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA== meow@^5.0.0: version "5.0.0" @@ -6857,11 +7013,11 @@ meow@^5.0.0: yargs-parser "^10.0.0" merge-anything@^2.2.4, merge-anything@^2.2.5: - version "2.4.0" - resolved "https://registry.yarnpkg.com/merge-anything/-/merge-anything-2.4.0.tgz#86959caf02bb8969d1ae5e1b652862bc5fe54e44" - integrity sha512-MhJcPOEcDUIbwU0LnEfx5S9s9dfQ/KPu4g2UA5T5G1LRKS0XmpDvJ9+UUfTkfhge+nA1gStE4tJAvx6lXLs+rg== + version "2.4.4" + resolved "https://registry.yarnpkg.com/merge-anything/-/merge-anything-2.4.4.tgz#6226b2ac3d3d3fc5fb9e8d23aa400df25f98fdf0" + integrity sha512-l5XlriUDJKQT12bH+rVhAHjwIuXWdAIecGwsYjv2LJo+dA1AeRTmeQS+3QBpO6lEthBMDi2IUMpLC1yyRvGlwQ== dependencies: - is-what "^3.2.4" + is-what "^3.3.1" merge-deep@^3.0.2: version "3.0.2" @@ -6879,25 +7035,25 @@ merge-stream@^1.0.1: dependencies: readable-stream "^2.0.1" -merge2@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.3.tgz#7ee99dbd69bb6481689253f018488a1b902b0ed5" - integrity sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA== +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -merge@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.1.tgz#38bebf80c3220a8a487b6fcfb3941bb11720c145" - integrity sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ== +merge2@^1.2.3: + version "1.3.0" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" + integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw== methods@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= -metro-babel-register@0.51.0: - version "0.51.0" - resolved "https://registry.yarnpkg.com/metro-babel-register/-/metro-babel-register-0.51.0.tgz#d86d3f2d90b45c7a3c6ae67a53bd1e50bad7a24d" - integrity sha512-rhdvHFOZ7/ub019A3+aYs8YeLydb02/FAMsKr2Nz2Jlf6VUxWrMnrcT0NYX16F9TGdi2ulRlJ9dwvUmdhkk+Bw== +metro-babel-register@0.56.3: + version "0.56.3" + resolved "https://registry.yarnpkg.com/metro-babel-register/-/metro-babel-register-0.56.3.tgz#d0cfb38adf45cb35965649ede794f2308562e20f" + integrity sha512-ILCRtNFdW6vzqmLAG2MYWdTSE1vCAZqDKNggiNhlfViuoxmWAIL0vOqixl1CHZF5z4t55+fk46A0jSN7UgPyVw== dependencies: "@babel/core" "^7.0.0" "@babel/plugin-proposal-class-properties" "^7.0.0" @@ -6912,10 +7068,10 @@ metro-babel-register@0.51.0: core-js "^2.2.2" escape-string-regexp "^1.0.5" -metro-babel-register@0.54.1: - version "0.54.1" - resolved "https://registry.yarnpkg.com/metro-babel-register/-/metro-babel-register-0.54.1.tgz#7d2bfe444b1ccef8de99aedc7d9330891d806076" - integrity sha512-j3VydgncUG8HP6AZala6GTIt3V01nptodnnOke3JMYLqgk8EJ1LOVOdotK9pXi80o7EmmNKFs/LyyH8z+uAJzQ== +metro-babel-register@0.57.0: + version "0.57.0" + resolved "https://registry.yarnpkg.com/metro-babel-register/-/metro-babel-register-0.57.0.tgz#43acb47a7f45543428830db5634b33e8e7543c39" + integrity sha512-toZwgFY/y/+8GxSLT6kDRI5/hcnm7VtVglMo8WN9p9LEeGjKgWeJrf6YrrqQ8L+Ycy771w00jHZVw2QwlvCQUQ== dependencies: "@babel/core" "^7.0.0" "@babel/plugin-proposal-class-properties" "^7.0.0" @@ -6930,115 +7086,58 @@ metro-babel-register@0.54.1: core-js "^2.2.2" escape-string-regexp "^1.0.5" -metro-babel-transformer@0.51.0: - version "0.51.0" - resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.51.0.tgz#9ee5199163ac46b2057527b3f8cbd8b089ffc03e" - integrity sha512-M7KEY/hjD3E8tJEliWgI0VOSaJtqaznC0ItM6FiMrhoGDqqa1BvGofl+EPcKqjBSOV1UgExua/T1VOIWbjwQsw== - dependencies: - "@babel/core" "^7.0.0" - -metro-babel-transformer@0.51.1: - version "0.51.1" - resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.51.1.tgz#97be9e2b96c78aa202b52ae05fb86f71327aef72" - integrity sha512-+tOnZZzOzufB86ASdfimUEGB1jBKsdsVpPdjNJZkueTFyvYlGqWDQKHM1w9bwKMeM/czPQ48Y6m8Bou6le0X4w== +metro-babel-transformer@0.56.3: + version "0.56.3" + resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.56.3.tgz#6559c3a8565238a704a181353cef59fdb974e6db" + integrity sha512-N5/ftb3rBkt6uKlgYAv+lwtzYc4dK0tBpfZ8pjec3kcypGuGTuf4LTHEh65EuzySreLngYI0bQzoFSn3G3DYsw== dependencies: "@babel/core" "^7.0.0" + metro-source-map "0.56.3" -metro-babel-transformer@0.54.1: - version "0.54.1" - resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.54.1.tgz#371ffa2d1118b22cc9e40b3c3ea6738c49dae9dc" - integrity sha512-2aiAnuYBdcLV1VINb8ENAA4keIaJIepHgR9+iRvIde+9GSjKnexqx4nNmJN392285gRDp1fVZ7uY0uQawK/A5g== +metro-babel-transformer@0.57.0: + version "0.57.0" + resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.57.0.tgz#8f4bd17ad5631937cdb5651e7d77f9c73b9f935c" + integrity sha512-679BstNiPUUt5a4f86iJTa7q8jFntgd9SQBVWN+CLI5L9T7iTxi7JDbR+oHIOi3OT/dBlY9s2dWZCVAuNW9DHA== dependencies: "@babel/core" "^7.0.0" + metro-source-map "0.57.0" -metro-babel7-plugin-react-transform@0.51.0: - version "0.51.0" - resolved "https://registry.yarnpkg.com/metro-babel7-plugin-react-transform/-/metro-babel7-plugin-react-transform-0.51.0.tgz#af27dd81666b91f05d2b371b0d6d283c585e38b6" - integrity sha512-dZ95kXcE2FJMoRsYhxr7YLCbOlHWKwe0bOpihRhfImDTgFfuKIzU4ROQwMUbE0NCbzB+ATFsa2FZ3pHDJ5GI0w== - dependencies: - "@babel/helper-module-imports" "^7.0.0" - -metro-babel7-plugin-react-transform@0.51.1: - version "0.51.1" - resolved "https://registry.yarnpkg.com/metro-babel7-plugin-react-transform/-/metro-babel7-plugin-react-transform-0.51.1.tgz#9cce2c340cc4006fc82aa6dfab27af22d592607e" - integrity sha512-wzn4X9KgmAMZ7Bi6v9KxA7dw+AHGL0RODPxU5NDJ3A6d0yERvzfZ3qkzWhz8jbFkVBK12cu5DTho3HBazKQDOw== - dependencies: - "@babel/helper-module-imports" "^7.0.0" - -metro-babel7-plugin-react-transform@0.54.1: - version "0.54.1" - resolved "https://registry.yarnpkg.com/metro-babel7-plugin-react-transform/-/metro-babel7-plugin-react-transform-0.54.1.tgz#5335b810284789724886dc483d5bde9c149a1996" - integrity sha512-jWm5myuMoZAOhoPsa8ItfDxdTcOzKhTTzzhFlbZnRamE7i9qybeMdrZt8KHQpF7i2p/mKzE9Yhf4ouOz5K/jHg== - dependencies: - "@babel/helper-module-imports" "^7.0.0" - -metro-cache@0.51.1: - version "0.51.1" - resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.51.1.tgz#d0b296eab8e009214413bba87e4eac3d9b44cd04" - integrity sha512-0m1+aicsw77LVAehNuTxDpE1c/7Xv/ajRD+UL/lFCWUxnrjSbxVtIKr8l5DxEY11082c1axVRuaV9e436W+eXg== - dependencies: - jest-serializer "24.0.0-alpha.6" - metro-core "0.51.1" - mkdirp "^0.5.1" - rimraf "^2.5.4" - -metro-cache@0.54.1: - version "0.54.1" - resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.54.1.tgz#2e9017cbd11106837b8c385c9eb8c8175469a8c1" - integrity sha512-RxCFoNcANHXZYi4MIQNnqh68gUnC3bMpzCFJY5pBoqqdrkkn8ibYglBweA0/DW7hx1OZTJWelwS1Dp8xxmE2CA== +metro-cache@0.56.3: + version "0.56.3" + resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.56.3.tgz#1b0759bc45291cc3ffc77736c09dcfbd322edb8b" + integrity sha512-SsryVe/TVkt2IkEGnYhB3gQlg9iMlu8WJikQHcCEjMfPEnSIzmeymrX73fwQNPnTnN7F3E0HVjH6Wvq6fh0mcA== dependencies: jest-serializer "^24.4.0" - metro-core "0.54.1" + metro-core "0.56.3" mkdirp "^0.5.1" rimraf "^2.5.4" -metro-config@0.51.1, metro-config@^0.51.0: - version "0.51.1" - resolved "https://registry.yarnpkg.com/metro-config/-/metro-config-0.51.1.tgz#8f1a241ce2c0b521cd492c39bc5c6c69e3397b82" - integrity sha512-WCNd0tTI9gb/ubgTqK1+ljZL4b3hsXVinsOAtep4nHiVb6DSDdbO2yXDD2rpYx3NE6hDRMFS9HHg6G0139pAqQ== - dependencies: - cosmiconfig "^5.0.5" - metro "0.51.1" - metro-cache "0.51.1" - metro-core "0.51.1" - pretty-format "24.0.0-alpha.6" - -metro-config@0.54.1, metro-config@^0.54.1: - version "0.54.1" - resolved "https://registry.yarnpkg.com/metro-config/-/metro-config-0.54.1.tgz#808b4e17625d9f4e9afa34232778fdf8e63cc8dd" - integrity sha512-FpxrA+63rGkPGvGI653dvuSreJzU+eOTILItVnnhmqwn2SAK5V00N/qGTOIJe2YIuWEFXwCzw9lXmANrXbwuGg== +metro-config@0.56.3, metro-config@^0.56.0: + version "0.56.3" + resolved "https://registry.yarnpkg.com/metro-config/-/metro-config-0.56.3.tgz#b16e600817c58c768946f24b039d2a1ba6a67651" + integrity sha512-C3ZLA5y5gW5auDSQN5dsCTduJg7LXEiX/tLAADOkgXWVImr5P74x9Wt8y1MMWrKx6p+4p5RMDyEwWDMXJt/DwA== dependencies: cosmiconfig "^5.0.5" jest-validate "^24.7.0" - metro "0.54.1" - metro-cache "0.54.1" - metro-core "0.54.1" + metro "0.56.3" + metro-cache "0.56.3" + metro-core "0.56.3" pretty-format "^24.7.0" -metro-core@0.51.1, metro-core@^0.51.0: - version "0.51.1" - resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.51.1.tgz#e7227fb1dd1bb3f953272fad9876e6201140b038" - integrity sha512-sG1yACjdFqmIzZN50HqLTKUMp1oy0AehHhmIuYeIllo1DjX6Y2o3UAT3rGP8U+SAqJGXf/OWzl6VNyRPGDENfA== - dependencies: - jest-haste-map "24.0.0-alpha.6" - lodash.throttle "^4.1.1" - metro-resolver "0.51.1" - wordwrap "^1.0.0" - -metro-core@0.54.1, metro-core@^0.54.1: - version "0.54.1" - resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.54.1.tgz#17f6ecc167918da8819d4af5726349e55714954b" - integrity sha512-8oz3Ck7QFBzW9dG9tKFhrXHKPu2Ajx3R7eatf61Gl6Jf/tF7PNouv3wHxPsJW3oXDFiwKLszd89+OgleTGkB5g== +metro-core@0.56.3, metro-core@^0.56.0: + version "0.56.3" + resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.56.3.tgz#34bb3a92621fd9b1ed3e6a01c6a4324fbb1201d9" + integrity sha512-OAaHP3mBdlACMZRwDJzZzYC0o2S3qfb4BBK75L8H4Ds+y3QUSrjsDEpHACcpaMTOds8rBvjzn+jjB5tqNoHfBA== dependencies: jest-haste-map "^24.7.1" lodash.throttle "^4.1.1" - metro-resolver "0.54.1" + metro-resolver "0.56.3" wordwrap "^1.0.0" -metro-inspector-proxy@0.54.1: - version "0.54.1" - resolved "https://registry.yarnpkg.com/metro-inspector-proxy/-/metro-inspector-proxy-0.54.1.tgz#0ef48ee3feb11c6da47aa100151a9bf2a7c358ee" - integrity sha512-sf6kNu7PgFW6U+hU7YGZfbAUKAPVvCJhY8YVu/A1RMKH9nNULrCo+jlWh0gWgmFfWRQiAPCElevROg+5somk8A== +metro-inspector-proxy@0.56.3: + version "0.56.3" + resolved "https://registry.yarnpkg.com/metro-inspector-proxy/-/metro-inspector-proxy-0.56.3.tgz#48046f9e3f7153be2409e0bee9252dede932ac39" + integrity sha512-7WtHinw+VJcunQ3q8El1MqqzYSRvXEjW5QE13VYwcLtnay3pvcqACeiQmGbWI0IqxB1+QH8tf3nkA7z7pQ7Vpw== dependencies: connect "^3.6.5" debug "^2.2.0" @@ -7046,111 +7145,17 @@ metro-inspector-proxy@0.54.1: ws "^1.1.5" yargs "^9.0.0" -metro-memory-fs@^0.51.0: - version "0.51.1" - resolved "https://registry.yarnpkg.com/metro-memory-fs/-/metro-memory-fs-0.51.1.tgz#624291f5956b0fd11532d80b1b85d550926f96c9" - integrity sha512-dXVUpLPLwfQcYHd1HlqHGVzBsiwvUdT92TDSbdc10152TP+iynHBqLDWbxt0MAtd6c/QXwOuGZZ1IcX3+lv5iw== - -metro-minify-uglify@0.51.1: - version "0.51.1" - resolved "https://registry.yarnpkg.com/metro-minify-uglify/-/metro-minify-uglify-0.51.1.tgz#60cd8fe4d3e82d6670c717b8ddb52ae63199c0e4" - integrity sha512-HAqd/rFrQ6mnbqVAszDXIKTg2rqHlY9Fm8DReakgbkAeyMbF2mH3kEgtesPmTrhajdFk81UZcNSm6wxj1JMgVg== - dependencies: - uglify-es "^3.1.9" - -metro-minify-uglify@0.54.1: - version "0.54.1" - resolved "https://registry.yarnpkg.com/metro-minify-uglify/-/metro-minify-uglify-0.54.1.tgz#54ed1cb349245ce82dba8cc662bbf69fbca142c3" - integrity sha512-z+pOPna/8IxD4OhjW6Xo1mV2EszgqqQHqBm1FdmtdF6IpWkQp33qpDBNEi9NGZTOr7pp2bvcxZnvNJdC2lrK9Q== +metro-minify-uglify@0.56.3: + version "0.56.3" + resolved "https://registry.yarnpkg.com/metro-minify-uglify/-/metro-minify-uglify-0.56.3.tgz#763b26895f79d0589d3391dc94083d348cf9c2be" + integrity sha512-b9ljyeUpkJWVlFy8M/i4aNbvEBI0zN9vJh1jfU7yx+k9dX7FulLnpGmAQxxQdEszcM//sJrsKNS1oLYBxr0NMQ== dependencies: uglify-es "^3.1.9" -metro-react-native-babel-preset@0.51.0: - version "0.51.0" - resolved "https://registry.yarnpkg.com/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.51.0.tgz#978d960acf2d214bbbe43e59145878d663bd07de" - integrity sha512-Y/aPeLl4RzY8IEAneOyDcpdjto/8yjIuX9eUWRngjSqdHYhGQtqiSBpfTpo0BvXpwNRLwCLHyXo58gNpckTJFw== - dependencies: - "@babel/plugin-proposal-class-properties" "^7.0.0" - "@babel/plugin-proposal-export-default-from" "^7.0.0" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.0.0" - "@babel/plugin-proposal-object-rest-spread" "^7.0.0" - "@babel/plugin-proposal-optional-catch-binding" "^7.0.0" - "@babel/plugin-proposal-optional-chaining" "^7.0.0" - "@babel/plugin-syntax-dynamic-import" "^7.0.0" - "@babel/plugin-syntax-export-default-from" "^7.0.0" - "@babel/plugin-transform-arrow-functions" "^7.0.0" - "@babel/plugin-transform-block-scoping" "^7.0.0" - "@babel/plugin-transform-classes" "^7.0.0" - "@babel/plugin-transform-computed-properties" "^7.0.0" - "@babel/plugin-transform-destructuring" "^7.0.0" - "@babel/plugin-transform-exponentiation-operator" "^7.0.0" - "@babel/plugin-transform-flow-strip-types" "^7.0.0" - "@babel/plugin-transform-for-of" "^7.0.0" - "@babel/plugin-transform-function-name" "^7.0.0" - "@babel/plugin-transform-literals" "^7.0.0" - "@babel/plugin-transform-modules-commonjs" "^7.0.0" - "@babel/plugin-transform-object-assign" "^7.0.0" - "@babel/plugin-transform-parameters" "^7.0.0" - "@babel/plugin-transform-react-display-name" "^7.0.0" - "@babel/plugin-transform-react-jsx" "^7.0.0" - "@babel/plugin-transform-react-jsx-source" "^7.0.0" - "@babel/plugin-transform-regenerator" "^7.0.0" - "@babel/plugin-transform-runtime" "^7.0.0" - "@babel/plugin-transform-shorthand-properties" "^7.0.0" - "@babel/plugin-transform-spread" "^7.0.0" - "@babel/plugin-transform-sticky-regex" "^7.0.0" - "@babel/plugin-transform-template-literals" "^7.0.0" - "@babel/plugin-transform-typescript" "^7.0.0" - "@babel/plugin-transform-unicode-regex" "^7.0.0" - "@babel/template" "^7.0.0" - metro-babel7-plugin-react-transform "0.51.0" - react-transform-hmr "^1.0.4" - -metro-react-native-babel-preset@0.51.1: - version "0.51.1" - resolved "https://registry.yarnpkg.com/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.51.1.tgz#44aeeedfea37f7c2ab8f6f273fa71b90fe65f089" - integrity sha512-e9tsYDFhU70gar0jQWcZXRPJVCv4k7tEs6Pm74wXO2OO/T1MEumbvniDIGwGG8bG8RUnYdHhjcaiub2Vc5BRWw== - dependencies: - "@babel/plugin-proposal-class-properties" "^7.0.0" - "@babel/plugin-proposal-export-default-from" "^7.0.0" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.0.0" - "@babel/plugin-proposal-object-rest-spread" "^7.0.0" - "@babel/plugin-proposal-optional-catch-binding" "^7.0.0" - "@babel/plugin-proposal-optional-chaining" "^7.0.0" - "@babel/plugin-syntax-dynamic-import" "^7.0.0" - "@babel/plugin-syntax-export-default-from" "^7.0.0" - "@babel/plugin-transform-arrow-functions" "^7.0.0" - "@babel/plugin-transform-block-scoping" "^7.0.0" - "@babel/plugin-transform-classes" "^7.0.0" - "@babel/plugin-transform-computed-properties" "^7.0.0" - "@babel/plugin-transform-destructuring" "^7.0.0" - "@babel/plugin-transform-exponentiation-operator" "^7.0.0" - "@babel/plugin-transform-flow-strip-types" "^7.0.0" - "@babel/plugin-transform-for-of" "^7.0.0" - "@babel/plugin-transform-function-name" "^7.0.0" - "@babel/plugin-transform-literals" "^7.0.0" - "@babel/plugin-transform-modules-commonjs" "^7.0.0" - "@babel/plugin-transform-object-assign" "^7.0.0" - "@babel/plugin-transform-parameters" "^7.0.0" - "@babel/plugin-transform-react-display-name" "^7.0.0" - "@babel/plugin-transform-react-jsx" "^7.0.0" - "@babel/plugin-transform-react-jsx-source" "^7.0.0" - "@babel/plugin-transform-regenerator" "^7.0.0" - "@babel/plugin-transform-runtime" "^7.0.0" - "@babel/plugin-transform-shorthand-properties" "^7.0.0" - "@babel/plugin-transform-spread" "^7.0.0" - "@babel/plugin-transform-sticky-regex" "^7.0.0" - "@babel/plugin-transform-template-literals" "^7.0.0" - "@babel/plugin-transform-typescript" "^7.0.0" - "@babel/plugin-transform-unicode-regex" "^7.0.0" - "@babel/template" "^7.0.0" - metro-babel7-plugin-react-transform "0.51.1" - react-transform-hmr "^1.0.4" - -metro-react-native-babel-preset@0.54.1: - version "0.54.1" - resolved "https://registry.yarnpkg.com/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.54.1.tgz#b8f03865c381841d7f8912e7ba46804ea3a928b8" - integrity sha512-Hfr32+u5yYl3qhYQJU8NQ26g4kQlc3yFMg7keVR/3H8rwBIbFqXgsKt8oe0dOrv7WvrMqBHhDtVdU9ls3sSq8g== +metro-react-native-babel-preset@0.56.3: + version "0.56.3" + resolved "https://registry.yarnpkg.com/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.56.3.tgz#5a1097c2f94e8ee0797a8ba2ab8f86d096f4c093" + integrity sha512-tGPzX2ZwI8vQ8SiNVBPUIgKqmaRNVB6rtJtHCBQZAYRiMbxh0NHCUoFfKBej6U5qVgxiYYHyN8oB23evG4/Oow== dependencies: "@babel/plugin-proposal-class-properties" "^7.0.0" "@babel/plugin-proposal-export-default-from" "^7.0.0" @@ -7186,13 +7191,12 @@ metro-react-native-babel-preset@0.54.1: "@babel/plugin-transform-typescript" "^7.0.0" "@babel/plugin-transform-unicode-regex" "^7.0.0" "@babel/template" "^7.0.0" - metro-babel7-plugin-react-transform "0.54.1" - react-transform-hmr "^1.0.4" + react-refresh "^0.4.0" -metro-react-native-babel-preset@^0.55.0: - version "0.55.0" - resolved "https://registry.yarnpkg.com/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.55.0.tgz#d5d4a6cbe9ccbcedd72fcbb71c0c311e3d56876e" - integrity sha512-HUI+dEiVym8f1NYIF1grY9PdoY0d3SSS/HED2dDDvTORwndsAEWuXiUgKFOGWX18+RUAQog8obVQuBMgrr8ZBQ== +metro-react-native-babel-preset@0.57.0, metro-react-native-babel-preset@^0.57.0: + version "0.57.0" + resolved "https://registry.yarnpkg.com/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.57.0.tgz#bbbce26a20d9ca3fdc08f0df564bc982b82651b7" + integrity sha512-pvLh1QOwdxsjgYE2a+4aTKs3LSF3+t4jscxHtkND6wsJnKVVspLt8FkDaORa6zr3Fq12tVpEt5NJMdgtWqBpaA== dependencies: "@babel/plugin-proposal-class-properties" "^7.0.0" "@babel/plugin-proposal-export-default-from" "^7.0.0" @@ -7228,129 +7232,89 @@ metro-react-native-babel-preset@^0.55.0: "@babel/plugin-transform-typescript" "^7.0.0" "@babel/plugin-transform-unicode-regex" "^7.0.0" "@babel/template" "^7.0.0" - react-refresh "^0.2.0" + react-refresh "^0.4.0" -metro-react-native-babel-transformer@0.51.0: - version "0.51.0" - resolved "https://registry.yarnpkg.com/metro-react-native-babel-transformer/-/metro-react-native-babel-transformer-0.51.0.tgz#57a695e97a19d95de63c9633f9d0dc024ee8e99a" - integrity sha512-VFnqtE0qrVmU1HV9B04o53+NZHvDwR+CWCoEx4+7vCqJ9Tvas741biqCjah9xtifoKdElQELk6x0soOAWCDFJA== +metro-react-native-babel-transformer@0.57.0: + version "0.57.0" + resolved "https://registry.yarnpkg.com/metro-react-native-babel-transformer/-/metro-react-native-babel-transformer-0.57.0.tgz#60e3b97f73f016c138096c1a706ccc3bc4590fcf" + integrity sha512-Pw8N3InjUVJT23w/LNKwrWeXY50aODv2js/WCfwguZqriJqELOCxF1BWgvsChGNuDpkl0ihKct4224w0+4ktyA== dependencies: "@babel/core" "^7.0.0" - babel-preset-fbjs "^3.0.1" - metro-babel-transformer "0.51.0" - metro-react-native-babel-preset "0.51.0" + babel-preset-fbjs "^3.3.0" + metro-babel-transformer "0.57.0" + metro-react-native-babel-preset "0.57.0" + metro-source-map "0.57.0" -metro-react-native-babel-transformer@^0.51.0: - version "0.51.1" - resolved "https://registry.yarnpkg.com/metro-react-native-babel-transformer/-/metro-react-native-babel-transformer-0.51.1.tgz#bac34f988c150c725cd1875c13701cc2032615f9" - integrity sha512-D0KU+JPb/Z76nUWt3+bkjKggOlGvqAVI2BpIH2JFKprpUyBjWaCRqHnkBfZGixYwUfmu93MIlKJWr6iKzzFrlg== - dependencies: - "@babel/core" "^7.0.0" - babel-preset-fbjs "^3.0.1" - metro-babel-transformer "0.51.1" - metro-react-native-babel-preset "0.51.1" - -metro-react-native-babel-transformer@^0.54.1: - version "0.54.1" - resolved "https://registry.yarnpkg.com/metro-react-native-babel-transformer/-/metro-react-native-babel-transformer-0.54.1.tgz#45b56db004421134e10e739f69e8de50775fef17" - integrity sha512-ECw7xG91t8dk/PHdiyoC5SP1s9OQzfmJzG5m0YOZaKtHMe534qTDbncxaKfTI3CP99yti2maXFBRVj+xyvph/g== +metro-react-native-babel-transformer@^0.56.0: + version "0.56.3" + resolved "https://registry.yarnpkg.com/metro-react-native-babel-transformer/-/metro-react-native-babel-transformer-0.56.3.tgz#e68205230be65c07290b932f7684226013dae310" + integrity sha512-T87m4jDu0gIvJo8kWEvkodWFgQ8XBzJUESs1hUUTBSMIqTa31MdWfA1gs+MipadG7OsEJpcb9m83mGr8K70MWw== dependencies: "@babel/core" "^7.0.0" babel-preset-fbjs "^3.1.2" - metro-babel-transformer "0.54.1" - metro-react-native-babel-preset "0.54.1" - -metro-resolver@0.51.1: - version "0.51.1" - resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.51.1.tgz#4c26f0baee47d30250187adca3d34c902e627611" - integrity sha512-zmWbD/287NDA/jLPuPV0hne/YMMSG0dljzu21TYMg2lXRLur/zROJHHhyepZvuBHgInXBi4Vhr2wvuSnY39SuA== - dependencies: - absolute-path "^0.0.0" + metro-babel-transformer "0.56.3" + metro-react-native-babel-preset "0.56.3" + metro-source-map "0.56.3" -metro-resolver@0.54.1: - version "0.54.1" - resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.54.1.tgz#0295b38624b678b88b16bf11d47288845132b087" - integrity sha512-Byv1LIawYAASy9CFRwzrncYnqaFGLe8vpw178EtzStqP05Hu6hXSqkNTrfoXa+3V9bPFGCrVzFx2NY3gFp2btg== +metro-resolver@0.56.3: + version "0.56.3" + resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.56.3.tgz#f18978b919a5ecc67028732609a564880715ef75" + integrity sha512-VvMl4xUp0fy76WiP3YDtzMmrn6tN/jwxOBqlTy9MjN6R9sUXrGyO5thwn/uKQqp5vwBTuJev7nZL7OKzwludKA== dependencies: absolute-path "^0.0.0" -metro-source-map@0.51.1: - version "0.51.1" - resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.51.1.tgz#1a8da138e98e184304d5558b4f92a5c2141822d0" - integrity sha512-JyrE+RV4YumrboHPHTGsUUGERjQ681ImRLrSYDGcmNv4tfpk9nvAK26UAas4IvBYFCC9oW90m0udt3kaQGv59Q== +metro-source-map@0.56.3: + version "0.56.3" + resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.56.3.tgz#0cadc9f9eca9ece224a6fd28b9e4fa3a9834e24c" + integrity sha512-CheqWbJZSM0zjcNBqELUiocwH3XArrOk6alhVuzJ2gV/WTMBQFwP0TtQssSMwjnouMHNEzY8RxErXKXBk/zJmQ== dependencies: + "@babel/traverse" "^7.0.0" + "@babel/types" "^7.0.0" + invariant "^2.2.4" + metro-symbolicate "0.56.3" + ob1 "0.56.3" source-map "^0.5.6" + vlq "^1.0.0" -metro-source-map@0.54.1: - version "0.54.1" - resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.54.1.tgz#e17bad53c11978197d3c05c9168d799c2e04dcc5" - integrity sha512-E9iSYMSUSq5qYi1R2hTQtxH4Mxjzfgr/jaSmQIWi7h3fG2P1qOZNNSzeaeUeTK+s2N/ksVlkcL5kMikol8CDrQ== +metro-source-map@0.57.0: + version "0.57.0" + resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.57.0.tgz#f6715b8687041804e4e0679bad4e8946bf9dd5a7" + integrity sha512-hYd2MmLUOmOJkQCzABLV3mYW7JwzkfvL9SUAHhRDzUS4Z69k+Yh2805HpH8/gN6SGvfw0PuPXXEixtvW66b6yQ== dependencies: "@babel/traverse" "^7.0.0" "@babel/types" "^7.0.0" + invariant "^2.2.4" + metro-symbolicate "0.57.0" + ob1 "0.57.0" source-map "^0.5.6" + vlq "^1.0.0" -metro@0.51.1, metro@^0.51.0: - version "0.51.1" - resolved "https://registry.yarnpkg.com/metro/-/metro-0.51.1.tgz#b0aad4731593b9f244261bad1abb2a006d1c8969" - integrity sha512-nM0dqn8LQlMjhChl2fzTUq2EWiUebZM7nkesD9vQe47W10bj/tbRLPiIIAxht6SRDbPd/hRA+t39PxLhPSKEKg== +metro-symbolicate@0.56.3: + version "0.56.3" + resolved "https://registry.yarnpkg.com/metro-symbolicate/-/metro-symbolicate-0.56.3.tgz#20f9dc52fab3209903715716402692b3ac16831c" + integrity sha512-fSQtjjy4eiJDThSl9eloxMElhrs+5PQB+DKKzmTFXT8e2GDga+pa1xTBFRUACMO8BXGuWmxR7SnGDw0wo5Ngrw== dependencies: - "@babel/core" "^7.0.0" - "@babel/generator" "^7.0.0" - "@babel/parser" "^7.0.0" - "@babel/plugin-external-helpers" "^7.0.0" - "@babel/template" "^7.0.0" - "@babel/traverse" "^7.0.0" - "@babel/types" "^7.0.0" - absolute-path "^0.0.0" - async "^2.4.0" - babel-preset-fbjs "^3.0.1" - buffer-crc32 "^0.2.13" - chalk "^2.4.1" - concat-stream "^1.6.0" - connect "^3.6.5" - debug "^2.2.0" - denodeify "^1.2.1" - eventemitter3 "^3.0.0" - fbjs "^1.0.0" - fs-extra "^1.0.0" - graceful-fs "^4.1.3" - image-size "^0.6.0" invariant "^2.2.4" - jest-haste-map "24.0.0-alpha.6" - jest-worker "24.0.0-alpha.6" - json-stable-stringify "^1.0.1" - lodash.throttle "^4.1.1" - merge-stream "^1.0.1" - metro-babel-transformer "0.51.1" - metro-cache "0.51.1" - metro-config "0.51.1" - metro-core "0.51.1" - metro-minify-uglify "0.51.1" - metro-react-native-babel-preset "0.51.1" - metro-resolver "0.51.1" - metro-source-map "0.51.1" - mime-types "2.1.11" - mkdirp "^0.5.1" - node-fetch "^2.2.0" - nullthrows "^1.1.0" - react-transform-hmr "^1.0.4" - resolve "^1.5.0" - rimraf "^2.5.4" - serialize-error "^2.1.0" + metro-source-map "0.56.3" source-map "^0.5.6" - temp "0.8.3" - throat "^4.1.0" - wordwrap "^1.0.0" - write-file-atomic "^1.2.0" - ws "^1.1.5" - xpipe "^1.0.5" - yargs "^9.0.0" + through2 "^2.0.1" + vlq "^1.0.0" + +metro-symbolicate@0.57.0: + version "0.57.0" + resolved "https://registry.yarnpkg.com/metro-symbolicate/-/metro-symbolicate-0.57.0.tgz#64693841190ad3d9b832af0490f16e95f51e4045" + integrity sha512-Gq30gqGAGYIpO7FdeUboQXaMUeiQqq2VNiPaLJg67zCz9FKLuS3Laf4i/mpUCzHv9+lqcEKIOEYP7SQaluUIPQ== + dependencies: + invariant "^2.2.4" + metro-source-map "0.57.0" + source-map "^0.5.6" + through2 "^2.0.1" + vlq "^1.0.0" -metro@0.54.1, metro@^0.54.1: - version "0.54.1" - resolved "https://registry.yarnpkg.com/metro/-/metro-0.54.1.tgz#a629be00abee5a450a25a8f71c24745f70cc9b44" - integrity sha512-6ODPT4mEo4FCpbExRNnQAcZmf1VeNvYOTMj2Na03FjGqhNODHhI2U/wF/Ul5gqTyJ2dVdkXeyvKW3gl/LrnJRg== +metro@0.56.3, metro@^0.56.0: + version "0.56.3" + resolved "https://registry.yarnpkg.com/metro/-/metro-0.56.3.tgz#3a38706bf6b1200421e871a4c53ddc2f359f65a9" + integrity sha512-mxHpvBGWanZ46wAEZVLinNO5IYMcFbTdMZIRhC7r+rvoSK6r9iPj95AujBfzLXMAl36RI2O3D7yp5hOYif/gEQ== dependencies: "@babel/core" "^7.0.0" "@babel/generator" "^7.0.0" @@ -7379,21 +7343,21 @@ metro@0.54.1, metro@^0.54.1: json-stable-stringify "^1.0.1" lodash.throttle "^4.1.1" merge-stream "^1.0.1" - metro-babel-register "0.54.1" - metro-babel-transformer "0.54.1" - metro-cache "0.54.1" - metro-config "0.54.1" - metro-core "0.54.1" - metro-inspector-proxy "0.54.1" - metro-minify-uglify "0.54.1" - metro-react-native-babel-preset "0.54.1" - metro-resolver "0.54.1" - metro-source-map "0.54.1" + metro-babel-register "0.56.3" + metro-babel-transformer "0.56.3" + metro-cache "0.56.3" + metro-config "0.56.3" + metro-core "0.56.3" + metro-inspector-proxy "0.56.3" + metro-minify-uglify "0.56.3" + metro-react-native-babel-preset "0.56.3" + metro-resolver "0.56.3" + metro-source-map "0.56.3" + metro-symbolicate "0.56.3" mime-types "2.1.11" mkdirp "^0.5.1" node-fetch "^2.2.0" nullthrows "^1.1.0" - react-transform-hmr "^1.0.4" resolve "^1.5.0" rimraf "^2.5.4" serialize-error "^2.1.0" @@ -7406,25 +7370,6 @@ metro@0.54.1, metro@^0.54.1: xpipe "^1.0.5" yargs "^9.0.0" -micromatch@^2.3.11: - version "2.3.11" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" - integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU= - dependencies: - arr-diff "^2.0.0" - array-unique "^0.2.1" - braces "^1.8.2" - expand-brackets "^0.1.4" - extglob "^0.3.1" - filename-regex "^2.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.1" - kind-of "^3.0.2" - normalize-path "^2.0.1" - object.omit "^2.0.0" - parse-glob "^3.0.4" - regex-cache "^0.4.2" - micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" @@ -7460,10 +7405,10 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@1.40.0, "mime-db@>= 1.40.0 < 2": - version "1.40.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32" - integrity sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA== +mime-db@1.43.0, "mime-db@>= 1.43.0 < 2": + version "1.43.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58" + integrity sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ== mime-db@~1.23.0: version "1.23.0" @@ -7478,13 +7423,13 @@ mime-types@2.1.11: mime-db "~1.23.0" mime-types@^2.1.12, mime-types@~2.1.19, mime-types@~2.1.24: - version "2.1.24" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.24.tgz#b6f8d0b3e951efb77dedeca194cff6d16f676f81" - integrity sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ== + version "2.1.26" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.26.tgz#9c921fc09b7e149a65dfdc0da4d20997200b0a06" + integrity sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ== dependencies: - mime-db "1.40.0" + mime-db "1.43.0" -mime@1.6.0, mime@^1.3.4: +mime@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== @@ -7499,7 +7444,7 @@ mimic-fn@^1.0.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== -mimic-fn@^2.0.0: +mimic-fn@^2.0.0, mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== @@ -7556,21 +7501,6 @@ minimist@~0.0.1: resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= -minipass@^2.2.1, minipass@^2.3.5: - version "2.3.5" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848" - integrity sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA== - dependencies: - safe-buffer "^5.1.2" - yallist "^3.0.0" - -minizlib@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.1.tgz#dd27ea6136243c7c880684e8672bb3a45fd9b614" - integrity sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA== - dependencies: - minipass "^2.2.1" - mixin-deep@^1.2.0: version "1.3.2" resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" @@ -7587,17 +7517,17 @@ mixin-object@^2.0.1: for-in "^0.1.3" is-extendable "^0.1.1" -mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: +mkdirp@0.5.1, mkdirp@^0.5.1, mkdirp@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= dependencies: minimist "0.0.8" -mocha@^6.1.4: - version "6.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-6.2.0.tgz#f896b642843445d1bb8bca60eabd9206b8916e56" - integrity sha512-qwfFgY+7EKAAUAdv7VYMZQknI7YJSGesxHyhn6qD52DV8UcSZs5XwCifcZGMVIE4a5fbmhvbotxC0DLQ0oKohQ== +mocha@^6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-6.2.2.tgz#5d8987e28940caf8957a7d7664b910dc5b2fea20" + integrity sha512-FgDS9Re79yU1xz5d+C4rv1G7QagNGHZ+iXF81hO8zY35YZZcLEsJVfFolfsqKFWunATEvNzMK0r/CwWd/szO9A== dependencies: ansi-colors "3.2.3" browser-stdout "1.3.1" @@ -7619,9 +7549,9 @@ mocha@^6.1.4: supports-color "6.0.0" which "1.3.1" wide-align "1.1.3" - yargs "13.2.2" - yargs-parser "13.0.0" - yargs-unparser "1.5.0" + yargs "13.3.0" + yargs-parser "13.1.1" + yargs-unparser "1.6.0" moment@^2.10.6: version "2.24.0" @@ -7664,6 +7594,11 @@ mute-stream@0.0.7: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= +mute-stream@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" + integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== + mv@~2: version "2.1.1" resolved "https://registry.yarnpkg.com/mv/-/mv-2.1.1.tgz#ae6ce0d6f6d5e0a4f7d893798d03c1ea9559b6a2" @@ -7673,15 +7608,15 @@ mv@~2: ncp "~2.0.0" rimraf "~2.4.0" -nan@^2.10.0, nan@^2.12.1: +nan@^2.12.1, nan@^2.14.0: version "2.14.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== -nanoid@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-2.0.3.tgz#dde999e173bc9d7bd2ee2746b89909ade98e075e" - integrity sha512-NbaoqdhIYmY6FXDRB4eYtDVC9Z9eCbn8TyaiC16LNKtpPv/aqa0tOPD8y6gNE4yUNnaZ7LLhYtXOev/6+cBtfw== +nanoid@^2.1.6: + version "2.1.8" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-2.1.8.tgz#2dbb0224231b246e3b4c819de7bfea6384dabf08" + integrity sha512-g1z+n5s26w0TGKh7gjn7HCqurNKMZWzH08elXzh/gM/csQHd/UqDV6uxMghQYg9IvqRPm1QpeMk50YMofHvEjQ== nanomatch@^1.2.9: version "1.2.13" @@ -7710,15 +7645,6 @@ ncp@~2.0.0: resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3" integrity sha1-GVoh1sRuNh0vsSgbo4uR6d9727M= -needle@^2.2.1: - version "2.4.0" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.0.tgz#6833e74975c444642590e15a750288c5f939b57c" - integrity sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg== - dependencies: - debug "^3.2.6" - iconv-lite "^0.4.4" - sax "^1.2.4" - negotiator@0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" @@ -7734,6 +7660,11 @@ netmask@^1.0.6: resolved "https://registry.yarnpkg.com/netmask/-/netmask-1.0.6.tgz#20297e89d86f6f6400f250d9f4f6b4c1945fcd35" integrity sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU= +next-tick@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" + integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= + nice-try@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" @@ -7770,7 +7701,7 @@ node-fetch@^1.0.1: encoding "^0.1.11" is-stream "^1.0.1" -node-fetch@^2.2.0, node-fetch@^2.5.0: +node-fetch@^2.0.0-alpha.8, node-fetch@^2.1.2, node-fetch@^2.2.0, node-fetch@^2.5.0: version "2.6.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== @@ -7785,10 +7716,10 @@ node-modules-regexp@^1.0.0: resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= -node-notifier@^5.2.1: - version "5.4.0" - resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.4.0.tgz#7b455fdce9f7de0c63538297354f3db468426e6a" - integrity sha512-SUDEb+o71XR5lXSTyivXd9J7fCloE3SyP4lSgt3lU2oSANiox+SxlNRGPjDKrwU1YN3ix2KN/VGGCg0t01rttQ== +node-notifier@^5.2.1, node-notifier@^5.4.2: + version "5.4.3" + resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.4.3.tgz#cb72daf94c93904098e28b9c590fd866e464bd50" + integrity sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q== dependencies: growly "^1.3.0" is-wsl "^1.1.0" @@ -7796,48 +7727,24 @@ node-notifier@^5.2.1: shellwords "^0.1.1" which "^1.3.0" -node-pre-gyp@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149" - integrity sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A== +node-releases@^1.1.44: + version "1.1.44" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.44.tgz#cd66438a6eb875e3eb012b6a12e48d9f4326ffd7" + integrity sha512-NwbdvJyR7nrcGrXvKAvzc5raj/NkoJudkarh2yIpJ4t0NH4aqjUDz/486P+ynIW5eokKOfzGNRdYoLfBlomruw== dependencies: - detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.1" - nopt "^4.0.1" - npm-packlist "^1.1.6" - npmlog "^4.0.2" - rc "^1.2.7" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^4" - -node-releases@^1.1.25: - version "1.1.26" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.26.tgz#f30563edc5c7dc20cf524cc8652ffa7be0762937" - integrity sha512-fZPsuhhUHMTlfkhDLGtfY80DSJTjOcx+qD1j5pqPkuhUHVS7xHZIg9EE4DHK8O3f0zTxXHX5VIkDG8pu98/wfQ== - dependencies: - semver "^5.3.0" + semver "^6.3.0" node-version@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/node-version/-/node-version-1.2.0.tgz#34fde3ffa8e1149bd323983479dda620e1b5060d" integrity sha512-ma6oU4Sk0qOoKEAymVoTvk8EdXEobdS7m/mAGhDJ8Rouugho48crHBORAmy5BoOcv8wraPM6xumapQp5hl4iIQ== -nopt@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" - integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= - dependencies: - abbrev "1" - osenv "^0.1.4" - normalize-css-color@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/normalize-css-color/-/normalize-css-color-1.0.2.tgz#02991e97cccec6623fe573afbbf0de6a1f3e9f8d" integrity sha1-Apkel8zOxmI/5XOvu/Deah8+n40= -normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: +normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== @@ -7847,7 +7754,7 @@ normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" -normalize-path@^2.0.1, normalize-path@^2.1.1: +normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= @@ -7871,19 +7778,6 @@ normalize-svg-path@^1.0.1: dependencies: svg-arc-to-cubic-bezier "^3.0.0" -npm-bundled@^1.0.1: - version "1.0.6" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd" - integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g== - -npm-packlist@^1.1.6: - version "1.4.4" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.4.tgz#866224233850ac534b63d1a6e76050092b5d2f44" - integrity sha512-zTLo8UcVYtDU3gdeaFu2Xu0n0EvelfHDGuqtNIn5RO7yQj4H1TqNdBc/yZjxnWA0PVB8D3Woyp0i5B43JwQ6Vw== - dependencies: - ignore-walk "^3.0.1" - npm-bundled "^1.0.1" - npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" @@ -7891,24 +7785,12 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" -npmlog@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-2.0.4.tgz#98b52530f2514ca90d09ec5b22c8846722375692" - integrity sha1-mLUlMPJRTKkNCexbIsiEZyI3VpI= - dependencies: - ansi "~0.3.1" - are-we-there-yet "~1.1.2" - gauge "~1.2.5" - -npmlog@^4.0.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== +npm-run-path@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" + path-key "^3.0.0" nth-check@^1.0.2: version "1.0.2" @@ -7917,7 +7799,7 @@ nth-check@^1.0.2: dependencies: boolbase "~1.0.0" -nullthrows@^1.1.0: +nullthrows@^1.1.0, nullthrows@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/nullthrows/-/nullthrows-1.1.1.tgz#7818258843856ae971eae4208ad7d7eb19a431b1" integrity sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw== @@ -7933,15 +7815,25 @@ number-is-nan@^1.0.0: integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= nwsapi@^2.0.7: - version "2.1.4" - resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.1.4.tgz#e006a878db23636f8e8a67d33ca0e4edf61a842f" - integrity sha512-iGfd9Y6SFdTNldEy2L0GUhcarIutFmk+MPWIn9dmj8NMIup03G08uUF2KGbbmv/Ux4RT0VZJoP/sVbWA6d/VIw== + version "2.2.0" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" + integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ== oauth-sign@~0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== +ob1@0.56.3: + version "0.56.3" + resolved "https://registry.yarnpkg.com/ob1/-/ob1-0.56.3.tgz#5829e446587c9bf89c22ece4f3757b29f2ccfd18" + integrity sha512-3JL2ZyWOHDGTEAe4kcG+TxhGPKCCikgyoUIjE82JnXnmpR1LXItM9K3WhGsi4+O7oYngMW6FjpHHoc5xJTMkTQ== + +ob1@0.57.0: + version "0.57.0" + resolved "https://registry.yarnpkg.com/ob1/-/ob1-0.57.0.tgz#2023173d54579ed5b28dc5943ab5d977401dbe0d" + integrity sha512-BRAyYcG7NeA8vZFQ/oMqw1fiRLdFcxi/x9DJ3KWeaSI7+tiO3MZwMjnkL9sdsZMEL4OtpggbeAK2dL3zYNiI1A== + object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -7961,7 +7853,17 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" -object-keys@^1.0.11, object-keys@^1.0.12: +object-inspect@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" + integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== + +object-is@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.2.tgz#6b80eb84fe451498f65007982f035a5b445edec4" + integrity sha512-Epah+btZd5wrrfjkJZq1AOB9O6OxUQto45hzFd7lXGrpHPGE0W1k+426yrZV+k6NJOzLNNW/nVsmZdIWsAqoOQ== + +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== @@ -7993,40 +7895,32 @@ object.assign@4.1.0, object.assign@^4.1.0: object-keys "^1.0.11" object.entries@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.0.tgz#2024fc6d6ba246aee38bdb0ffd5cfbcf371b7519" - integrity sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA== + version "1.1.1" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.1.tgz#ee1cf04153de02bb093fec33683900f57ce5399b" + integrity sha512-ilqR7BgdyZetJutmDPfXCDffGa0/Yzl2ivVNpbx/g4UeWrCdRnFDUBrKJGLhGieRHDATnyZXWBeCb29k9CJysQ== dependencies: define-properties "^1.1.3" - es-abstract "^1.12.0" + es-abstract "^1.17.0-next.1" function-bind "^1.1.1" has "^1.0.3" -object.fromentries@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.0.tgz#49a543d92151f8277b3ac9600f1e930b189d30ab" - integrity sha512-9iLiI6H083uiqUuvzyY6qrlmc/Gz8hLQFOcb/Ri/0xXFkSNS3ctV+CbE6yM2+AnkYfOB3dGjdzC0wrMLIhQICA== +object.fromentries@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.2.tgz#4a09c9b9bb3843dd0f89acdb517a794d4f355ac9" + integrity sha512-r3ZiBH7MQppDJVLx6fhD618GKNG40CZYH9wgwdhKxBDDbQgjeWGGd4AtkZad84d291YxvWe7bJGuE65Anh0dxQ== dependencies: - define-properties "^1.1.2" - es-abstract "^1.11.0" + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" function-bind "^1.1.1" - has "^1.0.1" + has "^1.0.3" object.getownpropertydescriptors@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" - integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= - dependencies: - define-properties "^1.1.2" - es-abstract "^1.5.1" - -object.omit@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" - integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo= + version "2.1.0" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz#369bf1f9592d8ab89d712dced5cb81c7c5352649" + integrity sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg== dependencies: - for-own "^0.1.4" - is-extendable "^0.1.1" + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" object.omit@^3.0.0: version "3.0.0" @@ -8043,12 +7937,12 @@ object.pick@^1.1.1, object.pick@^1.3.0: isobject "^3.0.1" object.values@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.0.tgz#bf6810ef5da3e5325790eaaa2be213ea84624da9" - integrity sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg== + version "1.1.1" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.1.tgz#68a99ecde356b7e9295a3c5e0ce31dc8c953de5e" + integrity sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA== dependencies: define-properties "^1.1.3" - es-abstract "^1.12.0" + es-abstract "^1.17.0-next.1" function-bind "^1.1.1" has "^1.0.3" @@ -8088,6 +7982,13 @@ onetime@^2.0.0: dependencies: mimic-fn "^1.0.0" +onetime@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" + integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== + dependencies: + mimic-fn "^2.1.0" + open@^6.2.0: version "6.4.0" resolved "https://registry.yarnpkg.com/open/-/open-6.4.0.tgz#5c13e96d0dc894686164f18965ecfe889ecfc8a9" @@ -8095,7 +7996,14 @@ open@^6.2.0: dependencies: is-wsl "^1.1.0" -opencollective-postinstall@^2.0.2: +open@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/open/-/open-7.0.0.tgz#7e52999b14eb73f90f0f0807fe93897c4ae73ec9" + integrity sha512-K6EKzYqnwQzk+/dzJAQSBORub3xlBTxMz+ntpZpH/LyCa1o6KjXhuN+2npAaI9jaSmU3R1Q8NWf4KUWcyytGsQ== + dependencies: + is-wsl "^2.1.0" + +opencollective-postinstall@^2.0.1, opencollective-postinstall@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.2.tgz#5657f1bede69b6e33a45939b061eb53d3c6c3a89" integrity sha512-pVOEP16TrAO2/fjej1IdOyupJY8KDUM1CvsaScRbw6oddvpQoOfGk4ywha0HKKVAD6RkW4x6Q+tNBwhf3Bgpuw== @@ -8120,12 +8028,12 @@ opn@4.0.2: object-assign "^4.0.1" pinkie-promise "^2.0.0" -opn@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/opn/-/opn-3.0.3.tgz#b6d99e7399f78d65c3baaffef1fb288e9b85243a" - integrity sha1-ttmec5n3jWXDuq/+8fsojpuFJDo= +opn@^5.4.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc" + integrity sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA== dependencies: - object-assign "^4.0.1" + is-wsl "^1.1.0" optimist@^0.6.1: version "0.6.1" @@ -8135,17 +8043,17 @@ optimist@^0.6.1: minimist "~0.0.1" wordwrap "~0.0.2" -optionator@^0.8.1, optionator@^0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" - integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q= +optionator@^0.8.1, optionator@^0.8.3: + version "0.8.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== dependencies: deep-is "~0.1.3" - fast-levenshtein "~2.0.4" + fast-levenshtein "~2.0.6" levn "~0.3.0" prelude-ls "~1.1.2" type-check "~0.3.2" - wordwrap "~1.0.0" + word-wrap "~1.2.3" options@>=0.0.5: version "0.0.6" @@ -8164,11 +8072,6 @@ ora@^3.4.0: strip-ansi "^5.2.0" wcwidth "^1.0.1" -os-homedir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= - os-locale@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" @@ -8178,7 +8081,7 @@ os-locale@^2.0.0: lcid "^1.0.0" mem "^1.1.0" -os-locale@^3.0.0, os-locale@^3.1.0: +os-locale@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q== @@ -8197,14 +8100,6 @@ os-tmpdir@^1.0.0, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2: resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= -osenv@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" - integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.0" - output-file-sync@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/output-file-sync/-/output-file-sync-2.0.1.tgz#f53118282f5f553c2799541792b723a4c71430c0" @@ -8231,6 +8126,11 @@ p-finally@^1.0.0: resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= +p-finally@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-2.0.1.tgz#bd6fcaa9c559a096b680806f4d657b3f0f240561" + integrity sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw== + p-is-promise@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e" @@ -8243,10 +8143,10 @@ p-limit@^1.1.0: dependencies: p-try "^1.0.0" -p-limit@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.0.tgz#417c9941e6027a9abcba5092dd2904e255b5fbc2" - integrity sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ== +p-limit@^2.0.0, p-limit@^2.2.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.2.tgz#61279b67721f5287aa1c13a9a7fbbc48c9291b1e" + integrity sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ== dependencies: p-try "^2.0.0" @@ -8264,6 +8164,13 @@ p-locate@^3.0.0: dependencies: p-limit "^2.0.0" +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + p-reduce@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa" @@ -8279,16 +8186,16 @@ p-try@^2.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== -pac-proxy-agent@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-3.0.0.tgz#11d578b72a164ad74bf9d5bac9ff462a38282432" - integrity sha512-AOUX9jES/EkQX2zRz0AW7lSx9jD//hQS8wFXBvcnd/J2Py9KaMJMqV/LPqJssj1tgGufotb2mmopGPR15ODv1Q== +pac-proxy-agent@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-3.0.1.tgz#115b1e58f92576cac2eba718593ca7b0e37de2ad" + integrity sha512-44DUg21G/liUZ48dJpUSjZnFfZro/0K5JTyFYLBcmh9+T6Ooi4/i4efwUiEy0+4oQusCBqWdhv16XohIj1GqnQ== dependencies: agent-base "^4.2.0" - debug "^3.1.0" + debug "^4.1.1" get-uri "^2.0.0" http-proxy-agent "^2.1.0" - https-proxy-agent "^2.2.1" + https-proxy-agent "^3.0.0" pac-resolver "^3.0.0" raw-body "^2.2.0" socks-proxy-agent "^4.0.1" @@ -8327,9 +8234,9 @@ parent-module@^1.0.0: callsites "^3.0.0" parse-asn1@^5.0.0: - version "5.1.4" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.4.tgz#37f6628f823fbdeb2273b4d540434a22f3ef1fcc" - integrity sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw== + version "5.1.5" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.5.tgz#003271343da58dc94cace494faef3d2147ecea0e" + integrity sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ== dependencies: asn1.js "^4.0.0" browserify-aes "^1.0.0" @@ -8350,16 +8257,6 @@ parse-entities@^1.0.2, parse-entities@^1.1.0: is-decimal "^1.0.0" is-hexadecimal "^1.0.0" -parse-glob@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" - integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw= - dependencies: - glob-base "^0.3.0" - is-dotfile "^1.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.0" - parse-json@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" @@ -8375,6 +8272,21 @@ parse-json@^4.0.0: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" +parse-json@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.0.0.tgz#73e5114c986d143efa3712d4ea24db9a4266f60f" + integrity sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + lines-and-columns "^1.1.6" + +parse-ms@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-2.1.0.tgz#348565a753d4391fa524029956b172cb7753097d" + integrity sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA== + parse-node-version@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parse-node-version/-/parse-node-version-1.0.1.tgz#e2b5dbede00e7fa9bc363607f53327e8b073189b" @@ -8414,10 +8326,10 @@ pascalcase@^0.1.1: resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= -patch-package@^6.1.2: - version "6.1.2" - resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.1.2.tgz#9ed0b3defb5c34ecbef3f334ddfb13e01b3d3ff6" - integrity sha512-5GnzR8lEyeleeariG+hGabUnD2b1yL7AIGFjlLo95zMGRWhZCel58IpeKD46wwPb7i+uNhUI8unV56ogk8Bgqg== +patch-package@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.2.0.tgz#677de858e352b6ca4e6cb48a6efde2cec9fde566" + integrity sha512-HWlQflaBBMjLBfOWomfolF8aqsFDeNbSNro1JDUgYqnVvPM5OILJ9DQdwIRiKmGaOsmHvhkl1FYkvv1I9r2ZJw== dependencies: "@yarnpkg/lockfile" "^1.1.0" chalk "^2.4.2" @@ -8448,12 +8360,17 @@ path-exists@^3.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= -path-is-inside@^1.0.1, path-is-inside@^1.0.2: +path-is-inside@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= @@ -8463,15 +8380,20 @@ path-key@^2.0.0, path-key@^2.0.1: resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + path-parse@^1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== path-to-regexp@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d" - integrity sha1-Wf3g9DW62suhA6hOnTvGTpa5k30= + version "1.8.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a" + integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA== dependencies: isarray "0.0.1" @@ -8518,9 +8440,9 @@ performance-now@^2.1.0: integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= picomatch@^2.0.5: - version "2.0.7" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.0.7.tgz#514169d8c7cd0bdbeecc8a2609e34a7163de69f6" - integrity sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA== + version "2.2.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.1.tgz#21bac888b6ed8601f831ce7816e335bc779f0a4a" + integrity sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA== pify@^2.0.0: version "2.3.0" @@ -8570,6 +8492,20 @@ pkg-dir@^3.0.0: dependencies: find-up "^3.0.0" +pkg-dir@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +please-upgrade-node@^3.1.1: + version "3.2.0" + resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942" + integrity sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg== + dependencies: + semver-compare "^1.0.0" + plist@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/plist/-/plist-2.0.1.tgz#0a32ca9481b1c364e92e18dc55c876de9d01da8b" @@ -8704,25 +8640,20 @@ postcss-value-parser@^3.3.0, postcss-value-parser@^3.3.1: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== -postcss-value-parser@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.0.tgz#99a983d365f7b2ad8d0f9b8c3094926eab4b936d" - integrity sha512-ESPktioptiSUchCKgggAkzdmkgzKfmp0EU8jXH+5kbIUB+unr0Y4CY9SRMvibuvYUBjNh1ACLbxqYNpdTQOteQ== +postcss-value-parser@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.2.tgz#482282c09a42706d1fc9a069b73f44ec08391dc9" + integrity sha512-LmeoohTpp/K4UiyQCwuGWlONxXamGzCMtFxLq4W1nZVGIQLYvMCJx3yAF9qyyuFpflABI9yVdtJAqbihOsCsJQ== -postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.13, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.7: - version "7.0.17" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.17.tgz#4da1bdff5322d4a0acaab4d87f3e782436bad31f" - integrity sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ== +postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.13, postcss@^7.0.14, postcss@^7.0.2, postcss@^7.0.23, postcss@^7.0.7: + version "7.0.26" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.26.tgz#5ed615cfcab35ba9bbb82414a4fa88ea10429587" + integrity sha512-IY4oRjpXWYshuTDFxMVkJDtWIk2LhsTlu8bZnbEJA4+bYT16Lvpo8Qv6EvDumhYRgzjZl489pmsY3qVgJQ08nA== dependencies: chalk "^2.4.2" source-map "^0.6.1" supports-color "^6.1.0" -postinstall-build@^5.0.1: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postinstall-build/-/postinstall-build-5.0.3.tgz#238692f712a481d8f5bc8960e94786036241efc7" - integrity sha512-vPvPe8TKgp4FLgY3+DfxCE5PIfoXBK2lyLfNCxsRbDsV6vS4oU5RG/IWxrblMn6heagbnMED3MemUQllQ2bQUg== - postinstall-postinstall@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/postinstall-postinstall/-/postinstall-postinstall-2.0.0.tgz#7ba6711b4420575c4f561638836a81faad47f43f" @@ -8738,35 +8669,24 @@ prepend-http@^1.0.1: resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= -preserve@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" - integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= - -prettier@1.16.4: - version "1.16.4" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.16.4.tgz#73e37e73e018ad2db9c76742e2647e21790c9717" - integrity sha512-ZzWuos7TI5CKUeQAtFd6Zhm2s6EpAD/ZLApIhsF9pRvRtM1RFo61dM/4MSRUA0SuLugA/zgrZD8m0BaY46Og7g== +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" prettier@^1.17.1: - version "1.18.2" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea" - integrity sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw== - -pretty-format@24.0.0-alpha.6: - version "24.0.0-alpha.6" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.0.0-alpha.6.tgz#25ad2fa46b342d6278bf241c5d2114d4376fbac1" - integrity sha512-zG2m6YJeuzwBFqb5EIdmwYVf30sap+iMRuYNPytOccEXZMAJbPIFGKVJ/U0WjQegmnQbRo9CI7j6j3HtDaifiA== - dependencies: - ansi-regex "^4.0.0" - ansi-styles "^3.2.0" + version "1.19.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" + integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== -pretty-format@^24.7.0, pretty-format@^24.8.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.8.0.tgz#8dae7044f58db7cb8be245383b565a963e3c27f2" - integrity sha512-P952T7dkrDEplsR+TuY7q3VXDae5Sr7zmQb12JU/NDQa/3CH7/QW0yvqLcGN6jL+zQFKaoJcPc+yJxMTGmosqw== +pretty-format@^24.7.0, pretty-format@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.9.0.tgz#12fac31b37019a4eea3c11aa9a959eb7628aa7c9" + integrity sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA== dependencies: - "@jest/types" "^24.8.0" + "@jest/types" "^24.9.0" ansi-regex "^4.0.0" ansi-styles "^3.2.0" react-is "^16.8.4" @@ -8786,6 +8706,11 @@ process@^0.11.10, process@^0.11.9, process@~0.11.0: resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= +progress@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" + integrity sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8= + progress@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" @@ -8804,12 +8729,12 @@ promise@^7.1.1: asap "~2.0.3" prompts@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.1.0.tgz#bf90bc71f6065d255ea2bdc0fe6520485c1b45db" - integrity sha512-+x5TozgqYdOwWsQFZizE/Tra3fKvAoy037kOyU6cgz84n8f6zxngLOV4O32kTwt9FcLCxAqw0P/c8rOr9y+Gfg== + version "2.3.0" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.3.0.tgz#a444e968fa4cc7e86689a74050685ac8006c4cc4" + integrity sha512-NfbbPPg/74fT7wk2XYQ7hAIp9zJyZp5Fu19iRbORqqy1BhtrkZ0fPafBU+7bmn8ie69DpT0R6QpJIN2oisYjJg== dependencies: - kleur "^3.0.2" - sisteransi "^1.0.0" + kleur "^3.0.3" + sisteransi "^1.0.3" prop-types@15.5.8: version "15.5.8" @@ -8818,7 +8743,7 @@ prop-types@15.5.8: dependencies: fbjs "^0.8.9" -prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.8, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -8837,16 +8762,16 @@ proper-lockfile@^3.0.2: signal-exit "^3.0.2" proxy-agent@3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-3.1.0.tgz#3cf86ee911c94874de4359f37efd9de25157c113" - integrity sha512-IkbZL4ClW3wwBL/ABFD2zJ8iP84CY0uKMvBPk/OceQe/cEjrxzN1pMHsLwhbzUoRhG9QbSxYC+Z7LBkTiBNvrA== + version "3.1.1" + resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-3.1.1.tgz#7e04e06bf36afa624a1540be247b47c970bd3014" + integrity sha512-WudaR0eTsDx33O3EJE16PjBRZWcX8GqCEeERw1W3hZJgH/F2a46g7jty6UGty6NeJ4CKQy8ds2CJPMiyeqaTvw== dependencies: agent-base "^4.2.0" - debug "^3.1.0" + debug "4" http-proxy-agent "^2.1.0" - https-proxy-agent "^2.2.1" - lru-cache "^4.1.2" - pac-proxy-agent "^3.0.0" + https-proxy-agent "^3.0.0" + lru-cache "^5.1.1" + pac-proxy-agent "^3.0.1" proxy-from-env "^1.0.0" socks-proxy-agent "^4.0.1" @@ -8871,9 +8796,9 @@ pseudomap@^1.0.2: integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= psl@^1.1.24, psl@^1.1.28: - version "1.2.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.2.0.tgz#df12b5b1b3a30f51c329eacbdef98f3a6e136dc6" - integrity sha512-GEn74ZffufCmkDDLNcl3uuyF/aSD6exEyh1v/ZSdAomB82t6G9hzJVRx0jBmLDW+VfZqks3aScmMw9DszwUalA== + version "1.7.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.7.0.tgz#f1c4c47a8ef97167dea5d6bbf4816d736e884a3c" + integrity sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ== public-encrypt@^4.0.0: version "4.0.3" @@ -8916,19 +8841,22 @@ q@^1.1.2, q@^1.4.1: integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= qrcode@^1.2.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.4.1.tgz#2126814985d0dbbd9aee050fc523d319c6a7dc3b" - integrity sha512-3JhHQJkKqJL4PfoM6t+B40f0GWv9eNJAJmuNx2X/sHEOLvMyvEPN8GfbdN1qmr19O8N2nLraOzeWjXocHz1S4w== + version "1.4.4" + resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.4.4.tgz#f0c43568a7e7510a55efc3b88d9602f71963ea83" + integrity sha512-oLzEC5+NKFou9P0bMj5+v6Z40evexeE29Z9cummZXZ9QXyMr3lphkURzxjXgPJC5azpxcshoDWV1xE46z+/c3Q== dependencies: + buffer "^5.4.3" + buffer-alloc "^1.2.0" + buffer-from "^1.1.1" dijkstrajs "^1.0.1" isarray "^2.0.1" pngjs "^3.3.0" yargs "^13.2.4" -qs@^6.7.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" - integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== +qs@^6.9.1: + version "6.9.1" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.1.tgz#20082c65cb78223635ab1a9eaca8875a29bf8ec9" + integrity sha512-Cxm7/SS/y/Z3MHWSxXb8lIFqgqBowP5JMlTUFyJN88y0SGQhVmZnqFK/PeuMX9LzUyWsqqhNxIyg0jlzq946yA== qs@~6.5.2: version "6.5.2" @@ -8936,9 +8864,9 @@ qs@~6.5.2: integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== query-string@^6.4.2: - version "6.8.2" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.8.2.tgz#36cb7e452ae11a4b5e9efee83375e0954407b2f6" - integrity sha512-J3Qi8XZJXh93t2FiKyd/7Ec6GNifsjKXUsVFkSBj/kjLsDylWhnCz4NT1bkPcKotttPW+QbKGqqPH8OoI2pdqw== + version "6.9.0" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.9.0.tgz#1c3b727c370cf00f177c99f328fda2108f8fa3dd" + integrity sha512-KG4bhCFYapExLsUHrFt+kQVEegF2agm4cpF/VNc6pZVthIfCc/GK8t8VyNIE3nyXG9DK3Tf2EGkxjR6/uRdYsA== dependencies: decode-uri-component "^0.2.0" split-on-first "^1.0.0" @@ -8959,22 +8887,30 @@ quick-lru@^1.0.0: resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8" integrity sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g= -randomatic@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed" - integrity sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw== +r2@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/r2/-/r2-2.0.1.tgz#94cd802ecfce9a622549c8182032d8e4a2b2e612" + integrity sha512-EEmxoxYCe3LHzAUhRIRxdCKERpeRNmlLj6KLUSORqnK6dWl/K5ShmDGZqM2lRZQeqJgF+wyqk0s1M7SWUveNOQ== dependencies: - is-number "^4.0.0" - kind-of "^6.0.0" - math-random "^1.0.1" + caseless "^0.12.0" + node-fetch "^2.0.0-alpha.8" + typedarray-to-buffer "^3.1.2" -randombytes@^2.0.0, randombytes@^2.0.1: +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== dependencies: safe-buffer "^5.1.0" +randomfill@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== + dependencies: + randombytes "^2.0.5" + safe-buffer "^5.1.0" + range-parser@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" @@ -8990,7 +8926,7 @@ raw-body@^2.2.0: iconv-lite "0.4.24" unpipe "1.0.0" -rc@^1.0.1, rc@^1.1.6, rc@^1.2.7: +rc@^1.0.1, rc@^1.1.6: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== @@ -9000,42 +8936,38 @@ rc@^1.0.1, rc@^1.1.6, rc@^1.2.7: minimist "^1.2.0" strip-json-comments "~2.0.1" -react-clone-referenced-element@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/react-clone-referenced-element/-/react-clone-referenced-element-1.1.0.tgz#9cdda7f2aeb54fea791f3ab8c6ab96c7a77d0158" - integrity sha512-FKOsfKbBkPxYE8576EM6uAfHC4rnMpLyH6/TJUL4WcHUEB3EUn8AxPjnnV/IiwSSzsClvHYK+sDELKN/EJ0WYg== - -react-coin-icon@^0.1.9: - version "0.1.9" - resolved "https://registry.yarnpkg.com/react-coin-icon/-/react-coin-icon-0.1.9.tgz#20d4ec2361ce74a756188df728d0f7b55f0f412b" - integrity sha512-M62K8YHDUh1byPqNs4SHYpHbW/6z13PC5NlqIIZ35lErYJzJwZmFJkkii+RsameLjiGaButGic/ydlEM4tEYNQ== +react-coin-icon@0.1.14: + version "0.1.14" + resolved "https://registry.yarnpkg.com/react-coin-icon/-/react-coin-icon-0.1.14.tgz#4d919b2d60f40405bf48fd86b6b02278e7d8bbb8" + integrity sha512-UkBGfEHRJBMkoEXLnALbiD/KBBmrTTPvz2VAAvBDr2LAwDN7Izj1Yy0vXvLLBBuzznjulH1NRWMWC5b5yViRpg== dependencies: "@svgr/cli" "^4.3.0" lodash "^4.17.11" - styled-components "4.3.1" - -react-deep-force-update@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/react-deep-force-update/-/react-deep-force-update-1.1.2.tgz#3d2ae45c2c9040cbb1772be52f8ea1ade6ca2ee1" - integrity sha512-WUSQJ4P/wWcusaH+zZmbECOk7H5N2pOIl0vzheeornkIMhu+qrNdGFm0bDZLCb0hSF0jf/kH1SgkNGfBdTc4wA== + styled-components "4.4.1" -react-devtools-core@^3.6.0: - version "3.6.3" - resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-3.6.3.tgz#977d95b684c6ad28205f0c62e1e12c5f16675814" - integrity sha512-+P+eFy/yo8Z/UH9J0DqHZuUM5+RI2wl249TNvMx3J2jpUomLQa4Zxl56GEotGfw3PIP1eI+hVf1s53FlUONStQ== +react-devtools-core@^4.0.6: + version "4.4.0" + resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-4.4.0.tgz#614cabe5f3d6fb69730dc76da10f8fa4eb033695" + integrity sha512-ayyz+clbjekj5rqTjieI/eE0xGZkgotklVnxfa4Pyk9se5+AHUAhUwMhLvK5N2+mR2PGOZkv159RDTmvgs+wZQ== dependencies: + es6-symbol "^3" shell-quote "^1.6.1" - ws "^3.3.1" + ws "^7" react-display-name@^0.2.4: - version "0.2.4" - resolved "https://registry.yarnpkg.com/react-display-name/-/react-display-name-0.2.4.tgz#e2a670b81d79a2204335510c01246f4c92ff12cf" - integrity sha512-zvU6iouW+SWwHTyThwxGICjJYCMZFk/6r/+jmOdC7ntQoPlS/Pqb81MkxaMf2bHTSq9TN3K3zX2/ayMW/jCtyA== + version "0.2.5" + resolved "https://registry.yarnpkg.com/react-display-name/-/react-display-name-0.2.5.tgz#304c7cbfb59ee40389d436e1a822c17fe27936c6" + integrity sha512-I+vcaK9t4+kypiSgaiVWAipqHRXYmZIuAiS8vzFvXHHXVigg/sMKwlRgLy6LH2i3rmP+0Vzfl5lFsFRwF1r3pg== + +react-fast-compare@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9" + integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw== -react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.3, react-is@^16.8.4, react-is@^16.8.6: - version "16.8.6" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16" - integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA== +react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6, react-is@^16.9.0: + version "16.12.0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.12.0.tgz#2cc0fe0fba742d97fd527c42a13bec4eeb06241c" + integrity sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q== react-lifecycles-compat@^3.0.0, react-lifecycles-compat@^3.0.2, react-lifecycles-compat@^3.0.4: version "3.0.4" @@ -9047,31 +8979,43 @@ react-native-actionsheet@^2.4.2: resolved "https://registry.yarnpkg.com/react-native-actionsheet/-/react-native-actionsheet-2.4.2.tgz#6a00dd51a75ef2c8974312130e405af73191500f" integrity sha512-DBoWIvVwuWXuptF4t46pBqkFxaUxS+rsIdHiA05t0n4BdTIDV2R4s9bLEUVOGzb94D7VxIamsXZPA/3mmw+SXg== -react-native-camera@^2.11.0: - version "2.11.1" - resolved "https://registry.yarnpkg.com/react-native-camera/-/react-native-camera-2.11.1.tgz#a72062f59bb57c0cb2bd57fe6713fa23b2a90571" - integrity sha512-ZmPZHcY7UXEf7Z8PoJX/WhFtmLFtdRPBGDwemOLlPRVwTVyu/OXVINDUWCug4daBqV8Fs3X1O6V927+K2u2GfA== +react-native-bundle-visualizer@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/react-native-bundle-visualizer/-/react-native-bundle-visualizer-2.1.1.tgz#9f94364097caf0c0e146ac6ab5a83f9af52aa2d2" + integrity sha512-2zRiZhU9ymiKzfkUnI9w8X8PCnn1ie4+uLZ1aSLfjh9tENNI2TzEXmYquiUL4dLe8if3FpEDhefa+OjLE0NNoA== + dependencies: + chalk "^3.0.0" + execa "^3.4.0" + minimist "^1.2.0" + open "^7.0.0" + rimraf "^3.0.0" + source-map-explorer "^2.1.2" + +react-native-camera@^3.9.0: + version "3.15.1" + resolved "https://registry.yarnpkg.com/react-native-camera/-/react-native-camera-3.15.1.tgz#8e4eb67cb6687b5250f849b348f0d19a01649105" + integrity sha512-xj1sljzFq8HVX22d2T945dsJdK/KFb3jaXUHEYGwMp/zz0ypIs3mY3NezdpyYpS1ioKKzdIcLrxz2VKzDCXaCg== dependencies: prop-types "^15.6.2" -react-native-circular-progress@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/react-native-circular-progress/-/react-native-circular-progress-1.3.0.tgz#76bf4062d8ddc059e4f2bce88be600dbf5efd857" - integrity sha512-g9T6S9320PeDW7T4l+7fV9Bdt9oy2OdWWm2UXceP6VGF1bE19I0++1Di01WQyc9nPpo2ZQ4pO51zkbg1sbY77Q== +react-native-circular-progress@^1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/react-native-circular-progress/-/react-native-circular-progress-1.3.4.tgz#91b8aed6ff5ecb8841d2a5a9089af41a5d962087" + integrity sha512-gch73x1qcx7vQewXdY7GdDgvgFSXZHVJ7hp4lXpOWT4Vo7ZnSAeeXYW11sMg2VkFpfA2gu6F+JRQLefDpMzcWQ== dependencies: prop-types "^15.7.2" react-native-clean-project@^3.1.0: - version "3.2.4" - resolved "https://registry.yarnpkg.com/react-native-clean-project/-/react-native-clean-project-3.2.4.tgz#55a71006eb4336dff91d0ca5ab3564d8f0db45cc" - integrity sha512-VF5angZrFIxFILH4NxFsJk5QCjGdPam/Ti4ht2Wd25RbwAyDMPjVNLD2NYf3jZPUCbVtl3TR+uN9uAt1RBnb8g== + version "3.3.0" + resolved "https://registry.yarnpkg.com/react-native-clean-project/-/react-native-clean-project-3.3.0.tgz#89974c4a291123e6d1f72c32185a012a649f1fa8" + integrity sha512-IudFlNsaQd6QcgcbTZcNEXDlrJ9zzRspIUV7yvBX3bfB72Z9et9hIceH9+F+xYSlvwUSB4L/fvkIPosYKa+q9Q== react-native-code-push@^5.6.0: - version "5.6.1" - resolved "https://registry.yarnpkg.com/react-native-code-push/-/react-native-code-push-5.6.1.tgz#d08d5a05ec619c6909822c2f6c4130da5d264d93" - integrity sha512-3iAKPeVCiqOdpBes7KQ4mUXjFTYiY2YdNR5smFfebGZQTgMj1hDWknQfIULaIwr7yE7+UiBe+WsnoAzepoNOIA== + version "5.7.0" + resolved "https://registry.yarnpkg.com/react-native-code-push/-/react-native-code-push-5.7.0.tgz#38667c1ba5a5e1a6dd1b4271468c6ef6284b3ca4" + integrity sha512-Sy54tRfV9kKH9gcu4mVlcmpGLzPinw3fuSlxxmOdndIH03zZdclys2QU9ipk1zYEgmYhT7ls/MjXFz84YdJL2w== dependencies: - code-push "^2.0.7" + code-push "^3.0.1" glob "^5.0.15" hoist-non-react-statics "^2.3.1" inquirer "^1.1.2" @@ -9079,10 +9023,10 @@ react-native-code-push@^5.6.0: semver "^5.6.0" xcode "1.0.0" -react-native-crypto@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/react-native-crypto/-/react-native-crypto-2.1.2.tgz#cfe68cad51cd1f73a4202b7ac164f96c1144cb2a" - integrity sha1-z+aMrVHNH3OkICt6wWT5bBFEyyo= +react-native-crypto@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/react-native-crypto/-/react-native-crypto-2.2.0.tgz#c999ed7c96064f830e1f958687f53d0c44025770" + integrity sha512-eZu9Y8pa8BN9FU2pIex7MLRAi+Cd1Y6bsxfiufKh7sfraAACJvjQTeW7/zcQAT93WMfM+D0OVk+bubvkrbrUkw== dependencies: browserify-cipher "^1.0.0" browserify-sign "^4.0.4" @@ -9093,11 +9037,12 @@ react-native-crypto@^2.1.2: inherits "^2.0.1" pbkdf2 "3.0.8" public-encrypt "^4.0.0" + randomfill "^1.0.3" -react-native-device-info@^2.1.3: - version "2.3.1" - resolved "https://registry.yarnpkg.com/react-native-device-info/-/react-native-device-info-2.3.1.tgz#363267c4574dbd779290cdc06bb423f9c16d68d8" - integrity sha512-4kIBeBdYB/IwNjbSTEvfnWgFB4cXL0drvdXKfcAgfI5vxmsLElR5HI6t9fqVkPyMCiRtI7mvS6PbG2kjGdbQMw== +react-native-device-info@5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/react-native-device-info/-/react-native-device-info-5.3.1.tgz#d764732c4841b6b6c2f42516e8840075717ea88a" + integrity sha512-e/fRDoah+HxItscOJTGJY8zyVKmBUdf53VWIDGLGV4VVZ0mfzIQ2uo0ULGri0vjGUYqgyqgnW3jybPSznMxKcA== react-native-dotenv@^0.2.0: version "0.2.0" @@ -9113,38 +9058,29 @@ react-native-emoji@1.5.0: dependencies: node-emoji "1.10.0" -react-native-fast-image@^6.0.3: - version "6.1.1" - resolved "https://registry.yarnpkg.com/react-native-fast-image/-/react-native-fast-image-6.1.1.tgz#502165beeafdd117e09dfb68ba322fe602534b8e" - integrity sha512-9bYUY8GLKpuTF9WOC28VM/ceH0+GyV60g3bcwYeiq0A+oDBVyVlj/ovMaJqRxHII6GQYX0WbTkiT5kWtPCtWkA== - -react-native-firebase@^4.3.8: - version "4.3.8" - resolved "https://registry.yarnpkg.com/react-native-firebase/-/react-native-firebase-4.3.8.tgz#a425b260aca0b97cde023dd2556fc18d16a3b7b3" - integrity sha512-lQuRrcnRd6Y3Drk8X66GYodfqPhWqy82+3S0rjOCoB3LhapnYXpi6QCqKJwkdBsy49zTyVsuH9cmMgQyejYW+w== - dependencies: - opencollective "^1.0.3" - postinstall-build "^5.0.1" - prop-types "^15.6.1" +react-native-fast-image@andrewschenk-linx/react-native-fast-image#fix-ios-xcode-proj: + version "7.0.2" + resolved "https://codeload.github.com/andrewschenk-linx/react-native-fast-image/tar.gz/d19ae11a6469de94cb49211d00a7bc002ea76ff8" -react-native-gesture-handler@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-1.3.0.tgz#d0386f565928ccc1849537f03f2e37fd5f6ad43f" - integrity sha512-ASRFIXBuKRvqlmwkWJhV8yP2dTpvcqVrLNpd7FKVBFHYWr6SAxjGyO9Ik8w1lAxDhMlRP2IcJ9p9eq5X2WWeLQ== +react-native-gesture-handler@1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-1.5.2.tgz#281111550bf1eee10b7feba5278d142169892731" + integrity sha512-Xp03dq4XYVTD0xmWx4DW4eX+ox1NQLjHmbykspTdS5FCNIVIOekVXRLFCw1698/v8dYUHApNo6K3s3BCD8fqPA== dependencies: + hammerjs "^2.0.8" hoist-non-react-statics "^2.3.1" - invariant "^2.2.2" - prop-types "^15.5.10" + invariant "^2.2.4" + prop-types "^15.7.2" react-native-haptic-feedback@^1.8.2: version "1.8.2" resolved "https://registry.yarnpkg.com/react-native-haptic-feedback/-/react-native-haptic-feedback-1.8.2.tgz#532dfcdfe2eaaaf3c30ff5dff97973ff05399fcd" integrity sha512-arY2vsQtcF6Z/HggcfASTFzXm5HLUvK08rj6xPs6b95mpUDyStxEoC2c6MCFx+GSqnpBuOQvQCf42Zp0ATnWoQ== -react-native-indicators@^0.13.0: - version "0.13.0" - resolved "https://registry.yarnpkg.com/react-native-indicators/-/react-native-indicators-0.13.0.tgz#001824bba194b1ca6e654d903beaf0168d4e6ac8" - integrity sha1-ABgku6GUscpuZU2QO+rwFo1Oasg= +react-native-indicators@0.17.0: + version "0.17.0" + resolved "https://registry.yarnpkg.com/react-native-indicators/-/react-native-indicators-0.17.0.tgz#92f95efaf5fb53be576dfe4e1980a25655a93f55" + integrity sha512-s23em477GHGxWeGczWrixScAZD6tQU4mx1fttlrwhEGKOxhBgp55Kh3RoD9Wj4yna4e5W35xQNoPqoJAT6QW5A== dependencies: prop-types "^15.5.10" @@ -9158,10 +9094,10 @@ react-native-iphone-x-helper@^1.2.1: resolved "https://registry.yarnpkg.com/react-native-iphone-x-helper/-/react-native-iphone-x-helper-1.2.1.tgz#645e2ffbbb49e80844bb4cbbe34a126fda1e6772" integrity sha512-/VbpIEp8tSNNHIvstuA3Swx610whci1Zpc9mqNkqn14DkMbw+ORviln2u0XyHG1kPvvwTNGZY6QpeFwxYaSdbQ== -react-native-keychain@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/react-native-keychain/-/react-native-keychain-3.1.3.tgz#fce176e7b95243cecda1896a7e6bdfe0335d778a" - integrity sha512-eWUbjYJge4icX8FhWJk/OPlyGxPnW9bZDysBX3WwOG37iurdH692HKnM2Ih+S+0te65RytImvUrcVnHVBbumYg== +react-native-keychain@4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/react-native-keychain/-/react-native-keychain-4.0.3.tgz#38c6c0021ed697b6149d460dd5910c3c92d36ae7" + integrity sha512-mXlBcHueQ3i73GU9hc7giXJqkh+oL0f8As2H+1XWW2GovkM7xQEZNoro3DsYDIWzFW3eRoF8DmUZIGbLLEVp3Q== react-native-languages@^3.0.0: version "3.0.2" @@ -9176,25 +9112,24 @@ react-native-level-fs@^3.0.1: level-filesystem "^1.0.1" levelup "^0.18.2" -react-native-linear-gradient@^2.5.4: +react-native-linear-gradient@^2.5.6: version "2.5.6" resolved "https://registry.yarnpkg.com/react-native-linear-gradient/-/react-native-linear-gradient-2.5.6.tgz#96215cbc5ec7a01247a20890888aa75b834d44a0" integrity sha512-HDwEaXcQIuXXCV70O+bK1rizFong3wj+5Q/jSyifKFLg0VWF95xh8XQgfzXwtq0NggL9vNjPKXa016KuFu+VFg== -react-native-mail@^3.0.6: - version "3.0.7" - resolved "https://registry.yarnpkg.com/react-native-mail/-/react-native-mail-3.0.7.tgz#07e6aca43f6f1f85f3e58e96e7fcd16b31a927b8" - integrity sha512-FHe4kKJKAGuCPPWcDwaRSjdUhEE4IWIsVtTZ05dgD/MgOm00isYmM20zuJHla7oiHVQ2HmzGji76g6IuhIrCjw== +react-native-mail@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/react-native-mail/-/react-native-mail-4.1.0.tgz#2ebe2df2211a84862a3aea77316736189e23435b" + integrity sha512-3IHQmUQJwFFV7HwDONeIEahhaEvK9u23liqIUQajPy7frk/AoIGhkdKf4FVSTeq+VlUx97qls4uNizP7hBXIIw== -react-native-os@^1.2.2: - version "1.2.4" - resolved "https://registry.yarnpkg.com/react-native-os/-/react-native-os-1.2.4.tgz#f9ea7423cc9a9e865bc9cad590941ce37b7a3aee" - integrity sha512-ohlP5BxJxvWp8JZ99g8+xdZ2s8Z4bEoP6g99VDeytz04m+VYdVrCP7Xovy6FoEqA4qxyUbv4xeGHR+pzNnkZeg== +react-native-os@icxcat/react-native-os#master: + version "1.1.0" + resolved "https://codeload.github.com/icxcat/react-native-os/tar.gz/1efb92b990fb4c02475fcc98a8260c3991c59b2d" -react-native-permissions@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/react-native-permissions/-/react-native-permissions-1.2.0.tgz#0deb616bf1565c17c91f1cb1f953809b2892c29e" - integrity sha512-+KrP1JZ30RI9p30wsGlGQx22qwiClDnznSQZPpvBMkOIZQ9kXOkLAFXS+vwiHRiiRu/pBMBXYHfI7ng6t2+LbQ== +react-native-permissions@^1.1.1, react-native-permissions@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/react-native-permissions/-/react-native-permissions-1.2.1.tgz#cb1f6e53b8992b3912de5a4cfc1553ac2e82d0f6" + integrity sha512-6NOGsA7EsuKT9hfULccQfMrsGmRhBkmN6Uv8nz2QObjEG87XtroQtw4Qi1+tAjIkSHawCeAMJp+SCtiXSGUD5Q== react-native-qrcode-scanner@mikedemarais/react-native-qrcode-scanner#2ca70b8c64afb87e712aba578e11409c6406069e: version "1.0.1" @@ -9222,25 +9157,29 @@ react-native-randombytes@^3.5.3: buffer "^4.9.1" sjcl "^1.0.3" -react-native-reanimated@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-1.1.0.tgz#ba6864055ec3a206cdd5209a293fe653ce276206" - integrity sha512-UGDVNfvuIkMqYUx6aytSzihuzv6sWubn0MQi8dRcw7BjgezhjJnVnJ/NSOcpL3cO+Ld7lFcRX6GKcskwkHdPkw== +react-native-reanimated@software-mansion/react-native-reanimated: + version "1.4.0" + resolved "https://codeload.github.com/software-mansion/react-native-reanimated/tar.gz/1ea8cc3d8b713d4bac2529c010b035c6d1529df4" -react-native-redash@^7.2.1: - version "7.5.0" - resolved "https://registry.yarnpkg.com/react-native-redash/-/react-native-redash-7.5.0.tgz#fa72c7a23ad2f3f884a494ed76a0e79041ae70e1" - integrity sha512-y2J19HbBYWOYq4kq+3U86wfbsDusxv1/ak4a6KqvfTmt/E3i85mnnUDIF+nk1Shqz0aYcwNMB2KD7bEWsVK/sw== +react-native-redash@9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/react-native-redash/-/react-native-redash-9.0.0.tgz#3fe5426c982a036cc4e7b2df9a94bd210ddd5750" + integrity sha512-2OV8ECpI6ruCwGA3nkhv1j3dGLUhoUVVDwgzAwOfhFrF3LglUaDhT8IG3DQFw7Q5sUuyPQY7HjLu9P0VkQ94LA== dependencies: abs-svg-path "^0.1.1" normalize-svg-path "^1.0.1" parse-svg-path "^0.1.2" use-memo-one "^1.1.1" -react-native-safe-area-view@^0.14.1: - version "0.14.6" - resolved "https://registry.yarnpkg.com/react-native-safe-area-view/-/react-native-safe-area-view-0.14.6.tgz#9a9d37d9f8f3887d60c4076eae7b5d2319539446" - integrity sha512-dbzuvaeHFV1VBpyMaC0gtJ2BqFt6ls/405A0t78YN1sXiTrVr3ki86Ysct8mzifWqLdvWzcWagE5wfMtdxnqoA== +react-native-safe-area-context@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/react-native-safe-area-context/-/react-native-safe-area-context-0.5.0.tgz#2185519ad6296dd7bd4ecc79864c02ca3a7f40b5" + integrity sha512-ukg9gO9jCdQIkYYwQf0/mp+67XiFSJH7BOxthoBbJq0x3f61Q/6U6E2v5MkcHO0vJg1Ul4/Pq77V+nR5eY/9fA== + +react-native-safe-area-view@^0.14.1, react-native-safe-area-view@^0.14.6: + version "0.14.8" + resolved "https://registry.yarnpkg.com/react-native-safe-area-view/-/react-native-safe-area-view-0.14.8.tgz#ef33c46ff8164ae77acad48c3039ec9c34873e5b" + integrity sha512-MtRSIcZNstxv87Jet+UsPhEd1tpGe8cVskDXlP657x6rHpSrbrc+y13ZNXrwAgGNNhqQNX7UJT68ZIq//ZRmvw== dependencies: hoist-non-react-statics "^2.3.1" @@ -9275,22 +9214,30 @@ react-native-store-review@^0.1.5: resolved "https://registry.yarnpkg.com/react-native-store-review/-/react-native-store-review-0.1.5.tgz#9df69786a137580748e368641698d2104519e4cf" integrity sha512-vVx7NYaQva3bGU5MdqXn4yEB+o+GPdmjqAuj7PnkepfeCS6Bi3sqniiKoXmKOKDgRTfIobBZjUkHzWeHli1+3A== -react-native-svg@^9.5.1: - version "9.5.3" - resolved "https://registry.yarnpkg.com/react-native-svg/-/react-native-svg-9.5.3.tgz#2389f3ffd700c6441166496a1aeade31ead89c59" - integrity sha512-VUOe4TLz7RFdmm/XT9EH87VSwlRykx49qbwJMA+dh9eFM7KPY1qH3kEyN7uRCqJD2eE8toxt9NpjR6ByvtPNlA== +react-native-svg@9.13.6: + version "9.13.6" + resolved "https://registry.yarnpkg.com/react-native-svg/-/react-native-svg-9.13.6.tgz#5365fba2bc460054b90851e71f2a71006a5d373f" + integrity sha512-vjjuJhEhQCwWjqsgWyGy6/C/LIBM2REDxB40FU1PMhi8T3zQUwUHnA6M15pJKlQG8vaZyA+QnLyIVhjtujRgig== + dependencies: + css-select "^2.0.2" + css-tree "^1.0.0-alpha.37" -react-native-tab-view@^1.2.0, react-native-tab-view@^1.4.1: +react-native-tab-view@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/react-native-tab-view/-/react-native-tab-view-1.4.1.tgz#f113cd87485808f0c991abec937f70fa380478b9" integrity sha512-Bke8KkDcDhvB/z0AS7MnQKMD2p6Kwfc1rSKlMOvg9CC5CnClQ2QEnhPSbwegKDYhUkBI92iH/BYy7hNSm5kbUQ== dependencies: prop-types "^15.6.1" -react-native-tcp@^3.3.0: - version "3.3.1" - resolved "https://registry.yarnpkg.com/react-native-tcp/-/react-native-tcp-3.3.1.tgz#dfb35ac48356fa8b707dafe69a971feb0845d88b" - integrity sha512-kySTh7oUixfoNHCNAuxjSMjGPYXkg06sgCQOzj1bVInrTNMOSQpYvlKVSSqIorHvus2yvMmYOguTgLffMe65TA== +react-native-tab-view@^2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/react-native-tab-view/-/react-native-tab-view-2.11.0.tgz#2e57d1f617ccc88c7f452708804f3409f880b700" + integrity sha512-vqetlxGO7A8bnqvXcB50MWpRZAImXFrDGz1WCQKdCqe03Ey3ZzENe7yLuWrtBJYlepGfOLAsmCXv+wW82Yfm1w== + +react-native-tcp@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/react-native-tcp/-/react-native-tcp-3.3.2.tgz#b38c153039acac89294caa4991689c003ec62dce" + integrity sha512-zjFmjAvYOsBkR1MF7htuPlk+uOzTykKaeu/eN+I7fkZ7UqBCW+9u/gJgWCv6Tjfn2tGgku6hsEWril4Oy3zJhg== dependencies: base64-js "0.0.8" buffer "^5.0.0" @@ -9299,20 +9246,18 @@ react-native-tcp@^3.3.0: process "^0.11.9" util "^0.10.3" -react-native-tooltip@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/react-native-tooltip/-/react-native-tooltip-5.2.0.tgz#4358ea1e9bdcb49dad28bf5881440b0182927422" - integrity sha512-3mbPGd/VDfb3dUZmdmgg4eE8idJU4OyYM9ItGifnofz+Cz50Aua+sVGo2Ecc7zHV0S+kM0mOyLL758hhTz2gDw== +react-native-text-input-mask@waqas19921/react-native-text-input-mask: + version "2.0.0" + resolved "https://codeload.github.com/waqas19921/react-native-text-input-mask/tar.gz/10af70f94cb61b092abe3911708b1c10005b6b57" -react-native-touch-id@^4.4.1: - version "4.4.1" - resolved "https://registry.yarnpkg.com/react-native-touch-id/-/react-native-touch-id-4.4.1.tgz#8b1bb2d04c30bac36bb9696d2d723e719c4a8b08" - integrity sha512-1jTl8fC+0fxvqegy/XXTyo6vMvPhjzkoDdaqoYZx0OH8AT250NuXnNPyKktvigIcys3+2acciqOeaCall7lrvg== +react-native-tooltip@marcosrdz/react-native-tooltip#master: + version "5.2.1" + resolved "https://codeload.github.com/marcosrdz/react-native-tooltip/tar.gz/e0e88d212b5b7f350e5eabba87f588a32e0f2590" react-native-udp@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/react-native-udp/-/react-native-udp-2.6.1.tgz#ce9f2479f8af6d1bb356cfee69c89cf92fdd50be" - integrity sha512-KctAXtfBjRe+rGLvms92C82MsrZUwUyODwGskY6mDPigMaDTmsKdNqLCXgWh0g6ZmB2UtOzFsbPphy36NyM3KA== + version "2.7.0" + resolved "https://registry.yarnpkg.com/react-native-udp/-/react-native-udp-2.7.0.tgz#d04c5100fcbff343f8a2bf35a3025743d8960f93" + integrity sha512-tT+Wn0yLbdaTohXkGGor0HYgScGaASWCaCLSO1kCIUdNke7AtcOX5a5nfNLYrEjdUn7/2HRofuplyky7iJHSQA== dependencies: base64-js "0.0.8" events "^1.0.2" @@ -9325,94 +9270,77 @@ react-native-version-number@^0.3.6: resolved "https://registry.yarnpkg.com/react-native-version-number/-/react-native-version-number-0.3.6.tgz#dd8b1435fc217df0a166d7e4a61fdc993f3e7437" integrity sha512-TdyXiK90NiwmSbmAUlUBOV6WI1QGoqtvZZzI5zQY4fKl67B3ZrZn/h+Wy/OYIKKFMfePSiyfeIs8LtHGOZ/NgA== -react-native@0.59.9: - version "0.59.9" - resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.59.9.tgz#c94ee4fa35121720c05235a2dd6cdd2784bf5177" - integrity sha512-/+8EgIZwFpYHyyJ7Zav7B6LHNrytwUQ+EKGT/QV7HSrgpf2Y5NZNeUYUHKiVKLYpBip1G32/LcAECQj37YRwGQ== +react-native@facebook/react-native: + version "1000.0.0" + resolved "https://codeload.github.com/facebook/react-native/tar.gz/bd0c37e456392090507f227b8fb90c1eb7c3d327" dependencies: "@babel/runtime" "^7.0.0" - "@react-native-community/cli" "^1.2.1" - absolute-path "^0.0.0" - art "^0.10.0" + "@react-native-community/cli" "^3.0.0-alpha.1" + "@react-native-community/cli-platform-android" "^3.0.0-alpha.1" + "@react-native-community/cli-platform-ios" "^3.0.0-alpha.1" + abort-controller "^3.0.0" base64-js "^1.1.2" - chalk "^2.4.1" - commander "^2.9.0" - compression "^1.7.1" connect "^3.6.5" create-react-class "^15.6.3" - debug "^2.2.0" - denodeify "^1.2.1" - errorhandler "^1.5.0" escape-string-regexp "^1.0.5" - event-target-shim "^1.0.5" + eslint-plugin-relay "1.3.12" + event-target-shim "^5.0.1" fbjs "^1.0.0" - fbjs-scripts "^1.0.0" - fs-extra "^1.0.0" - glob "^7.1.1" - graceful-fs "^4.1.3" - inquirer "^3.0.6" + fbjs-scripts "^1.1.0" + hermes-engine "^0.2.1" invariant "^2.2.4" - lodash "^4.17.5" - metro-babel-register "0.51.0" - metro-react-native-babel-transformer "0.51.0" - mime "^1.3.4" - minimist "^1.2.0" - mkdirp "^0.5.1" - morgan "^1.9.0" - node-fetch "^2.2.0" - node-notifier "^5.2.1" - npmlog "^2.0.4" - nullthrows "^1.1.0" - opn "^3.0.2" - optimist "^0.6.1" - plist "^3.0.0" - pretty-format "24.0.0-alpha.6" + jsc-android "^245459.0.0" + metro-babel-register "0.56.3" + metro-react-native-babel-transformer "0.56.3" + metro-source-map "0.56.3" + nullthrows "^1.1.1" + pretty-format "^24.7.0" promise "^7.1.1" - prop-types "^15.5.8" - react-clone-referenced-element "^1.0.1" - react-devtools-core "^3.6.0" - regenerator-runtime "^0.11.0" - rimraf "^2.5.4" - semver "^5.0.3" - serve-static "^1.13.1" - shell-quote "1.6.1" + prop-types "^15.7.2" + react-devtools-core "^4.0.6" + react-refresh "^0.4.0" + regenerator-runtime "^0.13.2" + scheduler "0.16.2" stacktrace-parser "^0.1.3" - ws "^1.1.5" - xmldoc "^0.4.0" - yargs "^9.0.0" + use-subscription "^1.0.0" + whatwg-fetch "^3.0.0" -react-navigation-drawer@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/react-navigation-drawer/-/react-navigation-drawer-1.2.1.tgz#7bd5efeee7d2f611d3ebb0933e0c8e8eb7cafe52" - integrity sha512-T2kaBjY2c4/3I6noWFnaf/c18ntNH5DsST38i+pdc2NPxn5Yi5lkK+ZZTeKuHSFD4a7G0jWY9OGf1iRkHWLMAQ== - dependencies: - react-native-tab-view "^1.2.0" +react-navigation-hooks@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/react-navigation-hooks/-/react-navigation-hooks-1.1.0.tgz#337c41a50ebc7b9030bb9d9333cd4fd6e1f86b68" + integrity sha512-ZY/aiYJ88KXaOo8iOa4171O/0x6ztGhUPd2OYzdaJhLT/tP64zi5HB/RZFImuKhaBTODXjoSpFaOTA5xpePG4g== -react-navigation-stack@~1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/react-navigation-stack/-/react-navigation-stack-1.4.0.tgz#69cdb029ea4ee5877d7e933b3117dc90bc841eb2" - integrity sha512-zEe9wCA0Ot8agarYb//0nSWYW1GM+1R0tY/nydUV0EizeJ27At0EklYVWvYEuYU6C48va6cu8OPL7QD/CcJACw== +react-navigation-stack@2.0.0-alpha.39: + version "2.0.0-alpha.39" + resolved "https://registry.yarnpkg.com/react-navigation-stack/-/react-navigation-stack-2.0.0-alpha.39.tgz#e138a116f69397ead27d5760559489e23990ed3f" + integrity sha512-G6cKfiPodPpoTmEdTZhZQ1yYkjU9UeqM3W7KzEQp1Pk3iTswel9z+Arry1YFkR42zPDkzuSg7phU7VFwkvo+uw== -react-navigation-tabs@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/react-navigation-tabs/-/react-navigation-tabs-1.1.4.tgz#00a312250df3c519c60b7815a523ace5ee11163a" - integrity sha512-py2hLCRxPwXOzmY1W9XcY1rWXxdK6RGW/aXh56G9gIf8cpHNDhy/bJV4e46/JrVcse3ybFaN0liT09/DM/NdwQ== +react-navigation-tabs-v1@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/react-navigation-tabs-v1/-/react-navigation-tabs-v1-1.2.0.tgz#7cdfdfee62689cc0835d87da574c81486b4ad6ee" + integrity sha512-vpd/WLmh5OZr1Bl2CONk5b4/pSNKeQCMcnlqFcOPFRsnkewLXlcyqax8G6wMSp3CRES1+X7DZxe133ybLgwdiA== dependencies: hoist-non-react-statics "^2.5.0" prop-types "^15.6.1" - react-lifecycles-compat "^3.0.4" react-native-tab-view "^1.4.1" -react-navigation@^3.11.1: - version "3.11.1" - resolved "https://registry.yarnpkg.com/react-navigation/-/react-navigation-3.11.1.tgz#ba696ad6b512088a97a20cc7e6a250c53dbddd26" - integrity sha512-n64HxLG5s5ucVFo1Gs+D9ujChhHDd98lpQ1p27wL7gq8V1PaRJMvsBEIsguhtc2rTIL/TWDynOesXQDG+Eg6FQ== +react-navigation-tabs@2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/react-navigation-tabs/-/react-navigation-tabs-2.6.2.tgz#6611f3bbc5fcbc004a96a457e1dbe8d957d09ef5" + integrity sha512-b7Bwio3pOyb2dJOsfICm1eXUCekULO63VitLlkslsuwB5v5qXD9u+TkuSGADPiAybRH3Fts4cQX/xA5WGsIsfg== + dependencies: + hoist-non-react-statics "^3.3.0" + react-lifecycles-compat "^3.0.4" + react-native-safe-area-view "^0.14.6" + react-native-tab-view "^2.11.0" + +react-navigation@4.0.10: + version "4.0.10" + resolved "https://registry.yarnpkg.com/react-navigation/-/react-navigation-4.0.10.tgz#ddf41134600689d6ba99e35dd22ba1f664f91e5c" + integrity sha512-7PqvmsdQ7HIyxPUMYbd9Uq//VoMdniEOLAOSvIhb/ExtbAt/1INSjUF+RiMWOMCWLTCNvNPRvTz7xy7qwWureg== dependencies: - "@react-navigation/core" "~3.4.1" - "@react-navigation/native" "~3.5.0" - react-navigation-drawer "~1.2.1" - react-navigation-stack "~1.4.0" - react-navigation-tabs "~1.1.4" + "@react-navigation/core" "^3.5.1" + "@react-navigation/native" "^3.6.2" react-primitives@^0.8.0: version "0.8.0" @@ -9424,31 +9352,23 @@ react-primitives@^0.8.0: prop-types "^15.7.2" react-timer-mixin "^0.13.4" -react-proxy@^1.1.7: - version "1.1.8" - resolved "https://registry.yarnpkg.com/react-proxy/-/react-proxy-1.1.8.tgz#9dbfd9d927528c3aa9f444e4558c37830ab8c26a" - integrity sha1-nb/Z2SdSjDqp9ETkVYw3gwq4wmo= - dependencies: - lodash "^4.6.1" - react-deep-force-update "^1.0.0" - react-redux@^5.0.7: - version "5.1.1" - resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.1.1.tgz#88e368682c7fa80e34e055cd7ac56f5936b0f52f" - integrity sha512-LE7Ned+cv5qe7tMV5BPYkGQ5Lpg8gzgItK07c67yHvJ8t0iaD9kPFPAli/mYkiyJYrs2pJgExR2ZgsGqlrOApg== + version "5.1.2" + resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.1.2.tgz#b19cf9e21d694422727bf798e934a916c4080f57" + integrity sha512-Ns1G0XXc8hDyH/OcBHOxNgQx9ayH3SPxBnFCOidGKSle8pKihysQw2rG/PmciUQRoclhVBO8HMhiRmGXnDja9Q== dependencies: "@babel/runtime" "^7.1.2" - hoist-non-react-statics "^3.1.0" + hoist-non-react-statics "^3.3.0" invariant "^2.2.4" loose-envify "^1.1.0" prop-types "^15.6.1" react-is "^16.6.0" react-lifecycles-compat "^3.0.0" -react-refresh@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.2.0.tgz#f0cff375e8f75dea7133a847a1b40cf5c073dd0d" - integrity sha512-ITw8t/HOFNose2yf1y9pPFSSeB9ISOq2JdHpuZvj/Qb+iSsLml8GkkHdDlURzieO7B3dFDtMrrneZLl3N5z/hg== +react-refresh@^0.4.0: + version "0.4.2" + resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.4.2.tgz#54a277a6caaac2803d88f1d6f13c1dcfbd81e334" + integrity sha512-kv5QlFFSZWo7OlJFNYbxRtY66JImuP2LcrFgyJfQaf85gSP+byzG21UbDQEYjU7f//ny8rwiEkO6py2Y+fEgAQ== react-spring@^5.7.2: version "5.9.2" @@ -9464,38 +9384,36 @@ react-style-proptype@^3.2.2: dependencies: prop-types "^15.5.4" -react-test-renderer@16.8.3: - version "16.8.3" - resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.8.3.tgz#230006af264cc46aeef94392e04747c21839e05e" - integrity sha512-rjJGYebduKNZH0k1bUivVrRLX04JfIQ0FKJLPK10TAb06XWhfi4gTobooF9K/DEFNW98iGac3OSxkfIJUN9Mdg== +react-test-renderer@16.9.0: + version "16.9.0" + resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.9.0.tgz#7ed657a374af47af88f66f33a3ef99c9610c8ae9" + integrity sha512-R62stB73qZyhrJo7wmCW9jgl/07ai+YzvouvCXIJLBkRlRqLx4j9RqcLEAfNfU3OxTGucqR2Whmn3/Aad6L3hQ== dependencies: object-assign "^4.1.1" prop-types "^15.6.2" - react-is "^16.8.3" - scheduler "^0.13.3" + react-is "^16.9.0" + scheduler "^0.15.0" react-timer-mixin@^0.13.4: version "0.13.4" resolved "https://registry.yarnpkg.com/react-timer-mixin/-/react-timer-mixin-0.13.4.tgz#75a00c3c94c13abe29b43d63b4c65a88fc8264d3" integrity sha512-4+ow23tp/Tv7hBM5Az5/Be/eKKF7DIvJ09voz5LyHGQaqqz9WV8YMs31eFvcYQs7d451LSg7kDJV70XYN/Ug/Q== -react-transform-hmr@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/react-transform-hmr/-/react-transform-hmr-1.0.4.tgz#e1a40bd0aaefc72e8dfd7a7cda09af85066397bb" - integrity sha1-4aQL0Krvxy6N/Xp82gmvhQZjl7s= - dependencies: - global "^4.3.0" - react-proxy "^1.1.7" - -react@16.8.3: - version "16.8.3" - resolved "https://registry.yarnpkg.com/react/-/react-16.8.3.tgz#c6f988a2ce895375de216edcfaedd6b9a76451d9" - integrity sha512-3UoSIsEq8yTJuSu0luO1QQWYbgGEILm+eJl2QN/VLDi7hL+EN18M3q3oVZwmVzzBJ3DkM7RMdRwBmZZ+b4IzSA== +react@16.11.0: + version "16.11.0" + resolved "https://registry.yarnpkg.com/react/-/react-16.11.0.tgz#d294545fe62299ccee83363599bf904e4a07fdbb" + integrity sha512-M5Y8yITaLmU0ynd0r1Yvfq98Rmll6q8AxaEe88c8e7LxO8fZ2cNgmFt0aGAS9wzf1Ao32NKXtCl+/tVVtkxq6g== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" prop-types "^15.6.2" - scheduler "^0.13.3" + +read-env@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/read-env/-/read-env-1.3.0.tgz#e26e1e446992b3216e9a3c6f6ac51064fe91fdff" + integrity sha512-DbCgZ8oHwZreK/E2E27RGk3EUPapMhYGSGIt02k9sX6R3tCFc4u4tkltKvkCvzEQ3SOLUaiYHAnGb+TdsnPp0A== + dependencies: + camelcase "5.0.0" read-pkg-up@^2.0.0: version "2.0.0" @@ -9539,6 +9457,16 @@ read-pkg@^3.0.0: normalize-package-data "^2.3.2" path-type "^3.0.0" +read-pkg@^5.1.1: + version "5.2.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" + integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== + dependencies: + "@types/normalize-package-data" "^2.4.0" + normalize-package-data "^2.5.0" + parse-json "^5.0.0" + type-fest "^0.6.0" + readable-stream@1.1.x, readable-stream@^1.0.26-4, readable-stream@^1.0.27-1, readable-stream@^1.0.33: version "1.1.14" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" @@ -9549,19 +9477,10 @@ readable-stream@1.1.x, readable-stream@^1.0.26-4, readable-stream@^1.0.27-1, rea isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@3, readable-stream@^3.1.1, readable-stream@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc" - integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readable-stream@^2.0.1, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@~2.3.6: - version "2.3.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== +readable-stream@2, readable-stream@^2.0.1, readable-stream@^2.2.2, readable-stream@~2.3.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -9571,6 +9490,15 @@ readable-stream@^2.0.1, readable-stream@^2.0.6, readable-stream@^2.2.2, readable string_decoder "~1.1.1" util-deprecate "~1.0.1" +readable-stream@^3.1.1, readable-stream@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc" + integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + readable-stream@~1.0.26, readable-stream@~1.0.26-4: version "1.0.34" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" @@ -9624,7 +9552,7 @@ recursive-readdir@^2.2.2: dependencies: minimatch "3.0.4" -recyclerlistview@^2.0.1-alpha.1: +recyclerlistview@2.0.1-alpha.1: version "2.0.1-alpha.1" resolved "https://registry.yarnpkg.com/recyclerlistview/-/recyclerlistview-2.0.1-alpha.1.tgz#881955e6917911fb54a9b272004e39e5c0d64f4a" integrity sha512-UaeJyxG9LL8lcfiAqkp0kPLxvjbYg95Dcq1U/QUvzwXU4+H2khg/LAws/FssxPX6CXNMw7BLcT2YHAhkFElqRQ== @@ -9652,14 +9580,14 @@ redux-thunk@^2.3.0: integrity sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw== redux@^4.0.1: - version "4.0.4" - resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.4.tgz#4ee1aeb164b63d6a1bcc57ae4aa0b6e6fa7a3796" - integrity sha512-vKv4WdiJxOWKxK0yRoaK3Y4pxxB0ilzVx6dszU2W8wLxlb2yikRph4iV/ymtdJ6ZxpBLFbyrxklnT5yBbQSl3Q== + version "4.0.5" + resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.5.tgz#4db5de5816e17891de8a80c424232d06f051d93f" + integrity sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w== dependencies: loose-envify "^1.4.0" symbol-observable "^1.2.0" -regenerate-unicode-properties@^8.0.2: +regenerate-unicode-properties@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e" integrity sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA== @@ -9693,13 +9621,6 @@ regenerator-transform@^0.14.0: dependencies: private "^0.1.6" -regex-cache@^0.4.2: - version "0.4.4" - resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" - integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ== - dependencies: - is-equal-shallow "^0.1.3" - regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" @@ -9708,18 +9629,26 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" +regexp.prototype.flags@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz#7aba89b3c13a64509dabcf3ca8d9fbb9bdf5cb75" + integrity sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + regexpp@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== -regexpu-core@^4.5.4: - version "4.5.4" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.5.4.tgz#080d9d02289aa87fe1667a4f5136bc98a6aebaae" - integrity sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ== +regexpu-core@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.6.0.tgz#2037c18b327cfce8a6fea2a4ec441f2432afb8b6" + integrity sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg== dependencies: regenerate "^1.4.0" - regenerate-unicode-properties "^8.0.2" + regenerate-unicode-properties "^8.1.0" regjsgen "^0.5.0" regjsparser "^0.6.0" unicode-match-property-ecmascript "^1.0.4" @@ -9741,17 +9670,38 @@ registry-url@^3.0.3: rc "^1.0.1" regjsgen@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.0.tgz#a7634dc08f89209c2049adda3525711fb97265dd" - integrity sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA== + version "0.5.1" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.1.tgz#48f0bf1a5ea205196929c0d9798b42d1ed98443c" + integrity sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg== regjsparser@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.0.tgz#f1e6ae8b7da2bae96c99399b868cd6c933a2ba9c" - integrity sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ== + version "0.6.2" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.2.tgz#fd62c753991467d9d1ffe0a9f67f27a529024b96" + integrity sha512-E9ghzUtoLwDekPT0DYCp+c4h+bvuUpe6rRHCTYn6eGoqj1LgKXxT6I0Il4WbjhQkOghzi/V+y03bPKvbllL93Q== dependencies: jsesc "~0.5.0" +remark-parse@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-5.0.0.tgz#4c077f9e499044d1d5c13f80d7a98cf7b9285d95" + integrity sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA== + dependencies: + collapse-white-space "^1.0.2" + is-alphabetical "^1.0.0" + is-decimal "^1.0.0" + is-whitespace-character "^1.0.0" + is-word-character "^1.0.0" + markdown-escapes "^1.0.0" + parse-entities "^1.1.0" + repeat-string "^1.5.4" + state-toggle "^1.0.0" + trim "0.0.1" + trim-trailing-lines "^1.0.0" + unherit "^1.0.4" + unist-util-remove-position "^1.0.0" + vfile-location "^2.0.0" + xtend "^4.0.1" + remark-parse@^6.0.0: version "6.0.3" resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-6.0.3.tgz#c99131052809da482108413f87b0ee7f52180a3a" @@ -9802,6 +9752,11 @@ remark@^10.0.1: remark-stringify "^6.0.0" unified "^7.0.0" +remove-accents@0.4.2: + version "0.4.2" + resolved "https://registry.yarnpkg.com/remove-accents/-/remove-accents-0.4.2.tgz#0a43d3aaae1e80db919e07ae254b285d9e1c7bb5" + integrity sha1-CkPTqq4egNuRngeuJUsoXZ4ce7U= + remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" @@ -9812,7 +9767,7 @@ repeat-element@^1.1.2: resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== -repeat-string@^1.5.2, repeat-string@^1.5.4, repeat-string@^1.6.1: +repeat-string@^1.5.4, repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= @@ -9822,19 +9777,19 @@ replace-ext@1.0.0: resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= -request-promise-core@1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.2.tgz#339f6aababcafdb31c799ff158700336301d3346" - integrity sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag== +request-promise-core@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.3.tgz#e9a3c081b51380dfea677336061fea879a829ee9" + integrity sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ== dependencies: - lodash "^4.17.11" + lodash "^4.17.15" request-promise-native@^1.0.5: - version "1.0.7" - resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.7.tgz#a49868a624bdea5069f1251d0a836e0d89aa2c59" - integrity sha512-rIMnbBdgNViL37nZ1b3L/VfPOpSi0TqVDQPAvO6U14lMzOLrt5nilxCQqtDKhZeDiW0/hkCXGoQjhgJd/tCh6w== + version "1.0.8" + resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.8.tgz#a455b960b826e44e2bf8999af64dff2bfe58cb36" + integrity sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ== dependencies: - request-promise-core "1.1.2" + request-promise-core "1.1.3" stealthy-require "^1.1.1" tough-cookie "^2.3.3" @@ -9916,7 +9871,7 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@1.1.7, resolve@1.8.1, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.11.0, resolve@^1.3.2, resolve@^1.5.0, resolve@^1.6.0, resolve@^1.8.1, resolve@^1.9.0: +resolve@1.1.7, resolve@1.8.1, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.3.2, resolve@^1.5.0, resolve@^1.6.0, resolve@^1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" integrity sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA== @@ -9939,6 +9894,14 @@ restore-cursor@^2.0.0: onetime "^2.0.0" signal-exit "^3.0.2" +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" @@ -9949,13 +9912,27 @@ retry@^0.12.0: resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= -rimraf@2.6.3, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3: +rimraf@2.6.3, rimraf@~2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== dependencies: glob "^7.1.3" +rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.3: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +rimraf@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.0.tgz#614176d4b3010b75e5c390eb0ee96f6dc0cebb9b" + integrity sha512-NDGVxTsjqfunkds7CqsOiEnxln4Bo7Nddl3XhS4pXg5OzwkLqJ971ZVAAnB+DDLnF76N+VnDEiBHaVV8I06SUg== + dependencies: + glob "^7.1.3" + rimraf@~2.2.6: version "2.2.8" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.2.8.tgz#e439be2aaee327321952730f99a8929e4fc50582" @@ -9981,10 +9958,10 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" -rn-nodeify@^10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/rn-nodeify/-/rn-nodeify-10.0.1.tgz#b54a3f2a61eda88b40639ee9262f51f34039e353" - integrity sha512-x7vxo7Nzp5wu6DLLW/qHJ3jRJtcxSe0L/Nb7oUTWAViTRJFEan05Ewlvd5aNrh1fjSztPuqciNtohZesM4oLZQ== +rn-nodeify@10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/rn-nodeify/-/rn-nodeify-10.2.0.tgz#e68843bf280edf878b7615b255fb5e71cde9f8f6" + integrity sha512-mPNe2vNR14UTwAbpebI9fXn9HAU37vebyZDCqZOK6G5GBEUiMCANIVa7zgc9aJ1JeziLUGLR9c+H9/BSbVdd4Q== dependencies: "@yarnpkg/lockfile" "^1.0.0" deep-equal "^1.0.0" @@ -9996,11 +9973,6 @@ rn-nodeify@^10.0.1: semver "^5.0.1" xtend "^4.0.0" -rsvp@^3.3.3: - version "3.6.2" - resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a" - integrity sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw== - rsvp@^4.8.4: version "4.8.5" resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" @@ -10013,6 +9985,11 @@ run-async@^2.2.0: dependencies: is-promise "^2.1.0" +run-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/run-node/-/run-node-1.0.0.tgz#46b50b946a2aa2d4947ae1d886e9856fd9cabe5e" + integrity sha512-kc120TBlQ3mih1LSzdAJXo4xn/GWS2ec0l3S+syHDXP9uRr0JAT8Qd3mdMuyjqCzeZktgP3try92cEgf9Nks8A== + run-parallel@^1.1.2: version "1.1.9" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" @@ -10042,10 +10019,10 @@ rxjs@^5.4.3: dependencies: symbol-observable "1.0.1" -rxjs@^6.4.0: - version "6.5.2" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.2.tgz#2e35ce815cd46d84d02a209fb4e5921e051dbec7" - integrity sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg== +rxjs@^6.4.0, rxjs@^6.5.3: + version "6.5.4" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.4.tgz#e0777fe0d184cec7872df147f303572d414e211c" + integrity sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q== dependencies: tslib "^1.9.0" @@ -10054,7 +10031,7 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2: +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== @@ -10076,23 +10053,6 @@ safe-regex@^1.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -sane@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/sane/-/sane-3.1.0.tgz#995193b7dc1445ef1fe41ddfca2faf9f111854c6" - integrity sha512-G5GClRRxT1cELXfdAq7UKtUsv8q/ZC5k8lQGmjEm4HcAl3HzBy68iglyNCmw4+0tiXPCBZntslHlRhbnsSws+Q== - dependencies: - anymatch "^2.0.0" - capture-exit "^1.2.0" - exec-sh "^0.2.0" - execa "^1.0.0" - fb-watchman "^2.0.0" - micromatch "^3.1.4" - minimist "^1.1.1" - walker "~1.0.5" - watch "~0.18.0" - optionalDependencies: - fsevents "^1.2.3" - sane@^4.0.3: version "4.1.0" resolved "https://registry.yarnpkg.com/sane/-/sane-4.1.0.tgz#ed881fd922733a6c461bc189dc2b6c006f3ffded" @@ -10109,33 +10069,36 @@ sane@^4.0.3: walker "~1.0.5" sanitize-filename@^1.6.1: - version "1.6.2" - resolved "https://registry.yarnpkg.com/sanitize-filename/-/sanitize-filename-1.6.2.tgz#01b4fc8809f14e9d22761fe70380fe7f3f902185" - integrity sha512-cmTzND7RMxUB+f7gI+4+KAVHWEg0lfXvQJdko+FXDP5bNbGIdx4KMP5pX6lv5jfT9jSf6OBbjyxjFtZQwYA/ig== + version "1.6.3" + resolved "https://registry.yarnpkg.com/sanitize-filename/-/sanitize-filename-1.6.3.tgz#755ebd752045931977e30b2025d340d7c9090378" + integrity sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg== dependencies: truncate-utf8-bytes "^1.0.0" -sax@^1.2.4, sax@~1.2.4: +sax@^1.2.1, sax@^1.2.4, sax@~1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== -sax@~1.1.1: - version "1.1.6" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.1.6.tgz#5d616be8a5e607d54e114afae55b7eaf2fcc3240" - integrity sha1-XWFr6KXmB9VOEUr65Vt+ry/MMkA= +schedule@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/schedule/-/schedule-0.5.0.tgz#c128fffa0b402488b08b55ae74bb9df55cc29cc8" + integrity sha512-HUcJicG5Ou8xfR//c2rPT0lPIRR09vVvN81T9fqfVgBmhERUbDEQoYKjpBxbueJnCPpSu2ujXzOnRQt6x9o/jw== + dependencies: + object-assign "^4.1.1" -schedule@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/schedule/-/schedule-0.4.0.tgz#fa20cfd0bfbf91c47d02272fd7096780d3170bbb" - integrity sha512-hYjmoaEMojiMkWCxKr6ue+LYcZ29u29+AamWYmzwT2VOO9ws5UJp/wNhsVUPiUeNh+EdRfZm7nDeB40ffTfMhA== +scheduler@0.17.0: + version "0.17.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.17.0.tgz#7c9c673e4ec781fac853927916d1c426b6f3ddfe" + integrity sha512-7rro8Io3tnCPuY4la/NuI5F2yfESpnfZyT6TtkXnSWVkcu0BCDJ+8gk5ozUaFaxpIyNuWAPXrH0yFcSi28fnDA== dependencies: + loose-envify "^1.1.0" object-assign "^4.1.1" -scheduler@^0.13.3: - version "0.13.6" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.13.6.tgz#466a4ec332467b31a91b9bf74e5347072e4cd889" - integrity sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ== +scheduler@^0.15.0: + version "0.15.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.15.0.tgz#6bfcf80ff850b280fed4aeecc6513bc0b4f17f8e" + integrity sha512-xAefmSfN6jqAa7Kuq7LIJY0bwAPG3xlCj0HMEBQk1lxYiDKZscY2xJ5U/61ZTrYbmNQbXa+gc7czPkVo11tnCg== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -10145,6 +10108,11 @@ scrypt-js@2.0.4: resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.4.tgz#32f8c5149f0797672e551c07e230f834b6af5f16" integrity sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw== +semver-compare@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" + integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= + semver-diff@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" @@ -10152,17 +10120,17 @@ semver-diff@^2.0.0: dependencies: semver "^5.0.3" -"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.0: - version "5.7.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" - integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== +"semver@2 || 3 || 4 || 5", semver@^5.0.1, semver@^5.0.3, semver@^5.1.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== semver@5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== -semver@^6.0.0, semver@^6.1.1: +semver@^6.0.0, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -10206,7 +10174,7 @@ serve-static@^1.13.1: parseurl "~1.3.3" send "0.17.1" -set-blocking@^2.0.0, set-blocking@~2.0.0: +set-blocking@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= @@ -10254,6 +10222,15 @@ shallow-clone@^0.1.2: lazy-cache "^0.2.3" mixin-object "^2.0.1" +shallow-clone@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-1.0.0.tgz#4480cd06e882ef68b2ad88a3ea54832e2c48b571" + integrity sha512-oeXreoKR/SyNJtRJMAKPDSvd28OqEwG4eR/xc856cRGBII7gX9lvAqDxusPm0846z/w/hWYjI1NpKwJ00NHzRA== + dependencies: + is-extendable "^0.1.1" + kind-of "^5.0.0" + mixin-object "^2.0.1" + shallowequal@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" @@ -10266,12 +10243,24 @@ shebang-command@^1.2.0: dependencies: shebang-regex "^1.0.0" +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= -shell-quote@1.6.1, shell-quote@^1.6.1: +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +shell-quote@1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.6.1.tgz#f4781949cce402697127430ea3b3c5476f481767" integrity sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c= @@ -10281,6 +10270,11 @@ shell-quote@1.6.1, shell-quote@^1.6.1: array-reduce "~0.0.0" jsonify "~0.0.0" +shell-quote@^1.6.1: + version "1.7.2" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2" + integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg== + shell-utils@^1.0.9: version "1.0.10" resolved "https://registry.yarnpkg.com/shell-utils/-/shell-utils-1.0.10.tgz#7fe7b8084f5d6d21323d941267013bc38aed063e" @@ -10308,18 +10302,18 @@ simple-plist@^0.2.1: plist "2.0.1" simple-plist@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/simple-plist/-/simple-plist-1.0.0.tgz#bed3085633b22f371e111f45d159a1ccf94b81eb" - integrity sha512-043L2rO80LVF7zfZ+fqhsEkoJFvW8o59rt/l4ctx1TJWoTx7/jkiS1R5TatD15Z1oYnuLJytzE7gcnnBuIPL2g== + version "1.1.0" + resolved "https://registry.yarnpkg.com/simple-plist/-/simple-plist-1.1.0.tgz#8354ab63eb3922a054c78ce96c209c532e907a23" + integrity sha512-2i5Tc0BYAqppM7jVzmNrI+aEUntPolIq4fDgji6WuNNn1D/qYdn2KwoLhZdzQkE04lu9L5tUoeJsjuJAvd+lFg== dependencies: - bplist-creator "0.0.7" - bplist-parser "0.1.1" + bplist-creator "0.0.8" + bplist-parser "0.2.0" plist "^3.0.1" -sisteransi@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.2.tgz#ec57d64b6f25c4f26c0e2c7dd23f2d7f12f7e418" - integrity sha512-ZcYcZcT69nSLAR2oLN2JwNmLkJEKGooFMCdvOkFrToUt/WfcRWqhIg4P4KwY4dmLbuyXIx4o4YmPsvMRJYJd/w== +sisteransi@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.4.tgz#386713f1ef688c7c0304dc4c0632898941cad2e3" + integrity sha512-/ekMoM4NJ59ivGSfKapeG+FWtrmWvA1p6FBZwXrqojw90vJu8lBmrTxCMuBCydKtkaUe2zt4PlxeTKpjwMbyig== sjcl@^1.0.3: version "1.0.8" @@ -10350,10 +10344,10 @@ slide@^1.1.5: resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" integrity sha1-VusCfWW00tzmyy4tMsTUr8nh1wc= -smart-buffer@4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.0.2.tgz#5207858c3815cc69110703c6b94e46c15634395d" - integrity sha512-JDhEpTKzXusOqXZ0BUIdH+CjFdO/CR3tLlf5CN34IypI+xMmXW1uB16OOY8z3cICbJlDAVJzNbwBhNO0wt9OAw== +smart-buffer@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.1.0.tgz#91605c25d91652f4661ea69ccf45f1b331ca21ba" + integrity sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw== snapdragon-node@^2.0.1: version "2.1.1" @@ -10386,16 +10380,16 @@ snapdragon@^0.8.1: use "^3.1.0" socket.io-client@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.2.0.tgz#84e73ee3c43d5020ccc1a258faeeb9aec2723af7" - integrity sha512-56ZrkTDbdTLmBIyfFYesgOxsjcLnwAKoN4CiPyTVkMQj3zTUh0QAx3GbvIvLpFEOvQWu92yyWICxB0u7wkVbYA== + version "2.3.0" + resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.3.0.tgz#14d5ba2e00b9bcd145ae443ab96b3f86cbcc1bb4" + integrity sha512-cEQQf24gET3rfhxZ2jJ5xzAOo/xhZwK+mOqtGRg5IowZsMgwvHwnf/mCRapAAkadhM26y+iydgwsXGObBB5ZdA== dependencies: backo2 "1.0.2" base64-arraybuffer "0.1.5" component-bind "1.0.0" component-emitter "1.2.1" - debug "~3.1.0" - engine.io-client "~3.3.1" + debug "~4.1.0" + engine.io-client "~3.4.0" has-binary2 "~1.0.2" has-cors "1.1.0" indexof "0.0.1" @@ -10423,28 +10417,45 @@ socks-proxy-agent@^4.0.1: socks "~2.3.2" socks@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/socks/-/socks-2.3.2.tgz#ade388e9e6d87fdb11649c15746c578922a5883e" - integrity sha512-pCpjxQgOByDHLlNqlnh/mNSAxIUkyBBuwwhTcV+enZGbDaClPvHdvm6uvOwZfFJkam7cGhBNbb4JxiP8UZkRvQ== + version "2.3.3" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.3.3.tgz#01129f0a5d534d2b897712ed8aceab7ee65d78e3" + integrity sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA== dependencies: - ip "^1.1.5" - smart-buffer "4.0.2" + ip "1.1.5" + smart-buffer "^4.1.0" + +source-map-explorer@^2.1.2: + version "2.2.1" + resolved "https://registry.yarnpkg.com/source-map-explorer/-/source-map-explorer-2.2.1.tgz#4bd236a1fe73e8b9db475f60197c48fc041928b8" + integrity sha512-vfjS5IRaENgXtTq2Bym0ctEorYGYNHLVCVZZeL1fvkD5iBoWKMlUhF/oFBTcTn9cxry1flplyvk0QGTROafB3Q== + dependencies: + btoa "^1.2.1" + chalk "^3.0.0" + convert-source-map "^1.7.0" + ejs "^3.0.1" + escape-html "^1.0.3" + glob "^7.1.6" + lodash "^4.17.15" + open "^7.0.0" + source-map "^0.7.3" + temp "^0.9.1" + yargs "^15.1.0" source-map-resolve@^0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" - integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== dependencies: - atob "^2.1.1" + atob "^2.1.2" decode-uri-component "^0.2.0" resolve-url "^0.2.1" source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@^0.5.6, source-map-support@^0.5.9: - version "0.5.12" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599" - integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ== +source-map-support@^0.5.16, source-map-support@^0.5.6: + version "0.5.16" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" + integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" @@ -10454,7 +10465,12 @@ source-map-url@^0.4.0: resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= -source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6: +source-map@0.5.6: + version "0.5.6" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" + integrity sha1-dc449SvwczxafwwRjYEzSiu19BI= + +source-map@^0.5.0, source-map@^0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= @@ -10464,6 +10480,11 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +source-map@^0.7.3: + version "0.7.3" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" + integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== + spawn-sync@^1.0.15: version "1.0.15" resolved "https://registry.yarnpkg.com/spawn-sync/-/spawn-sync-1.0.15.tgz#b00799557eb7fb0c8376c29d44e8a1ea67e57476" @@ -10540,17 +10561,46 @@ stable@^0.1.8: resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== +stack-generator@^2.0.4: + version "2.0.5" + resolved "https://registry.yarnpkg.com/stack-generator/-/stack-generator-2.0.5.tgz#fb00e5b4ee97de603e0773ea78ce944d81596c36" + integrity sha512-/t1ebrbHkrLrDuNMdeAcsvynWgoH/i4o8EGGfX7dEYDoTXOYVAkEpFdtshlvabzc6JlJ8Kf9YdFEoz7JkzGN9Q== + dependencies: + stackframe "^1.1.1" + stack-utils@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8" integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA== +stackframe@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.1.1.tgz#ffef0a3318b1b60c3b58564989aca5660729ec71" + integrity sha512-0PlYhdKh6AfFxRyK/v+6/k+/mMfyiEBbTM5L94D0ZytQnJ166wuwoTYLHFWGbs2dpA8Rgq763KGWmN1EQEYHRQ== + +stacktrace-gps@^3.0.3: + version "3.0.4" + resolved "https://registry.yarnpkg.com/stacktrace-gps/-/stacktrace-gps-3.0.4.tgz#7688dc2fc09ffb3a13165ebe0dbcaf41bcf0c69a" + integrity sha512-qIr8x41yZVSldqdqe6jciXEaSCKw1U8XTXpjDuy0ki/apyTn/r3w9hDAAQOhZdxvsC93H+WwwEu5cq5VemzYeg== + dependencies: + source-map "0.5.6" + stackframe "^1.1.1" + +stacktrace-js@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/stacktrace-js/-/stacktrace-js-2.0.1.tgz#ebdb0e9a16e6f171f96ca7878404e7f15c3d42ba" + integrity sha512-13oDNgBSeWtdGa4/2BycNyKqe+VktCoJ8VLx4pDoJkwGGJVtiHdfMOAj3aW9xTi8oR2v34z9IcvfCvT6XNdNAw== + dependencies: + error-stack-parser "^2.0.4" + stack-generator "^2.0.4" + stacktrace-gps "^3.0.3" + stacktrace-parser@^0.1.3: - version "0.1.6" - resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.6.tgz#c17d466d15ba51bee2f753d064f17327a886ff37" - integrity sha512-wXhu0Z8YgCGigUtHQq+J7pjXCppk3Um5DwH4qskOKHMlJmKwuuUSm+wDAgU7t4sbVjvuDTNGwOfFKgjMEqSflA== + version "0.1.8" + resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.8.tgz#28b0272bd9aeb41636f0c8265c03ba270c865e1b" + integrity sha512-ig5rHJSdJrAsVqdb3oAI/8C6aQ7dEwJXoy/TIEIOTzdJHssmn12o6RsFoeQSLHoKjq0lX+kqhmnLDpyQTuWiJA== dependencies: - type-fest "^0.3.0" + type-fest "^0.7.1" state-toggle@^1.0.0: version "1.0.2" @@ -10632,14 +10682,30 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string-width@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.1.0.tgz#ba846d1daa97c3c596155308063e075ed1c99aff" - integrity sha512-NrX+1dVVh+6Y9dnQ19pR0pP4FiEIlUvdTGn8pw6CKTNq5sgib2nIhmUNT5TAmhWmvKr3WcxBcP3E8nWezuipuQ== +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" + integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== dependencies: emoji-regex "^8.0.0" is-fullwidth-code-point "^3.0.0" - strip-ansi "^5.2.0" + strip-ansi "^6.0.0" + +string.prototype.trimleft@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz#9bdb8ac6abd6d602b17a4ed321870d2f8dcefc74" + integrity sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + +string.prototype.trimright@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz#440314b15996c866ce8a0341894d45186200c5d9" + integrity sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" string_decoder@^0.10.31, string_decoder@~0.10.x: version "0.10.31" @@ -10647,11 +10713,11 @@ string_decoder@^0.10.31, string_decoder@~0.10.x: integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= string_decoder@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d" - integrity sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w== + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== dependencies: - safe-buffer "~5.1.0" + safe-buffer "~5.2.0" string_decoder@~1.1.1: version "1.1.1" @@ -10691,6 +10757,13 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" + strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" @@ -10701,28 +10774,39 @@ strip-eof@^1.0.0: resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + strip-indent@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g= -strip-json-comments@2.0.1, strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: +strip-json-comments@2.0.1, strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= +strip-json-comments@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" + integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw== + style-search@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/style-search/-/style-search-0.1.0.tgz#7958c793e47e32e07d2b5cafe5c0bf8e12e77902" integrity sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI= -styled-components@4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-4.3.1.tgz#18c3709f4ed9d582cd206b1acd8b758a211dd114" - integrity sha512-04XKQFFSEx3qTeN5I4kiSeajrwG6juDMw2+vUgvfxeXFegE40TuPKS4fFey8RJP1Ii1AoVQVUOglrdUUey0ZHw== +styled-components@4.4.1: + version "4.4.1" + resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-4.4.1.tgz#e0631e889f01db67df4de576fedaca463f05c2f2" + integrity sha512-RNqj14kYzw++6Sr38n7197xG33ipEOktGElty4I70IKzQF1jzaD1U4xQ+Ny/i03UUhHlC5NWEO+d8olRCDji6g== dependencies: "@babel/helper-module-imports" "^7.0.0" - "@emotion/is-prop-valid" "^0.7.3" + "@babel/traverse" "^7.0.0" + "@emotion/is-prop-valid" "^0.8.1" "@emotion/unitless" "^0.7.0" babel-plugin-styled-components ">= 1" css-to-react-native "^2.2.2" @@ -10734,10 +10818,10 @@ styled-components@4.3.1: stylis-rule-sheet "^0.0.10" supports-color "^5.5.0" -styled-components@^5.0.0-beta.8: - version "5.0.0-beta.6-ej4" - resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-5.0.0-beta.6-ej4.tgz#7570ebbf9c9356a8cca03ea37dd94233f2e40e84" - integrity sha512-WaytinYy4+Zc1TKXdTlPmkAOIj58QWvjn1rdgxCSAMAR4GFLlu2m7rQXwZ6WYWYk6GJd141rnZnE2Ig3XERc5A== +styled-components@5.0.0-beta.9: + version "5.0.0-beta.9" + resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-5.0.0-beta.9.tgz#12943e3d5b2f7035e821ccb0c7bed3ae996c74d8" + integrity sha512-kAehGNjhGjGLxT6sHUDQtMlKn9aE3Vpz4vMoYzRezK4ewcbdGx65IAcMyg6AHq1+di+LjUnlURBWaW71NdCHnA== dependencies: "@babel/helper-module-imports" "^7.0.0" "@babel/traverse" "^7.4.5" @@ -10815,6 +10899,11 @@ stylis@^3.5.0: resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.5.4.tgz#f665f25f5e299cf3d64654ab949a57c768b73fbe" integrity sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q== +sudo-prompt@^9.0.0: + version "9.1.1" + resolved "https://registry.yarnpkg.com/sudo-prompt/-/sudo-prompt-9.1.1.tgz#73853d729770392caec029e2470db9c221754db0" + integrity sha512-es33J1g2HjMpyAhz8lOR+ICmXXAqTuKbuXuUWLhOLew20oN9oUCgCJx615U/v7aioZg7IX5lIh9x34vwneu4pA== + sugarss@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/sugarss/-/sugarss-2.0.0.tgz#ddd76e0124b297d40bf3cca31c8b22ecb43bc61d" @@ -10831,21 +10920,29 @@ superagent-proxy@^2.0.0: proxy-agent "3" superagent@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/superagent/-/superagent-5.1.0.tgz#9ce4f38bee64d65a56166423b573222fa1b8f041" - integrity sha512-7V6JVx5N+eTL1MMqRBX0v0bG04UjrjAvvZJTF/VDH/SH2GjSLqlrcYepFlpTrXpm37aSY6h3GGVWGxXl/98TKA== + version "5.1.3" + resolved "https://registry.yarnpkg.com/superagent/-/superagent-5.1.3.tgz#9502db541559d3d9e7acfa30f70d1186c0faa88d" + integrity sha512-2bno1Nb4uvZPECTJ7NDYlae6Q8LLQoZZZ9Vumd346jU1UGVkNC/lQI42jHwtrqVoepyt0QxNKFty01IRKgD4CA== dependencies: component-emitter "^1.3.0" cookiejar "^2.1.2" debug "^4.1.1" - fast-safe-stringify "^2.0.6" - form-data "^2.3.3" + fast-safe-stringify "^2.0.7" + form-data "^3.0.0" formidable "^1.2.1" methods "^1.1.2" mime "^2.4.4" - qs "^6.7.0" + qs "^6.9.1" readable-stream "^3.4.0" - semver "^6.1.1" + semver "^6.3.0" + +superstruct@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-0.6.2.tgz#c5eb034806a17ff98d036674169ef85e4c7f6a1c" + integrity sha512-lvA97MFAJng3rfjcafT/zGTSWm6Tbpk++DP6It4Qg7oNaeM+2tdJMuVgGje21/bIpBEs6iQql1PJH6dKTjl4Ig== + dependencies: + clone-deep "^2.0.1" + kind-of "^6.0.1" supports-color@6.0.0: version "6.0.0" @@ -10873,6 +10970,13 @@ supports-color@^6.1.0: dependencies: has-flag "^3.0.0" +supports-color@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" + integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== + dependencies: + has-flag "^4.0.0" + svg-arc-to-cubic-bezier@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/svg-arc-to-cubic-bezier/-/svg-arc-to-cubic-bezier-3.2.0.tgz#390c450035ae1c4a0104d90650304c3bc814abe6" @@ -10889,16 +10993,16 @@ svg-tags@^1.0.0: integrity sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q= svgo@^1.2.2: - version "1.3.0" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.0.tgz#bae51ba95ded9a33a36b7c46ce9c359ae9154313" - integrity sha512-MLfUA6O+qauLDbym+mMZgtXCGRfIxyQoeH6IKVcFslyODEe/ElJNwr0FohQ3xG4C6HK6bk3KYPPXwHVJk3V5NQ== + version "1.3.2" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" + integrity sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw== dependencies: chalk "^2.4.1" coa "^2.0.2" css-select "^2.0.0" css-select-base-adapter "^0.1.1" - css-tree "1.0.0-alpha.33" - csso "^3.5.1" + css-tree "1.0.0-alpha.37" + csso "^4.0.2" js-yaml "^3.13.1" mkdirp "~0.5.1" object.values "^1.1.0" @@ -10931,9 +11035,9 @@ symbol-tree@^3.2.2: integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== table@^5.2.3: - version "5.4.4" - resolved "https://registry.yarnpkg.com/table/-/table-5.4.4.tgz#6e0f88fdae3692793d1077fd172a4667afe986a6" - integrity sha512-IIfEAUx5QlODLblLrGTTLJA7Tk0iLSGBvgY8essPRVNGHAzThujww1YqHLs6h3HfTg55h++RzLHH5Xw/rfv+mg== + version "5.4.6" + resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" + integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== dependencies: ajv "^6.10.2" lodash "^4.17.14" @@ -10941,22 +11045,9 @@ table@^5.2.3: string-width "^3.0.0" tail@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/tail/-/tail-2.0.2.tgz#86073f3a9a568807b7fd886897a7350314275b5f" - integrity sha512-raFipiKWdGKEzxbvZwnhUGqjvsv0gpa/1A479rL//NOxnNwYZDN4MPk6xJJdUFs8P2Xrff3nbH5fcyYRLU4UHQ== - -tar@^4: - version "4.4.10" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.10.tgz#946b2810b9a5e0b26140cf78bea6b0b0d689eba1" - integrity sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA== - dependencies: - chownr "^1.1.1" - fs-minipass "^1.2.5" - minipass "^2.3.5" - minizlib "^1.2.1" - mkdirp "^0.5.0" - safe-buffer "^5.1.2" - yallist "^3.0.3" + version "2.0.3" + resolved "https://registry.yarnpkg.com/tail/-/tail-2.0.3.tgz#37567adc4624a70b35f1d146c3376fa3d6ef7c04" + integrity sha512-s9NOGkLqqiDEtBttQZI7acLS8ycYK5sTlDwNjGnpXG9c8AWj0cfAtwEIzo/hVRMMiC5EYz+bXaJWC1u1u0GPpQ== telnet-client@0.15.3: version "0.15.3" @@ -10978,6 +11069,13 @@ temp@0.8.3: os-tmpdir "^1.0.0" rimraf "~2.2.6" +temp@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/temp/-/temp-0.9.1.tgz#2d666114fafa26966cd4065996d7ceedd4dd4697" + integrity sha512-WMuOgiua1xb5R56lE0eH6ivpVmg/lq2OHm4+LtT/xtEtPQ+sz6N3bBM6WZ5FvO1lO4IKIOb43qnhoc4qxP5OeA== + dependencies: + rimraf "~2.6.2" + tempfile@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/tempfile/-/tempfile-2.0.0.tgz#6b0446856a9b1114d1856ffcbe509cccb0977265" @@ -11013,7 +11111,7 @@ throat@^4.0.0, throat@^4.1.0: resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" integrity sha1-iQN8vJLFarGJJua6TLsgDhVnKmo= -through2@^2.0.0: +through2@^2.0.0, through2@^2.0.1: version "2.0.5" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== @@ -11147,11 +11245,6 @@ trim-newlines@^2.0.0: resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-2.0.0.tgz#b403d0b91be50c331dfc4b82eeceb22c3de16d20" integrity sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA= -trim-right@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= - trim-trailing-lines@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.2.tgz#d2f1e153161152e9f02fabc670fb40bec2ea2e3a" @@ -11179,15 +11272,15 @@ ts-object-utils@0.0.5: resolved "https://registry.yarnpkg.com/ts-object-utils/-/ts-object-utils-0.0.5.tgz#95361cdecd7e52167cfc5e634c76345e90a26077" integrity sha1-lTYc3s1+UhZ8/F5jTHY0XpCiYHc= -tslib@^1.8.1, tslib@^1.9.0: +tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: version "1.10.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== tsutils@^3.7.0: - version "3.14.1" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.14.1.tgz#f1d2b93d2a0876481f2f1f98c25ba42bbd7ee860" - integrity sha512-kiuZzD1uUA5DxGj/uxbde+ymp6VVdAxdzOIlAFbYKrPyla8/uiJ9JLBm1QsPhOm4Muj0/+cWEDP99yoCUcSl6Q== + version "3.17.1" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" + integrity sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g== dependencies: tslib "^1.8.1" @@ -11215,10 +11308,37 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" -type-fest@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" - integrity sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ== +type-fest@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" + integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== + +type-fest@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" + integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== + +type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + +type@^1.0.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" + integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== + +type@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/type/-/type-2.0.0.tgz#5f16ff6ef2eb44f260494dae271033b29c09a9c3" + integrity sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow== + +typedarray-to-buffer@^3.1.2: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" typedarray@^0.0.6: version "0.0.6" @@ -11226,9 +11346,9 @@ typedarray@^0.0.6: integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= ua-parser-js@^0.7.18: - version "0.7.20" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.20.tgz#7527178b82f6a62a0f243d1f94fd30e3e3c21098" - integrity sha512-8OaIKfzL5cpx8eCMAhhvTlft8GYF8b2eQr6JkCyVdrgjcytyOmPCXrqXFcUnhonRpLlh5yxEZVohm6mzaowUOw== + version "0.7.21" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.21.tgz#853cf9ce93f642f67174273cc34565ae6f308777" + integrity sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ== uglify-es@^3.1.9: version "3.3.9" @@ -11239,11 +11359,11 @@ uglify-es@^3.1.9: source-map "~0.6.1" uglify-js@^3.1.4: - version "3.6.0" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.6.0.tgz#704681345c53a8b2079fb6cec294b05ead242ff5" - integrity sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg== + version "3.7.3" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.3.tgz#f918fce9182f466d5140f24bb0ff35c2d32dcc6a" + integrity sha512-7tINm46/3puUA4hCkKYo4Xdts+JDaVC9ZPRcG8Xw9R4nhO/gZgUM3TENq8IF4Vatk8qCig4MzP/c8G4u2BkVQg== dependencies: - commander "~2.20.0" + commander "~2.20.3" source-map "~0.6.1" ultron@1.0.x: @@ -11287,6 +11407,18 @@ unicode-property-aliases-ecmascript@^1.0.4: resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz#a9cc6cc7ce63a0a3023fc99e341b94431d405a57" integrity sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw== +unified@^6.1.2: + version "6.2.0" + resolved "https://registry.yarnpkg.com/unified/-/unified-6.2.0.tgz#7fbd630f719126d67d40c644b7e3f617035f6dba" + integrity sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA== + dependencies: + bail "^1.0.0" + extend "^3.0.0" + is-plain-obj "^1.1.0" + trough "^1.0.0" + vfile "^2.0.0" + x-is-string "^0.1.0" + unified@^7.0.0: version "7.1.0" resolved "https://registry.yarnpkg.com/unified/-/unified-7.1.0.tgz#5032f1c1ee3364bd09da12e27fdd4a7553c7be13" @@ -11324,9 +11456,9 @@ unique-string@^1.0.0: crypto-random-string "^1.0.0" unist-util-find-all-after@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unist-util-find-all-after/-/unist-util-find-all-after-1.0.4.tgz#2eeaba818fd98492d69c44f9bee52c6a25282eef" - integrity sha512-CaxvMjTd+yF93BKLJvZnEfqdM7fgEACsIpQqz8vIj9CJnUb9VpyymFS3tg6TCtgrF7vfCJBF5jbT2Ox9CBRYRQ== + version "1.0.5" + resolved "https://registry.yarnpkg.com/unist-util-find-all-after/-/unist-util-find-all-after-1.0.5.tgz#5751a8608834f41d117ad9c577770c5f2f1b2899" + integrity sha512-lWgIc3rrTMTlK1Y0hEuL+k+ApzFk78h+lsaa2gHf63Gp5Ww+mt11huDniuaoq1H+XMK2lIIjjPkncxXcDp3QDw== dependencies: unist-util-is "^3.0.0" @@ -11336,9 +11468,9 @@ unist-util-is@^3.0.0: integrity sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A== unist-util-remove-position@^1.0.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-1.1.3.tgz#d91aa8b89b30cb38bad2924da11072faa64fd972" - integrity sha512-CtszTlOjP2sBGYc2zcKA/CvNdTdEs3ozbiJ63IPBxh8iZg42SCCb8m04f8z2+V1aSk5a7BxbZKEdoDjadmBkWA== + version "1.1.4" + resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-1.1.4.tgz#ec037348b6102c897703eee6d0294ca4755a2020" + integrity sha512-tLqd653ArxJIPnKII6LMZwH+mb5q+n/GtXQZo6S6csPRs5zB0u79Yw8ouR3wTw8wxvdJFhpP6Y7jorWdCgLO0A== dependencies: unist-util-visit "^1.1.0" @@ -11347,6 +11479,13 @@ unist-util-stringify-position@^1.0.0, unist-util-stringify-position@^1.1.1: resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz#3f37fcf351279dcbca7480ab5889bb8a832ee1c6" integrity sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ== +unist-util-stringify-position@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.2.tgz#5a3866e7138d55974b640ec69a94bc19e0f3fa12" + integrity sha512-nK5n8OGhZ7ZgUwoUbL8uiVRwAbZyzBsB/Ddrlbu6jwwubFza4oe15KlyEaLNMXQW1svOQq4xesUeqA85YrIUQA== + dependencies: + "@types/unist" "^2.0.2" + unist-util-visit-parents@^2.0.0: version "2.1.2" resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz#25e43e55312166f3348cae6743588781d112c1e9" @@ -11437,6 +11576,13 @@ use-memo-one@^1.1.1: resolved "https://registry.yarnpkg.com/use-memo-one/-/use-memo-one-1.1.1.tgz#39e6f08fe27e422a7d7b234b5f9056af313bd22c" integrity sha512-oFfsyun+bP7RX8X2AskHNTxu+R3QdE/RC5IefMbqptmACAA/gfol1KDD5KRzPsGMa62sWxGZw+Ui43u6x4ddoQ== +use-subscription@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/use-subscription/-/use-subscription-1.3.0.tgz#3df13a798e826c8d462899423293289a3362e4e6" + integrity sha512-buZV7FUtnbOr+65dN7PHK7chHhQGfk/yjgqfpRLoWuHIAc4klAD/rdot2FsPNtFthN1ZydvA8tR/mWBMQ+/fDQ== + dependencies: + object-assign "^4.1.1" + use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" @@ -11490,9 +11636,14 @@ uuid@3.0.1: integrity sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE= uuid@^3.0.1, uuid@^3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" - integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== + version "3.3.3" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866" + integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ== + +v8-compile-cache@^2.0.3: + version "2.1.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e" + integrity sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g== validate-npm-package-license@^3.0.1: version "3.0.4" @@ -11517,9 +11668,17 @@ verror@1.10.0: extsprintf "^1.2.0" vfile-location@^2.0.0: - version "2.0.5" - resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-2.0.5.tgz#c83eb02f8040228a8d2b3f10e485be3e3433e0a2" - integrity sha512-Pa1ey0OzYBkLPxPZI3d9E+S4BmvfVwNAAXrrqGbwTVXWaX2p9kM1zZ+n35UtVM06shmWKH4RPRN8KI80qE3wNQ== + version "2.0.6" + resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-2.0.6.tgz#8a274f39411b8719ea5728802e10d9e0dff1519e" + integrity sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA== + +vfile-message@*: + version "2.0.2" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-2.0.2.tgz#75ba05090ec758fa8420f2c11ce049bcddd8cf3e" + integrity sha512-gNV2Y2fDvDOOqq8bEe7cF3DXU6QgV4uA9zMR2P8tix11l1r7zju3zry3wZ8sx+BEfuO6WQ7z2QzfWTvqHQiwsA== + dependencies: + "@types/unist" "^2.0.0" + unist-util-stringify-position "^2.0.0" vfile-message@^1.0.0: version "1.1.1" @@ -11528,6 +11687,16 @@ vfile-message@^1.0.0: dependencies: unist-util-stringify-position "^1.1.1" +vfile@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-2.3.0.tgz#e62d8e72b20e83c324bc6c67278ee272488bf84a" + integrity sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w== + dependencies: + is-buffer "^1.1.4" + replace-ext "1.0.0" + unist-util-stringify-position "^1.0.0" + vfile-message "^1.0.0" + vfile@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/vfile/-/vfile-3.0.1.tgz#47331d2abe3282424f4a4bb6acd20a44c4121803" @@ -11538,6 +11707,11 @@ vfile@^3.0.0: unist-util-stringify-position "^1.0.0" vfile-message "^1.0.0" +vlq@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/vlq/-/vlq-1.0.1.tgz#c003f6e7c0b4c1edd623fd6ee50bbc0d6a1de468" + integrity sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w== + vm-browserify@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" @@ -11545,6 +11719,37 @@ vm-browserify@0.0.4: dependencies: indexof "0.0.1" +vscode-json-languageservice@^3.2.1: + version "3.4.11" + resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.4.11.tgz#7c0632bccc4b2b955f99f99f43d96d3eece1de42" + integrity sha512-26Qv1SFp6x3XmCqU1BRceRsSKRO3xkQa6/K8ziSRt52/LQPiw5ipSxlGVSlzIoi5LCmQVEqUajhiVEMNlFXhNw== + dependencies: + jsonc-parser "^2.2.0" + vscode-languageserver-textdocument "^1.0.0-next.5" + vscode-languageserver-types "^3.15.0-next.9" + vscode-nls "^4.1.1" + vscode-uri "^2.1.1" + +vscode-languageserver-textdocument@^1.0.0-next.5: + version "1.0.0-next.5" + resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.0-next.5.tgz#dbb7a45dd973a19261a7c57ab9a439c40f3799ee" + integrity sha512-1jp/zAidN/bF/sqPimhBX1orH5G4rzRw63k75TesukJDuxm8yW79ECStWbDSy41BHGOwSGN4M69QFvhancSr5A== + +vscode-languageserver-types@^3.15.0-next.9: + version "3.15.0-next.9" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.9.tgz#957a9d1d5998a02edf62298fb7e37d9efcc6c157" + integrity sha512-Rl/8qJ6932nrHCdPn+9y0x08uLVQaSLRG+U4JzhyKpWU4eJbVaDRoAcz1Llj7CErJGbPr6kdBvShPy5fRfR+Uw== + +vscode-nls@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.1.tgz#f9916b64e4947b20322defb1e676a495861f133c" + integrity sha512-4R+2UoUUU/LdnMnFjePxfLqNhBS8lrAFyX7pjb2ud/lqDkrUavFUTcG7wR0HBZFakae0Q6KLBFjMS6W93F403A== + +vscode-uri@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.1.1.tgz#5aa1803391b6ebdd17d047f51365cf62c38f6e90" + integrity sha512-eY9jmGoEnVf8VE8xr5znSah7Qt1P/xsCdErz+g8HYZtJ7bZqKH5E3d+6oVNm1AC/c6IHUDokbmVXKOi4qPAC9A== + w3c-hr-time@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz#82ac2bff63d950ea9e3189a58a65625fedf19045" @@ -11566,14 +11771,6 @@ warning@^4.0.2: dependencies: loose-envify "^1.0.0" -watch@~0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/watch/-/watch-0.18.0.tgz#28095476c6df7c90c963138990c0a5423eb4b986" - integrity sha1-KAlUdsbffJDJYxOJkMClQj60uYY= - dependencies: - exec-sh "^0.2.0" - minimist "^1.2.0" - wcwidth@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" @@ -11593,7 +11790,7 @@ whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3: dependencies: iconv-lite "0.4.24" -whatwg-fetch@>=0.10.0: +whatwg-fetch@>=0.10.0, whatwg-fetch@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb" integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q== @@ -11613,9 +11810,9 @@ whatwg-url@^6.4.1: webidl-conversions "^4.0.2" whatwg-url@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.0.0.tgz#fde926fa54a599f3adf82dff25a9f7be02dc6edd" - integrity sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ== + version "7.1.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06" + integrity sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg== dependencies: lodash.sortby "^4.7.0" tr46 "^1.0.1" @@ -11633,7 +11830,14 @@ which@1.3.1, which@^1.2.9, which@^1.3.0, which@^1.3.1: dependencies: isexe "^2.0.0" -wide-align@1.1.3, wide-align@^1.1.0: +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wide-align@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== @@ -11647,7 +11851,12 @@ widest-line@^2.0.0: dependencies: string-width "^2.1.1" -wordwrap@^1.0.0, wordwrap@~1.0.0: +word-wrap@~1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + +wordwrap@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= @@ -11674,6 +11883,15 @@ wrap-ansi@^5.1.0: string-width "^3.0.0" strip-ansi "^5.0.0" +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -11737,6 +11955,11 @@ ws@^5.2.0: dependencies: async-limiter "~1.0.0" +ws@^7: + version "7.2.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.2.1.tgz#03ed52423cd744084b2cf42ed197c8b65a936b8e" + integrity sha512-sucePNSafamSKoOqoNfBd8V0StlkzJKL2ZAhGQinCfNQ+oacw+Pk7lcdAElecBF2VkLNZRiIb5Oi1Q5lVUVt2A== + ws@~6.1.0: version "6.1.4" resolved "https://registry.yarnpkg.com/ws/-/ws-6.1.4.tgz#5b5c8800afab925e94ccb29d153c8d02c1776ef9" @@ -11758,7 +11981,7 @@ xcode@1.0.0: simple-plist "^0.2.1" uuid "3.0.1" -xcode@^2.0.0: +xcode@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/xcode/-/xcode-2.0.0.tgz#134f1f94c26fbfe8a9aaa9724bfb2772419da1a2" integrity sha512-5xF6RCjAdDEiEsbbZaS/gBRt3jZ/177otZcpoLCjGN/u1LrfgH7/Sgeeavpr/jELpyDqN2im3AKosl2G2W8hfw== @@ -11766,6 +11989,14 @@ xcode@^2.0.0: simple-plist "^1.0.0" uuid "^3.3.2" +xcode@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/xcode/-/xcode-2.1.0.tgz#bab64a7e954bb50ca8d19da7e09531c65a43ecfe" + integrity sha512-uCrmPITrqTEzhn0TtT57fJaNaw8YJs1aCzs+P/QqxsDbvPZSv7XMPPwXrKvHtD6pLjBM/NaVwraWJm8q83Y4iQ== + dependencies: + simple-plist "^1.0.0" + uuid "^3.3.2" + xdg-basedir@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" @@ -11786,17 +12017,17 @@ xmlbuilder@^9.0.7: resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0= -xmldoc@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/xmldoc/-/xmldoc-0.4.0.tgz#d257224be8393eaacbf837ef227fd8ec25b36888" - integrity sha1-0lciS+g5PqrL+DfvIn/Y7CWzaIg= +xmldoc@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/xmldoc/-/xmldoc-1.1.2.tgz#6666e029fe25470d599cd30e23ff0d1ed50466d7" + integrity sha512-ruPC/fyPNck2BD1dpz0AZZyrEwMOrWTO5lDdIXS91rs3wtm4j+T8Rp2o+zoOYkkAxJTZRPOSnOGei1egoRmKMQ== dependencies: - sax "~1.1.1" + sax "^1.2.1" xmldom@0.1.x: - version "0.1.27" - resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.27.tgz#d501f97b3bdb403af8ef9ecc20573187aadac0e9" - integrity sha1-1QH5ezvbQDr4757MIFcxh6rawOk= + version "0.1.31" + resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.31.tgz#b76c9a1bd9f0a9737e5a72dc37231cf38375e2ff" + integrity sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ== xmlhttprequest-ssl@~1.5.4: version "1.5.5" @@ -11856,15 +12087,15 @@ yallist@^2.1.2: resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= -yallist@^3.0.0, yallist@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" - integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A== +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== -yargs-parser@13.0.0: - version "13.0.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.0.0.tgz#3fc44f3e76a8bdb1cc3602e860108602e5ccde8b" - integrity sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw== +yargs-parser@13.1.1, yargs-parser@^13.0.0, yargs-parser@^13.1.1: + version "13.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" + integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== dependencies: camelcase "^5.0.0" decamelize "^1.2.0" @@ -11884,10 +12115,10 @@ yargs-parser@^11.1.1: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^13.0.0, yargs-parser@^13.1.1: - version "13.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" - integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== +yargs-parser@^16.1.0: + version "16.1.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-16.1.0.tgz#73747d53ae187e7b8dbe333f95714c76ea00ecf1" + integrity sha512-H/V41UNZQPkUMIT5h5hiwg4QKIY1RPvoBV4XcjUbRM8Bk2oKqqyZ0DIEbTFZB0XjbtSPG8SAa/0DxCQmiRgzKg== dependencies: camelcase "^5.0.0" decamelize "^1.2.0" @@ -11899,31 +12130,30 @@ yargs-parser@^7.0.0: dependencies: camelcase "^4.1.0" -yargs-unparser@1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.5.0.tgz#f2bb2a7e83cbc87bb95c8e572828a06c9add6e0d" - integrity sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw== +yargs-unparser@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" + integrity sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw== dependencies: flat "^4.1.0" - lodash "^4.17.11" - yargs "^12.0.5" + lodash "^4.17.15" + yargs "^13.3.0" -yargs@13.2.2: - version "13.2.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.2.tgz#0c101f580ae95cea7f39d927e7770e3fdc97f993" - integrity sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA== +yargs@13.3.0, yargs@^13.0.0, yargs@^13.2.4, yargs@^13.3.0: + version "13.3.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" + integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== dependencies: - cliui "^4.0.0" + cliui "^5.0.0" find-up "^3.0.0" get-caller-file "^2.0.1" - os-locale "^3.1.0" require-directory "^2.1.1" require-main-filename "^2.0.0" set-blocking "^2.0.0" string-width "^3.0.0" which-module "^2.0.0" y18n "^4.0.0" - yargs-parser "^13.0.0" + yargs-parser "^13.1.1" yargs@^12.0.2, yargs@^12.0.5: version "12.0.5" @@ -11943,21 +12173,22 @@ yargs@^12.0.2, yargs@^12.0.5: y18n "^3.2.1 || ^4.0.0" yargs-parser "^11.1.1" -yargs@^13.0.0, yargs@^13.2.4: - version "13.3.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" - integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== +yargs@^15.1.0: + version "15.1.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.1.0.tgz#e111381f5830e863a89550bd4b136bb6a5f37219" + integrity sha512-T39FNN1b6hCW4SOIk1XyTOWxtXdcen0t+XYrysQmChzSipvhBO8Bj0nK1ozAasdk24dNWuMZvr4k24nz+8HHLg== dependencies: - cliui "^5.0.0" - find-up "^3.0.0" + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" get-caller-file "^2.0.1" require-directory "^2.1.1" require-main-filename "^2.0.0" set-blocking "^2.0.0" - string-width "^3.0.0" + string-width "^4.2.0" which-module "^2.0.0" y18n "^4.0.0" - yargs-parser "^13.1.1" + yargs-parser "^16.1.0" yargs@^9.0.0: version "9.0.1"