diff --git a/.github/workflows/update-attributions.yml b/.github/workflows/update-attributions.yml new file mode 100644 index 00000000000..785a1ee5f7d --- /dev/null +++ b/.github/workflows/update-attributions.yml @@ -0,0 +1,195 @@ +name: Update Attributions + +on: + issue_comment: + types: created + +jobs: + is-fork-pull-request: + name: Determine whether this issue comment was on a pull request from a fork + if: ${{ github.event.issue.pull_request && startsWith(github.event.comment.body, '@metamaskbot update-attributions') }} + runs-on: ubuntu-latest + outputs: + IS_FORK: ${{ steps.is-fork.outputs.IS_FORK }} + steps: + - uses: actions/checkout@v4 + - name: Determine whether this PR is from a fork + id: is-fork + run: echo "IS_FORK=$(gh pr view --json isCrossRepository --jq '.isCrossRepository' "${PR_NUMBER}" )" >> "$GITHUB_OUTPUT" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR_NUMBER: ${{ github.event.issue.number }} + + react-to-comment: + name: React to the comment + runs-on: ubuntu-latest + needs: is-fork-pull-request + # Early exit if this is a fork, since later steps are skipped for forks + if: ${{ needs.is-fork-pull-request.outputs.IS_FORK == 'false' }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: React to the comment + run: | + gh api \ + --method POST \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "/repos/${REPO}/issues/comments/${COMMENT_ID}/reactions" \ + -f content='+1' + env: + COMMENT_ID: ${{ github.event.comment.id }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + REPO: ${{ github.repository }} + + prepare: + name: Prepare dependencies + runs-on: ubuntu-latest + needs: is-fork-pull-request + # Early exit if this is a fork, since later steps are skipped for forks + if: ${{ needs.is-fork-pull-request.outputs.IS_FORK == 'false' }} + outputs: + COMMIT_SHA: ${{ steps.commit-sha.outputs.COMMIT_SHA }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Checkout pull request + run: gh pr checkout "${PR_NUMBER}" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR_NUMBER: ${{ github.event.issue.number }} + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version-file: '.nvmrc' + cache: 'yarn' + - name: Install Yarn dependencies + run: yarn --immutable + - name: Get commit SHA + id: commit-sha + run: echo "COMMIT_SHA=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT" + + update-attributions: + name: Update Attributions + runs-on: ubuntu-latest + needs: + - prepare + - is-fork-pull-request + # Early exit if this is a fork, since later steps are skipped for forks + if: ${{ needs.is-fork-pull-request.outputs.IS_FORK == 'false' }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Checkout pull request + run: gh pr checkout "${PR_NUMBER}" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR_NUMBER: ${{ github.event.issue.number }} + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version-file: '.nvmrc' + cache: 'yarn' + - name: Install dependencies from cache + run: yarn --immutable --immutable-cache + - name: Generate Attributions + run: yarn build:attribution + - name: Cache attributions file + uses: actions/cache/save@v3 + with: + path: attribution.txt + key: cache-build-${{ needs.prepare.outputs.COMMIT_SHA }} + + commit-updated-attributions: + name: Commit the updated Attributions + runs-on: ubuntu-latest + needs: + - prepare + - is-fork-pull-request + - update-attributions + if: ${{ needs.is-fork-pull-request.outputs.IS_FORK == 'false' }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + # Use PAT to ensure that the commit later can trigger status check workflows + token: ${{ secrets.GITHUB_TOKEN }} + - name: Checkout pull request + run: gh pr checkout "${PR_NUMBER}" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR_NUMBER: ${{ github.event.issue.number }} + - name: Get commit SHA + id: commit-sha + run: echo "COMMIT_SHA=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT" + - name: Restore attributions file + uses: actions/cache/restore@v3 + with: + path: attribution.txt + key: cache-build-${{ needs.prepare.outputs.COMMIT_SHA }} + fail-on-cache-miss: true + - name: Check whether there are attributions changes + id: attributions-changes + run: | + if git diff --exit-code + then + echo "HAS_CHANGES=false" >> "$GITHUB_OUTPUT" + else + echo "HAS_CHANGES=true" >> "$GITHUB_OUTPUT" + fi + - name: Commit the updated attributions + if: steps.attributions-changes.outputs.HAS_CHANGES == 'true' + run: | + git config --global user.name 'MetaMask Bot' + git config --global user.email 'metamaskbot@users.noreply.github.com' + git commit -am "Update Attributions" + git push + - name: Post comment + run: | + if [[ $HAS_CHANGES == 'true' ]] + then + gh pr comment "${PR_NUMBER}" --body 'Attributions updated' + else + gh pr comment "${PR_NUMBER}" --body 'No attributions changes' + fi + env: + HAS_CHANGES: ${{ steps.attributions-changes.outputs.HAS_CHANGES }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR_NUMBER: ${{ github.event.issue.number }} + + check-status: + name: Check whether the attributions update succeeded + runs-on: ubuntu-latest + needs: + - commit-updated-attributions + - is-fork-pull-request + # Early exit if this is a fork, since later steps are skipped for forks + if: ${{ needs.is-fork-pull-request.outputs.IS_FORK == 'false' }} + outputs: + PASSED: ${{ steps.set-output.outputs.PASSED }} + steps: + - name: Set PASSED output + id: set-output + run: echo "PASSED=true" >> "$GITHUB_OUTPUT" + + failure-comment: + name: Comment about the attributions update failure + if: ${{ always() && needs.is-fork-pull-request.outputs.IS_FORK == 'false' }} + runs-on: ubuntu-latest + needs: + - is-fork-pull-request + - check-status + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: Post comment if the update failed + run: | + passed="${{ needs.check-status.outputs.PASSED }}" + if [[ $passed != "true" ]]; then + gh pr comment "${PR_NUMBER}" --body "Attributions update failed. You can [review the logs or retry the attributions update here](${ACTION_RUN_URL})" + fi + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR_NUMBER: ${{ github.event.issue.number }} + ACTION_RUN_URL: '${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}' diff --git a/.gitignore b/.gitignore index f4c8af6ff83..d0ee5c4774a 100644 --- a/.gitignore +++ b/.gitignore @@ -45,6 +45,8 @@ android/app/google-services.json node_modules/ npm-debug.log yarn-error.log +.yalc +yalc.lock # buck buck-out/ diff --git a/.storybook/storybook.requires.js b/.storybook/storybook.requires.js index 8c929c9fe7d..4c8963175cc 100644 --- a/.storybook/storybook.requires.js +++ b/.storybook/storybook.requires.js @@ -117,6 +117,8 @@ const getStories = () => { './app/components/UI/Name/Name.stories.tsx': require('../app/components/UI/Name/Name.stories.tsx'), "./app/components/UI/SimulationDetails/SimulationDetails.stories.tsx": require("../app/components/UI/SimulationDetails/SimulationDetails.stories.tsx"), "./app/component-library/components-temp/CellSelectWithMenu/CellSelectWithMenu.stories.tsx": require("../app/component-library/components-temp/CellSelectWithMenu/CellSelectWithMenu.stories.tsx"), + './app/component-library/components-temp/Price/AggregatedPercentage/AggregatedPercentage.stories': require('../app/component-library/components-temp/Price/AggregatedPercentage/AggregatedPercentage.stories.tsx'), + './app/component-library/components-temp/Price/PercentageChange/PercentageChange.stories': require('../app/component-library/components-temp/Price/PercentageChange/PercentageChange.stories.tsx'), }; }; diff --git a/CHANGELOG.md b/CHANGELOG.md index 94dc5e5e7cf..e51efda74ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,105 @@ ## Current Main Branch +## 7.26.0 - Jul 5, 2024 +### Added +- [#9937](https://github.com/MetaMask/metamask-mobile/pull/9937): feat: modification of the network bottom sheet to use the new UI redesign by adding the popular network section as additional network (#9937) +- [#9856](https://github.com/MetaMask/metamask-mobile/pull/9856): feat: new attribution github workflow (#9856) +- [#9768](https://github.com/MetaMask/metamask-mobile/pull/9768): feat: add MetaMetrics delete on Wallet delete (#9768) +- [#9785](https://github.com/MetaMask/metamask-mobile/pull/9785): feat: Log the validity of the keyringController in the top 3 Migrations that appear in Sentry (#9785) +- [#9885](https://github.com/MetaMask/metamask-mobile/pull/9885): feat: Feat/9492 add unsupported method and legacy method middlewares (#9885) +- [#9743](https://github.com/MetaMask/metamask-mobile/pull/9743): feat: Metrics/1803 emit error viewed event (#9743) +- [#9888](https://github.com/MetaMask/metamask-mobile/pull/9888): feat: add set approve for all screen (#9888) +- [#9794](https://github.com/MetaMask/metamask-mobile/pull/9794): feat: add increase allowance screen (#9794) +- [#9828](https://github.com/MetaMask/metamask-mobile/pull/9828): feat: enable transaction simulations (#9828) +- [#9648](https://github.com/MetaMask/metamask-mobile/pull/9648): feat: add transaction simulations preference (#9648) +- [#9783](https://github.com/MetaMask/metamask-mobile/pull/9783): feat: add transaction simulation metrics (#9783) +- [#9793](https://github.com/MetaMask/metamask-mobile/pull/9793): feat: add fiat support to simulations (#9793) +- [#9410](https://github.com/MetaMask/metamask-mobile/pull/9410): feat: add SimulationDetails component (#9410) +- [#9070](https://github.com/MetaMask/metamask-mobile/pull/9070): feat: remove selectSelectedAddress in favour of selectSelectedInternalAccount (#9070) +- [#9845](https://github.com/MetaMask/metamask-mobile/pull/9845): feat: updated design-tokens to v4 (#9845) +- [#9653](https://github.com/MetaMask/metamask-mobile/pull/9653): feat: added design tokens eslint rules to mobile (#9653) +- [#9473](https://github.com/MetaMask/metamask-mobile/pull/9473): feat: notifications details screen (#9473) + +### Changed +- [#9884](https://github.com/MetaMask/metamask-mobile/pull/9884): chore(pr template + readme): add link to contributor docs (#9884) +- [#9863](https://github.com/MetaMask/metamask-mobile/pull/9863): chore: Revert ""fix: swaps quote nan to bnjs (#9848)"" (#9863) +- [#9915](https://github.com/MetaMask/metamask-mobile/pull/9915): test: 1454 refactor modal pages batch 4 (#9915) +- [#9998](https://github.com/MetaMask/metamask-mobile/pull/9998): test: marketing optin date trigger testing. (#9998) +- [#9941](https://github.com/MetaMask/metamask-mobile/pull/9941): chore: Revert ""chore: fitness quality gate to only allow TS & TSX files in app directory"" (#9941) +- [#9913](https://github.com/MetaMask/metamask-mobile/pull/9913): chore: Update signature controller to v16 (#9913) +- [#9723](https://github.com/MetaMask/metamask-mobile/pull/9723): chore: fitness quality gate to only allow TS & TSX files in app directory (#9723) +- [#9926](https://github.com/MetaMask/metamask-mobile/pull/9926): chore: Resolve braces package to address audit issue (#9926) +- [#9814](https://github.com/MetaMask/metamask-mobile/pull/9814): chore: Update Preferences Controller v^11 (#9814) +- [#9714](https://github.com/MetaMask/metamask-mobile/pull/9714): test: import tokens detected (#9714) +- [#9693](https://github.com/MetaMask/metamask-mobile/pull/9693): chore: update gas fee controller to 15.1.2 (#9693) +- [#9868](https://github.com/MetaMask/metamask-mobile/pull/9868): chore: add source to setup script (#9868) +- [#9886](https://github.com/MetaMask/metamask-mobile/pull/9886): test: Update Browserstack url as old link deprecated (#9886) +- [#9865](https://github.com/MetaMask/metamask-mobile/pull/9865): chore: swap view crash fetching quotes (#9865) +- [#9852](https://github.com/MetaMask/metamask-mobile/pull/9852): test: fix Assertion only working on IOS (#9852) +- [#9838](https://github.com/MetaMask/metamask-mobile/pull/9838): test: E2e Regression failure fix (#9838) +- [#9805](https://github.com/MetaMask/metamask-mobile/pull/9805): chore: Upgrade address-book-controller (#9805) +- [#9809](https://github.com/MetaMask/metamask-mobile/pull/9809): chore: merge 7.23.0 tag (#9809) +- [#9952](https://github.com/MetaMask/metamask-mobile/pull/9952): chore: update code owners (#9952) +- [#9790](https://github.com/MetaMask/metamask-mobile/pull/9790): chore(ci): update @rhysd/actionlint to 1.7.1 (#9790) +- [#9545](https://github.com/MetaMask/metamask-mobile/pull/9545): chore: Fix CocoaPods install on Linux (#9545) +- [#9883](https://github.com/MetaMask/metamask-mobile/pull/9883): chore: Update ppom package to 1.4.7 (#9883) +- [#9866](https://github.com/MetaMask/metamask-mobile/pull/9866): chore: commit changes to project.pgxproj caused by known issue in xcode 15 (#9866) +- [#9986](https://github.com/MetaMask/metamask-mobile/pull/9986): test: fix `TransactionReview` snapshots (#9986) +- [#9965](https://github.com/MetaMask/metamask-mobile/pull/9965): test: comment out flaky test from `encryption-with-key` (#9965) +- [#9964](https://github.com/MetaMask/metamask-mobile/pull/9964): test: fix snapshots from `AesCryptoTestForm` (#9964) +- [#9898](https://github.com/MetaMask/metamask-mobile/pull/9898): test: AES module E2E tests (#9898) +- [#9949](https://github.com/MetaMask/metamask-mobile/pull/9949): chore: add SmokeAccounts E2E tag (#9949) +- [#9942](https://github.com/MetaMask/metamask-mobile/pull/9942): refactor: updated cellbase to allow size changes (#9942) +- [#9922](https://github.com/MetaMask/metamask-mobile/pull/9922): refactor: replace secondary colors with warning colors (#9922) +- [#9899](https://github.com/MetaMask/metamask-mobile/pull/9899): chore: align ButtonIcons with design (#9899) +- [#9875](https://github.com/MetaMask/metamask-mobile/pull/9875): refactor: update brandColors to be imported from design system (#9875) +- [#9718](https://github.com/MetaMask/metamask-mobile/pull/9718): chore: upgrade snaps-controller and adapts its usage (#9718) +- [#9920](https://github.com/MetaMask/metamask-mobile/pull/9920): chore: remove update-attributions.yml (#9920) +- [#9570](https://github.com/MetaMask/metamask-mobile/pull/9570): chore: Update `@metamask/keyring-controller` to v16 (#9570) +- [#9234](https://github.com/MetaMask/metamask-mobile/pull/9234): chore: update the 'CODEOWNERS' file to include directories relevant to the 'sdk-devs' team (#9234) + +### Fixed +- [#9903](https://github.com/MetaMask/metamask-mobile/pull/9903): fix: upgrade test failure fix for 7.24.0 release branch (#9903) +- [#9844](https://github.com/MetaMask/metamask-mobile/pull/9844): fix: confirmations failing ci tests (#9844) +- [#9831](https://github.com/MetaMask/metamask-mobile/pull/9831): fix: Fix audit ci (#9831) +- [#9893](https://github.com/MetaMask/metamask-mobile/pull/9893): fix: contributor docs link is not correct in pr template (#9893) +- [#9847](https://github.com/MetaMask/metamask-mobile/pull/9847): Fix/release testing issues (#9847) +- [#9946](https://github.com/MetaMask/metamask-mobile/pull/9946): fix: Update help center URLs (#9946) +- [#9848](https://github.com/MetaMask/metamask-mobile/pull/9848): fix: swaps quote nan to bnjs (#9848) +- [#9781](https://github.com/MetaMask/metamask-mobile/pull/9781): fix: Update Basic Functionality settings description.json (#9781) +- [#9763](https://github.com/MetaMask/metamask-mobile/pull/9763): "fix: JS ""pseudo protocol"" works when pasted on mobile browser (#9763)" +- [#9993](https://github.com/MetaMask/metamask-mobile/pull/9993): fix: Fix/re order internal accounts (#9993) +- [#9991](https://github.com/MetaMask/metamask-mobile/pull/9991): fix: fixed snapshots (#9991) +- [#9905](https://github.com/MetaMask/metamask-mobile/pull/9905): "fix: ""data collection for marketing"" from PR #9687 (#9905)" +- [#9980](https://github.com/MetaMask/metamask-mobile/pull/9980): fix: add migration to fix engine does not exist and (#9980) +- [#9982](https://github.com/MetaMask/metamask-mobile/pull/9982): fix: migration 43 stringify to type of (#9982) +- [#9894](https://github.com/MetaMask/metamask-mobile/pull/9894): fix: Update bitrise.yml with correct Browserstack url (#9894) +- [#9887](https://github.com/MetaMask/metamask-mobile/pull/9887): fix: Update Browserstack url as old link deprecated (#9887) +- [#9869](https://github.com/MetaMask/metamask-mobile/pull/9869): fix: Cherry pick of e2e fixes from main (#9869) +- [#9855](https://github.com/MetaMask/metamask-mobile/pull/9855): fix: Undefined balance when fetching from chain (#9855) +- [#9812](https://github.com/MetaMask/metamask-mobile/pull/9812): fix: main token balance not updating when switching accounts (#9812) +- [#9674](https://github.com/MetaMask/metamask-mobile/pull/9674): fix: update Delete MetaMetrics Data copy to 30 days (#9674) +- [#9819](https://github.com/MetaMask/metamask-mobile/pull/9819): fix: Add .e2e as part of the setup script (#9819) +- [#9791](https://github.com/MetaMask/metamask-mobile/pull/9791): fix: Disable segment in E2E mode (#9791) +- [#9934](https://github.com/MetaMask/metamask-mobile/pull/9934): fix: flakey CI asdf node version (#9934) +- [#9584](https://github.com/MetaMask/metamask-mobile/pull/9584): fix: @metamask/swaps-controller v6 -> v9 (#9584) +- [#9867](https://github.com/MetaMask/metamask-mobile/pull/9867): fix: only remove SES from exception if exception exists (#9867) +- [#9870](https://github.com/MetaMask/metamask-mobile/pull/9870): fix: yarn deduplicate release/7.24.0 to fix dupe in #9864 (#9870) +- [#9842](https://github.com/MetaMask/metamask-mobile/pull/9842): fix: error validating wallet connect signature with security provider (#9842) +- [#9999](https://github.com/MetaMask/metamask-mobile/pull/9999): fix: new locales (#9999) +- [#9826](https://github.com/MetaMask/metamask-mobile/pull/9826): fix: add migration for linea goerli (#9826) +- [#9876](https://github.com/MetaMask/metamask-mobile/pull/9876): fix: update patch for updateNftMetadata fct (#9876) +- [#9759](https://github.com/MetaMask/metamask-mobile/pull/9759): fix: remove unecessary calls to third party apis (#9759) +- [#9746](https://github.com/MetaMask/metamask-mobile/pull/9746): fix: render images of networks removed from popularNetwork list (#9746) +- [#9970](https://github.com/MetaMask/metamask-mobile/pull/9970): fix: error 'Invalid character in NaN' while gas editing (#9970) +- [#9902](https://github.com/MetaMask/metamask-mobile/pull/9902): fix: Update PPOM controller to fix handling of HTTP status codes (#9902) +- [#9943](https://github.com/MetaMask/metamask-mobile/pull/9943): fix: Duplicate accounts (#9943) +- [#9974](https://github.com/MetaMask/metamask-mobile/pull/9974): fix(ramp): memoize asset before passing it to balance hook (#9968) (#9974) +- [#9882](https://github.com/MetaMask/metamask-mobile/pull/9882): fix: edit account name screen display incorrect account name (#9882) +- [#9891](https://github.com/MetaMask/metamask-mobile/pull/9891): fix: bug report template - remove reference to recordit (#9891) +- [#9755](https://github.com/MetaMask/metamask-mobile/pull/9755): fix: display the DApp URL in connect screen for MetaMask IOS-SDK (#9755) + ## 7.24.4 - Jun 25, 2024 ### Fixed - [10064](https://github.com/MetaMask/metamask-mobile/pull/10064) fix: Always mark the STX Opt In modal as seen diff --git a/android/app/build.gradle b/android/app/build.gradle index b9d2c2f58e5..1133709a933 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -181,8 +181,8 @@ android { applicationId "io.metamask" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1354 - versionName "7.24.4" + versionCode 1359 + versionName "7.26.0" testBuildType System.getProperty('testBuildType', 'debug') missingDimensionStrategy 'react-native-camera', 'general' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/android/gradle.properties b/android/gradle.properties index f06abec2465..75e96754502 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -48,4 +48,3 @@ hermesEnabled=true # TODO: explain following config options android.disableResourceValidation=true android.enableDexingArtifactTransform.desugaring=false -AsyncStorage_db_size_in_MB=10 diff --git a/app/component-library/components-temp/Price/AggregatedPercentage/AggregatedPercentage.stories.tsx b/app/component-library/components-temp/Price/AggregatedPercentage/AggregatedPercentage.stories.tsx new file mode 100644 index 00000000000..d9706d5e2e6 --- /dev/null +++ b/app/component-library/components-temp/Price/AggregatedPercentage/AggregatedPercentage.stories.tsx @@ -0,0 +1,63 @@ +import React from 'react'; +import { Provider } from 'react-redux'; +import AggregatedPercentage from './AggregatedPercentage'; +import { createStore } from 'redux'; +import initialBackgroundState from '../../../../util/test/initial-background-state.json'; + +const mockInitialState = { + wizard: { + step: 1, + }, + engine: { + backgroundState: initialBackgroundState, + }, +}; + +const rootReducer = (state = mockInitialState) => state; +const store = createStore(rootReducer); + +export default { + title: 'Component Library / AggregatedPercentage', + component: AggregatedPercentage, + decorators: [ + (Story) => ( + + + + ), + ], +}; + +const Template = (args) => ; + +export const Default = Template.bind({}); +Default.args = { + ethFiat: 1000, + tokenFiat: 500, + tokenFiat1dAgo: 950, + ethFiat1dAgo: 450, +}; + +export const NegativePercentageChange = Template.bind({}); +NegativePercentageChange.args = { + ethFiat: 900, + tokenFiat: 400, + tokenFiat1dAgo: 950, + ethFiat1dAgo: 1000, +}; + +export const PositivePercentageChange = Template.bind({}); +PositivePercentageChange.args = { + ethFiat: 1100, + tokenFiat: 600, + tokenFiat1dAgo: 500, + ethFiat1dAgo: 1000, +}; + +export const MixedPercentageChange = Template.bind({}); +MixedPercentageChange.args = { + ethFiat: 1050, + tokenFiat: 450, + tokenFiat1dAgo: 500, + ethFiat1dAgo: 1000, +}; diff --git a/app/component-library/components-temp/Price/AggregatedPercentage/AggregatedPercentage.styles.ts b/app/component-library/components-temp/Price/AggregatedPercentage/AggregatedPercentage.styles.ts new file mode 100644 index 00000000000..4852ce1d684 --- /dev/null +++ b/app/component-library/components-temp/Price/AggregatedPercentage/AggregatedPercentage.styles.ts @@ -0,0 +1,20 @@ +// Third party dependencies. +import { StyleSheet } from 'react-native'; + +/** + * Style sheet function for AggregatedPercentage component. + * + * @param params Style sheet params. + * @param params.theme App theme from ThemeContext. + * @param params.vars Inputs that the style sheet depends on. + * @returns StyleSheet object. + */ +const styleSheet = () => + StyleSheet.create({ + wrapper: { + flexDirection: 'row', + alignItems: 'center', + }, + }); + +export default styleSheet; diff --git a/app/component-library/components-temp/Price/AggregatedPercentage/AggregatedPercentage.test.tsx b/app/component-library/components-temp/Price/AggregatedPercentage/AggregatedPercentage.test.tsx new file mode 100644 index 00000000000..affec361321 --- /dev/null +++ b/app/component-library/components-temp/Price/AggregatedPercentage/AggregatedPercentage.test.tsx @@ -0,0 +1,68 @@ +import React from 'react'; +import { render } from '@testing-library/react-native'; +import AggregatedPercentage from './AggregatedPercentage'; +import { mockTheme } from '../../../../util/theme'; +import { useSelector } from 'react-redux'; +import { selectCurrentCurrency } from '../../../../selectors/currencyRateController'; + +jest.mock('react-redux', () => ({ + ...jest.requireActual('react-redux'), + useSelector: jest.fn(), +})); +describe('AggregatedPercentage', () => { + beforeEach(() => { + (useSelector as jest.Mock).mockImplementation((selector) => { + if (selector === selectCurrentCurrency) return 'USD'; + }); + }); + afterEach(() => { + (useSelector as jest.Mock).mockClear(); + }); + it('should render correctly', () => { + const { toJSON } = render( + , + ); + expect(toJSON()).toMatchSnapshot(); + }); + + it('renders positive percentage change correctly', () => { + const { getByText } = render( + , + ); + + expect(getByText('(+25.00%)')).toBeTruthy(); + expect(getByText('+100 USD')).toBeTruthy(); + + expect(getByText('(+25.00%)').props.style).toMatchObject({ + color: mockTheme.colors.success.default, + }); + }); + + it('renders negative percentage change correctly', () => { + const { getByText } = render( + , + ); + + expect(getByText('(-30.00%)')).toBeTruthy(); + expect(getByText('-150 USD')).toBeTruthy(); + + expect(getByText('(-30.00%)').props.style).toMatchObject({ + color: mockTheme.colors.error.default, + }); + }); +}); diff --git a/app/component-library/components-temp/Price/AggregatedPercentage/AggregatedPercentage.tsx b/app/component-library/components-temp/Price/AggregatedPercentage/AggregatedPercentage.tsx new file mode 100644 index 00000000000..3e0907f937b --- /dev/null +++ b/app/component-library/components-temp/Price/AggregatedPercentage/AggregatedPercentage.tsx @@ -0,0 +1,76 @@ +import React from 'react'; +import Text, { + TextColor, + TextVariant, +} from '../../../../component-library/components/Texts/Text'; +import { View } from 'react-native'; +import { renderFiat } from '../../../../util/number'; +import { useSelector } from 'react-redux'; +import { selectCurrentCurrency } from '../../../../selectors/currencyRateController'; +import styleSheet from './AggregatedPercentage.styles'; +import { useStyles } from '../../../hooks'; + +const isValidAmount = (amount: number | null | undefined): boolean => + amount !== null && amount !== undefined && !Number.isNaN(amount); + +const AggregatedPercentage = ({ + ethFiat, + tokenFiat, + tokenFiat1dAgo, + ethFiat1dAgo, +}: { + ethFiat: number; + tokenFiat: number; + tokenFiat1dAgo: number; + ethFiat1dAgo: number; +}) => { + const { styles } = useStyles(styleSheet, {}); + + const currentCurrency = useSelector(selectCurrentCurrency); + const DECIMALS_TO_SHOW = 2; + + const totalBalance = ethFiat + tokenFiat; + const totalBalance1dAgo = ethFiat1dAgo + tokenFiat1dAgo; + + const amountChange = totalBalance - totalBalance1dAgo; + + const percentageChange = + ((totalBalance - totalBalance1dAgo) / totalBalance1dAgo) * 100 || 0; + + let percentageTextColor = TextColor.Default; + + if (percentageChange === 0) { + percentageTextColor = TextColor.Default; + } else if (percentageChange > 0) { + percentageTextColor = TextColor.Success; + } else { + percentageTextColor = TextColor.Error; + } + + const formattedPercentage = isValidAmount(percentageChange) + ? `(${(percentageChange as number) >= 0 ? '+' : ''}${( + percentageChange as number + ).toFixed(2)}%)` + : ''; + + const formattedValuePrice = isValidAmount(amountChange) + ? `${(amountChange as number) >= 0 ? '+' : ''}${renderFiat( + amountChange, + currentCurrency, + DECIMALS_TO_SHOW, + )} ` + : ''; + + return ( + + + {formattedValuePrice} + + + {formattedPercentage} + + + ); +}; + +export default AggregatedPercentage; diff --git a/app/component-library/components-temp/Price/AggregatedPercentage/__snapshots__/AggregatedPercentage.test.tsx.snap b/app/component-library/components-temp/Price/AggregatedPercentage/__snapshots__/AggregatedPercentage.test.tsx.snap new file mode 100644 index 00000000000..7eea6a3bd9f --- /dev/null +++ b/app/component-library/components-temp/Price/AggregatedPercentage/__snapshots__/AggregatedPercentage.test.tsx.snap @@ -0,0 +1,43 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`AggregatedPercentage should render correctly 1`] = ` + + + +20 USD + + + (+11.11%) + + +`; diff --git a/app/component-library/components-temp/Price/AggregatedPercentage/index.ts b/app/component-library/components-temp/Price/AggregatedPercentage/index.ts new file mode 100644 index 00000000000..3e7965d02fa --- /dev/null +++ b/app/component-library/components-temp/Price/AggregatedPercentage/index.ts @@ -0,0 +1 @@ +export { default } from './AggregatedPercentage'; diff --git a/app/component-library/components-temp/Price/PercentageChange/PercentageChange.stories.tsx b/app/component-library/components-temp/Price/PercentageChange/PercentageChange.stories.tsx new file mode 100644 index 00000000000..59612dcf9ba --- /dev/null +++ b/app/component-library/components-temp/Price/PercentageChange/PercentageChange.stories.tsx @@ -0,0 +1,56 @@ +import React from 'react'; +import { Provider } from 'react-redux'; +import PercentageChange from './PercentageChange'; +import { createStore } from 'redux'; +import initialBackgroundState from '../../../../util/test/initial-background-state.json'; + +const mockInitialState = { + wizard: { + step: 1, + }, + engine: { + backgroundState: initialBackgroundState, + }, +}; + +const rootReducer = (state = mockInitialState) => state; +const store = createStore(rootReducer); + +export default { + title: 'Component Library / PercentageChange', + component: PercentageChange, + decorators: [ + (Story) => ( + + + + ), + ], +}; + +const Template = (args) => ; + +export const Default = Template.bind({}); +Default.args = { + value: 0, +}; + +export const PositiveChange = Template.bind({}); +PositiveChange.args = { + value: 5.5, +}; + +export const NegativeChange = Template.bind({}); +NegativeChange.args = { + value: -3.75, +}; + +export const NoChange = Template.bind({}); +NoChange.args = { + value: 0, +}; + +export const InvalidValue = Template.bind({}); +InvalidValue.args = { + value: null, +}; diff --git a/app/component-library/components-temp/Price/PercentageChange/PercentageChange.test.tsx b/app/component-library/components-temp/Price/PercentageChange/PercentageChange.test.tsx new file mode 100644 index 00000000000..f01d3e7606f --- /dev/null +++ b/app/component-library/components-temp/Price/PercentageChange/PercentageChange.test.tsx @@ -0,0 +1,40 @@ +import React from 'react'; +import { render } from '@testing-library/react-native'; +import PercentageChange from './PercentageChange'; +import { mockTheme } from '../../../../util/theme'; + +describe('PercentageChange', () => { + it('should render correctly', () => { + const { toJSON } = render(); + expect(toJSON()).toMatchSnapshot(); + }); + it('displays a positive value correctly', () => { + const { getByText } = render(); + const positiveText = getByText('+5.50%'); + expect(positiveText).toBeTruthy(); + expect(positiveText.props.style).toMatchObject({ + color: mockTheme.colors.success.default, + }); + }); + + it('displays a negative value correctly', () => { + const { getByText } = render(); + const negativeText = getByText('-3.25%'); + expect(negativeText).toBeTruthy(); + expect(negativeText.props.style).toMatchObject({ + color: mockTheme.colors.error.default, + }); + }); + + it('handles null value correctly', () => { + const { queryByText } = render(); + expect(queryByText(/\+/)).toBeNull(); + expect(queryByText(/-/)).toBeNull(); + }); + + it('handles undefined value correctly', () => { + const { queryByText } = render(); + expect(queryByText(/\+/)).toBeNull(); + expect(queryByText(/-/)).toBeNull(); + }); +}); diff --git a/app/component-library/components-temp/Price/PercentageChange/PercentageChange.tsx b/app/component-library/components-temp/Price/PercentageChange/PercentageChange.tsx new file mode 100644 index 00000000000..206b905fc92 --- /dev/null +++ b/app/component-library/components-temp/Price/PercentageChange/PercentageChange.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import Text, { + TextColor, + TextVariant, +} from '../../../../component-library/components/Texts/Text'; +import { View } from 'react-native'; + +const PercentageChange = ({ value }: { value: number | null | undefined }) => { + const percentageColorText = + value && value >= 0 ? TextColor.Success : TextColor.Error; + + const isValidAmount = (amount: number | null | undefined): boolean => + amount !== null && amount !== undefined && !Number.isNaN(amount); + + const formattedValue = isValidAmount(value) + ? `${(value as number) >= 0 ? '+' : ''}${(value as number).toFixed(2)}%` + : ''; + + return ( + + + {formattedValue} + + + ); +}; + +export default PercentageChange; diff --git a/app/component-library/components-temp/Price/PercentageChange/__snapshots__/PercentageChange.test.tsx.snap b/app/component-library/components-temp/Price/PercentageChange/__snapshots__/PercentageChange.test.tsx.snap new file mode 100644 index 00000000000..571dec70ebc --- /dev/null +++ b/app/component-library/components-temp/Price/PercentageChange/__snapshots__/PercentageChange.test.tsx.snap @@ -0,0 +1,21 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`PercentageChange should render correctly 1`] = ` + + + +5.50% + + +`; diff --git a/app/component-library/components-temp/Price/PercentageChange/index.ts b/app/component-library/components-temp/Price/PercentageChange/index.ts new file mode 100644 index 00000000000..6a3f076bb2a --- /dev/null +++ b/app/component-library/components-temp/Price/PercentageChange/index.ts @@ -0,0 +1 @@ +export { default } from './PercentageChange'; diff --git a/app/component-library/components/Navigation/TabBar/TabBar.stories.tsx b/app/component-library/components/Navigation/TabBar/TabBar.stories.tsx index 50389c64ea7..55874e85b0a 100644 --- a/app/component-library/components/Navigation/TabBar/TabBar.stories.tsx +++ b/app/component-library/components/Navigation/TabBar/TabBar.stories.tsx @@ -7,7 +7,7 @@ import { createStore } from 'redux'; import { Provider } from 'react-redux'; // External dependencies. -import initialBackgroundState from '../../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../../util/test/initial-root-state'; // Internal dependencies. import { default as TabBarComponent } from './TabBar'; @@ -18,7 +18,7 @@ const mockInitialState = { step: 1, }, engine: { - backgroundState: initialBackgroundState, + backgroundState, }, }; const rootReducer = (state = mockInitialState) => state; diff --git a/app/component-library/components/Navigation/TabBar/TabBar.test.tsx b/app/component-library/components/Navigation/TabBar/TabBar.test.tsx index e009d59d2bf..0d9ee3d09f9 100644 --- a/app/component-library/components/Navigation/TabBar/TabBar.test.tsx +++ b/app/component-library/components/Navigation/TabBar/TabBar.test.tsx @@ -5,7 +5,7 @@ import { ParamListBase, TabNavigationState } from '@react-navigation/native'; // External dependencies import renderWithProvider from '../../../../util/test/renderWithProvider'; -import initialBackgroundState from '../../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../../util/test/initial-root-state'; // Internal dependencies import TabBar from './TabBar'; @@ -22,7 +22,7 @@ const mockInitialState = { step: 1, }, engine: { - backgroundState: initialBackgroundState, + backgroundState, }, }; diff --git a/app/component-library/components/Pickers/PickerAccount/PickerAccount.tsx b/app/component-library/components/Pickers/PickerAccount/PickerAccount.tsx index 2f6ee293579..29fdaffa08f 100644 --- a/app/component-library/components/Pickers/PickerAccount/PickerAccount.tsx +++ b/app/component-library/components/Pickers/PickerAccount/PickerAccount.tsx @@ -2,7 +2,7 @@ // Third party dependencies. import React, { forwardRef } from 'react'; -import { Platform, TouchableOpacity, View } from 'react-native'; +import { TouchableOpacity, View } from 'react-native'; // External dependencies. import Avatar, { AvatarSize, AvatarVariant } from '../../Avatars/Avatar'; @@ -15,8 +15,7 @@ import { strings } from '../../../../../locales/i18n'; import PickerBase from '../PickerBase'; import { PickerAccountProps } from './PickerAccount.types'; import styleSheet from './PickerAccount.styles'; -import generateTestId from '../../../../../wdio/utils/generateTestId'; -import { WALLET_ACCOUNT_NAME_LABEL_TEXT } from '../../../../../wdio/screen-objects/testIDs/Screens/WalletView.testIds'; +import { WalletViewSelectorsIDs } from '../../../../../e2e/selectors/wallet/WalletView.selectors'; const PickerAccount: React.ForwardRefRenderFunction< TouchableOpacity, @@ -52,7 +51,7 @@ const PickerAccount: React.ForwardRefRenderFunction< {accountName} diff --git a/app/component-library/components/Pickers/PickerNetwork/PickerNetwork.tsx b/app/component-library/components/Pickers/PickerNetwork/PickerNetwork.tsx index 586c53d09fb..9c4dd1f150a 100644 --- a/app/component-library/components/Pickers/PickerNetwork/PickerNetwork.tsx +++ b/app/component-library/components/Pickers/PickerNetwork/PickerNetwork.tsx @@ -2,7 +2,7 @@ // Third party dependencies. import React from 'react'; -import { Platform, TouchableOpacity } from 'react-native'; +import { TouchableOpacity } from 'react-native'; // External dependencies. import Avatar, { AvatarSize, AvatarVariant } from '../../Avatars/Avatar'; @@ -13,8 +13,7 @@ import { useStyles } from '../../../hooks'; // Internal dependencies. import { PickerNetworkProps } from './PickerNetwork.types'; import stylesheet from './PickerNetwork.styles'; -import generateTestId from '../../../../../wdio/utils/generateTestId'; -import { NAVBAR_NETWORK_TEXT } from '../../../../../wdio/screen-objects/testIDs/Screens/WalletView.testIds'; +import { WalletViewSelectorsIDs } from '../../../../../e2e/selectors/wallet/WalletView.selectors'; import { PICKERNETWORK_ARROW_TESTID } from './PickerNetwork.constants'; const PickerNetwork = ({ @@ -38,7 +37,7 @@ const PickerNetwork = ({ style={styles.label} numberOfLines={1} variant={TextVariant.BodyMD} - {...generateTestId(Platform, NAVBAR_NETWORK_TEXT)} + testID={WalletViewSelectorsIDs.NAVBAR_NETWORK_TEXT} > {label} diff --git a/app/component-library/components/Toast/Toast.tsx b/app/component-library/components/Toast/Toast.tsx index e4a37893279..b7916a32b93 100644 --- a/app/component-library/components/Toast/Toast.tsx +++ b/app/component-library/components/Toast/Toast.tsx @@ -10,7 +10,6 @@ import React, { import { Dimensions, LayoutChangeEvent, - Platform, StyleProp, View, ViewStyle, @@ -39,8 +38,7 @@ import { ToastVariants, } from './Toast.types'; import styles from './Toast.styles'; -import generateTestId from '../../../../wdio/utils/generateTestId'; -import { TOAST_ID } from '../../../../wdio/screen-objects/testIDs/Common.testIds'; +import { ToastSelectorsIDs } from '../../../../e2e/selectors/Modals/ToastModal.selectors'; import { ButtonProps } from '../Buttons/Button/Button.types'; const visibilityDuration = 2750; @@ -210,7 +208,7 @@ const Toast = forwardRef((_, ref: React.ForwardedRef) => { {renderAvatar()} {renderLabel(labelOptions)} {renderButtonLink(linkButtonOptions)} diff --git a/app/components/Approvals/PermissionApproval/PermissionApproval.test.tsx b/app/components/Approvals/PermissionApproval/PermissionApproval.test.tsx index 3333b2b3501..fd84b0f9915 100644 --- a/app/components/Approvals/PermissionApproval/PermissionApproval.test.tsx +++ b/app/components/Approvals/PermissionApproval/PermissionApproval.test.tsx @@ -6,7 +6,7 @@ import PermissionApproval from './PermissionApproval'; import { createAccountConnectNavDetails } from '../../Views/AccountConnect'; import { useSelector } from 'react-redux'; import { MetaMetricsEvents } from '../../../core/Analytics'; -import initialBackgroundState from '../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../util/test/initial-root-state'; import { render } from '@testing-library/react-native'; import { useMetrics } from '../../../components/hooks/useMetrics'; @@ -129,7 +129,7 @@ describe('PermissionApproval', () => { mockSelectorState({ engine: { backgroundState: { - ...initialBackgroundState, + ...backgroundState, AccountTrackerController: { accounts: { 1: 'testAccount', diff --git a/app/components/Base/RemoteImage/index.js b/app/components/Base/RemoteImage/index.js index 53aba49ae0d..f47269f60ce 100644 --- a/app/components/Base/RemoteImage/index.js +++ b/app/components/Base/RemoteImage/index.js @@ -10,6 +10,7 @@ import ComponentErrorBoundary from '../../UI/ComponentErrorBoundary'; import useIpfsGateway from '../../hooks/useIpfsGateway'; import { getFormattedIpfsUrl } from '@metamask/assets-controllers'; import Identicon from '../../UI/Identicon'; +import useSvgUriViewBox from '../../hooks/useSvgUriViewBox'; const createStyles = () => StyleSheet.create({ @@ -40,16 +41,19 @@ const RemoteImage = (props) => { const onError = ({ nativeEvent: { error } }) => setError(error); + const isSVG = + source && + source.uri && + source.uri.match('.svg') && + (isImageUrl || resolvedIpfsUrl); + + const viewbox = useSvgUriViewBox(uri, isSVG); + if (error && props.address) { return ; } - if ( - source && - source.uri && - source.uri.match('.svg') && - (isImageUrl || resolvedIpfsUrl) - ) { + if (isSVG) { const style = props.style || {}; if (source.__packager_asset && typeof style !== 'number') { if (!style.width) { @@ -66,7 +70,13 @@ const RemoteImage = (props) => { componentLabel="RemoteImage-SVG" > - + ); diff --git a/app/components/Nav/App/index.js b/app/components/Nav/App/index.js index 59ec7fb2b12..4b43ede6c99 100644 --- a/app/components/Nav/App/index.js +++ b/app/components/Nav/App/index.js @@ -6,7 +6,7 @@ import React, { useState, } from 'react'; import { CommonActions, NavigationContainer } from '@react-navigation/native'; -import { Animated, Linking } from 'react-native'; +import { Animated, Linking, View } from 'react-native'; import { createStackNavigator } from '@react-navigation/stack'; import Login from '../../Views/Login'; import QRScanner from '../../Views/QRScanner'; @@ -110,6 +110,9 @@ import DefaultSettings from '../../Views/OnboardingSuccess/DefaultSettings'; import BasicFunctionalityModal from '../../UI/BasicFunctionality/BasicFunctionalityModal/BasicFunctionalityModal'; import SmartTransactionsOptInModal from '../../Views/SmartTransactionsOptInModal/SmartTranactionsOptInModal'; import NFTAutoDetectionModal from '../../../../app/components/Views/NFTAutoDetectionModal/NFTAutoDetectionModal'; +///: BEGIN:ONLY_INCLUDE_IF(preinstalled-snaps,external-snaps) +import { SnapsExecutionWebView } from '../../../lib/snaps'; +///: END:ONLY_INCLUDE_IF const clearStackNavigatorOptions = { headerShown: false, @@ -770,6 +773,15 @@ const App = ({ userLoggedIn }) => { // do not render unless a route is defined (route && ( <> + { + ///: BEGIN:ONLY_INCLUDE_IF(preinstalled-snaps,external-snaps) + } + + + + { + ///: END:ONLY_INCLUDE_IF + } { ) : ( renderLoader() )} - { - ///: BEGIN:ONLY_INCLUDE_IF(preinstalled-snaps,external-snaps) - } - - - - { - ///: END:ONLY_INCLUDE_IF - } diff --git a/app/components/UI/AccountApproval/__snapshots__/index.test.tsx.snap b/app/components/UI/AccountApproval/__snapshots__/index.test.tsx.snap index 9864f17e99f..c5704972d10 100644 --- a/app/components/UI/AccountApproval/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/AccountApproval/__snapshots__/index.test.tsx.snap @@ -334,7 +334,7 @@ exports[`AccountApproval should render correctly 1`] = ` } } > - 0xC496...a756 + Account 2 ({ const mockInitialState = { engine: { backgroundState: { - ...initialBackgroundState, + ...backgroundState, AccountsController: MOCK_ACCOUNTS_CONTROLLER_STATE, }, }, diff --git a/app/components/UI/AccountFromToInfoCard/AccountFromToInfoCard.test.tsx b/app/components/UI/AccountFromToInfoCard/AccountFromToInfoCard.test.tsx index 5f9914e8d3e..eb71e64fec7 100644 --- a/app/components/UI/AccountFromToInfoCard/AccountFromToInfoCard.test.tsx +++ b/app/components/UI/AccountFromToInfoCard/AccountFromToInfoCard.test.tsx @@ -8,7 +8,7 @@ import { ENSCache } from '../../../util/ENSUtils'; import { Transaction } from './AccountFromToInfoCard.types'; import AccountFromToInfoCard from '.'; import Engine from '../../../core/Engine'; -import initialBackgroundState from '../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../util/test/initial-root-state'; import { createMockAccountsControllerState } from '../../../util/test/accountsControllerTestUtils'; const MOCK_ADDRESS_1 = '0xe64dD0AB5ad7e8C5F2bf6Ce75C34e187af8b920A'; @@ -23,7 +23,7 @@ const mockInitialState = { settings: {}, engine: { backgroundState: { - ...initialBackgroundState, + ...backgroundState, AccountTrackerController: { accounts: { [MOCK_ADDRESS_1]: { @@ -39,19 +39,6 @@ const mockInitialState = { '0x326836cc6cd09B5aa59B81A7F72F25FcC0136b95': '0x5', }, }, - PreferencesController: { - selectedAddress: MOCK_ADDRESS_1, - identities: { - [MOCK_ADDRESS_1]: { - address: MOCK_ADDRESS_1, - name: 'Account 1', - }, - [MOCK_ADDRESS_2]: { - address: MOCK_ADDRESS_2, - name: 'Account 2', - }, - }, - }, AccountsController: MOCK_ACCOUNTS_CONTROLLER_STATE, }, }, diff --git a/app/components/UI/AccountFromToInfoCard/AccountFromToInfoCard.tsx b/app/components/UI/AccountFromToInfoCard/AccountFromToInfoCard.tsx index f567bfee7b7..599042c9476 100644 --- a/app/components/UI/AccountFromToInfoCard/AccountFromToInfoCard.tsx +++ b/app/components/UI/AccountFromToInfoCard/AccountFromToInfoCard.tsx @@ -9,7 +9,6 @@ import { selectChainId, selectTicker, } from '../../../selectors/networkController'; -import { selectIdentities } from '../../../selectors/preferencesController'; import { collectConfusables } from '../../../util/confusables'; import { decodeTransferData } from '../../../util/transactions'; import { doENSReverseLookup } from '../../../util/ENSUtils'; @@ -20,10 +19,13 @@ import useExistingAddress from '../../hooks/useExistingAddress'; import { AddressFrom, AddressTo } from '../AddressInputs'; import createStyles from './AccountFromToInfoCard.styles'; import { AccountFromToInfoCardProps } from './AccountFromToInfoCard.types'; +import { selectInternalAccounts } from '../../../selectors/accountsController'; +import { toLowerCaseEquals } from '../../../util/general'; +import { RootState } from '../../../reducers'; const AccountFromToInfoCard = (props: AccountFromToInfoCardProps) => { const { - identities, + internalAccounts, chainId, onPressFromAddressIcon, ticker, @@ -33,7 +35,6 @@ const AccountFromToInfoCard = (props: AccountFromToInfoCardProps) => { const { transaction: { from: rawFromAddress, data, to }, transactionTo, - transactionToName, transactionFromName, selectedAsset, ensRecipient, @@ -56,50 +57,88 @@ const AccountFromToInfoCard = (props: AccountFromToInfoCardProps) => { ); useEffect(() => { - if (!fromAddress) { - return; - } - if (transactionFromName) { - setFromAccountName(transactionFromName); - return; - } - (async () => { + const fetchFromAccountDetails = async () => { + if (!fromAddress) { + return; + } + + if (transactionFromName) { + if (fromAccountName !== transactionFromName) { + setFromAccountName(transactionFromName); + } + return; + } + const fromEns = await doENSReverseLookup(fromAddress, chainId); if (fromEns) { - setFromAccountName(fromEns); + if (fromAccountName !== fromEns) { + setFromAccountName(fromEns); + } } else { - const { name: fromName } = identities[fromAddress]; - setFromAccountName(fromName); + const accountWithMatchingFromAddress = internalAccounts.find( + (account) => toLowerCaseEquals(account.address, fromAddress), + ); + + const newName = accountWithMatchingFromAddress + ? accountWithMatchingFromAddress.metadata.name + : fromAddress; + + if (fromAccountName !== newName) { + setFromAccountName(newName); + } } - })(); - }, [fromAddress, identities, transactionFromName, chainId]); + }; + + fetchFromAccountDetails(); + }, [ + fromAddress, + transactionFromName, + chainId, + internalAccounts, + fromAccountName, + ]); useEffect(() => { - if (existingToAddress) { - setToAccountName(existingToAddress?.name); - return; - } - (async () => { + const fetchAccountDetails = async () => { + if (existingToAddress) { + if (toAccountName !== existingToAddress.name) { + setToAccountName(existingToAddress.name); + } + return; + } + const toEns = await doENSReverseLookup(toAddress, chainId); if (toEns) { - setToAccountName(toEns); - } else if (identities[toAddress]) { - const { name: toName } = identities[toAddress]; - setToAccountName(toName); + if (toAccountName !== toEns) { + setToAccountName(toEns); + } + } else { + const accountWithMatchingToAddress = internalAccounts.find((account) => + toLowerCaseEquals(account.address, toAddress), + ); + + const newName = accountWithMatchingToAddress + ? accountWithMatchingToAddress.metadata.name + : toAddress; + + if (toAccountName !== newName) { + setToAccountName(newName); + } } - })(); - }, [existingToAddress, identities, chainId, toAddress, transactionToName]); + }; + + fetchAccountDetails(); + }, [existingToAddress, chainId, toAddress, internalAccounts, toAccountName]); useEffect(() => { - const accountNames = - (identities && - Object.keys(identities).map((hash) => identities[hash].name)) || - []; + const accountNames = internalAccounts.map( + (account) => account.metadata.name, + ); const isOwnAccount = ensRecipient && accountNames.includes(ensRecipient); if (ensRecipient && !isOwnAccount) { setConfusableCollection(collectConfusables(ensRecipient)); } - }, [identities, ensRecipient]); + }, [internalAccounts, ensRecipient]); useEffect(() => { let toAddr; @@ -172,10 +211,8 @@ const AccountFromToInfoCard = (props: AccountFromToInfoCardProps) => { ); }; -// TODO: Replace "any" with type -// eslint-disable-next-line @typescript-eslint/no-explicit-any -const mapStateToProps = (state: any) => ({ - identities: selectIdentities(state), +const mapStateToProps = (state: RootState) => ({ + internalAccounts: selectInternalAccounts(state), chainId: selectChainId(state), ticker: selectTicker(state), }); diff --git a/app/components/UI/AccountFromToInfoCard/AccountFromToInfoCard.types.tsx b/app/components/UI/AccountFromToInfoCard/AccountFromToInfoCard.types.tsx index ece567c7bdd..84690a6c732 100644 --- a/app/components/UI/AccountFromToInfoCard/AccountFromToInfoCard.types.tsx +++ b/app/components/UI/AccountFromToInfoCard/AccountFromToInfoCard.types.tsx @@ -1,9 +1,4 @@ -interface Identity { - address: string; - name: string; -} - -type Identities = Record; +import { InternalAccount } from '@metamask/keyring-api'; interface SelectedAsset { isETH: boolean; @@ -26,7 +21,7 @@ export interface Transaction { } export interface AccountFromToInfoCardProps { - identities: Identities; + internalAccounts: InternalAccount[]; chainId: string; onPressFromAddressIcon?: () => void; ticker?: string; diff --git a/app/components/UI/AccountInfoCard/__snapshots__/index.test.tsx.snap b/app/components/UI/AccountInfoCard/__snapshots__/index.test.tsx.snap index b8b3d0ae551..6a4a79370c7 100644 --- a/app/components/UI/AccountInfoCard/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/AccountInfoCard/__snapshots__/index.test.tsx.snap @@ -232,7 +232,7 @@ exports[`AccountInfoCard should match snapshot 1`] = ` } } > - 0xC495...D272 + Account 1 StyleSheet.create({ @@ -111,9 +111,9 @@ class AccountInfoCard extends PureComponent { */ accounts: PropTypes.object, /** - * List of accounts from the PreferencesController + * List of accounts from the AccountsController */ - identities: PropTypes.object, + internalAccounts: PropTypes.array, /** * A number that specifies the ETH/USD conversion rate */ @@ -142,7 +142,7 @@ class AccountInfoCard extends PureComponent { render() { const { accounts, - identities, + internalAccounts, conversionRate, currentCurrency, operation, @@ -162,7 +162,7 @@ class AccountInfoCard extends PureComponent { ? hexToBN(accounts[fromAddress].balance) : 0; const balance = `${renderFromWei(weiBalance)} ${getTicker(ticker)}`; - const accountLabel = renderAccountName(fromAddress, identities); + const accountLabel = renderAccountName(fromAddress, internalAccounts); const address = renderShortAddress(fromAddress); const dollarBalance = showFiatBalance ? weiToFiat(weiBalance, conversionRate, currentCurrency, 2)?.toUpperCase() @@ -248,7 +248,7 @@ class AccountInfoCard extends PureComponent { const mapStateToProps = (state) => ({ accounts: selectAccounts(state), - identities: selectIdentities(state), + internalAccounts: selectInternalAccounts(state), conversionRate: selectConversionRate(state), currentCurrency: selectCurrentCurrency(state), ticker: selectTicker(state), diff --git a/app/components/UI/AccountInfoCard/index.test.tsx b/app/components/UI/AccountInfoCard/index.test.tsx index d8500ab9d38..2462c41d648 100644 --- a/app/components/UI/AccountInfoCard/index.test.tsx +++ b/app/components/UI/AccountInfoCard/index.test.tsx @@ -1,7 +1,7 @@ import React from 'react'; import AccountInfoCard from './'; import renderWithProvider from '../../../util/test/renderWithProvider'; -import initialBackgroundState from '../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../util/test/initial-root-state'; import { MOCK_ACCOUNTS_CONTROLLER_STATE, MOCK_ADDRESS_1, @@ -27,7 +27,7 @@ const mockInitialState = { }, engine: { backgroundState: { - ...initialBackgroundState, + ...backgroundState, AccountTrackerController: { accounts: { [MOCK_ADDRESS_1]: { diff --git a/app/components/UI/AccountOverview/index.js b/app/components/UI/AccountOverview/index.js index c65706e35a0..b844d7ac534 100644 --- a/app/components/UI/AccountOverview/index.js +++ b/app/components/UI/AccountOverview/index.js @@ -2,7 +2,6 @@ import PropTypes from 'prop-types'; import React, { PureComponent } from 'react'; import { InteractionManager, - Platform, ScrollView, StyleSheet, TextInput, @@ -11,12 +10,7 @@ import { } from 'react-native'; import { connect } from 'react-redux'; import { strings } from '../../../../locales/i18n'; -import { - WALLET_ACCOUNT_ICON, - WALLET_ACCOUNT_NAME_LABEL_INPUT, - WALLET_ACCOUNT_NAME_LABEL_TEXT, -} from '../../../../wdio/screen-objects/testIDs/Screens/WalletView.testIds'; -import generateTestId from '../../../../wdio/utils/generateTestId'; +import { WalletViewSelectorsIDs } from '../../../../e2e/selectors/wallet/WalletView.selectors'; import { showAlert } from '../../../actions/alert'; import { toggleReceiveModal } from '../../../actions/modals'; import { newAssetTransaction } from '../../../actions/transaction'; @@ -41,14 +35,17 @@ import AppConstants from '../../../core/AppConstants'; import Engine from '../../../core/Engine'; import { selectChainId } from '../../../selectors/networkController'; import { selectCurrentCurrency } from '../../../selectors/currencyRateController'; -import { selectIdentities } from '../../../selectors/preferencesController'; -import { selectSelectedInternalAccountChecksummedAddress } from '../../../selectors/accountsController'; +import { + selectInternalAccounts, + selectSelectedInternalAccountChecksummedAddress, +} from '../../../selectors/accountsController'; import { createAccountSelectorNavDetails } from '../../Views/AccountSelector'; import Text, { TextVariant, } from '../../../component-library/components/Texts/Text'; import { withMetricsAwareness } from '../../../components/hooks/useMetrics'; import { isPortfolioUrl } from '../../../util/url'; +import { toLowerCaseEquals } from '../../../util/general'; const createStyles = (colors) => StyleSheet.create({ @@ -157,18 +154,14 @@ class AccountOverview extends PureComponent { */ selectedAddress: PropTypes.string, /** - /* Identities object required to get account name + /* InternalAccounts object required to get account name */ - identities: PropTypes.object, + internalAccounts: PropTypes.object, /** * Object that represents the selected account */ account: PropTypes.object, /** - /* Selected currency - */ - currentCurrency: PropTypes.string, - /** /* Triggers global alert */ showAlert: PropTypes.func, @@ -184,19 +177,11 @@ class AccountOverview extends PureComponent { * Prompts protect wallet modal */ protectWalletModalVisible: PropTypes.func, - /** - * Start transaction with asset - */ - newAssetTransaction: PropTypes.func, /** /* navigation object required to access the props /* passed by the parent component */ navigation: PropTypes.object, - /** - * Action that toggles the receive modal - */ - toggleReceiveModal: PropTypes.func, /** * The chain ID for the current selected network */ @@ -234,8 +219,8 @@ class AccountOverview extends PureComponent { input = React.createRef(); componentDidMount = () => { - const { identities, selectedAddress, onRef } = this.props; - const accountLabel = renderAccountName(selectedAddress, identities); + const { internalAccounts, selectedAddress, onRef } = this.props; + const accountLabel = renderAccountName(selectedAddress, internalAccounts); this.setState({ accountLabel }); onRef && onRef(this); InteractionManager.runAfterInteractions(() => { @@ -259,16 +244,18 @@ class AccountOverview extends PureComponent { } setAccountLabel = () => { - const { selectedAddress, identities } = this.props; + const { selectedAddress, internalAccounts } = this.props; const { accountLabel } = this.state; - const lastAccountLabel = identities[selectedAddress].name; + const accountWithMatchingToAddress = internalAccounts.find((account) => + toLowerCaseEquals(account.address, selectedAddress), + ); Engine.setAccountLabel( selectedAddress, this.isAccountLabelDefined(accountLabel) ? accountLabel - : lastAccountLabel, + : accountWithMatchingToAddress.metadata.name, ); this.setState({ accountLabelEditable: false }); }; @@ -278,8 +265,8 @@ class AccountOverview extends PureComponent { }; setAccountLabelEditable = () => { - const { identities, selectedAddress } = this.props; - const accountLabel = renderAccountName(selectedAddress, identities); + const { internalAccounts, selectedAddress } = this.props; + const accountLabel = renderAccountName(selectedAddress, internalAccounts); this.setState({ accountLabelEditable: true, accountLabel }); setTimeout(() => { this.input && this.input.current && this.input.current.focus(); @@ -287,8 +274,8 @@ class AccountOverview extends PureComponent { }; cancelAccountLabelEdition = () => { - const { identities, selectedAddress } = this.props; - const accountLabel = renderAccountName(selectedAddress, identities); + const { internalAccounts, selectedAddress } = this.props; + const accountLabel = renderAccountName(selectedAddress, internalAccounts); this.setState({ accountLabelEditable: false, accountLabel }); }; @@ -368,7 +355,7 @@ class AccountOverview extends PureComponent { style={styles.identiconBorder} disabled={onboardingWizard} onPress={this.openAccountSelector} - {...generateTestId(Platform, WALLET_ACCOUNT_ICON)} + testID={WalletViewSelectorsIDs.ACCOUNT_ICON} > {isDefaultAccountName(name) && ens ? ens : name} @@ -461,7 +445,7 @@ class AccountOverview extends PureComponent { const mapStateToProps = (state) => ({ selectedAddress: selectSelectedInternalAccountChecksummedAddress(state), - identities: selectIdentities(state), + internalAccounts: selectInternalAccounts(state), currentCurrency: selectCurrentCurrency(state), chainId: selectChainId(state), browserTabs: state.browser.tabs, diff --git a/app/components/UI/AccountOverview/index.test.tsx b/app/components/UI/AccountOverview/index.test.tsx index 90d3b464d96..303d3fe177d 100644 --- a/app/components/UI/AccountOverview/index.test.tsx +++ b/app/components/UI/AccountOverview/index.test.tsx @@ -1,7 +1,7 @@ import React from 'react'; import renderWithProvider from '../../../util/test/renderWithProvider'; import AccountOverview from './'; -import initialBackgroundState from '../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../util/test/initial-root-state'; import Engine from '../../../core/Engine'; import { @@ -33,7 +33,7 @@ const mockInitialState = { settings: {}, engine: { backgroundState: { - ...initialBackgroundState, + ...backgroundState, PreferencesController: { selectedAddress: MOCK_ADDRESS_1, }, diff --git a/app/components/UI/AccountRightButton/index.test.tsx b/app/components/UI/AccountRightButton/index.test.tsx index 8d8b409c78f..ce5b1f12c23 100644 --- a/app/components/UI/AccountRightButton/index.test.tsx +++ b/app/components/UI/AccountRightButton/index.test.tsx @@ -1,12 +1,12 @@ import { renderScreen } from '../../../util/test/renderWithProvider'; import AccountRightButton from './'; -import initialBackgroundState from '../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../util/test/initial-root-state'; const mockInitialState = { settings: {}, engine: { backgroundState: { - ...initialBackgroundState, + ...backgroundState, NetworkController: { providerConfig: { chainId: 0x1, diff --git a/app/components/UI/AccountSelectorList/AccountSelector.test.tsx b/app/components/UI/AccountSelectorList/AccountSelector.test.tsx index 8961cd92278..5b26df8e705 100644 --- a/app/components/UI/AccountSelectorList/AccountSelector.test.tsx +++ b/app/components/UI/AccountSelectorList/AccountSelector.test.tsx @@ -6,7 +6,7 @@ import AccountSelectorList from './AccountSelectorList'; import { useAccounts } from '../../../components/hooks/useAccounts'; import { View } from 'react-native'; import { ACCOUNT_BALANCE_BY_ADDRESS_TEST_ID } from '../../../../wdio/screen-objects/testIDs/Components/AccountListComponent.testIds'; -import initialBackgroundState from '../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../util/test/initial-root-state'; import { regex } from '../../../../app/util/regex'; import { createMockAccountsControllerState } from '../../../util/test/accountsControllerTestUtils'; @@ -29,7 +29,7 @@ jest.mock('../../../util/address', () => { const initialState = { engine: { backgroundState: { - ...initialBackgroundState, + ...backgroundState, NetworkController: { network: '1', providerConfig: { @@ -48,16 +48,6 @@ const initialState = { PreferencesController: { isMultiAccountBalancesEnabled: true, selectedAddress: BUSINESS_ACCOUNT, - identities: { - [BUSINESS_ACCOUNT]: { - address: BUSINESS_ACCOUNT, - name: 'Business Account', - }, - [PERSONAL_ACCOUNT]: { - address: PERSONAL_ACCOUNT, - name: 'Personal Account', - }, - }, }, CurrencyRateController: { currentCurrency: 'usd', @@ -120,12 +110,12 @@ describe('AccountSelectorList', () => { onRemoveImportedAccount.mockClear(); }); - it('should render correctly', async () => { + it('renders correctly', async () => { const { toJSON } = renderComponent(initialState); await waitFor(() => expect(toJSON()).toMatchSnapshot()); }); - it('should render all accounts with balances', async () => { + it('renders all accounts with balances', async () => { const { queryByTestId, getAllByTestId, toJSON } = renderComponent(initialState); @@ -186,7 +176,7 @@ describe('AccountSelectorList', () => { }); }); - it('should render all accounts with right acessory', async () => { + it('renders all accounts with right accessory', async () => { const { getAllByTestId, toJSON } = renderComponent( initialState, AccountSelectorListRightAccessoryUseAccounts, @@ -199,4 +189,13 @@ describe('AccountSelectorList', () => { expect(toJSON()).toMatchSnapshot(); }); }); + it('renders correct account names', async () => { + const { getAllByTestId } = renderComponent(initialState); + + await waitFor(() => { + const accountNameItems = getAllByTestId('cellbase-avatar-title'); + expect(within(accountNameItems[0]).getByText('Account 1')).toBeDefined(); + expect(within(accountNameItems[1]).getByText('Account 2')).toBeDefined(); + }); + }); }); diff --git a/app/components/UI/AccountSelectorList/__snapshots__/AccountSelector.test.tsx.snap b/app/components/UI/AccountSelectorList/__snapshots__/AccountSelector.test.tsx.snap index 8b7c6c08b72..1e4cbf6b45b 100644 --- a/app/components/UI/AccountSelectorList/__snapshots__/AccountSelector.test.tsx.snap +++ b/app/components/UI/AccountSelectorList/__snapshots__/AccountSelector.test.tsx.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`AccountSelectorList should render all accounts but only the balance for selected account 1`] = ` +exports[`AccountSelectorList renders all accounts with balances 1`] = ` - + > + + + + + + + + - - - - - Account 2 - - - 0xd018...78E7 - - - - - - - - -`; - -exports[`AccountSelectorList should render all accounts with balances 1`] = ` - + + + + + + + + + + + Account 2 + + + 0xd018...78E7 + + + + + + $6400.00 +2 ETH + + + + + + + + + +`; + +exports[`AccountSelectorList renders all accounts with right accessory 1`] = ` + - - $3200.00 -1 ETH - + 0xC4955C0d639D99699Bfd7Ec54d9FaFEe40e4D272 - Account 1 + + + + - - - - - - - - - $6400.00 -2 ETH - + 0xd018538C87232FF95acbCe4870629b75640a78E7 - Account 2 @@ -937,7 +1139,7 @@ exports[`AccountSelectorList should render all accounts with balances 1`] = ` `; -exports[`AccountSelectorList should render all accounts with right acessory 1`] = ` +exports[`AccountSelectorList renders correctly 1`] = ` - 0xC4955C0d639D99699Bfd7Ec54d9FaFEe40e4D272 - Account 1 + + $3200.00 +1 ETH + + + + - 0xd018538C87232FF95acbCe4870629b75640a78E7 - Account 2 + + $6400.00 +2 ETH + @@ -1473,7 +1742,7 @@ exports[`AccountSelectorList should render all accounts with right acessory 1`] `; -exports[`AccountSelectorList should render correctly 1`] = ` +exports[`AccountSelectorList should render all accounts but only the balance for selected account 1`] = ` - - - - - - - - + } + /> - - - - - - - - + } + /> - - - - $6400.00 -2 ETH - - - diff --git a/app/components/UI/AddCustomCollectible/index.test.tsx b/app/components/UI/AddCustomCollectible/index.test.tsx index 3ca9f3d80e2..33afc2910a9 100644 --- a/app/components/UI/AddCustomCollectible/index.test.tsx +++ b/app/components/UI/AddCustomCollectible/index.test.tsx @@ -3,15 +3,11 @@ import { shallow } from 'enzyme'; import AddCustomCollectible from './'; import configureMockStore from 'redux-mock-store'; import { Provider } from 'react-redux'; -import initialBackgroundState from '../../../util/test/initial-background-state.json'; +import initialRootState from '../../../util/test/initial-root-state'; const mockStore = configureMockStore(); -const initialState = { - engine: { - backgroundState: initialBackgroundState, - }, -}; -const store = mockStore(initialState); + +const store = mockStore(initialRootState); jest.mock('react-redux', () => ({ ...jest.requireActual('react-redux'), diff --git a/app/components/UI/AddToAddressBookWrapper/AddToAddressBookWrapper.test.tsx b/app/components/UI/AddToAddressBookWrapper/AddToAddressBookWrapper.test.tsx index b2ce68ace60..00ad7df7a8c 100644 --- a/app/components/UI/AddToAddressBookWrapper/AddToAddressBookWrapper.test.tsx +++ b/app/components/UI/AddToAddressBookWrapper/AddToAddressBookWrapper.test.tsx @@ -5,36 +5,33 @@ import { Text } from 'react-native'; import AddToAddressBookWrapper from './AddToAddressBookWrapper'; import { AddAddressModalSelectorsIDs } from '../../../../e2e/selectors/Modals/AddAddressModal.selectors'; import renderWithProvider from '../../../util/test/renderWithProvider'; -import initialBackgroundState from '../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../util/test/initial-root-state'; +import { createMockAccountsControllerState } from '../../../util/test/accountsControllerTestUtils'; + +const MOCK_ADDRESS_1 = '0x0'; +const MOCK_ADDRESS_2 = '0x1'; + +const MOCK_ACCOUNTS_CONTROLLER_STATE = createMockAccountsControllerState([ + MOCK_ADDRESS_1, + MOCK_ADDRESS_2, +]); const initialState = { settings: {}, engine: { backgroundState: { - ...initialBackgroundState, - PreferencesController: { - selectedAddress: '0x0', - identities: { - '0x0': { - address: '0x0', - name: 'Account 1', - }, - '0x1': { - address: '0x1', - name: 'Account 2', - }, - }, - }, + ...backgroundState, AddressBookController: { addressBook: { - '0x1': { - '0x1': { - address: '0x1', + [MOCK_ADDRESS_2]: { + [MOCK_ADDRESS_2]: { + address: MOCK_ADDRESS_2, name: 'Account 2', }, }, }, }, + AccountsController: MOCK_ACCOUNTS_CONTROLLER_STATE, }, }, }; @@ -66,7 +63,7 @@ describe('AddToAddressBookWrapper', () => { }); it('should not render touchable wrapper if address is already saved', async () => { const { queryByText } = renderWithProvider( - + DUMMY , { state: initialState }, @@ -78,7 +75,7 @@ describe('AddToAddressBookWrapper', () => { }); it('should return null if address is already saved and defaultNull is true', async () => { const { queryByText } = renderWithProvider( - + DUMMY , { state: initialState }, diff --git a/app/components/UI/AddressCopy/AddressCopy.tsx b/app/components/UI/AddressCopy/AddressCopy.tsx index 80af16dcbeb..17f8dbd1550 100644 --- a/app/components/UI/AddressCopy/AddressCopy.tsx +++ b/app/components/UI/AddressCopy/AddressCopy.tsx @@ -18,17 +18,17 @@ import ClipboardManager from '../../../core/ClipboardManager'; import { showAlert } from '../../../actions/alert'; import { protectWalletModalVisible } from '../../../actions/user'; import { strings } from '../../../../locales/i18n'; -import { Platform, View } from 'react-native'; +import { View } from 'react-native'; import { MetaMetricsEvents } from '../../../core/Analytics'; import { useStyles } from '../../../component-library/hooks'; -import generateTestId from '../../../../wdio/utils/generateTestId'; +import { WalletViewSelectorsIDs } from '../../../../e2e/selectors/wallet/WalletView.selectors'; // Internal dependencies import styleSheet from './AddressCopy.styles'; import { AddressCopyProps } from './AddressCopy.types'; -import { selectIdentities } from '../../../selectors/preferencesController'; -import { selectSelectedInternalAccountChecksummedAddress } from '../../../selectors/accountsController'; +import { selectSelectedInternalAccount } from '../../../selectors/accountsController'; import { useMetrics } from '../../../components/hooks/useMetrics'; +import { toChecksumHexAddress } from '@metamask/controller-utils'; const AddressCopy = ({ formatAddressType = 'full' }: AddressCopyProps) => { const { styles } = useStyles(styleSheet, {}); @@ -49,22 +49,14 @@ const AddressCopy = ({ formatAddressType = 'full' }: AddressCopyProps) => { /** * A string that represents the selected address */ - const selectedAddress = useSelector( - selectSelectedInternalAccountChecksummedAddress, - ); - - /** - * An object containing each identity in the format address => account - */ - const identities = useSelector(selectIdentities); - - const account = { - ...identities[selectedAddress], - address: selectedAddress, - }; + const selectedInternalAccount = useSelector(selectSelectedInternalAccount); const copyAccountToClipboard = async () => { - await ClipboardManager.setString(selectedAddress); + if (selectedInternalAccount?.address) { + await ClipboardManager.setString( + toChecksumHexAddress(selectedInternalAccount.address), + ); + } handleShowAlert({ isVisible: true, autodismiss: 1500, @@ -83,14 +75,16 @@ const AddressCopy = ({ formatAddressType = 'full' }: AddressCopyProps) => { - {formatAddress(account.address, formatAddressType)} + {selectedInternalAccount + ? formatAddress(selectedInternalAccount.address, formatAddressType) + : null} { - {renderSlightlyLongAddress(toSelectedAddress, 4, 9)} + {toSelectedAddress + ? renderSlightlyLongAddress(toSelectedAddress, 4, 9) + : ''} diff --git a/app/components/UI/AddressInputs/index.test.jsx b/app/components/UI/AddressInputs/index.test.jsx index cc3a6d2bfc5..73a80cda421 100644 --- a/app/components/UI/AddressInputs/index.test.jsx +++ b/app/components/UI/AddressInputs/index.test.jsx @@ -3,26 +3,15 @@ import { fireEvent } from '@testing-library/react-native'; import renderWithProvider from '../../../util/test/renderWithProvider'; import { AddressFrom, AddressTo } from './index'; -import initialBackgroundState from '../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../util/test/initial-root-state'; import { AddAddressModalSelectorsIDs } from '../../../../e2e/selectors/Modals/AddAddressModal.selectors'; const initialState = { settings: {}, engine: { backgroundState: { - ...initialBackgroundState, + ...backgroundState, PreferencesController: { - selectedAddress: '0xe64dD0AB5ad7e8C5F2bf6Ce75C34e187af8b920A', - identities: { - '0xe64dD0AB5ad7e8C5F2bf6Ce75C34e187af8b920A': { - address: '0xe64dD0AB5ad7e8C5F2bf6Ce75C34e187af8b920A', - name: 'Account 1', - }, - '0x519d2CE57898513F676a5C3b66496c3C394c9CC7': { - address: '0x519d2CE57898513F676a5C3b66496c3C394c9CC7', - name: 'Account 2', - }, - }, useTokenDetection: false, }, AddressBookController: { diff --git a/app/components/UI/AssetElement/__snapshots__/index.test.tsx.snap b/app/components/UI/AssetElement/__snapshots__/index.test.tsx.snap index 5704e5960e9..99fc71bcbfc 100644 --- a/app/components/UI/AssetElement/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/AssetElement/__snapshots__/index.test.tsx.snap @@ -14,5 +14,15 @@ exports[`AssetElement should render correctly 1`] = ` } } testID="asset-DAI" -/> +> + + `; diff --git a/app/components/UI/AssetElement/index.tsx b/app/components/UI/AssetElement/index.tsx index e95c3a3a1f6..fdf638bb125 100644 --- a/app/components/UI/AssetElement/index.tsx +++ b/app/components/UI/AssetElement/index.tsx @@ -1,6 +1,6 @@ /* eslint-disable react/prop-types */ import React from 'react'; -import { TouchableOpacity, StyleSheet, Platform } from 'react-native'; +import { TouchableOpacity, StyleSheet, Platform, View } from 'react-native'; import Text, { TextVariant, } from '../../../component-library/components/Texts/Text'; @@ -12,15 +12,20 @@ import { TOKEN_BALANCE_LOADING, TOKEN_RATE_UNDEFINED, } from '../Tokens/constants'; +import { Colors } from '../../../util/theme/models'; +import { fontStyles } from '../../../styles/common'; +import { useTheme } from '../../../util/theme'; + interface AssetElementProps { children?: React.ReactNode; asset: TokenI; onPress?: (asset: TokenI) => void; onLongPress?: ((asset: TokenI) => void) | null; balance?: string; + mainBalance?: string | null; } -const createStyles = () => +const createStyles = (colors: Colors) => StyleSheet.create({ itemWrapper: { flex: 1, @@ -32,6 +37,7 @@ const createStyles = () => arrow: { flex: 1, alignSelf: 'flex-end', + alignItems: 'flex-end', }, arrowIcon: { marginTop: 16, @@ -39,6 +45,12 @@ const createStyles = () => skeleton: { width: 50, }, + balanceFiat: { + color: colors.text.alternative, + paddingHorizontal: 0, + ...fontStyles.normal, + textTransform: 'uppercase', + }, }); /** @@ -48,10 +60,12 @@ const AssetElement: React.FC = ({ children, balance, asset, + mainBalance = null, onPress, onLongPress, }) => { - const styles = createStyles(); + const { colors } = useTheme(); + const styles = createStyles(colors); const handleOnPress = () => { onPress?.(asset); @@ -70,21 +84,32 @@ const AssetElement: React.FC = ({ > {children} - {balance && ( - - {balance === TOKEN_BALANCE_LOADING ? ( - - ) : ( - balance - )} - - )} + + {balance && ( + + {balance === TOKEN_BALANCE_LOADING ? ( + + ) : ( + balance + )} + + )} + {mainBalance ? ( + + {mainBalance === TOKEN_BALANCE_LOADING ? ( + + ) : ( + mainBalance + )} + + ) : null} + ); }; diff --git a/app/components/UI/AssetIcon/index.test.tsx b/app/components/UI/AssetIcon/index.test.tsx index fd256ddb41e..626428cd36a 100644 --- a/app/components/UI/AssetIcon/index.test.tsx +++ b/app/components/UI/AssetIcon/index.test.tsx @@ -2,21 +2,14 @@ import React from 'react'; import renderWithProvider from '../../../util/test/renderWithProvider'; import AssetIcon from './'; const sampleLogo = 'https://s3.amazonaws.com/airswap-token-images/WBTC.png'; -import initialBackgroundState from '../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../util/test/initial-root-state'; const mockInitialState = { engine: { backgroundState: { - ...initialBackgroundState, + ...backgroundState, PreferencesController: { featureFlags: {}, - identities: { - '0x76cf1CdD1fcC252442b50D6e97207228aA4aefC3': { - address: '0x76cf1CdD1fcC252442b50D6e97207228aA4aefC3', - name: 'Account 1', - importTime: 1684232000456, - }, - }, ipfsGateway: 'https://cloudflare-ipfs.com/ipfs/', lostIdentities: {}, selectedAddress: '0x76cf1CdD1fcC252442b50D6e97207228aA4aefC3', @@ -34,13 +27,6 @@ const mockInitialState = { _W: { featureFlags: {}, frequentRpcList: [], - identities: { - '0x76cf1CdD1fcC252442b50D6e97207228aA4aefC3': { - address: '0x76cf1CdD1fcC252442b50D6e97207228aA4aefC3', - name: 'Account 1', - importTime: 1684232000456, - }, - }, ipfsGateway: 'https://cloudflare-ipfs.com/ipfs/', lostIdentities: {}, selectedAddress: '0x76cf1CdD1fcC252442b50D6e97207228aA4aefC3', diff --git a/app/components/UI/AssetSearch/index.test.tsx b/app/components/UI/AssetSearch/index.test.tsx index e58041c7314..9838088af3b 100644 --- a/app/components/UI/AssetSearch/index.test.tsx +++ b/app/components/UI/AssetSearch/index.test.tsx @@ -1,7 +1,7 @@ import React from 'react'; import renderWithProvider from '../../../util/test/renderWithProvider'; import AssetSearch from './'; -import initialBackgroundState from '../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../util/test/initial-root-state'; import Engine from '../../../core/Engine'; const mockedEngine = Engine; @@ -48,7 +48,7 @@ jest.mock('../../../core/Engine.ts', () => ({ const initialState = { engine: { - backgroundState: initialBackgroundState, + backgroundState, }, }; diff --git a/app/components/UI/CollectibleContractInformation/index.test.tsx b/app/components/UI/CollectibleContractInformation/index.test.tsx index 526e2d4159b..2629113abd8 100644 --- a/app/components/UI/CollectibleContractInformation/index.test.tsx +++ b/app/components/UI/CollectibleContractInformation/index.test.tsx @@ -3,12 +3,12 @@ import { shallow } from 'enzyme'; import CollectibleContractInformation from './'; import configureMockStore from 'redux-mock-store'; import { Provider } from 'react-redux'; -import initialBackgroundState from '../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../util/test/initial-root-state'; const mockStore = configureMockStore(); const initialState = { engine: { - backgroundState: initialBackgroundState, + backgroundState, }, }; const store = mockStore(initialState); diff --git a/app/components/UI/CollectibleContractOverview/index.test.tsx b/app/components/UI/CollectibleContractOverview/index.test.tsx index df1b0e37866..e1e358db0ad 100644 --- a/app/components/UI/CollectibleContractOverview/index.test.tsx +++ b/app/components/UI/CollectibleContractOverview/index.test.tsx @@ -3,12 +3,12 @@ import CollectibleContractOverview from './'; import configureMockStore from 'redux-mock-store'; import { shallow } from 'enzyme'; import { Provider } from 'react-redux'; -import initialBackgroundState from '../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../util/test/initial-root-state'; const mockStore = configureMockStore(); const initialState = { engine: { - backgroundState: initialBackgroundState, + backgroundState, }, }; const store = mockStore(initialState); diff --git a/app/components/UI/CollectibleContracts/index.js b/app/components/UI/CollectibleContracts/index.js index 866d8b96d7b..d03c8bce4d3 100644 --- a/app/components/UI/CollectibleContracts/index.js +++ b/app/components/UI/CollectibleContracts/index.js @@ -5,7 +5,6 @@ import { StyleSheet, View, Image, - Platform, FlatList, RefreshControl, ActivityIndicator, @@ -30,7 +29,6 @@ import { compareTokenIds } from '../../../util/tokens'; import CollectibleDetectionModal from '../CollectibleDetectionModal'; import { useTheme } from '../../../util/theme'; import { MAINNET } from '../../../constants/network'; -import generateTestId from '../../../../wdio/utils/generateTestId'; import { selectChainId, selectProviderType, @@ -41,10 +39,7 @@ import { selectUseNftDetection, } from '../../../selectors/preferencesController'; import { selectSelectedInternalAccountChecksummedAddress } from '../../../selectors/accountsController'; -import { - IMPORT_NFT_BUTTON_ID, - NFT_TAB_CONTAINER_ID, -} from '../../../../wdio/screen-objects/testIDs/Screens/WalletView.testIds'; +import { WalletViewSelectorsIDs } from '../../../../e2e/selectors/wallet/WalletView.selectors'; import { useMetrics } from '../../../components/hooks/useMetrics'; import { RefreshTestId, SpinnerTestId } from './constants'; @@ -239,7 +234,7 @@ const CollectibleContracts = ({ {strings('wallet.add_collectibles')} @@ -376,7 +371,7 @@ const CollectibleContracts = ({ return ( {renderList()} diff --git a/app/components/UI/CollectibleContracts/index.test.tsx b/app/components/UI/CollectibleContracts/index.test.tsx index 946a654ba62..db7045fdb84 100644 --- a/app/components/UI/CollectibleContracts/index.test.tsx +++ b/app/components/UI/CollectibleContracts/index.test.tsx @@ -3,7 +3,7 @@ import { shallow } from 'enzyme'; import CollectibleContracts from './'; import configureMockStore from 'redux-mock-store'; import { Provider } from 'react-redux'; -import initialBackgroundState from '../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../util/test/initial-root-state'; import renderWithProvider from '../../../util/test/renderWithProvider'; import { act } from '@testing-library/react-hooks'; @@ -51,7 +51,7 @@ const initialState = { favorites: {}, }, engine: { - backgroundState: initialBackgroundState, + backgroundState, }, }; const store = mockStore(initialState); @@ -79,7 +79,7 @@ describe('CollectibleContracts', () => { }, engine: { backgroundState: { - ...initialBackgroundState, + ...backgroundState, NetworkController: { network: '1', providerConfig: { @@ -196,7 +196,7 @@ describe('CollectibleContracts', () => { }, engine: { backgroundState: { - ...initialBackgroundState, + ...backgroundState, NetworkController: { network: '1', providerConfig: { @@ -309,7 +309,7 @@ describe('CollectibleContracts', () => { }, engine: { backgroundState: { - ...initialBackgroundState, + ...backgroundState, NetworkController: { network: '1', providerConfig: { @@ -426,7 +426,7 @@ describe('CollectibleContracts', () => { }, engine: { backgroundState: { - ...initialBackgroundState, + ...backgroundState, NetworkController: { network: '1', providerConfig: { @@ -505,7 +505,7 @@ describe('CollectibleContracts', () => { }, engine: { backgroundState: { - ...initialBackgroundState, + ...backgroundState, NetworkController: { network: '1', providerConfig: { @@ -564,7 +564,7 @@ describe('CollectibleContracts', () => { }, engine: { backgroundState: { - ...initialBackgroundState, + ...backgroundState, NetworkController: { network: '1', providerConfig: { diff --git a/app/components/UI/CollectibleMedia/CollectibleMedia.test.tsx b/app/components/UI/CollectibleMedia/CollectibleMedia.test.tsx index 978e0e12042..f45d0051d4c 100644 --- a/app/components/UI/CollectibleMedia/CollectibleMedia.test.tsx +++ b/app/components/UI/CollectibleMedia/CollectibleMedia.test.tsx @@ -3,11 +3,11 @@ import React from 'react'; import CollectibleMedia from './CollectibleMedia'; import renderWithProvider from '../../../util/test/renderWithProvider'; -import initialBackgroundState from '../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../util/test/initial-root-state'; const mockInitialState = { engine: { - backgroundState: initialBackgroundState, + backgroundState, }, }; diff --git a/app/components/UI/CollectibleModal/CollectibleModal.test.tsx b/app/components/UI/CollectibleModal/CollectibleModal.test.tsx index 3d69d9c6a27..c7c9a52687e 100644 --- a/app/components/UI/CollectibleModal/CollectibleModal.test.tsx +++ b/app/components/UI/CollectibleModal/CollectibleModal.test.tsx @@ -3,7 +3,7 @@ import React from 'react'; import CollectibleModal from './CollectibleModal'; import renderWithProvider from '../../../util/test/renderWithProvider'; -import initialBackgroundState from '../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../util/test/initial-root-state'; import { collectiblesSelector } from '../../../reducers/collectibles'; import { selectDisplayNftMedia, @@ -15,7 +15,7 @@ import { MOCK_ACCOUNTS_CONTROLLER_STATE } from '../../../util/test/accountsContr const mockInitialState = { engine: { backgroundState: { - ...initialBackgroundState, + ...backgroundState, AccountsController: MOCK_ACCOUNTS_CONTROLLER_STATE, }, }, diff --git a/app/components/UI/CollectibleOverview/index.test.tsx b/app/components/UI/CollectibleOverview/index.test.tsx index ea570feb266..6bc40a57a64 100644 --- a/app/components/UI/CollectibleOverview/index.test.tsx +++ b/app/components/UI/CollectibleOverview/index.test.tsx @@ -3,7 +3,7 @@ import CollectibleOverview from './'; import configureMockStore from 'redux-mock-store'; import { shallow } from 'enzyme'; import { Provider } from 'react-redux'; -import initialBackgroundState from '../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../util/test/initial-root-state'; const mockStore = configureMockStore(); const initialState = { @@ -11,7 +11,7 @@ const initialState = { favorites: {}, }, engine: { - backgroundState: initialBackgroundState, + backgroundState, }, }; const store = mockStore(initialState); diff --git a/app/components/UI/ConfirmAddAsset/ConfirmAddAsset.test.tsx b/app/components/UI/ConfirmAddAsset/ConfirmAddAsset.test.tsx index 9288d2fbcbb..73647c006f0 100644 --- a/app/components/UI/ConfirmAddAsset/ConfirmAddAsset.test.tsx +++ b/app/components/UI/ConfirmAddAsset/ConfirmAddAsset.test.tsx @@ -1,6 +1,6 @@ import React from 'react'; import ConfirmAddAsset from './ConfirmAddAsset'; -import initialBackgroundState from '../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../util/test/initial-root-state'; import renderWithProvider from '../../../util/test/renderWithProvider'; import useBalance from '../Ramp/hooks/useBalance'; import { toTokenMinimalUnit } from '../../../util/number'; @@ -58,7 +58,7 @@ const mockInitialState = { settings: {}, engine: { backgroundState: { - ...initialBackgroundState, + ...backgroundState, AccountTrackerController: { accounts: { '0xC4955C0d639D99699Bfd7Ec54d9FaFEe40e4D272': { diff --git a/app/components/UI/DrawerView/index.js b/app/components/UI/DrawerView/index.js index 82963e61ae0..f33822e83f3 100644 --- a/app/components/UI/DrawerView/index.js +++ b/app/components/UI/DrawerView/index.js @@ -81,12 +81,12 @@ import { selectCurrentCurrency } from '../../../selectors/currencyRateController import { selectTokens } from '../../../selectors/tokensController'; import { selectAccounts } from '../../../selectors/accountTrackerController'; import { selectContractBalances } from '../../../selectors/tokenBalancesController'; -import { selectIdentities } from '../../../selectors/preferencesController'; -import { selectSelectedInternalAccountChecksummedAddress } from '../../../selectors/accountsController'; +import { selectSelectedInternalAccount } from '../../../selectors/accountsController'; import { createAccountSelectorNavDetails } from '../../Views/AccountSelector'; import NetworkInfo from '../NetworkInfo'; import { withMetricsAwareness } from '../../../components/hooks/useMetrics'; +import { toChecksumHexAddress } from '@metamask/controller-utils'; const createStyles = (colors) => StyleSheet.create({ @@ -340,18 +340,14 @@ class DrawerView extends PureComponent { * Object representing the configuration of the current selected network */ providerConfig: PropTypes.object.isRequired, - /** - * Selected address as string - */ - selectedAddress: PropTypes.string, /** * List of accounts from the AccountTrackerController */ accounts: PropTypes.object, /** - * List of accounts from the PreferencesController + * Currently selected account */ - identities: PropTypes.object, + selectedInternalAccount: PropTypes.object, /** /* Selected currency */ @@ -474,16 +470,19 @@ class DrawerView extends PureComponent { previousBalance = null; processedNewBalance = false; animatingNetworksModal = false; + selectedChecksummedAddress = toChecksumHexAddress( + this.props.selectedInternalAccount.address, + ); isCurrentAccountImported() { let ret = false; - const { keyrings, selectedAddress } = this.props; + const { keyrings } = this.props; const allKeyrings = keyrings && keyrings.length ? keyrings : Engine.context.KeyringController.state.keyrings; for (const keyring of allKeyrings) { - if (keyring.accounts.includes(selectedAddress)) { + if (keyring.accounts.includes(this.selectedChecksummedAddress)) { ret = keyring.type !== 'HD Key Tree'; break; } @@ -495,7 +494,7 @@ class DrawerView extends PureComponent { renderTag() { const colors = this.context.colors || mockTheme.colors; const styles = createStyles(colors); - const label = getLabelTextByAddress(this.props.selectedAddress); + const label = getLabelTextByAddress(this.selectedChecksummedAddress); return label ? ( @@ -579,16 +578,16 @@ class DrawerView extends PureComponent { } updateAccountInfo = async () => { - const { identities, providerConfig, selectedAddress } = this.props; + const { providerConfig, selectedInternalAccount } = this.props; const { currentChainId, address, name } = this.state.account; - const accountName = identities[selectedAddress]?.name; + const accountName = selectedInternalAccount.metadata.name; if ( currentChainId !== providerConfig.chainId || - address !== selectedAddress || + address !== this.selectedChecksummedAddress || name !== accountName ) { const ens = await doENSReverseLookup( - selectedAddress, + this.selectedChecksummedAddress, providerConfig.chainId, ); this.setState((state) => ({ @@ -596,7 +595,7 @@ class DrawerView extends PureComponent { ens, name: accountName, currentChainId: providerConfig.chainId, - address: selectedAddress, + address: this.selectedChecksummedAddress, }, })); } @@ -697,18 +696,20 @@ class DrawerView extends PureComponent { }; viewInEtherscan = () => { - const { selectedAddress, providerConfig, networkConfigurations } = - this.props; + const { providerConfig, networkConfigurations } = this.props; if (providerConfig.type === RPC) { const blockExplorer = findBlockExplorerForRpc( providerConfig.rpcUrl, networkConfigurations, ); - const url = `${blockExplorer}/address/${selectedAddress}`; + const url = `${blockExplorer}/address/${this.selectedChecksummedAddress}`; const title = new URL(blockExplorer).hostname; this.goToBrowserUrl(url, title); } else { - const url = getEtherscanAddressUrl(providerConfig.type, selectedAddress); + const url = getEtherscanAddressUrl( + providerConfig.type, + this.selectedChecksummedAddress, + ); const etherscan_url = getEtherscanBaseUrl(providerConfig.type).replace( 'https://', '', @@ -892,8 +893,7 @@ class DrawerView extends PureComponent { }; copyAccountToClipboard = async () => { - const { selectedAddress } = this.props; - await ClipboardManager.setString(selectedAddress); + await ClipboardManager.setString(this.selectedChecksummedAddress); this.toggleReceiveModal(); InteractionManager.runAfterInteractions(() => { this.props.showAlert({ @@ -906,9 +906,8 @@ class DrawerView extends PureComponent { }; onShare = () => { - const { selectedAddress } = this.props; Share.open({ - message: selectedAddress, + message: this.selectedChecksummedAddress, }) .then(() => { this.props.protectWalletModalVisible(); @@ -996,8 +995,7 @@ class DrawerView extends PureComponent { const { providerConfig, accounts, - identities, - selectedAddress, + selectedInternalAccount, currentCurrency, seedphraseBackedUp, currentRoute, @@ -1011,16 +1009,16 @@ class DrawerView extends PureComponent { } = this.state; const account = { - address: selectedAddress, + address: this.selectedChecksummedAddress, name: nameFromState, ens: ensFromState, - ...identities[selectedAddress], - ...accounts[selectedAddress], + ...selectedInternalAccount, + ...accounts[this.selectedChecksummedAddress], }; const { name, ens } = account; account.balance = - (accounts[selectedAddress] && - renderFromWei(accounts[selectedAddress].balance)) || + (accounts[this.selectedChecksummedAddress] && + renderFromWei(accounts[this.selectedChecksummedAddress].balance)) || 0; const fiatBalance = Engine.getTotalFiatAccountBalance(); const totalFiatBalance = fiatBalance.ethFiat + fiatBalance.tokenFiat; @@ -1056,7 +1054,10 @@ class DrawerView extends PureComponent { testID={'navbar-account-identicon'} > - + ({ providerConfig: selectProviderConfig(state), accounts: selectAccounts(state), - selectedAddress: selectSelectedInternalAccountChecksummedAddress(state), - identities: selectIdentities(state), + selectedInternalAccount: selectSelectedInternalAccount(state), networkConfigurations: selectNetworkConfigurations(state), currentCurrency: selectCurrentCurrency(state), keyrings: state.engine.backgroundState.KeyringController.keyrings, diff --git a/app/components/UI/DrawerView/index.test.tsx b/app/components/UI/DrawerView/index.test.tsx index 9d06c981241..6eebe48bc6e 100644 --- a/app/components/UI/DrawerView/index.test.tsx +++ b/app/components/UI/DrawerView/index.test.tsx @@ -2,28 +2,16 @@ import React from 'react'; import renderWithProvider from '../../../util/test/renderWithProvider'; import DrawerView from './'; -import initialBackgroundState from '../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../util/test/initial-root-state'; import Engine from '../../../core/Engine'; -import { - MOCK_ACCOUNTS_CONTROLLER_STATE, - MOCK_ADDRESS_1, -} from '../../../util/test/accountsControllerTestUtils'; +import { MOCK_ACCOUNTS_CONTROLLER_STATE } from '../../../util/test/accountsControllerTestUtils'; const mockedEngine = Engine; const mockInitialState = { engine: { backgroundState: { - ...initialBackgroundState, - PreferencesController: { - selectedAddress: MOCK_ADDRESS_1, - identities: { - [MOCK_ADDRESS_1]: { - name: 'Account 1', - address: MOCK_ADDRESS_1, - }, - }, - }, + ...backgroundState, AccountsController: MOCK_ACCOUNTS_CONTROLLER_STATE, }, }, diff --git a/app/components/UI/EthereumAddress/index.js b/app/components/UI/EthereumAddress/index.js index b522b2bf0cd..82b2ce368a8 100644 --- a/app/components/UI/EthereumAddress/index.js +++ b/app/components/UI/EthereumAddress/index.js @@ -21,7 +21,7 @@ class EthereumAddress extends PureComponent { address: PropTypes.string, /** * Type of formatting for the address - * can be "short" or "full" + * can be "short", "mid" or "full" */ type: PropTypes.string, }; diff --git a/app/components/UI/Navbar/index.js b/app/components/UI/Navbar/index.js index 53b37cd4c9a..d56aec0c3db 100644 --- a/app/components/UI/Navbar/index.js +++ b/app/components/UI/Navbar/index.js @@ -27,12 +27,10 @@ import Device from '../../../util/device'; import PickerNetwork from '../../../component-library/components/Pickers/PickerNetwork'; import BrowserUrlBar from '../BrowserUrlBar'; import generateTestId from '../../../../wdio/utils/generateTestId'; -import { NAVBAR_NETWORK_BUTTON } from '../../../../wdio/screen-objects/testIDs/Screens/WalletView.testIds'; import { NAV_ANDROID_BACK_BUTTON } from '../../../../wdio/screen-objects/testIDs/Screens/NetworksScreen.testids'; import { ASSET_BACK_BUTTON } from '../../../../wdio/screen-objects/testIDs/Screens/TokenOverviewScreen.testIds'; import { REQUEST_SEARCH_RESULTS_BACK_BUTTON } from '../../../../wdio/screen-objects/testIDs/Screens/RequestToken.testIds'; import { BACK_BUTTON_SIMPLE_WEBVIEW } from '../../../../wdio/screen-objects/testIDs/Components/SimpleWebView.testIds'; -import { EDIT_BUTTON } from '../../../../wdio/screen-objects/testIDs/Common.testIds'; import Routes from '../../../constants/navigation/Routes'; import ButtonIcon, { @@ -53,6 +51,7 @@ import { NetworksViewSelectorsIDs } from '../../../../e2e/selectors/Settings/Net import { SendLinkViewSelectorsIDs } from '../../../../e2e/selectors/SendLinkView.selectors'; import { SendViewSelectorsIDs } from '../../../../e2e/selectors/SendView.selectors'; import { getBlockaidTransactionMetricsParams } from '../../../util/blockaid'; +import { AddContactViewSelectorsIDs } from '../../../../e2e/selectors/Settings/Contacts/AddContactView.selectors'; const trackEvent = (event, params = {}) => { MetaMetrics.getInstance().trackEvent(event, params); @@ -290,7 +289,7 @@ export function getEditableOptions(title, navigation, route, themeColors) { {editMode @@ -984,7 +983,7 @@ export function getWalletNavbarOptions( label={networkName} imageSource={networkImageSource} onPress={onPressTitle} - {...generateTestId(Platform, NAVBAR_NETWORK_BUTTON)} + testID={WalletViewSelectorsIDs.NAVBAR_NETWORK_BUTTON} /> ), diff --git a/app/components/UI/NavbarBrowserTitle/index.test.tsx b/app/components/UI/NavbarBrowserTitle/index.test.tsx index 65a46192a79..5d7e771bedc 100644 --- a/app/components/UI/NavbarBrowserTitle/index.test.tsx +++ b/app/components/UI/NavbarBrowserTitle/index.test.tsx @@ -1,22 +1,14 @@ import React from 'react'; import renderWithProvider from '../../../util/test/renderWithProvider'; import NavbarBrowserTitle from './'; -import initialBackgroundState from '../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../util/test/initial-root-state'; import Engine from '../../../core/Engine'; const mockedEngine = Engine; const mockInitialState = { engine: { - backgroundState: { - ...initialBackgroundState, - PreferencesController: { - selectedAddress: '0x', - identities: { - '0x': { name: 'Account 1', address: '0x' }, - }, - }, - }, + backgroundState, }, }; diff --git a/app/components/UI/NetworkInfo/index.test.tsx b/app/components/UI/NetworkInfo/index.test.tsx index 5e9cb5dfadf..e52882bc2a9 100644 --- a/app/components/UI/NetworkInfo/index.test.tsx +++ b/app/components/UI/NetworkInfo/index.test.tsx @@ -3,7 +3,7 @@ import { shallow } from 'enzyme'; import NetworkInfo from './'; import configureMockStore from 'redux-mock-store'; import { Provider } from 'react-redux'; -import initialBackgroundState from '../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../util/test/initial-root-state'; const mockStore = configureMockStore(); const initialState = { @@ -11,7 +11,7 @@ const initialState = { approvedHosts: {}, }, engine: { - backgroundState: initialBackgroundState, + backgroundState, }, }; diff --git a/app/components/UI/NetworkMainAssetLogo/index.test.tsx b/app/components/UI/NetworkMainAssetLogo/index.test.tsx index 687a841d2be..84a625a7c16 100644 --- a/app/components/UI/NetworkMainAssetLogo/index.test.tsx +++ b/app/components/UI/NetworkMainAssetLogo/index.test.tsx @@ -5,7 +5,7 @@ import { ChainId } from '@metamask/controller-utils'; import { render } from '@testing-library/react-native'; import NetworkMainAssetLogo from '.'; -import initialBackgroundState from '../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../util/test/initial-root-state'; jest.mock('../Swaps/components/TokenIcon', () => { const originalModule = jest.requireActual('../Swaps/components/TokenIcon'); @@ -18,9 +18,7 @@ jest.mock('../Swaps/components/TokenIcon', () => { const mockInitialState = { engine: { - backgroundState: { - ...initialBackgroundState, - }, + backgroundState, }, network: { provider: { diff --git a/app/components/UI/Notification/Row/Icon.test.tsx b/app/components/UI/Notification/Row/Icon.test.tsx index dbd6cda22e6..ba8081b5346 100644 --- a/app/components/UI/Notification/Row/Icon.test.tsx +++ b/app/components/UI/Notification/Row/Icon.test.tsx @@ -6,7 +6,7 @@ import renderWithProvider from '../../../../util/test/renderWithProvider'; import NotificationIcon from './Icon'; import { TRIGGER_TYPES } from '../../../../util/notifications'; import { IconName } from '../../../../component-library/components/Icons/Icon'; -import initialBackgroundState from '../../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../../util/test/initial-root-state'; import { CommonSelectorsIDs } from '../../../../../e2e/selectors/Common.selectors'; import SVG_MM_LOGO_PATH from '../../../../images/fox.svg'; @@ -17,7 +17,7 @@ Linking.openURL = jest.fn(() => Promise.resolve('opened https://metamask.io!')); const mockInitialState = { engine: { backgroundState: { - ...initialBackgroundState, + ...backgroundState, }, }, }; diff --git a/app/components/UI/PaymentRequest/AssetList/index.test.tsx b/app/components/UI/PaymentRequest/AssetList/index.test.tsx index 9320aa39c9c..02a3a1c73ea 100644 --- a/app/components/UI/PaymentRequest/AssetList/index.test.tsx +++ b/app/components/UI/PaymentRequest/AssetList/index.test.tsx @@ -3,12 +3,12 @@ import { shallow } from 'enzyme'; import AssetList from './'; import configureMockStore from 'redux-mock-store'; import { Provider } from 'react-redux'; -import initialBackgroundState from '../../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../../util/test/initial-root-state'; const mockStore = configureMockStore(); const initialState = { engine: { - backgroundState: initialBackgroundState, + backgroundState, }, }; const store = mockStore(initialState); diff --git a/app/components/UI/Ramp/Views/BuildQuote/BuildQuote.test.tsx b/app/components/UI/Ramp/Views/BuildQuote/BuildQuote.test.tsx index c9d0dc77f24..d818aa6a342 100644 --- a/app/components/UI/Ramp/Views/BuildQuote/BuildQuote.test.tsx +++ b/app/components/UI/Ramp/Views/BuildQuote/BuildQuote.test.tsx @@ -7,7 +7,7 @@ import BuildQuote from './BuildQuote'; import useRegions from '../../hooks/useRegions'; import { RampSDK } from '../../sdk'; import Routes from '../../../../../constants/navigation/Routes'; -import initialBackgroundState from '../../../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../../../util/test/initial-root-state'; import useCryptoCurrencies from '../../hooks/useCryptoCurrencies'; import useFiatCurrencies from '../../hooks/useFiatCurrencies'; import usePaymentMethods from '../../hooks/usePaymentMethods'; @@ -39,7 +39,7 @@ function render(Component: React.ComponentType) { state: { engine: { backgroundState: { - ...initialBackgroundState, + ...backgroundState, AccountsController: MOCK_ACCOUNTS_CONTROLLER_STATE, }, }, diff --git a/app/components/UI/Ramp/Views/GetStarted/GetStarted.test.tsx b/app/components/UI/Ramp/Views/GetStarted/GetStarted.test.tsx index 223396f1835..2a926c9a527 100644 --- a/app/components/UI/Ramp/Views/GetStarted/GetStarted.test.tsx +++ b/app/components/UI/Ramp/Views/GetStarted/GetStarted.test.tsx @@ -7,7 +7,7 @@ import { RampType, Region } from '../../types'; import { RampSDK } from '../../sdk'; import useRampNetwork from '../../hooks/useRampNetwork'; import Routes from '../../../../../constants/navigation/Routes'; -import initialBackgroundState from '../../../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../../../util/test/initial-root-state'; function render(Component: React.ComponentType) { return renderScreen( @@ -18,7 +18,7 @@ function render(Component: React.ComponentType) { { state: { engine: { - backgroundState: initialBackgroundState, + backgroundState, }, }, }, diff --git a/app/components/UI/Ramp/Views/NetworkSwitcher/NetworkSwitcher.test.tsx b/app/components/UI/Ramp/Views/NetworkSwitcher/NetworkSwitcher.test.tsx index 7970b289a16..bbb43e19a0f 100644 --- a/app/components/UI/Ramp/Views/NetworkSwitcher/NetworkSwitcher.test.tsx +++ b/app/components/UI/Ramp/Views/NetworkSwitcher/NetworkSwitcher.test.tsx @@ -8,7 +8,7 @@ import useFetchRampNetworks from '../../hooks/useFetchRampNetworks'; import useRampNetworksDetail from '../../hooks/useRampNetworksDetail'; import { RampSDK } from '../../sdk'; import Routes from '../../../../../constants/navigation/Routes'; -import initialBackgroundState from '../../../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../../../util/test/initial-root-state'; import Engine from '../../../../../core/Engine'; import { RampType } from '../../../../../reducers/fiatOrders/types'; @@ -76,9 +76,9 @@ function render(Component: React.ComponentType, chainId?: string) { state: { engine: { backgroundState: { - ...initialBackgroundState, + ...backgroundState, NetworkController: { - ...initialBackgroundState.NetworkController, + ...backgroundState.NetworkController, providerConfig: { chainId: chainId ?? '0x38', ticker: 'BNB', diff --git a/app/components/UI/Ramp/Views/OrderDetails/OrderDetails.test.tsx b/app/components/UI/Ramp/Views/OrderDetails/OrderDetails.test.tsx index 67c87bf41c7..9fabce779b3 100644 --- a/app/components/UI/Ramp/Views/OrderDetails/OrderDetails.test.tsx +++ b/app/components/UI/Ramp/Views/OrderDetails/OrderDetails.test.tsx @@ -3,7 +3,7 @@ import { processFiatOrder } from '../../index'; import { act, fireEvent, screen, waitFor } from '@testing-library/react-native'; import { renderScreen } from '../../../../../util/test/renderWithProvider'; import OrderDetails from './OrderDetails'; -import initialBackgroundState from '../../../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../../../util/test/initial-root-state'; import { FiatOrder } from '../../../../../reducers/fiatOrders'; import { FIAT_ORDER_PROVIDERS, @@ -141,7 +141,7 @@ function render(Component: React.ComponentType, orders = [mockOrder]) { state: { engine: { backgroundState: { - ...initialBackgroundState, + ...backgroundState, AccountsController: MOCK_ACCOUNTS_CONTROLLER_STATE, }, }, diff --git a/app/components/UI/Ramp/Views/OrderDetails/__snapshots__/OrderDetails.test.tsx.snap b/app/components/UI/Ramp/Views/OrderDetails/__snapshots__/OrderDetails.test.tsx.snap index dd227168f98..e7db500ff72 100644 --- a/app/components/UI/Ramp/Views/OrderDetails/__snapshots__/OrderDetails.test.tsx.snap +++ b/app/components/UI/Ramp/Views/OrderDetails/__snapshots__/OrderDetails.test.tsx.snap @@ -863,6 +863,7 @@ exports[`OrderDetails renders a cancelled order 1`] = ` ] } > + Account 1 ( + Account 1 ( + Account 1 ( + Account 1 ( + Account 1 ( + Account 1 ( + Account 1 ( + Account 1 ( + Account 1 ( = { @@ -21,7 +21,7 @@ function render(Component: React.ComponentType) { { state: { engine: { - backgroundState: initialBackgroundState, + backgroundState, }, }, }, diff --git a/app/components/UI/Ramp/components/Account.tsx b/app/components/UI/Ramp/components/Account.tsx index 23263f40612..900e96f3b33 100644 --- a/app/components/UI/Ramp/components/Account.tsx +++ b/app/components/UI/Ramp/components/Account.tsx @@ -7,8 +7,11 @@ import { View, StyleSheet } from 'react-native'; import { useTheme } from '../../../../util/theme'; import { Colors } from '../../../../util/theme/models'; import { colors as importedColors } from '../../../../styles/common'; -import { selectIdentities } from '../../../../selectors/preferencesController'; -import { selectSelectedInternalAccountChecksummedAddress } from '../../../../selectors/accountsController'; +import { + selectSelectedInternalAccountChecksummedAddress, + selectInternalAccounts, +} from '../../../../selectors/accountsController'; +import { toLowerCaseEquals } from '../../../../util/general'; // TODO: Convert into typescript and correctly type // TODO: Replace "any" with type @@ -51,14 +54,25 @@ const Account = ({ const selectedAddress = useSelector( selectSelectedInternalAccountChecksummedAddress, ); - const identities = useSelector(selectIdentities); + + const internalAccounts = useSelector(selectInternalAccounts); + + const selectedInternalAccount = address + ? internalAccounts.find((account) => + toLowerCaseEquals(account.address, address), + ) + : internalAccounts.find((account) => + toLowerCaseEquals(account.address, selectedAddress), + ); + + const accountName = selectedInternalAccount?.metadata?.name || ''; return ( - {identities[address || selectedAddress]?.name} ( + {accountName} ( ) diff --git a/app/components/UI/Ramp/hooks/useBalance.ts b/app/components/UI/Ramp/hooks/useBalance.ts index f0e49c63e3a..de0ed400742 100644 --- a/app/components/UI/Ramp/hooks/useBalance.ts +++ b/app/components/UI/Ramp/hooks/useBalance.ts @@ -1,5 +1,5 @@ -import { hexToBN } from '@metamask/controller-utils'; import { useSelector } from 'react-redux'; +import { hexToBN } from '@metamask/controller-utils'; import { NATIVE_ADDRESS } from '../../../../constants/on-ramp'; import { selectAccountsByChainId } from '../../../../selectors/accountTrackerController'; import { @@ -19,13 +19,18 @@ import { weiToFiat, } from '../../../../util/number'; +const defaultReturn = { + balance: null, + balanceFiat: null, + balanceBN: null, +}; + interface Asset { address: string; decimals: number; } export default function useBalance(asset?: Asset) { - const assetAddress = safeToChecksumAddress(asset?.address); const accountsByChainId = useSelector(selectAccountsByChainId); const chainId = useSelector(selectChainId); const selectedAddress = useSelector( @@ -36,8 +41,14 @@ export default function useBalance(asset?: Asset) { const tokenExchangeRates = useSelector(selectContractExchangeRates); const balances = useSelector(selectContractBalances); - if (!asset || !assetAddress) { - return { balance: null, balanceFiat: null, balanceBN: null }; + if (!asset) { + return defaultReturn; + } + + const assetAddress = safeToChecksumAddress(asset.address); + + if (!assetAddress) { + return defaultReturn; } let balance, balanceFiat, balanceBN; @@ -66,7 +77,9 @@ export default function useBalance(asset?: Asset) { currentCurrency, ); balanceBN = - assetAddress && assetAddress in balances ? balances[assetAddress] : null; + assetAddress && assetAddress in balances + ? hexToBN(balances[assetAddress]) + : null; } return { balance, balanceFiat, balanceBN }; diff --git a/app/components/UI/Ramp/hooks/useGasPriceEstimation.test.ts b/app/components/UI/Ramp/hooks/useGasPriceEstimation.test.ts index 33116230fad..08651f52b69 100644 --- a/app/components/UI/Ramp/hooks/useGasPriceEstimation.test.ts +++ b/app/components/UI/Ramp/hooks/useGasPriceEstimation.test.ts @@ -2,7 +2,7 @@ import { merge } from 'lodash'; import type { GasFeeState } from '@metamask/gas-fee-controller'; import useGasPriceEstimation from './useGasPriceEstimation'; import { renderHookWithProvider } from '../../../../util/test/renderWithProvider'; -import initialBackgroundState from '../../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../../util/test/initial-root-state'; import Engine from '../../../../core/Engine'; type DeepPartial = { @@ -23,7 +23,7 @@ jest.mock('../../../../core/Engine', () => ({ const mockInitialState = { engine: { - backgroundState: initialBackgroundState, + backgroundState, }, }; diff --git a/app/components/UI/ReceiveRequest/index.test.tsx b/app/components/UI/ReceiveRequest/index.test.tsx index 1b95e369856..8cddbd17e97 100644 --- a/app/components/UI/ReceiveRequest/index.test.tsx +++ b/app/components/UI/ReceiveRequest/index.test.tsx @@ -3,14 +3,14 @@ import { shallow } from 'enzyme'; import ReceiveRequest from './'; import configureMockStore from 'redux-mock-store'; import { Provider } from 'react-redux'; -import initialBackgroundState from '../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../util/test/initial-root-state'; import { MOCK_ACCOUNTS_CONTROLLER_STATE } from '../../../util/test/accountsControllerTestUtils'; const mockStore = configureMockStore(); const initialState = { engine: { backgroundState: { - ...initialBackgroundState, + ...backgroundState, AccountsController: MOCK_ACCOUNTS_CONTROLLER_STATE, }, }, diff --git a/app/components/UI/SearchTokenAutocomplete/index.test.tsx b/app/components/UI/SearchTokenAutocomplete/index.test.tsx index 8ea3e4bd99f..90f39f6d2c2 100644 --- a/app/components/UI/SearchTokenAutocomplete/index.test.tsx +++ b/app/components/UI/SearchTokenAutocomplete/index.test.tsx @@ -1,21 +1,14 @@ import { renderScreen } from '../../../util/test/renderWithProvider'; import SearchTokenAutocomplete from './'; -import initialBackgroundState from '../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../util/test/initial-root-state'; const mockInitialState = { settings: {}, engine: { backgroundState: { - ...initialBackgroundState, + ...backgroundState, PreferencesController: { useTokenDetection: true, - selectedAddress: '0x76cf1CdD1fcC252442b50D6e97207228aA4aefC3', - identities: { - '0x0': { - address: '0x76cf1CdD1fcC252442b50D6e97207228aA4aefC3', - name: 'Account 1', - }, - }, }, }, }, diff --git a/app/components/UI/SimulationDetails/FiatDisplay/FiatDisplay.test.tsx b/app/components/UI/SimulationDetails/FiatDisplay/FiatDisplay.test.tsx index c5c3a1f4a78..4c349bf1dd9 100644 --- a/app/components/UI/SimulationDetails/FiatDisplay/FiatDisplay.test.tsx +++ b/app/components/UI/SimulationDetails/FiatDisplay/FiatDisplay.test.tsx @@ -1,9 +1,10 @@ import React from 'react'; import { merge } from 'lodash'; import renderWithProvider from '../../../../util/test/renderWithProvider'; -import initialBackgroundState from '../../../../util/test/initial-background-state.json'; -import { FIAT_UNAVAILABLE } from '../types'; +import { backgroundState } from '../../../../util/test/initial-root-state'; + import { IndividualFiatDisplay, TotalFiatDisplay } from './FiatDisplay'; +import { FIAT_UNAVAILABLE } from '../types'; import useFiatFormatter from './useFiatFormatter'; import { NETWORKS_CHAIN_ID } from '../../../../constants/network'; @@ -11,7 +12,7 @@ jest.mock('./useFiatFormatter'); const mockInitialState = { engine: { - backgroundState: initialBackgroundState, + backgroundState, }, }; diff --git a/app/components/UI/Tabs/TabThumbnail/TabThumbnail.test.tsx b/app/components/UI/Tabs/TabThumbnail/TabThumbnail.test.tsx index 6d18a67b1c5..8fcf4cf67d3 100644 --- a/app/components/UI/Tabs/TabThumbnail/TabThumbnail.test.tsx +++ b/app/components/UI/Tabs/TabThumbnail/TabThumbnail.test.tsx @@ -1,6 +1,6 @@ import React from 'react'; import renderWithProvider from '../../../../util/test/renderWithProvider'; -import initialBackgroundState from '../../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../../util/test/initial-root-state'; import TabThumbnail from './TabThumbnail'; import { MOCK_ACCOUNTS_CONTROLLER_STATE } from '../../../../util/test/accountsControllerTestUtils'; @@ -10,7 +10,7 @@ const mockInitialState = { }, engine: { backgroundState: { - ...initialBackgroundState, + ...backgroundState, AccountsController: MOCK_ACCOUNTS_CONTROLLER_STATE, }, }, diff --git a/app/components/UI/Tabs/index.test.tsx b/app/components/UI/Tabs/index.test.tsx index c2360474440..60bf5b6bade 100644 --- a/app/components/UI/Tabs/index.test.tsx +++ b/app/components/UI/Tabs/index.test.tsx @@ -1,7 +1,7 @@ import React from 'react'; import renderWithProvider from '../../../util/test/renderWithProvider'; import Tabs from './'; -import initialBackgroundState from '../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../util/test/initial-root-state'; import { MOCK_ACCOUNTS_CONTROLLER_STATE } from '../../../util/test/accountsControllerTestUtils'; const mockInitialState = { @@ -10,7 +10,7 @@ const mockInitialState = { }, engine: { backgroundState: { - ...initialBackgroundState, + ...backgroundState, AccountsController: MOCK_ACCOUNTS_CONTROLLER_STATE, }, }, diff --git a/app/components/UI/TokenImage/index.test.tsx b/app/components/UI/TokenImage/index.test.tsx index 685ccafa16a..1a881dcfb0b 100644 --- a/app/components/UI/TokenImage/index.test.tsx +++ b/app/components/UI/TokenImage/index.test.tsx @@ -3,12 +3,12 @@ import { shallow } from 'enzyme'; import TokenImage from './'; import configureMockStore from 'redux-mock-store'; import { Provider } from 'react-redux'; -import initialBackgroundState from '../../../util/test/initial-background-state.json'; +import { backgroundState } from '../../../util/test/initial-root-state'; const mockStore = configureMockStore(); const initialState = { engine: { - backgroundState: initialBackgroundState, + backgroundState, }, settings: { primaryCurrency: 'usd', diff --git a/app/components/UI/Tokens/__snapshots__/index.test.tsx.snap b/app/components/UI/Tokens/__snapshots__/index.test.tsx.snap index 4aaccc2fc58..5e8f8125c9b 100644 --- a/app/components/UI/Tokens/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/Tokens/__snapshots__/index.test.tsx.snap @@ -327,19 +327,22 @@ exports[`Tokens should hide zero balance tokens when setting is on 1`] = ` } } > - + - 0 USD - + testID="total-balance-text" + > + 0 USD + + +