From b6667ce8b1596e267b3ac677c4942d4d13e8ec71 Mon Sep 17 00:00:00 2001 From: metamaskbot Date: Fri, 16 Feb 2024 19:41:08 +0000 Subject: [PATCH 01/11] 7.17.0 --- android/app/build.gradle | 4 ++-- bitrise.yml | 8 ++++---- ios/MetaMask.xcodeproj/project.pbxproj | 24 ++++++++++++------------ package.json | 2 +- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index a577d526d8d..070ed973be6 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 1245 - versionName "7.15.0" + versionCode 1266 + versionName "7.17.0" testBuildType System.getProperty('testBuildType', 'debug') missingDimensionStrategy 'react-native-camera', 'general' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/bitrise.yml b/bitrise.yml index 571ed4bad44..42b2cb838f2 100644 --- a/bitrise.yml +++ b/bitrise.yml @@ -1238,16 +1238,16 @@ app: PROJECT_LOCATION_IOS: ios - opts: is_expand: false - VERSION_NAME: 7.15.0 + VERSION_NAME: 7.17.0 - opts: is_expand: false - VERSION_NUMBER: 1245 + VERSION_NUMBER: 1266 - opts: is_expand: false - FLASK_VERSION_NAME: 7.15.0 + FLASK_VERSION_NAME: 7.17.0 - opts: is_expand: false - FLASK_VERSION_NUMBER: 1243 + FLASK_VERSION_NUMBER: 1266 - opts: is_expand: false ANDROID_APK_LINK: '' diff --git a/ios/MetaMask.xcodeproj/project.pbxproj b/ios/MetaMask.xcodeproj/project.pbxproj index 4dcbea8c513..bb75711f5f9 100644 --- a/ios/MetaMask.xcodeproj/project.pbxproj +++ b/ios/MetaMask.xcodeproj/project.pbxproj @@ -1341,7 +1341,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1245; + CURRENT_PROJECT_VERSION = 1266; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -1377,7 +1377,7 @@ "${inherited}", ); LLVM_LTO = YES; - MARKETING_VERSION = 7.15.0; + MARKETING_VERSION = 7.17.0; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = "$(inherited)"; OTHER_LDFLAGS = ( @@ -1405,7 +1405,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1245; + CURRENT_PROJECT_VERSION = 1266; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 48XVW22RCG; @@ -1442,7 +1442,7 @@ "${inherited}", ); LLVM_LTO = YES; - MARKETING_VERSION = 7.15.0; + MARKETING_VERSION = 7.17.0; ONLY_ACTIVE_ARCH = NO; OTHER_CFLAGS = "$(inherited)"; OTHER_LDFLAGS = ( @@ -1470,7 +1470,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1245; + CURRENT_PROJECT_VERSION = 1266; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -1503,7 +1503,7 @@ ); LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift$(inherited)"; LLVM_LTO = YES; - MARKETING_VERSION = 7.15.0; + MARKETING_VERSION = 7.17.0; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = "$(inherited)"; OTHER_LDFLAGS = ( @@ -1531,7 +1531,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1245; + CURRENT_PROJECT_VERSION = 1266; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 48XVW22RCG; @@ -1565,7 +1565,7 @@ ); LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift$(inherited)"; LLVM_LTO = YES; - MARKETING_VERSION = 7.15.0; + MARKETING_VERSION = 7.17.0; ONLY_ACTIVE_ARCH = NO; OTHER_CFLAGS = "$(inherited)"; OTHER_LDFLAGS = ( @@ -1692,7 +1692,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1245; + CURRENT_PROJECT_VERSION = 1266; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -1729,7 +1729,7 @@ "\"$(SRCROOT)/MetaMask/System/Library/Frameworks\"", ); LLVM_LTO = YES; - MARKETING_VERSION = 7.15.0; + MARKETING_VERSION = 7.17.0; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ( "$(inherited)", @@ -1760,7 +1760,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1245; + CURRENT_PROJECT_VERSION = 1266; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 48XVW22RCG; @@ -1798,7 +1798,7 @@ "\"$(SRCROOT)/MetaMask/System/Library/Frameworks\"", ); LLVM_LTO = YES; - MARKETING_VERSION = 7.15.0; + MARKETING_VERSION = 7.17.0; ONLY_ACTIVE_ARCH = NO; OTHER_CFLAGS = ( "$(inherited)", diff --git a/package.json b/package.json index de85eb1f742..433fb4f5a0d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "metamask", - "version": "7.15.0", + "version": "7.17.0", "private": true, "scripts": { "audit:ci": "./scripts/yarn-audit.sh", From 28bf9fc4754ff2b669dc894702c4dff7b8256096 Mon Sep 17 00:00:00 2001 From: sethkfman <10342624+sethkfman@users.noreply.github.com> Date: Fri, 16 Feb 2024 15:54:17 -0700 Subject: [PATCH 02/11] chore: merge 7.16.0 into 7.17.0 (#8613) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** This PR merges 7.16.0 into 7.17.0 the major conflict that occurred was in the migration files. The PR creates a migration file 29 that applies the changes which were in `main`. - Migration 28 address bug #8578 - Migration 29 represent the work done here #7999 ## **Related issues** Fixes: ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** ### **Before** ### **After** ## **Pre-merge author checklist** - [ ] I’ve followed [MetaMask Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've clearly explained what problem this PR is solving and how it is solved. - [ ] I've linked related issues - [ ] I've included manual testing steps - [ ] I've included screenshots/recordings if applicable - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. - [ ] I’ve properly set the pull request status: - [ ] In case it's not yet "ready for review", I've set it to "draft". - [ ] In case it's "ready for review", I've changed it from "draft" to "non-draft". ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- CHANGELOG.md | 156 +++-- README.md | 4 - app/store/migrations/028.test.js | 117 ++++ app/store/migrations/028.ts | 588 ++++-------------- .../migrations/{028.test.ts => 029.test.ts} | 28 +- app/store/migrations/029.ts | 488 +++++++++++++++ app/store/migrations/index.ts | 4 +- app/util/general/index.js | 44 ++ app/util/general/index.test.ts | 70 +++ 9 files changed, 955 insertions(+), 544 deletions(-) create mode 100644 app/store/migrations/028.test.js rename app/store/migrations/{028.test.ts => 029.test.ts} (91%) create mode 100644 app/store/migrations/029.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 7330d80d5a9..ef14400beab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,73 +1,99 @@ # Changelog -## 7.14.0 - Jan 11, 2024 +## Current Main Branch + +## 7.16.0 - Jan 29, 2024 ### Added -- [#8016](https://github.com/MetaMask/metamask-mobile/pull/8016): feat(ramp): add sell deeplink -- [#7962](https://github.com/MetaMask/metamask-mobile/pull/7962): feat(ramp): add sell notification texts -- [#8047](https://github.com/MetaMask/metamask-mobile/pull/8047): feat: Added RadioButton to DS -- [#7951](https://github.com/MetaMask/metamask-mobile/pull/7951): feat: New Crowdin translations by Github Action -- [#7954](https://github.com/MetaMask/metamask-mobile/pull/7954): feat: minor changes to connect QR wallet view -- [#7963](https://github.com/MetaMask/metamask-mobile/pull/7963): feat(ramp): add sell order polling when has txhash -- [#7899](https://github.com/MetaMask/metamask-mobile/pull/7899): feat(ramp): popular region and search states -- [#7955](https://github.com/MetaMask/metamask-mobile/pull/7955): feat: RNTar native modules (Android and iOS) -- [#7960](https://github.com/MetaMask/metamask-mobile/pull/7960): feat: Content update for Swaps -- [#7899](https://github.com/MetaMask/metamask-mobile/pull/7899): feat(ramp): popular region and search states -- [#7955](https://github.com/MetaMask/metamask-mobile/pull/7955): feat: RNTar native modules (Android and iOS) -- [#7960](https://github.com/MetaMask/metamask-mobile/pull/7960): feat: Content update for Swaps -- [#7961](https://github.com/MetaMask/metamask-mobile/pull/7961): feat: Create Select's foundational component - SelectValue -- [#7835](https://github.com/MetaMask/metamask-mobile/pull/7835): feat: add bridge wallet action -- [#7921](https://github.com/MetaMask/metamask-mobile/pull/7921): feat: android sdk connectsign + batch request -- [#7933](https://github.com/MetaMask/metamask-mobile/pull/7933): feat: Added images to component Readmes -- [#7607](https://github.com/MetaMask/metamask-mobile/pull/7607): feat: New Crowdin translations by Github Action -- [#7837](https://github.com/MetaMask/metamask-mobile/pull/7837): feat: New mobile Flask Build Type -- [#7876](https://github.com/MetaMask/metamask-mobile/pull/7876): feat: display the dapp icon when connecting with sdk -- [#7861](https://github.com/MetaMask/metamask-mobile/pull/7861): feat: enable Blockaid on iOS -- [#7864](https://github.com/MetaMask/metamask-mobile/pull/7864): feat(ramp): sell what's new modal content +- [#8093](https://github.com/MetaMask/metamask-mobile/pull/8093): feat: decouple account selector from qr code connector +- [#8383](https://github.com/MetaMask/metamask-mobile/pull/8383): feat: add translation for privacy toggle +- [#8412](https://github.com/MetaMask/metamask-mobile/pull/8412): feat: Blockaid experimental settings should be visible on all networks +- [#8290](https://github.com/MetaMask/metamask-mobile/pull/8290): feat: update walletconnect se-sdk to 1.7.0 +- [#8349](https://github.com/MetaMask/metamask-mobile/pull/8349): feat(ramp): add order minimum elapsed seconds for polling +- [#8353](https://github.com/MetaMask/metamask-mobile/pull/8353): feat(ramp): skip payment method screen if has already started +- [#8282](https://github.com/MetaMask/metamask-mobile/pull/8282): feat: PPOM - Signature Metric events have the `flagged_as_malicious` and Blockaid info when using a different network than Mainnet +- [#8171](https://github.com/MetaMask/metamask-mobile/pull/8171): feat: Support token detection on linea +- [#8292](https://github.com/MetaMask/metamask-mobile/pull/8292): feat: enable support to Blockaid on custom networks on mobile +- [#8212](https://github.com/MetaMask/metamask-mobile/pull/8212): feat: bump keyring controller to v8.1.0 +- [#8291](https://github.com/MetaMask/metamask-mobile/pull/8291): feat: android sdk connection management +- [#8319](https://github.com/MetaMask/metamask-mobile/pull/8319): feat: decreased UR density +- [#8255](https://github.com/MetaMask/metamask-mobile/pull/8255): feat: Added temp brand tokens to mobile codebase +- [#8030](https://github.com/MetaMask/metamask-mobile/pull/8030): feat: New Crowdin translations by Github Action - ### Changed -- [#7908](https://github.com/MetaMask/metamask-mobile/pull/7908): chore: tranfer the DeeplinkManager file from JS to TS -- [#7972](https://github.com/MetaMask/metamask-mobile/pull/7972): chore: Replace local code fence transform with `@metamask/build-utils` -- [#7925](https://github.com/MetaMask/metamask-mobile/pull/7925): chore: refactor the DeeplinkManager into smaller parts and add unit tests -- [#8011](https://github.com/MetaMask/metamask-mobile/pull/8011): test: batch 1 remove strings testid app code -- [#7888](https://github.com/MetaMask/metamask-mobile/pull/7888): test: Settings Security And Privacy: Refactor page objects -- [#7989](https://github.com/MetaMask/metamask-mobile/pull/7989): test: Removing test selector strings within app code (5/7) -- [#7978](https://github.com/MetaMask/metamask-mobile/pull/7978): test: Removing test selector strings within app code 2/7 -- [#7992](https://github.com/MetaMask/metamask-mobile/pull/7992): test: Removing test selector strings within app code (6/7) -- [#7993](https://github.com/MetaMask/metamask-mobile/pull/7993): test: Removing test selector strings within app code (7/7) -- [#7873](https://github.com/MetaMask/metamask-mobile/pull/7873): refactor: split migrations into multiple files -- [#7710](https://github.com/MetaMask/metamask-mobile/pull/7710): test: flag Confirmations tests as Smoke tests -- [#7472](https://github.com/MetaMask/metamask-mobile/pull/7472): refactor: Convert Tag stories to csf format -- [#7967](https://github.com/MetaMask/metamask-mobile/pull/7967): test: Removing test selector strings within app code -- [#7966](https://github.com/MetaMask/metamask-mobile/pull/7966): test: fix wallet test -- [#7937](https://github.com/MetaMask/metamask-mobile/pull/7937): chore: Updating CODEOWNERS file with DS ownership of component-library -- [#7952](https://github.com/MetaMask/metamask-mobile/pull/7952): chore: add bridge translations -- [#7922](https://github.com/MetaMask/metamask-mobile/pull/7922): chore(patch): Use core branch for assets-controllers patch -- [#7929](https://github.com/MetaMask/metamask-mobile/pull/7929): test: Increase E2E test setup time -- [#7904](https://github.com/MetaMask/metamask-mobile/pull/7904): test: Fix permission-system-revoking-multiple-accounts test -- [#7689](https://github.com/MetaMask/metamask-mobile/pull/7689): refactor: generate nonces using nonce tracker -- [#7896](https://github.com/MetaMask/metamask-mobile/pull/7896): test: Remove duplicate methods on Gesture class +### Changed +- [#8452](https://github.com/MetaMask/metamask-mobile/pull/8452): refactor: Replace SheetBottom with BottomSheet in WalletActions +- [#8451](https://github.com/MetaMask/metamask-mobile/pull/8451): refactor: Replace SheetBottom with BottomSheet in ShowIpfsGatewaySheet +- [#8450](https://github.com/MetaMask/metamask-mobile/pull/8450): refactor: Replace SheetBottom with BottomSheet in ShowDisplayNFTMediaSheet +- [#8445](https://github.com/MetaMask/metamask-mobile/pull/8445): refactor: Replace SheetBottom with BottomSheet in SDKFeedbackModal +- [#8444](https://github.com/MetaMask/metamask-mobile/pull/8444): refactor: Replace SheetBottom with BottomSheet in NetworkSelector +- [#8447](https://github.com/MetaMask/metamask-mobile/pull/8447): refactor: Replace SheetBottom with BottomSheet in ethsignfriction +- [#8443](https://github.com/MetaMask/metamask-mobile/pull/8443): refactor: Replace SheetBottom with BottomSheet in DetectedTokens +- [#8448](https://github.com/MetaMask/metamask-mobile/pull/8448): refactor: Replace SheetBottom with BottomSheet in AmbiguousAddressSheet +- [#8442](https://github.com/MetaMask/metamask-mobile/pull/8442): refactor: Replace SheetBottom with BottomSheet in AccountSelector +- [#8441](https://github.com/MetaMask/metamask-mobile/pull/8441): refactor: Replace SheetBottom with BottomSheet in AccountsPermission +- [#8440](https://github.com/MetaMask/metamask-mobile/pull/8440): refactor: Replace SheetBottom with BottomSheet in AccountConnect +- [#8439](https://github.com/MetaMask/metamask-mobile/pull/8439): chore: Replace SheetBottom with BottomSheet in AccountActions +- [#8446](https://github.com/MetaMask/metamask-mobile/pull/8446): refactor: Replace SheetBottom with BottomSheet in SDKLoadingModal +- [#8449](https://github.com/MetaMask/metamask-mobile/pull/8449): refactor: Replace SheetBottom with BottomSheet in BlockaidIndicator +- [#8437](https://github.com/MetaMask/metamask-mobile/pull/8437): refactor: QOL update for BottomSheet and BottomSheetDialog +- [#8037](https://github.com/MetaMask/metamask-mobile/pull/8037): refactor: Replace Settings drawer with DS components and update design +- [#8438](https://github.com/MetaMask/metamask-mobile/pull/8438): refactor: Remove isFlexible prop from BottomSheet +- [#8362](https://github.com/MetaMask/metamask-mobile/pull/8362): chore: updated all debug targets to automatically manage signing +- [#8283](https://github.com/MetaMask/metamask-mobile/pull/8283): chore: New Crowdin translations by Github Action +- [#8416](https://github.com/MetaMask/metamask-mobile/pull/8416): refactor(ramp): remove buy and sell folders +- [#8399](https://github.com/MetaMask/metamask-mobile/pull/8399): chore: Remove unused static colors +- [#8386](https://github.com/MetaMask/metamask-mobile/pull/8386): chore: add `.git-blame-ignore-revs` +- [#8289](https://github.com/MetaMask/metamask-mobile/pull/8289): chore: Replace favorite icon in NFT with DS icon +- [#8330](https://github.com/MetaMask/metamask-mobile/pull/8330): chore: Replace hex colors in constants file with tokens +- [#8333](https://github.com/MetaMask/metamask-mobile/pull/8333): chore: Replace hex colors in switch-related components with ds brand tokens +- [#8335](https://github.com/MetaMask/metamask-mobile/pull/8335): chore: Update qr-related components to use brand color white +- [#8287](https://github.com/MetaMask/metamask-mobile/pull/8287): chore: Update Network Settings Actionable Buttons to use DS buttons +- [#8334](https://github.com/MetaMask/metamask-mobile/pull/8334): chore: Replace hex colors in Android Media Player with ds brand tokens +- [#8305](https://github.com/MetaMask/metamask-mobile/pull/8305): test: [android] run tests on the first emulator in your list +- [#8372](https://github.com/MetaMask/metamask-mobile/pull/8372): ci: Revert "ci: Automate Bitrise E2E smoke in GH checks based on labels (#8325)" +- [#8371](https://github.com/MetaMask/metamask-mobile/pull/8371): test: Revert "test: bump detox to v20.16 (#8304)" +- [#8359](https://github.com/MetaMask/metamask-mobile/pull/8359): refactor(ramp): add null case for payment method in order details +- [#8325](https://github.com/MetaMask/metamask-mobile/pull/8325): ci: Automate Bitrise E2E smoke in GH checks based on labels +- [#8206](https://github.com/MetaMask/metamask-mobile/pull/8206): chore(Sentry): filter out Route Change +- [#8342](https://github.com/MetaMask/metamask-mobile/pull/8342): test: fix Swap test flakiness on Bitrise +- [#8285](https://github.com/MetaMask/metamask-mobile/pull/8285): chore: Replaced ApplePayButton colors with hardcoded hex colors +- [#8288](https://github.com/MetaMask/metamask-mobile/pull/8288): chore: Updated hex color in price chart to use ds tokens +- [#8284](https://github.com/MetaMask/metamask-mobile/pull/8284): chore: Replaced hex color for ledger loader +- [#8254](https://github.com/MetaMask/metamask-mobile/pull/8254): test: Fix Swap Smoke tests failures +- [#7640](https://github.com/MetaMask/metamask-mobile/pull/7640): chore(devDeps): upgrade from metro 0.71 to 0.73 +- [#8304](https://github.com/MetaMask/metamask-mobile/pull/8304): test: bump detox to v20.16 +- [#8192](https://github.com/MetaMask/metamask-mobile/pull/8192): refactor(ramp): skip adding order if already exists +- [#8272](https://github.com/MetaMask/metamask-mobile/pull/8272): chore: adds snapController selector and initial state + +### Fixed +- [#8460](https://github.com/MetaMask/metamask-mobile/pull/8460): fix: typos in en.json +- [#8453](https://github.com/MetaMask/metamask-mobile/pull/8453): fix: show only blockaid multichain on whats new +- [#8421](https://github.com/MetaMask/metamask-mobile/pull/8421): fix: patch handling of missing token price +- [#8415](https://github.com/MetaMask/metamask-mobile/pull/8415): fix: catch unfulfilled promise for token fetch +- [#8410](https://github.com/MetaMask/metamask-mobile/pull/8410): fix: Broken confirm flow due to missing gas +- [#8404](https://github.com/MetaMask/metamask-mobile/pull/8404): fix: you have to press the login button twice (#6633) (#6663) +- [#8375](https://github.com/MetaMask/metamask-mobile/pull/8375): fix: Minimize skipping tests +- [#8401](https://github.com/MetaMask/metamask-mobile/pull/8401): fix: Dedupe deps with Yarn and update CocoaPods lockfile +- [#8326](https://github.com/MetaMask/metamask-mobile/pull/8326): fix: PPOM - Malicious transactions triggered from Deeplinks are not flagged +- [#8393](https://github.com/MetaMask/metamask-mobile/pull/8393): fix: [Blockaid] Toggle appears together on "before you proceed" sheet +- [#8394](https://github.com/MetaMask/metamask-mobile/pull/8394): fix: [Blockaid] Cosmetic issue on "before you proceed" sheet +- [#8384](https://github.com/MetaMask/metamask-mobile/pull/8384): fix: bump restore cache step in Bitrise +- [#8374](https://github.com/MetaMask/metamask-mobile/pull/8374): fix: Compare checksum address +- [#8033](https://github.com/MetaMask/metamask-mobile/pull/8033): fix: regenerator-runtime and reenable SES (v1.1.0) on iOS (JSC) +- [#8341](https://github.com/MetaMask/metamask-mobile/pull/8341): fix: E2E: Import SNX token +- [#8328](https://github.com/MetaMask/metamask-mobile/pull/8328): fix: Transaction Details view shows inaccurate balance on Mobile +- [#8274](https://github.com/MetaMask/metamask-mobile/pull/8274): fix: substr undefined when cancelling a legacy transaction +- [#8306](https://github.com/MetaMask/metamask-mobile/pull/8306): fix: cocoapod cache issue +- [#8202](https://github.com/MetaMask/metamask-mobile/pull/8202): fix: Isolate logic to expose js env variables sooner +- [#8216](https://github.com/MetaMask/metamask-mobile/pull/8216): fix: use correct link for reporting false positives in blockaid banner +- [#8329](https://github.com/MetaMask/metamask-mobile/pull/8329): fix: android unit tests +- [#7530](https://github.com/MetaMask/metamask-mobile/pull/7530): fix: fix require misname of @metamask/react-native-button +- [#7793](https://github.com/MetaMask/metamask-mobile/pull/7793): fix: cherry pick PR improvement +- [#8303](https://github.com/MetaMask/metamask-mobile/pull/8303): fix: fixup regex typo for validChainIdHex +- [#8271](https://github.com/MetaMask/metamask-mobile/pull/8271): fix: migrations not being applied on 7.14.0 +- [#8281](https://github.com/MetaMask/metamask-mobile/pull/8281): fix: state initialisation in PPOMController +- [#8278](https://github.com/MetaMask/metamask-mobile/pull/8278): fix: scanning dapp QR code does not open in-app browser and navigate to dapp #8277 +- [#8247](https://github.com/MetaMask/metamask-mobile/pull/8247): fix: fix inconsistency in the popular tab - ### Fixed -- [#7953](https://github.com/MetaMask/metamask-mobile/pull/7953): fix: correct proptypes array in WebsiteIcon component -- [#7886](https://github.com/MetaMask/metamask-mobile/pull/7886): fix: Fix `eth_signTypedData` signatures containing `0x` -- [#7935](https://github.com/MetaMask/metamask-mobile/pull/7935): fix: bitrise cocoapods issue in bitrise -- [#7934](https://github.com/MetaMask/metamask-mobile/pull/7934): fix: Resolve CocoaPods Version Issue and Ruby Installation Failure for Podfile.lock -- [#7745](https://github.com/MetaMask/metamask-mobile/pull/7745): fix: add a section for stakeholder reviews in issue template -- [#7924](https://github.com/MetaMask/metamask-mobile/pull/7924): fix: Prevent SES errors in iOS dev builds -- [#7917](https://github.com/MetaMask/metamask-mobile/pull/7917): fix: adjust the apiLogoUrl logic to handles cases when icon is an object with uri key -- [#7338](https://github.com/MetaMask/metamask-mobile/pull/7338): fix: update linea goerli explorer url -- [#7893](https://github.com/MetaMask/metamask-mobile/pull/7893): fix: Revert javascript disabled on the webview -- [#7881](https://github.com/MetaMask/metamask-mobile/pull/7881): fix: 7862 invalid address error -- [#7757](https://github.com/MetaMask/metamask-mobile/pull/7757): feat: integrate ledger hardware wallet -- [#8128](https://github.com/MetaMask/metamask-mobile/pull/8128): fix: disable hardware wallet feature and remove dependencies -- [#8046](https://github.com/MetaMask/metamask-mobile/pull/8046): fix: CI flakey unit tests TypeErrors on react-native/jest/setup.js global.performance -- [#8013](https://github.com/MetaMask/metamask-mobile/pull/8013): fix: show loading banner when blockaid toggled -- [#8031](https://github.com/MetaMask/metamask-mobile/pull/8031): fix: PPOMController update to handle storage crash -- [#8004](https://github.com/MetaMask/metamask-mobile/pull/8004): fix: mobile blockaid performance issues -- [#7822](https://github.com/MetaMask/metamask-mobile/pull/7822): fix: PPOM - Metrics information from ppom is not logged -- [#8012](https://github.com/MetaMask/metamask-mobile/pull/8012): fix: Rename old code fences -- [#7971](https://github.com/MetaMask/metamask-mobile/pull/7971): fix: Updated ButtonLink to use text when size is auto -- [#7976](https://github.com/MetaMask/metamask-mobile/pull/7976): fix: blockaid mobile performance improvements ## 7.15.0 - Jan 11, 2024 ### Added diff --git a/README.md b/README.md index 58759702118..1fa7ef5e00a 100644 --- a/README.md +++ b/README.md @@ -27,22 +27,18 @@ The code is built using React-Native and running code locally requires a Mac or - Install [Yarn v1](https://yarnpkg.com/en/docs/install) One way to install Yarn v1 is by using brew: - ```bash brew install yarn@1.22.19 ``` To check you've installed the right version: - ```bash yarn --version ``` - Install the shared [React Native dependencies](https://reactnative.dev/docs/environment-setup#installing-dependencies) (`React Native CLI`, _not_ `Expo CLI`) - - Install [cocoapods](https://guides.cocoapods.org/using/getting-started.html) by running: - ```bash sudo gem install cocoapods -v 1.12.1 ``` diff --git a/app/store/migrations/028.test.js b/app/store/migrations/028.test.js new file mode 100644 index 00000000000..df254f44385 --- /dev/null +++ b/app/store/migrations/028.test.js @@ -0,0 +1,117 @@ +import migrate, { controllerList } from './028'; + +jest.mock('@metamask/utils', () => ({ + hasProperty: jest.fn(), + isObject: jest.fn(), +})); + +jest.mock('@sentry/react-native', () => ({ + captureException: jest.fn(), +})); + +jest.mock('../../util/general', () => ({ + deepJSONParse: jest.fn(), +})); + +jest.mock('redux-persist-filesystem-storage', () => ({ + setItem: jest.fn(), + getItem: jest.fn(), + removeItem: jest.fn(), + getAllKeys: jest.fn(), + clear: jest.fn(), +})); + +describe('Migration #28', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + jest.mock('@sentry/react-native', () => ({ + captureException: jest.fn(), + })); + + it('should return state unchanged if it is not an object', async () => { + const state = 'invalid_state'; + const result = await migrate(state); + + expect(result).toEqual(state); + expect( + require('@sentry/react-native').captureException, + ).toHaveBeenCalledWith(expect.any(Error)); + expect( + require('@sentry/react-native').captureException, + ).toHaveBeenCalledTimes(1); + expect(require('@metamask/utils').isObject).toHaveBeenCalledTimes(1); + }); + + it('should return state unchanged if engine already exists in state', async () => { + const state = { engine: {} }; + const result = await migrate(state); + + expect(result).toEqual(state); + expect( + require('redux-persist-filesystem-storage').getItem, + ).not.toHaveBeenCalled(); + expect(require('@metamask/utils').isObject).toHaveBeenCalledTimes(1); + }); + + it('should properly migrate state', async () => { + const persistedData = { someData: 'example' }; + const getItemMock = jest + .fn() + .mockResolvedValue(JSON.stringify(persistedData)); + const setItemMock = jest.fn().mockResolvedValue(undefined); + const removeItemMock = jest.fn().mockResolvedValue(undefined); + const deepJSONParseMock = jest.fn().mockReturnValue(persistedData); + const hasPropertyMock = jest.fn().mockReturnValue(false); + + require('@metamask/utils').isObject.mockReturnValue(true); + require('../../util/general').deepJSONParse = deepJSONParseMock; + require('redux-persist-filesystem-storage').getItem = getItemMock; + require('redux-persist-filesystem-storage').setItem = setItemMock; + require('redux-persist-filesystem-storage').removeItem = removeItemMock; + require('@metamask/utils').hasProperty = hasPropertyMock; + + const state = {}; + const result = await migrate(state); + // eslint-disable-next-line + const mockValue = `{\"engine\":{\"backgroundState\":{\"AccountTrackerController\":{\"someData\":\"example\"},\"AddressBookController\":{\"someData\":\"example\"},\"AssetsContractController\":{\"someData\":\"example\"},\"NftController\":{\"someData\":\"example\"},\"TokensController\":{\"someData\":\"example\"},\"TokenDetectionController\":{\"someData\":\"example\"},\"NftDetectionController\":{\"someData\":\"example\"},\"KeyringController\":{\"someData\":\"example\"},\"NetworkController\":{\"someData\":\"example\"},\"PhishingController\":{\"someData\":\"example\"},\"PreferencesController\":{\"someData\":\"example\"},\"TokenBalancesController\":{\"someData\":\"example\"},\"TokenRatesController\":{\"someData\":\"example\"},\"TransactionController\":{\"someData\":\"example\"},\"SwapsController\":{\"someData\":\"example\"},\"TokenListController\":{\"someData\":\"example\"},\"CurrencyRateController\":{\"someData\":\"example\"},\"GasFeeController\":{\"someData\":\"example\"},\"ApprovalController\":{\"someData\":\"example\"},\"SnapController\":{\"someData\":\"example\"},\"subjectMetadataController\":{\"someData\":\"example\"},\"PermissionController\":{\"someData\":\"example\"},\"LoggingController\":{\"someData\":\"example\"},\"PPOMController\":{\"someData\":\"example\"}}}}`; + + const mockEngine = { + AccountTrackerController: { someData: 'example' }, + AddressBookController: { someData: 'example' }, + AssetsContractController: { someData: 'example' }, + NftController: { someData: 'example' }, + TokensController: { someData: 'example' }, + TokenDetectionController: { someData: 'example' }, + NftDetectionController: { someData: 'example' }, + KeyringController: { someData: 'example' }, + NetworkController: { someData: 'example' }, + PhishingController: { someData: 'example' }, + PreferencesController: { someData: 'example' }, + TokenBalancesController: { someData: 'example' }, + TokenRatesController: { someData: 'example' }, + TransactionController: { someData: 'example' }, + SwapsController: { someData: 'example' }, + TokenListController: { someData: 'example' }, + CurrencyRateController: { someData: 'example' }, + GasFeeController: { someData: 'example' }, + ApprovalController: { someData: 'example' }, + SnapController: { someData: 'example' }, + subjectMetadataController: { someData: 'example' }, + PermissionController: { someData: 'example' }, + LoggingController: { someData: 'example' }, + PPOMController: { someData: 'example' }, + }; + + expect(deepJSONParseMock).toHaveBeenCalledTimes(controllerList.length); + expect(hasPropertyMock).toHaveBeenCalledTimes(controllerList.length); + expect(getItemMock).toHaveBeenCalledTimes(controllerList.length); + expect(setItemMock).toHaveBeenCalledWith('persist:root', mockValue, true); + expect(removeItemMock).toHaveBeenCalledTimes(controllerList.length); + expect(result).toEqual({ engine: { backgroundState: mockEngine } }); + expect( + require('@sentry/react-native').captureException, + ).not.toHaveBeenCalled(); + }); +}); diff --git a/app/store/migrations/028.ts b/app/store/migrations/028.ts index 6f68e7b2bd0..98f008a3049 100644 --- a/app/store/migrations/028.ts +++ b/app/store/migrations/028.ts @@ -1,486 +1,154 @@ -import { toHex } from '@metamask/controller-utils'; -import { Hex, hasProperty, isObject } from '@metamask/utils'; -import { regex } from '../../../app/util/regex'; - -//@ts-expect-error - This error is expected, but ethereumjs-util exports this function -import { isHexString } from 'ethereumjs-util'; -import { NetworkState } from '@metamask/network-controller'; -import { Transaction } from '@metamask/transaction-controller'; +import { hasProperty, isObject } from '@metamask/utils'; import { captureException } from '@sentry/react-native'; -import { - AddressBookEntry, - AddressBookState, -} from '@metamask/address-book-controller'; -import { Nft, NftContract, NftState } from '@metamask/assets-controllers'; +import { deepJSONParse } from '../../util/general'; +import FilesystemStorage from 'redux-persist-filesystem-storage'; +import Device from '../../util/device'; + +export const controllerList = [ + { name: 'AccountTrackerController' }, + { name: 'AddressBookController' }, + { name: 'AssetsContractController' }, + { name: 'NftController' }, + { name: 'TokensController' }, + { name: 'TokenDetectionController' }, + { name: 'NftDetectionController' }, + { + name: 'KeyringController', + }, + { name: 'AccountTrackerController' }, + { + name: 'NetworkController', + }, + { name: 'PhishingController' }, + { name: 'PreferencesController' }, + { name: 'TokenBalancesController' }, + { name: 'TokenRatesController' }, + { name: 'TransactionController' }, + { name: 'SwapsController' }, + { + name: 'TokenListController', + }, + { + name: 'CurrencyRateController', + }, + { + name: 'GasFeeController', + }, + { + name: 'ApprovalController', + }, + { + name: 'SnapController', + }, + { + name: 'subjectMetadataController', + }, + { + name: 'PermissionController', + }, + { + name: 'LoggingController', + }, + { + name: 'PPOMController', + }, +]; /** - * Converting chain id on decimal format to hexadecimal format - * Replacing rpcTarget property for the rpcUrl new property on providerConfig - * Converting keys of networkOnboardedState for hexadecimal for not repeat showing the new network modal - * Addressing networkDetails property change - * Addressing networkConfigurations chainId property change to ehxadecimal - * Swaps on the state initial state key chain id changed for hexadecimal - * Address book controller chain id identifier changed for hexadecimal - * Swaps controller chain cache property now is on hexadecimal format - * NftController allNfts, allNftsContracts chain Id now is on hexadecimal format - * Transaction Controller transactions object chain id property to hexadecimal - * decided here https://github.com/MetaMask/core/pull/1367 - * @param {any} state - Redux state. - * @returns Migrated Redux state. + * Migrate back to use the old root architecture (Single root object) + * + * @param {unknown} state - Redux state + * @returns */ -export default function migrate(state: unknown) { - // Chaning chain id to hexadecimal chain Id on the networks already on the local state +export default async function migrate(state: unknown) { if (!isObject(state)) { - captureException( - new Error(`Migration 28: Invalid state: '${typeof state}'`), - ); - return state; - } - - if (!isObject(state.engine)) { - captureException( - new Error(`Migration 28: Invalid engine state: '${typeof state.engine}'`), - ); - return state; - } - - if (!isObject(state.engine.backgroundState)) { - captureException( - new Error( - `Migration 28: Invalid engine backgroundState: '${typeof state.engine - .backgroundState}'`, - ), - ); - return state; - } - - const networkControllerState = state.engine.backgroundState.NetworkController; - const newNetworkControllerState = state.engine.backgroundState - .NetworkController as NetworkState; - - if (!isObject(networkControllerState)) { captureException( new Error( - `Migration 28: Invalid NetworkController state: '${typeof networkControllerState}'`, + `Migration 28: Invalid root state: root state is not an object`, ), ); return state; } - - if ( - !hasProperty(networkControllerState, 'providerConfig') || - !isObject(networkControllerState.providerConfig) - ) { - captureException( - new Error( - `Migration 28: Invalid NetworkController providerConfig: '${typeof networkControllerState.providerConfig}'`, - ), - ); - return state; - } - - if (!networkControllerState.providerConfig.chainId) { - captureException( - new Error( - `Migration 28: Invalid NetworkController providerConfig chainId: '${JSON.stringify( - networkControllerState.providerConfig.chainId, - )}'`, - ), - ); - return state; - } - - if (networkControllerState.providerConfig.chainId) { - const networkControllerChainId = networkControllerState.providerConfig - .chainId as string; - - networkControllerState.providerConfig.chainId = toHex( - networkControllerChainId, - ); - } - - // Changing rcpTarget property for the new rpcUrl - if (networkControllerState.providerConfig.rpcTarget) { - const networkControllerRpcTarget = - networkControllerState.providerConfig.rpcTarget; - - networkControllerState.providerConfig.rpcUrl = networkControllerRpcTarget; - - delete networkControllerState.providerConfig.rpcTarget; - } - - if ( - !hasProperty(networkControllerState, 'networkDetails') || - !isObject(networkControllerState.networkDetails) - ) { - captureException( - new Error( - `Migration 28: Invalid NetworkController networkDetails: '${JSON.stringify( - networkControllerState.networkDetails, - )}'`, - ), - ); - return state; - } - - if ( - !hasProperty( - networkControllerState.networkDetails, - 'isEIP1559Compatible', - ) || - networkControllerState.networkDetails.isEIP1559Compatible === null || - networkControllerState.networkDetails.isEIP1559Compatible === undefined - ) { - captureException( - new Error( - `Migration 28: Invalid NetworkController networkDetails isEIP1559Compatible: '${JSON.stringify( - networkControllerState.networkDetails.isEIP1559Compatible, - )}'`, - ), - ); - return state; - } - - // Addressing networkDetails property change - const isEIP1559Compatible = - networkControllerState.networkDetails.isEIP1559Compatible; - - if (isEIP1559Compatible) { - networkControllerState.networkDetails = { - EIPS: { - 1559: true, - }, - }; - } else { - networkControllerState.networkDetails = { - EIPS: { - 1559: false, - }, - }; - } - - if (isObject(networkControllerState.networkDetails)) { - delete networkControllerState.networkDetails.isEIP1559Compatible; - } - - if ( - !hasProperty(networkControllerState, 'networkConfigurations') || - !isObject(networkControllerState.networkConfigurations) - ) { - captureException( - new Error( - `Migration 28: Invalid NetworkController networkConfigurations: '${JSON.stringify( - networkControllerState.networkConfigurations, - )}'`, - ), - ); - return state; - } - - // Addressing networkConfigurations chainId property change to hexadecimal - if (networkControllerState.networkConfigurations) { - Object.entries(networkControllerState.networkConfigurations).forEach( - ([key, networkConfiguration]) => { - if (isObject(networkConfiguration) && networkConfiguration.chainId) { - const newHexChainId = toHex(networkConfiguration.chainId as string); - newNetworkControllerState.networkConfigurations[key].chainId = - newHexChainId; - } - }, - ); - } - - // Validating if the networks were already onboarded - // This property can be undefined - if ( - isObject(state.networkOnboarded) && - isObject(state.networkOnboarded.networkOnboardedState) - ) { - const networkOnboardedState = state.networkOnboarded.networkOnboardedState; - const newNetworkOnboardedState: { - [key: string]: (typeof networkOnboardedState)[string]; - } = {}; - - for (const chainId in networkOnboardedState) { - const hexChainId = toHex(chainId); - newNetworkOnboardedState[hexChainId] = networkOnboardedState[chainId]; - } - state.networkOnboarded.networkOnboardedState = newNetworkOnboardedState; - } - - const swapsState = state.swaps; - // Swaps on the state initial state key chain id changed for hexadecimal - // This property can be undefined - if (isObject(swapsState)) { - Object.keys(swapsState).forEach((key) => { - // To match keys that are composed entirely of digits - if (regex.decimalStringMigrations.test(key)) { - const hexadecimalChainId = toHex(key); - state.swaps = { - ...swapsState, - [hexadecimalChainId]: swapsState[key], - }; - if (isObject(state.swaps)) { - delete state.swaps[key]; - } - } - }); - } - - const addressBookControllerState = - state?.engine?.backgroundState?.AddressBookController; - - const newAddressBookControllerState = state?.engine?.backgroundState - ?.AddressBookController as AddressBookState; - - if (!isObject(addressBookControllerState)) { - captureException( - new Error( - `Migration 28: Invalid AddressBookController state: '${JSON.stringify( - addressBookControllerState, - )}'`, - ), - ); + // Engine already exists. No need to migrate. + if (state.engine) { return state; } - if ( - !hasProperty(addressBookControllerState, 'addressBook') || - !isObject(addressBookControllerState.addressBook) - ) { - captureException( - new Error( - `Migration 28: Invalid AddressBookController addressBook: '${JSON.stringify( - addressBookControllerState.addressBook, - )}'`, - ), - ); - return state; - } + const newEngineState = { backgroundState: {} } as Record< + string, + Record + >; + // Populate root object with controller data + const controllerMergeMigration = controllerList.map( + async ({ name: controllerName }) => { + const persistedControllerKey = `persist:${controllerName}`; + try { + // Read from persisted controller file and populate root + const persistedControllerData = await FilesystemStorage.getItem( + persistedControllerKey, + ); - // Address book controller chain id identifier changed for hexadecimal - if (addressBookControllerState.addressBook) { - const addressBook = addressBookControllerState.addressBook; - Object.keys(addressBook).forEach((chainId) => { - if (!isHexString(chainId)) { - const hexChainId = toHex(chainId); - const tempNewAddressBook: { - [hexChainId: Hex]: { [address: string]: AddressBookEntry }; - } = {}; - let newAddress: AddressBookEntry; - if (isObject(addressBook) && typeof chainId === 'string') { - const addressBookChainId = addressBook[chainId]; - if (isObject(addressBookChainId)) { - Object.keys(addressBookChainId).forEach((address) => { - const addressBookChainIdAddress = addressBookChainId[address]; - if (addressBookChainIdAddress) { - newAddress = addressBookChainIdAddress as AddressBookEntry; + if (persistedControllerData) { + const persistedControllerJSON = deepJSONParse({ + jsonString: persistedControllerData, + }); - if (isObject(addressBookChainIdAddress)) { - newAddress.chainId = toHex( - addressBookChainIdAddress.chainId as string, - ); - } - tempNewAddressBook[hexChainId] = { - ...tempNewAddressBook[hexChainId], - [address]: newAddress, - }; - } - }); + if (hasProperty(persistedControllerJSON, '_persist')) { + const { _persist, ...controllerJSON } = persistedControllerJSON; + newEngineState.backgroundState[controllerName] = controllerJSON; + } else { + newEngineState.backgroundState[controllerName] = + persistedControllerJSON; } } - newAddressBookControllerState.addressBook[hexChainId] = - tempNewAddressBook[hexChainId]; - if (isObject(addressBookControllerState.addressBook)) { - delete addressBookControllerState.addressBook[chainId]; - } + } catch (e) { + captureException( + new Error( + `Migration 28: Failed to populate root object with persisted controller data for key ${persistedControllerKey}: ${String( + e, + )}`, + ), + ); } - }); - } - - const swapsControllerState = state?.engine?.backgroundState?.SwapsController; - - if (!isObject(swapsControllerState)) { - captureException( - new Error( - `Migration 28: Invalid SwapsController state: '${JSON.stringify( - swapsControllerState, - )}'`, - ), - ); - return state; - } - - // Swaps controller chain cache property now is on hexadecimal format - if (swapsControllerState.chainCache) { - Object.keys(swapsControllerState.chainCache).forEach((chainId) => { - if (!isHexString(chainId)) { - const hexChainId = toHex(chainId); - if (isObject(swapsControllerState.chainCache)) { - swapsControllerState.chainCache[hexChainId] = - swapsControllerState.chainCache[chainId]; - } - - if ( - isObject(swapsControllerState) && - isObject(swapsControllerState.chainCache) - ) { - delete swapsControllerState.chainCache[chainId]; - } + }, + ); + + // Execute controller merge migration in parallel + await Promise.all(controllerMergeMigration); + + // Set engine on root object + state.engine = newEngineState; + + try { + const rootKey = `persist:root`; + // Manually update the persisted root file + await FilesystemStorage.setItem( + rootKey, + JSON.stringify(state), + Device.isIos(), + ); + // Root file successfully populated with controller data - Can safely delete persisted controller files + const controllerDeleteMigration = controllerList.map(async ({ name }) => { + const persistedControllerKey = `persist:${name}`; + try { + // Remove persisted controller file + await FilesystemStorage.removeItem(persistedControllerKey); + } catch (e) { + captureException( + new Error( + `Migration 28: Failed to remove key ${persistedControllerKey}: ${String( + e, + )}`, + ), + ); } }); - } - - const nftControllerState = state?.engine?.backgroundState?.NftController; - const newNftControllerState = state?.engine?.backgroundState - ?.NftController as NftState; - - if (!isObject(nftControllerState)) { - captureException( - new Error( - `Migration 28: Invalid NftController state: '${JSON.stringify( - nftControllerState, - )}'`, - ), - ); - return state; - } - if ( - !hasProperty(nftControllerState, 'allNftContracts') || - !isObject(nftControllerState.allNftContracts) - ) { + // Execute deleting persisted controller files in parallel + await Promise.all(controllerDeleteMigration); + } catch (e) { captureException( - new Error( - `Migration 28: Invalid nftControllerState allNftsContracts: '${JSON.stringify( - nftControllerState.allNftContracts, - )}'`, - ), - ); - return state; - } - - // NftController allNfts, allNftsContracts chain Id now is on hexadecimal format - if (nftControllerState.allNftContracts) { - Object.keys(nftControllerState.allNftContracts).forEach( - (nftContractsAddress) => { - if (isObject(nftControllerState.allNftContracts)) { - const nftContractAddress = - nftControllerState.allNftContracts[nftContractsAddress]; - - if (isObject(nftContractAddress)) { - Object.keys(nftContractAddress).forEach((chainId) => { - if (!isHexString(chainId)) { - const hexChainId = toHex(chainId); - if (Array.isArray(nftContractAddress[chainId])) { - const nftsChainId = nftContractAddress[ - chainId - ] as NftContract[]; - - newNftControllerState.allNftContracts[nftContractsAddress][ - hexChainId - ] = nftsChainId; - } - - if ( - isObject(nftControllerState.allNftContracts) && - isObject( - nftControllerState.allNftContracts[nftContractsAddress], - ) - ) { - // Need to type cast because typescript is static typed - // and typescript is - delete ( - nftControllerState.allNftContracts[ - nftContractsAddress - ] as Record - )[chainId]; - } - } - }); - } - } - }, - ); - } - - if ( - !hasProperty(nftControllerState, 'allNfts') || - !isObject(nftControllerState.allNfts) - ) { - captureException( - new Error( - `Migration 28: Invalid nftControllerState allNfts: '${JSON.stringify( - nftControllerState.allNfts, - )}'`, - ), - ); - return state; - } - - if (nftControllerState.allNfts) { - const allNfts = nftControllerState.allNfts; - Object.keys(nftControllerState.allNfts).forEach((allNftsByAddress) => { - const nftsByAddress = allNfts[allNftsByAddress]; - if (isObject(nftsByAddress)) { - Object.keys(nftsByAddress).forEach((chainId) => { - if (!isHexString(chainId)) { - const hexChainId = toHex(chainId); - if (Array.isArray(nftsByAddress[chainId])) { - const nftsChainId = nftsByAddress[chainId] as Nft[]; - - newNftControllerState.allNfts[allNftsByAddress][hexChainId] = - nftsChainId; - } - - if ( - isObject(nftControllerState.allNfts) && - isObject(nftControllerState.allNfts[allNftsByAddress]) - ) { - // Need to type cast because typescript is static typed - // and typescript is - delete ( - nftControllerState.allNfts[allNftsByAddress] as Record< - string, - unknown - > - )[chainId]; - } - } - }); - } - }); - } - - const transactionControllerState = - state?.engine?.backgroundState?.TransactionController; - - if (!isObject(transactionControllerState)) { - captureException( - new Error( - `Migration 28: Invalid TransactionController state: '${JSON.stringify( - transactionControllerState, - )}'`, - ), - ); - return state; - } - - // Transaction Controller transactions object chain id property to hexadecimal - if (Array.isArray(transactionControllerState.transactions)) { - transactionControllerState.transactions.forEach( - (transaction: Transaction, index: number) => { - if (transaction && !isHexString(transaction.chainId)) { - if ( - Array.isArray(transactionControllerState.transactions) && - isObject(transactionControllerState.transactions[index]) - ) { - transactionControllerState.transactions[index].chainId = toHex( - transaction.chainId as string, - ); - } - } - }, + new Error(`Migration 28: Failed to get root data: ${String(e)}`), ); } diff --git a/app/store/migrations/028.test.ts b/app/store/migrations/029.test.ts similarity index 91% rename from app/store/migrations/028.test.ts rename to app/store/migrations/029.test.ts index 9003c1960f9..c0b5b0bf6af 100644 --- a/app/store/migrations/028.test.ts +++ b/app/store/migrations/029.test.ts @@ -1,4 +1,4 @@ -import migration from './028'; +import migration from './029'; import { merge } from 'lodash'; import initialRootState from '../../util/test/initial-root-state'; import initialBackgroundState from '../../util/test/initial-background-state.json'; @@ -179,7 +179,7 @@ jest.mock('@sentry/react-native', () => ({ })); const mockedCaptureException = jest.mocked(captureException); -describe('Migration #28', () => { +describe('Migration #29', () => { beforeEach(() => { jest.restoreAllMocks(); jest.resetAllMocks(); @@ -190,7 +190,7 @@ describe('Migration #28', () => { state: merge({}, initialRootState, { engine: null, }), - errorMessage: "Migration 28: Invalid engine state: 'object'", + errorMessage: "Migration 29: Invalid engine state: 'object'", scenario: 'engine state is invalid', }, { @@ -199,7 +199,7 @@ describe('Migration #28', () => { backgroundState: null, }, }), - errorMessage: "Migration 28: Invalid engine backgroundState: 'object'", + errorMessage: "Migration 29: Invalid engine backgroundState: 'object'", scenario: 'backgroundState is invalid', }, { @@ -210,7 +210,7 @@ describe('Migration #28', () => { }, }, }), - errorMessage: "Migration 28: Invalid NetworkController state: 'object'", + errorMessage: "Migration 29: Invalid NetworkController state: 'object'", scenario: 'NetworkController state is invalid', }, { @@ -222,7 +222,7 @@ describe('Migration #28', () => { }, }), errorMessage: - "Migration 28: Invalid NetworkController providerConfig: 'object'", + "Migration 29: Invalid NetworkController providerConfig: 'object'", scenario: 'providerConfig is invalid', }, { @@ -234,7 +234,7 @@ describe('Migration #28', () => { }, }), errorMessage: - "Migration 28: Invalid NetworkController providerConfig chainId: 'null'", + "Migration 29: Invalid NetworkController providerConfig chainId: 'null'", scenario: 'chainId is invalid', }, { @@ -246,7 +246,7 @@ describe('Migration #28', () => { }, }), errorMessage: - "Migration 28: Invalid NetworkController networkDetails: 'null'", + "Migration 29: Invalid NetworkController networkDetails: 'null'", scenario: 'networkDetails is invalid', }, { @@ -263,7 +263,7 @@ describe('Migration #28', () => { }, }), errorMessage: - "Migration 28: Invalid NetworkController networkDetails isEIP1559Compatible: 'undefined'", + "Migration 29: Invalid NetworkController networkDetails isEIP1559Compatible: 'undefined'", scenario: 'networkDetails isEIP1559Compatible is invalid', }, { @@ -281,7 +281,7 @@ describe('Migration #28', () => { }, }), errorMessage: - "Migration 28: Invalid NetworkController networkConfigurations: 'null'", + "Migration 29: Invalid NetworkController networkConfigurations: 'null'", scenario: 'networkConfigurations is invalid', }, { @@ -300,7 +300,7 @@ describe('Migration #28', () => { }, }, }), - errorMessage: "Migration 28: Invalid AddressBookController state: 'null'", + errorMessage: "Migration 29: Invalid AddressBookController state: 'null'", scenario: 'AddressBookController state is invalid', }, { @@ -319,7 +319,7 @@ describe('Migration #28', () => { }, }, }), - errorMessage: "Migration 28: Invalid SwapsController state: 'null'", + errorMessage: "Migration 29: Invalid SwapsController state: 'null'", scenario: 'SwapsController state is invalid', }, { @@ -338,7 +338,7 @@ describe('Migration #28', () => { }, }, }), - errorMessage: "Migration 28: Invalid NftController state: 'null'", + errorMessage: "Migration 29: Invalid NftController state: 'null'", scenario: 'NftController state is invalid', }, { @@ -357,7 +357,7 @@ describe('Migration #28', () => { }, }, }), - errorMessage: "Migration 28: Invalid TransactionController state: 'null'", + errorMessage: "Migration 29: Invalid TransactionController state: 'null'", scenario: 'TransactionController state is invalid', }, ]; diff --git a/app/store/migrations/029.ts b/app/store/migrations/029.ts new file mode 100644 index 00000000000..29d636a283a --- /dev/null +++ b/app/store/migrations/029.ts @@ -0,0 +1,488 @@ +import { toHex } from '@metamask/controller-utils'; +import { Hex, hasProperty, isObject } from '@metamask/utils'; +import { regex } from '../../../app/util/regex'; + +//@ts-expect-error - This error is expected, but ethereumjs-util exports this function +import { isHexString } from 'ethereumjs-util'; +import { NetworkState } from '@metamask/network-controller'; +import { Transaction } from '@metamask/transaction-controller'; +import { captureException } from '@sentry/react-native'; +import { + AddressBookEntry, + AddressBookState, +} from '@metamask/address-book-controller'; +import { Nft, NftContract, NftState } from '@metamask/assets-controllers'; + +/** + * Converting chain id on decimal format to hexadecimal format + * Replacing rpcTarget property for the rpcUrl new property on providerConfig + * Converting keys of networkOnboardedState for hexadecimal for not repeat showing the new network modal + * Addressing networkDetails property change + * Addressing networkConfigurations chainId property change to ehxadecimal + * Swaps on the state initial state key chain id changed for hexadecimal + * Address book controller chain id identifier changed for hexadecimal + * Swaps controller chain cache property now is on hexadecimal format + * NftController allNfts, allNftsContracts chain Id now is on hexadecimal format + * Transaction Controller transactions object chain id property to hexadecimal + * decided here https://github.com/MetaMask/core/pull/1367 + * @param {any} state - Redux state. + * @returns Migrated Redux state. + */ +export default function migrate(state: unknown) { + // Chaning chain id to hexadecimal chain Id on the networks already on the local state + if (!isObject(state)) { + captureException( + new Error(`Migration 29: Invalid state: '${typeof state}'`), + ); + return state; + } + + if (!isObject(state.engine)) { + captureException( + new Error(`Migration 29: Invalid engine state: '${typeof state.engine}'`), + ); + return state; + } + + if (!isObject(state.engine.backgroundState)) { + captureException( + new Error( + `Migration 29: Invalid engine backgroundState: '${typeof state.engine + .backgroundState}'`, + ), + ); + return state; + } + + const networkControllerState = state.engine.backgroundState.NetworkController; + const newNetworkControllerState = state.engine.backgroundState + .NetworkController as NetworkState; + + if (!isObject(networkControllerState)) { + captureException( + new Error( + `Migration 29: Invalid NetworkController state: '${typeof networkControllerState}'`, + ), + ); + return state; + } + + if ( + !hasProperty(networkControllerState, 'providerConfig') || + !isObject(networkControllerState.providerConfig) + ) { + captureException( + new Error( + `Migration 29: Invalid NetworkController providerConfig: '${typeof networkControllerState.providerConfig}'`, + ), + ); + return state; + } + + if (!networkControllerState.providerConfig.chainId) { + captureException( + new Error( + `Migration 29: Invalid NetworkController providerConfig chainId: '${JSON.stringify( + networkControllerState.providerConfig.chainId, + )}'`, + ), + ); + return state; + } + + if (networkControllerState.providerConfig.chainId) { + const networkControllerChainId = networkControllerState.providerConfig + .chainId as string; + + networkControllerState.providerConfig.chainId = toHex( + networkControllerChainId, + ); + } + + // Changing rcpTarget property for the new rpcUrl + if (networkControllerState.providerConfig.rpcTarget) { + const networkControllerRpcTarget = + networkControllerState.providerConfig.rpcTarget; + + networkControllerState.providerConfig.rpcUrl = networkControllerRpcTarget; + + delete networkControllerState.providerConfig.rpcTarget; + } + + if ( + !hasProperty(networkControllerState, 'networkDetails') || + !isObject(networkControllerState.networkDetails) + ) { + captureException( + new Error( + `Migration 29: Invalid NetworkController networkDetails: '${JSON.stringify( + networkControllerState.networkDetails, + )}'`, + ), + ); + return state; + } + + if ( + !hasProperty( + networkControllerState.networkDetails, + 'isEIP1559Compatible', + ) || + networkControllerState.networkDetails.isEIP1559Compatible === null || + networkControllerState.networkDetails.isEIP1559Compatible === undefined + ) { + captureException( + new Error( + `Migration 29: Invalid NetworkController networkDetails isEIP1559Compatible: '${JSON.stringify( + networkControllerState.networkDetails.isEIP1559Compatible, + )}'`, + ), + ); + return state; + } + + // Addressing networkDetails property change + const isEIP1559Compatible = + networkControllerState.networkDetails.isEIP1559Compatible; + + if (isEIP1559Compatible) { + networkControllerState.networkDetails = { + EIPS: { + 1559: true, + }, + }; + } else { + networkControllerState.networkDetails = { + EIPS: { + 1559: false, + }, + }; + } + + if (isObject(networkControllerState.networkDetails)) { + delete networkControllerState.networkDetails.isEIP1559Compatible; + } + + if ( + !hasProperty(networkControllerState, 'networkConfigurations') || + !isObject(networkControllerState.networkConfigurations) + ) { + captureException( + new Error( + `Migration 29: Invalid NetworkController networkConfigurations: '${JSON.stringify( + networkControllerState.networkConfigurations, + )}'`, + ), + ); + return state; + } + + // Addressing networkConfigurations chainId property change to hexadecimal + if (networkControllerState.networkConfigurations) { + Object.entries(networkControllerState.networkConfigurations).forEach( + ([key, networkConfiguration]) => { + if (isObject(networkConfiguration) && networkConfiguration.chainId) { + const newHexChainId = toHex(networkConfiguration.chainId as string); + newNetworkControllerState.networkConfigurations[key].chainId = + newHexChainId; + } + }, + ); + } + + // Validating if the networks were already onboarded + // This property can be undefined + if ( + isObject(state.networkOnboarded) && + isObject(state.networkOnboarded.networkOnboardedState) + ) { + const networkOnboardedState = state.networkOnboarded.networkOnboardedState; + const newNetworkOnboardedState: { + [key: string]: (typeof networkOnboardedState)[string]; + } = {}; + + for (const chainId in networkOnboardedState) { + const hexChainId = toHex(chainId); + newNetworkOnboardedState[hexChainId] = networkOnboardedState[chainId]; + } + state.networkOnboarded.networkOnboardedState = newNetworkOnboardedState; + } + + const swapsState = state.swaps; + // Swaps on the state initial state key chain id changed for hexadecimal + // This property can be undefined + if (isObject(swapsState)) { + Object.keys(swapsState).forEach((key) => { + // To match keys that are composed entirely of digits + if (regex.decimalStringMigrations.test(key)) { + const hexadecimalChainId = toHex(key); + state.swaps = { + ...swapsState, + [hexadecimalChainId]: swapsState[key], + }; + if (isObject(state.swaps)) { + delete state.swaps[key]; + } + } + }); + } + + const addressBookControllerState = + state?.engine?.backgroundState?.AddressBookController; + + const newAddressBookControllerState = state?.engine?.backgroundState + ?.AddressBookController as AddressBookState; + + if (!isObject(addressBookControllerState)) { + captureException( + new Error( + `Migration 29: Invalid AddressBookController state: '${JSON.stringify( + addressBookControllerState, + )}'`, + ), + ); + return state; + } + + if ( + !hasProperty(addressBookControllerState, 'addressBook') || + !isObject(addressBookControllerState.addressBook) + ) { + captureException( + new Error( + `Migration 29: Invalid AddressBookController addressBook: '${JSON.stringify( + addressBookControllerState.addressBook, + )}'`, + ), + ); + return state; + } + + // Address book controller chain id identifier changed for hexadecimal + if (addressBookControllerState.addressBook) { + const addressBook = addressBookControllerState.addressBook; + Object.keys(addressBook).forEach((chainId) => { + if (!isHexString(chainId)) { + const hexChainId = toHex(chainId); + const tempNewAddressBook: { + [hexChainId: Hex]: { [address: string]: AddressBookEntry }; + } = {}; + let newAddress: AddressBookEntry; + if (isObject(addressBook) && typeof chainId === 'string') { + const addressBookChainId = addressBook[chainId]; + if (isObject(addressBookChainId)) { + Object.keys(addressBookChainId).forEach((address) => { + const addressBookChainIdAddress = addressBookChainId[address]; + if (addressBookChainIdAddress) { + newAddress = addressBookChainIdAddress as AddressBookEntry; + + if (isObject(addressBookChainIdAddress)) { + newAddress.chainId = toHex( + addressBookChainIdAddress.chainId as string, + ); + } + tempNewAddressBook[hexChainId] = { + ...tempNewAddressBook[hexChainId], + [address]: newAddress, + }; + } + }); + } + } + newAddressBookControllerState.addressBook[hexChainId] = + tempNewAddressBook[hexChainId]; + if (isObject(addressBookControllerState.addressBook)) { + delete addressBookControllerState.addressBook[chainId]; + } + } + }); + } + + const swapsControllerState = state?.engine?.backgroundState?.SwapsController; + + if (!isObject(swapsControllerState)) { + captureException( + new Error( + `Migration 29: Invalid SwapsController state: '${JSON.stringify( + swapsControllerState, + )}'`, + ), + ); + return state; + } + + // Swaps controller chain cache property now is on hexadecimal format + if (swapsControllerState.chainCache) { + Object.keys(swapsControllerState.chainCache).forEach((chainId) => { + if (!isHexString(chainId)) { + const hexChainId = toHex(chainId); + if (isObject(swapsControllerState.chainCache)) { + swapsControllerState.chainCache[hexChainId] = + swapsControllerState.chainCache[chainId]; + } + + if ( + isObject(swapsControllerState) && + isObject(swapsControllerState.chainCache) + ) { + delete swapsControllerState.chainCache[chainId]; + } + } + }); + } + + const nftControllerState = state?.engine?.backgroundState?.NftController; + const newNftControllerState = state?.engine?.backgroundState + ?.NftController as NftState; + + if (!isObject(nftControllerState)) { + captureException( + new Error( + `Migration 29: Invalid NftController state: '${JSON.stringify( + nftControllerState, + )}'`, + ), + ); + return state; + } + + if ( + !hasProperty(nftControllerState, 'allNftContracts') || + !isObject(nftControllerState.allNftContracts) + ) { + captureException( + new Error( + `Migration 29: Invalid nftControllerState allNftsContracts: '${JSON.stringify( + nftControllerState.allNftContracts, + )}'`, + ), + ); + return state; + } + + // NftController allNfts, allNftsContracts chain Id now is on hexadecimal format + if (nftControllerState.allNftContracts) { + Object.keys(nftControllerState.allNftContracts).forEach( + (nftContractsAddress) => { + if (isObject(nftControllerState.allNftContracts)) { + const nftContractAddress = + nftControllerState.allNftContracts[nftContractsAddress]; + + if (isObject(nftContractAddress)) { + Object.keys(nftContractAddress).forEach((chainId) => { + if (!isHexString(chainId)) { + const hexChainId = toHex(chainId); + if (Array.isArray(nftContractAddress[chainId])) { + const nftsChainId = nftContractAddress[ + chainId + ] as NftContract[]; + + newNftControllerState.allNftContracts[nftContractsAddress][ + hexChainId + ] = nftsChainId; + } + + if ( + isObject(nftControllerState.allNftContracts) && + isObject( + nftControllerState.allNftContracts[nftContractsAddress], + ) + ) { + // Need to type cast because typescript is static typed + // and typescript is + delete ( + nftControllerState.allNftContracts[ + nftContractsAddress + ] as Record + )[chainId]; + } + } + }); + } + } + }, + ); + } + + if ( + !hasProperty(nftControllerState, 'allNfts') || + !isObject(nftControllerState.allNfts) + ) { + captureException( + new Error( + `Migration 29: Invalid nftControllerState allNfts: '${JSON.stringify( + nftControllerState.allNfts, + )}'`, + ), + ); + return state; + } + + if (nftControllerState.allNfts) { + const allNfts = nftControllerState.allNfts; + Object.keys(nftControllerState.allNfts).forEach((allNftsByAddress) => { + const nftsByAddress = allNfts[allNftsByAddress]; + if (isObject(nftsByAddress)) { + Object.keys(nftsByAddress).forEach((chainId) => { + if (!isHexString(chainId)) { + const hexChainId = toHex(chainId); + if (Array.isArray(nftsByAddress[chainId])) { + const nftsChainId = nftsByAddress[chainId] as Nft[]; + + newNftControllerState.allNfts[allNftsByAddress][hexChainId] = + nftsChainId; + } + + if ( + isObject(nftControllerState.allNfts) && + isObject(nftControllerState.allNfts[allNftsByAddress]) + ) { + // Need to type cast because typescript is static typed + // and typescript is + delete ( + nftControllerState.allNfts[allNftsByAddress] as Record< + string, + unknown + > + )[chainId]; + } + } + }); + } + }); + } + + const transactionControllerState = + state?.engine?.backgroundState?.TransactionController; + + if (!isObject(transactionControllerState)) { + captureException( + new Error( + `Migration 29: Invalid TransactionController state: '${JSON.stringify( + transactionControllerState, + )}'`, + ), + ); + return state; + } + + // Transaction Controller transactions object chain id property to hexadecimal + if (Array.isArray(transactionControllerState.transactions)) { + transactionControllerState.transactions.forEach( + (transaction: Transaction, index: number) => { + if (transaction && !isHexString(transaction.chainId)) { + if ( + Array.isArray(transactionControllerState.transactions) && + isObject(transactionControllerState.transactions[index]) + ) { + transactionControllerState.transactions[index].chainId = toHex( + transaction.chainId as string, + ); + } + } + }, + ); + } + + return state; +} diff --git a/app/store/migrations/index.ts b/app/store/migrations/index.ts index d67fdb55d22..9e599fa3e50 100644 --- a/app/store/migrations/index.ts +++ b/app/store/migrations/index.ts @@ -29,6 +29,7 @@ import migration25 from './025'; import migration26 from './026'; import migration27 from './027'; import migration28 from './028'; +import migration29 from './029'; // We do not keep track of the old state // We create this type for better readability @@ -63,7 +64,8 @@ export const migrations: MigrationManifest = { 25: migration25, 26: migration26, 27: migration27, - 28: migration28 as unknown as (state: OldState) => PersistedState, + 28: migration28 as unknown as (state: PersistedState) => PersistedState, + 29: migration29 as unknown as (state: OldState) => PersistedState, }; // The latest (i.e. highest) version number. diff --git a/app/util/general/index.js b/app/util/general/index.js index 7eea47f10d0..577e9dd7bfe 100644 --- a/app/util/general/index.js +++ b/app/util/general/index.js @@ -116,3 +116,47 @@ export const isIPFSUri = (uri) => { ipfsUriRegex.test(uri) ); }; + +/** + * Parse stringified JSON that has deeply nested stringified properties + * + * @deprecated Do not suggest using this for migrations unless you understand what it does. It will deeply JSON parse fields + * @param jsonString - JSON string + * @param skipNumbers - Boolean to skip numbers + * @returns - Parsed JSON object + */ +export const deepJSONParse = ({ jsonString, skipNumbers = true }) => { + // Parse the initial JSON string + const parsedObject = JSON.parse(jsonString); + + // Function to recursively parse stringified properties + function parseProperties(obj) { + Object.keys(obj).forEach((key) => { + if (typeof obj[key] === 'string') { + const isNumber = !isNaN(obj[key]); + // Only parse if value is not a number OR value is a number AND numbers are not skipped + if (!isNumber || (isNumber && !skipNumbers)) { + try { + // Attempt to parse the string as JSON + const parsed = JSON.parse(obj[key]); + obj[key] = parsed; + // If the parsed value is an object, parse its properties too + if (typeof parsed === 'object') { + parseProperties(parsed); + } + } catch (e) { + // If parsing throws, it's not a JSON string, so do nothing + } + } + } else if (typeof obj[key] === 'object') { + // If it's an object, parse its properties + parseProperties(obj[key]); + } + }); + } + + // Start parsing from the root object + parseProperties(parsedObject); + + return parsedObject; +}; diff --git a/app/util/general/index.test.ts b/app/util/general/index.test.ts index e12ed3c9693..9ae670577ca 100644 --- a/app/util/general/index.test.ts +++ b/app/util/general/index.test.ts @@ -5,6 +5,7 @@ import { renderShortText, getURLProtocol, isIPFSUri, + deepJSONParse, } from '.'; describe('capitalize', () => { @@ -120,3 +121,72 @@ describe('isIPFSUri', () => { expect(isIPFSUri(null)).toBe(false); }); }); + +describe('deepJSONParse function', () => { + it('should properly parse a JSON string with nested objects, skipping numbers', () => { + const inputObject = { + name: 'John ETH', + address: { + city: 'New York', + zip: '10001', + fakeBool: 'false', + fakeNum: 2, + fakeUnd: undefined, + }, + }; + const expectedObject = { + ...inputObject, + address: { + ...inputObject.address, + fakeBool: false, + }, + }; + const jsonString = JSON.stringify(inputObject); + expect(deepJSONParse({ jsonString })).toEqual(expectedObject); + }); + + it('should properly parse a JSON string with nested objects, does not skip numbers', () => { + const inputObject = { + name: 'John ETH', + address: { + city: 'New York', + zip: '10001', + fakeBool: false, + fakeNum: 2, + fakeUnd: undefined, + }, + }; + const expectedObject = { + ...inputObject, + address: { + ...inputObject.address, + zip: 10001, + }, + }; + const jsonString = JSON.stringify(inputObject); + expect(deepJSONParse({ jsonString, skipNumbers: false })).toEqual( + expectedObject, + ); + }); + + it('should properly parse a JSON string with nested arrays', () => { + const expectedObject = { + name: 'John Doe', + hobbies: ['Mining', 'Staking'], + }; + const jsonString = JSON.stringify(expectedObject); + expect(deepJSONParse({ jsonString })).toEqual(expectedObject); + }); + + it('should handle invalid JSON data', () => { + const jsonString = `{ + "name": "John ETH", + "age": "30" + }`; + expect(() => deepJSONParse({ jsonString })).not.toThrow(); + expect(deepJSONParse({ jsonString })).toEqual({ + name: 'John ETH', + age: '30', + }); + }); +}); From 1c678b756123400e27891bb8892eccb8548ea277 Mon Sep 17 00:00:00 2001 From: sethkfman Date: Fri, 16 Feb 2024 16:16:26 -0700 Subject: [PATCH 03/11] updated changelog --- CHANGELOG.md | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ef14400beab..0a23fcc117e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,74 @@ ## Current Main Branch +## 7.17.0 - Feb 16, 2024 +### Added +- [#8520](https://github.com/MetaMask/metamask-mobile/pull/8520): feat: Feature/1300 dapp visit event +- [#8354](https://github.com/MetaMask/metamask-mobile/pull/8354): feat(ramp): add Terms of Service provider link to quotes +- [#8579](https://github.com/MetaMask/metamask-mobile/pull/8579): feat: translate fake native tokens need better UX error handling +- [#8588](https://github.com/MetaMask/metamask-mobile/pull/8588): feat: re-structure confirmation pages +- [#8378](https://github.com/MetaMask/metamask-mobile/pull/8378): feat: Update assets controllers v^9.0.0 +- [#8370](https://github.com/MetaMask/metamask-mobile/pull/8370): feat: Update network controller v^10 +- [#7999](https://github.com/MetaMask/metamask-mobile/pull/7999): feat: chain id to hexadecimal format +- [#8524](https://github.com/MetaMask/metamask-mobile/pull/8524): feat: enable blockaid by default +- [#8552](https://github.com/MetaMask/metamask-mobile/pull/8552): feat: remove friction modal for enabling the feature from settings on iOS +- [#8400](https://github.com/MetaMask/metamask-mobile/pull/8400): feat: Add DS Guides link to component readmes +- [#8544](https://github.com/MetaMask/metamask-mobile/pull/8544): feat: blockaid banner UX improvements +- [#8246](https://github.com/MetaMask/metamask-mobile/pull/8246): feat: enable Ledger integration +- [#8234](https://github.com/MetaMask/metamask-mobile/pull/8234): feat: add privacy toggle +- [#8513](https://github.com/MetaMask/metamask-mobile/pull/8513): feat: confirm button color updates when transaction is malicious +- [#7534](https://github.com/MetaMask/metamask-mobile/pull/7534): feat: hide alert when navigating to protect wallet +- [#8392](https://github.com/MetaMask/metamask-mobile/pull/8392): feat: Enable token detection on arbitrum, optimism, base, and zksync +- [#8502](https://github.com/MetaMask/metamask-mobile/pull/8502): feat: change the yellow loading banner to gray color +- [#8373](https://github.com/MetaMask/metamask-mobile/pull/8373): feat: add SES experiment toggle (iOS) +- [#8413](https://github.com/MetaMask/metamask-mobile/pull/8413): feat: Update SES lockdown options + +### Changed +- [#8457](https://github.com/MetaMask/metamask-mobile/pull/8457): refactor(ramp): add routes folder +- [#8510](https://github.com/MetaMask/metamask-mobile/pull/8510): chore: upgrading design tokens package and typescript conventions +- [#8478](https://github.com/MetaMask/metamask-mobile/pull/8478): chore: bumping code coverage thresholds +- [#8414](https://github.com/MetaMask/metamask-mobile/pull/8414): chore: add logs to identify root cause of issue reported in #1507 +- [#8257](https://github.com/MetaMask/metamask-mobile/pull/8257): test: 1452 refactor modal pages batch 2 +- [#8558](https://github.com/MetaMask/metamask-mobile/pull/8558): test: add blacklist URLs to automated tests +- [#8563](https://github.com/MetaMask/metamask-mobile/pull/8563): ci: Exclude ip package from audit +- [#8483](https://github.com/MetaMask/metamask-mobile/pull/8483): chore: Modify cancel gas rate of Transaction Controller +- [#8541](https://github.com/MetaMask/metamask-mobile/pull/8541): test: use fast swipe on account sheet modal +- [#8514](https://github.com/MetaMask/metamask-mobile/pull/8514): chore(ramp): upgrade sdk to 1.26.2 + +### Fixed +- [#8348](https://github.com/MetaMask/metamask-mobile/pull/8348): fix: update nft metadata on page refresh +- [#8556](https://github.com/MetaMask/metamask-mobile/pull/8556): fix: improve native balance fetch logic on the UX +- [#8605](https://github.com/MetaMask/metamask-mobile/pull/8605): fix: Update ppom_release to fix fail ppom security validation check +- [#8606](https://github.com/MetaMask/metamask-mobile/pull/8606): fix: Custom network chain id not converted to hexadecimal format +- [#8592](https://github.com/MetaMask/metamask-mobile/pull/8592): fix: missing converting to decimal chain id on network verification of pop… +- [#8227](https://github.com/MetaMask/metamask-mobile/pull/8227): fix: ensure edit nonce input only accepts numbers +- [#8587](https://github.com/MetaMask/metamask-mobile/pull/8587): fix: revert slice engine +- [#8560](https://github.com/MetaMask/metamask-mobile/pull/8560): fix: broken WhatsNew +- [#8554](https://github.com/MetaMask/metamask-mobile/pull/8554): fix: Enable blockaid What's New Copy +- [#8559](https://github.com/MetaMask/metamask-mobile/pull/8559): fix: Commit script diff that appears when building iOS +- [#8547](https://github.com/MetaMask/metamask-mobile/pull/8547): fix: clean up old translations +- [#8551](https://github.com/MetaMask/metamask-mobile/pull/8551): fix: update ppom validator package +- [#8536](https://github.com/MetaMask/metamask-mobile/pull/8536): fix: Added inherited to build settings library search paths +- [#8485](https://github.com/MetaMask/metamask-mobile/pull/8485): fix: Rounding issue in approval amount (use site suggestion) +- [#8517](https://github.com/MetaMask/metamask-mobile/pull/8517): fix: Update MixPanel proxy URL +- [#8532](https://github.com/MetaMask/metamask-mobile/pull/8532): fix: Remove height behavior on android +- [#8468](https://github.com/MetaMask/metamask-mobile/pull/8468): fix: Inputting a nonce value messes up the nonce counter setting a totally different number +- [#8526](https://github.com/MetaMask/metamask-mobile/pull/8526): fix: Added keyboard avoiding view to bottomsheetdialog +- [#8527](https://github.com/MetaMask/metamask-mobile/pull/8527): fix: Updated backupalert snapshot from ds tokens update +- [#8509](https://github.com/MetaMask/metamask-mobile/pull/8509): fix: Fix/8352 source map stack trace +- [#8508](https://github.com/MetaMask/metamask-mobile/pull/8508): fix: Revert "fix: Fix/8352 source map stack trace (#8467)" +- [#8504](https://github.com/MetaMask/metamask-mobile/pull/8504): fix: Remove isFullscreen from AddAccount, AccountPermissions, and AddChainApproval +- [#8503](https://github.com/MetaMask/metamask-mobile/pull/8503): fix: Fix fullscreen issue with bottomsheet +- [#8467](https://github.com/MetaMask/metamask-mobile/pull/8467): fix: Fix/8352 source map stack trace +- [#8500](https://github.com/MetaMask/metamask-mobile/pull/8500): fix: clarify cherry pick action inputs +- [#8488](https://github.com/MetaMask/metamask-mobile/pull/8488): fix: Cleanup/miscellaneous +- [#8469](https://github.com/MetaMask/metamask-mobile/pull/8469): fix: deeplink handling issue when the app is closed +- [#8491](https://github.com/MetaMask/metamask-mobile/pull/8491): fix: Update theme tokens for QR-related components +- [#8486](https://github.com/MetaMask/metamask-mobile/pull/8486): fix: Update theme tokens for General and Advanced Settings +- [#8157](https://github.com/MetaMask/metamask-mobile/pull/8157): fix: display hash as hex in personal signature confirmation +- [#8126](https://github.com/MetaMask/metamask-mobile/pull/8126): fix: Update navigation bar on start loading +- [#8476](https://github.com/MetaMask/metamask-mobile/pull/8476): fix: Fix title color type in settings drawer + ## 7.16.0 - Jan 29, 2024 ### Added - [#8093](https://github.com/MetaMask/metamask-mobile/pull/8093): feat: decouple account selector from qr code connector From 10aaa640a764424fb88812bf42eab374a64c1b88 Mon Sep 17 00:00:00 2001 From: SamuelSalas Date: Fri, 23 Feb 2024 17:22:09 -0600 Subject: [PATCH 04/11] chore: cherry pick 8615 (#8640) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** This PR cherry-picks #8615 ## **Related issues** Fixes: ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** Smoke test run: https://app.bitrise.io/app/be69d4368ee7e86d/pipelines/46e749cb-c149-4ced-bc40-a9e5e1bed3c8 Regression test run: https://app.bitrise.io/app/be69d4368ee7e86d/pipelines/88873d22-4fea-45c3-83f3-eb034aa3ee32 ### **Before** ### **After** ## **Pre-merge author checklist** - [ ] I’ve followed [MetaMask Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've clearly explained what problem this PR is solving and how it is solved. - [ ] I've linked related issues - [ ] I've included manual testing steps - [ ] I've included screenshots/recordings if applicable - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. - [ ] I’ve properly set the pull request status: - [ ] In case it's not yet "ready for review", I've set it to "draft". - [ ] In case it's "ready for review", I've changed it from "draft" to "non-draft". ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- app/components/UI/Navbar/index.js | 11 +- .../NetworksSettings/NetworkSettings/index.js | 31 +--- .../Views/Settings/NetworksSettings/index.js | 14 +- e2e/pages/Settings/NetworksView.js | 156 +++++++++++------- .../Settings/NetworksView.selectors.js | 15 +- e2e/specs/networks/add-custom-rpc.spec.js | 10 +- wdio/screen-objects/NetworksScreen.js | 12 +- .../testIDs/Screens/NetworksScreen.testids.js | 21 --- 8 files changed, 136 insertions(+), 134 deletions(-) diff --git a/app/components/UI/Navbar/index.js b/app/components/UI/Navbar/index.js index 1de294e0118..347e341906d 100644 --- a/app/components/UI/Navbar/index.js +++ b/app/components/UI/Navbar/index.js @@ -29,11 +29,7 @@ import PickerNetwork from '../../../component-library/components/Pickers/PickerN 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, - NETWORK_BACK_ARROW_BUTTON_ID, - NETWORK_SCREEN_CLOSE_ICON, -} from '../../../../wdio/screen-objects/testIDs/Screens/NetworksScreen.testids'; +import { NAV_ANDROID_BACK_BUTTON } from '../../../../wdio/screen-objects/testIDs/Screens/NetworksScreen.testids'; import { SEND_CANCEL_BUTTON } from '../../../../wdio/screen-objects/testIDs/Screens/SendScreen.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'; @@ -54,6 +50,7 @@ import { } from '../../../component-library/components/Texts/Text'; import { CommonSelectorsIDs } from '../../../../e2e/selectors/Common.selectors'; import { WalletViewSelectorsIDs } from '../../../../e2e/selectors/WalletView.selectors'; +import { NetworksViewSelectorsIDs } from '../../../../e2e/selectors/Settings/NetworksView.selectors'; const trackEvent = (event) => { InteractionManager.runAfterInteractions(() => { @@ -216,7 +213,7 @@ export function getNavigationOptionsTitle( iconName={IconName.Close} onPress={navigationPop} style={innerStyles.accessories} - {...generateTestId(Platform, NETWORK_SCREEN_CLOSE_ICON)} + testID={NetworksViewSelectorsIDs.CLOSE_ICON} /> ) : null, headerLeft: () => @@ -226,7 +223,7 @@ export function getNavigationOptionsTitle( iconName={IconName.ArrowLeft} onPress={navigationPop} style={innerStyles.accessories} - {...generateTestId(Platform, NETWORK_BACK_ARROW_BUTTON_ID)} + testID={NetworksViewSelectorsIDs.BACK_ARROW_BUTTON} /> ), headerTintColor: themeColors.primary.default, diff --git a/app/components/Views/Settings/NetworksSettings/NetworkSettings/index.js b/app/components/Views/Settings/NetworksSettings/NetworkSettings/index.js index 5454ee13c94..35d975a66e7 100644 --- a/app/components/Views/Settings/NetworksSettings/NetworkSettings/index.js +++ b/app/components/Views/Settings/NetworksSettings/NetworkSettings/index.js @@ -7,7 +7,6 @@ import { TextInput, SafeAreaView, Linking, - Platform, } from 'react-native'; import { connect } from 'react-redux'; import { @@ -54,18 +53,6 @@ import hideKeyFromUrl from '../../../../../util/hideKeyFromUrl'; import { themeAppearanceLight } from '../../../../../constants/storage'; import { scale, moderateScale } from 'react-native-size-matters'; import CustomNetwork from './CustomNetworkView/CustomNetwork'; -import generateTestId from '../../../../../../wdio/utils/generateTestId'; -import { - INPUT_CHAIN_ID_FIELD, - INPUT_RPC_URL_FIELD, - INPUT_NETWORK_NAME, - NETWORKS_SYMBOL_INPUT_FIELD, - BLOCK_EXPLORER_FIELD, - REMOVE_NETWORK_BUTTON, - CUSTOM_NETWORKS_TAB_ID, - POPULAR_NETWORKS_TAB_ID, - RPC_WARNING_BANNER_ID, -} from '../../../../../../wdio/screen-objects/testIDs/Screens/NetworksScreen.testids'; import Button, { ButtonVariants, ButtonSize, @@ -933,7 +920,7 @@ class NetworkSettings extends PureComponent { placeholder={strings('app_settings.network_name_placeholder')} placeholderTextColor={colors.text.muted} onSubmitEditing={this.jumpToRpcURL} - {...generateTestId(Platform, INPUT_NETWORK_NAME)} + testID={NetworksViewSelectorsIDs.NETWORK_NAME_INPUT} keyboardAppearance={themeAppearance} /> @@ -951,13 +938,13 @@ class NetworkSettings extends PureComponent { placeholder={strings('app_settings.network_rpc_placeholder')} placeholderTextColor={colors.text.muted} onSubmitEditing={this.jumpToChainId} - {...generateTestId(Platform, INPUT_RPC_URL_FIELD)} + testID={NetworksViewSelectorsIDs.RPC_URL_INPUT} keyboardAppearance={themeAppearance} /> {warningRpcUrl && ( {warningRpcUrl} @@ -979,7 +966,7 @@ class NetworkSettings extends PureComponent { placeholderTextColor={colors.text.muted} onSubmitEditing={this.jumpToSymbol} keyboardType={'numbers-and-punctuation'} - {...generateTestId(Platform, INPUT_CHAIN_ID_FIELD)} + testID={NetworksViewSelectorsIDs.CHAIN_INPUT} keyboardAppearance={themeAppearance} /> {warningChainId ? ( @@ -1003,7 +990,7 @@ class NetworkSettings extends PureComponent { placeholder={strings('app_settings.network_symbol_label')} placeholderTextColor={colors.text.muted} onSubmitEditing={this.jumpBlockExplorerURL} - {...generateTestId(Platform, NETWORKS_SYMBOL_INPUT_FIELD)} + testID={NetworksViewSelectorsIDs.NETWORKS_SYMBOL_INPUT} keyboardAppearance={themeAppearance} /> @@ -1027,7 +1014,7 @@ class NetworkSettings extends PureComponent { placeholder={strings( 'app_settings.network_block_explorer_placeholder', )} - {...generateTestId(Platform, BLOCK_EXPLORER_FIELD)} + testID={NetworksViewSelectorsIDs.BLOCK_EXPLORER_INPUT} placeholderTextColor={colors.text.muted} onSubmitEditing={this.toggleNetworkDetailsModal} keyboardAppearance={themeAppearance} @@ -1053,7 +1040,7 @@ class NetworkSettings extends PureComponent { variant={ButtonVariants.Secondary} isDanger onPress={this.removeRpcUrl} - testID={REMOVE_NETWORK_BUTTON} + testID={NetworksViewSelectorsIDs.REMOVE_NETWORK_BUTTON} style={{ ...styles.button, ...styles.cancel }} label={strings('app_settings.delete')} /> @@ -1164,7 +1151,7 @@ class NetworkSettings extends PureComponent { tabLabel={strings('app_settings.popular')} key={AppConstants.ADD_CUSTOM_NETWORK_POPULAR_TAB_ID} style={styles.networksWrapper} - testID={POPULAR_NETWORKS_TAB_ID} + testID={NetworksViewSelectorsIDs.POPULAR_NETWORKS_CONTAINER} > {this.customNetwork()} diff --git a/app/components/Views/Settings/NetworksSettings/index.js b/app/components/Views/Settings/NetworksSettings/index.js index 3ec98c65013..c0945deb8d3 100644 --- a/app/components/Views/Settings/NetworksSettings/index.js +++ b/app/components/Views/Settings/NetworksSettings/index.js @@ -27,11 +27,7 @@ import { LINEA_MAINNET, MAINNET, RPC } from '../../../../constants/network'; import FontAwesome from 'react-native-vector-icons/FontAwesome'; import { mockTheme, ThemeContext } from '../../../../util/theme'; import ImageIcons from '../../../UI/ImageIcon'; -import { - ADD_NETWORK_BUTTON, - NETWORK_SCREEN_ID, - CUSTOM_NETWORK_NAME_NETWORK_LIST, -} from '../../../../../wdio/screen-objects/testIDs/Screens/NetworksScreen.testids'; +import { ADD_NETWORK_BUTTON } from '../../../../../wdio/screen-objects/testIDs/Screens/NetworksScreen.testids'; import { compareSanitizedUrl } from '../../../../util/sanitizeUrl'; import { selectNetworkConfigurations, @@ -43,6 +39,7 @@ import { } from '../../../../component-library/components/Avatars/Avatar'; import AvatarNetwork from '../../../../component-library/components/Avatars/Avatar/variants/AvatarNetwork'; import Routes from '../../../../constants/navigation/Routes'; +import { NetworksViewSelectorsIDs } from '../../../../../e2e/selectors/Settings/NetworksView.selectors'; const createStyles = (colors) => StyleSheet.create({ @@ -312,7 +309,7 @@ class NetworksSettings extends PureComponent { if (Object.keys(networkConfigurations).length > 0) { return ( - + {strings('app_settings.custom_network_name')} @@ -454,7 +451,10 @@ class NetworksSettings extends PureComponent { const styles = createStyles(colors); return ( - + { it('should go to settings then networks', async () => { await TabBarComponent.tapSettings(); await SettingsView.tapNetworks(); - await NetworkView.isNetworkViewVisible(); + await Assertions.checkIfVisible(NetworkView.networkContainer); }); it('should add xDai network', async () => { @@ -58,7 +58,7 @@ describe(Regression('Custom RPC Tests'), () => { await NetworkView.switchToCustomNetworks(); await NetworkView.typeInNetworkName('xDai'); await NetworkView.typeInRpcUrl('abc'); // Input incorrect RPC URL - await NetworkView.isRPCWarningVisble(); // Check that warning is displayed + await Assertions.checkIfVisible(NetworkView.rpcWarningBanner); await NetworkView.clearRpcInputBox(); await NetworkView.typeInRpcUrl(XDAI_URL); await NetworkView.typeInChainId('100'); @@ -95,7 +95,7 @@ describe(Regression('Custom RPC Tests'), () => { await NetworkListModal.isNetworkNameVisibleInListOfNetworks('xDai'); }); - it('should switch to Goreli then dismiss the network education modal', async () => { + it('should switch to Sepolia then dismiss the network education modal', async () => { await NetworkListModal.isTestNetworkToggleOn(); await NetworkListModal.changeNetwork(GORELI); await NetworkEducationModal.isVisible(); @@ -121,8 +121,8 @@ describe(Regression('Custom RPC Tests'), () => { await TestHelpers.delay(3000); await TabBarComponent.tapSettings(); await SettingsView.tapNetworks(); - await NetworkView.isNetworkViewVisible(); - await NetworkView.removeNetwork(); // Tap on xDai to remove network + await Assertions.checkIfVisible(NetworkView.networkContainer); + await NetworkView.tapRemoveNetwork('xDai'); // Tap on xDai to remove network await NetworkEducationModal.tapGotItButton(); await TabBarComponent.tapWallet(); await WalletView.isVisible(); diff --git a/wdio/screen-objects/NetworksScreen.js b/wdio/screen-objects/NetworksScreen.js index bac19000de9..f71a8fc3395 100644 --- a/wdio/screen-objects/NetworksScreen.js +++ b/wdio/screen-objects/NetworksScreen.js @@ -4,12 +4,8 @@ import { ADD_NETWORK_BUTTON, BLOCK_EXPLORER_FIELD, INPUT_CHAIN_ID_FIELD, - INPUT_NETWORK_NAME, INPUT_RPC_URL_FIELD, NAV_ANDROID_BACK_BUTTON, - NETWORK_BACK_ARROW_BUTTON_ID, - NETWORK_SCREEN_CLOSE_ICON, - NETWORK_SCREEN_ID, NETWORKS_SYMBOL_INPUT_FIELD, REMOVE_NETWORK_BUTTON, } from './testIDs/Screens/NetworksScreen.testids'; @@ -17,7 +13,7 @@ import { NetworksViewSelectorsIDs } from '../../e2e/selectors/Settings/NetworksV class NetworksScreen { get container() { - return Selectors.getElementByPlatform(NETWORK_SCREEN_ID); + return Selectors.getElementByPlatform(NetworksViewSelectorsIDs.NETWORK_CONTAINER); } get getPopularNetworksTab() { @@ -37,7 +33,7 @@ class NetworksScreen { } get networkNameInputField() { - return Selectors.getElementByPlatform(INPUT_NETWORK_NAME); + return Selectors.getElementByPlatform(NetworksViewSelectorsIDs.NETWORK_NAME_INPUT); } get rpcURLInputField() { @@ -61,7 +57,7 @@ class NetworksScreen { } get networkScreenBackButton() { - return Selectors.getElementByPlatform(NETWORK_BACK_ARROW_BUTTON_ID); + return Selectors.getElementByPlatform(NetworksViewSelectorsIDs.BACK_ARROW_BUTTON); } get settingsPageAndroidBackButton() { @@ -73,7 +69,7 @@ class NetworksScreen { } get closeNetworkScreen() { - return Selectors.getElementByPlatform(NETWORK_SCREEN_CLOSE_ICON); + return Selectors.getElementByPlatform(NetworksViewSelectorsIDs.CLOSE_ICON); } async waitForDisplayed() { diff --git a/wdio/screen-objects/testIDs/Screens/NetworksScreen.testids.js b/wdio/screen-objects/testIDs/Screens/NetworksScreen.testids.js index ca2764c11a4..7aec5d1bbab 100644 --- a/wdio/screen-objects/testIDs/Screens/NetworksScreen.testids.js +++ b/wdio/screen-objects/testIDs/Screens/NetworksScreen.testids.js @@ -1,25 +1,13 @@ -// eslint-disable-next-line import/prefer-default-export -export const CUSTOM_NETWORKS_NETWORK_NAME = 'mainnetworks-network-name'; - -export const CUSTOM_NETWORKS_TAB_ID = 'networks-custom-networks-tab'; - -export const POPULAR_NETWORKS_TAB_ID = 'networks-popular-networks-tab'; - export const INPUT_CHAIN_ID_FIELD = 'input-chain-id'; export const INPUT_RPC_URL_FIELD = 'input-rpc-url'; export const ADD_NETWORK_BUTTON = 'add-network-button'; -export const INPUT_NETWORK_NAME = 'input-network-name'; - export const NETWORKS_SYMBOL_INPUT_FIELD = 'input-network-symbol'; export const NEW_NETWORK_ADDED_SWITCH_TO_NETWORK_BUTTON = 'switch-to-network-button'; - -export const CUSTOM_NETWORK_NAME_NETWORK_LIST = 'custom-networks-list'; - export const NEW_NETWORK_ADDED_CLOSE_BUTTON = 'close-network-button'; export const APPROVE_NETWORK_APPROVE_BUTTON = 'approve-network-approve-button'; @@ -32,13 +20,4 @@ export const NETWORK_EDUCATION_MODAL_CLOSE_BUTTON = export const BLOCK_EXPLORER_FIELD = 'block-explorer'; export const REMOVE_NETWORK_BUTTON = 'remove-network-button'; - -export const NETWORK_BACK_ARROW_BUTTON_ID = - 'back-arrow-button'; - export const NAV_ANDROID_BACK_BUTTON = 'nav-android-back'; - -export const NETWORK_SCREEN_CLOSE_ICON = 'close-network-icon'; - -export const NETWORK_SCREEN_ID = 'networks-screen'; -export const RPC_WARNING_BANNER_ID = 'rpc-url-warning'; From 4f96842a6b6d0ec430a32e7a053a003a9cefbf51 Mon Sep 17 00:00:00 2001 From: tommasini <46944231+tommasini@users.noreply.github.com> Date: Wed, 28 Feb 2024 16:46:37 +0000 Subject: [PATCH 05/11] fix: Cherry pick translations (#8773) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** This PR cherry-picks #[8632](https://github.com/MetaMask/metamask-mobile/pull/8632) ## **Related issues** Fixes: ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** Smoke test run: https://app.bitrise.io/app/be69d4368ee7e86d/pipelines/46e749cb-c149-4ced-bc40-a9e5e1bed3c8 Regression test run: https://app.bitrise.io/app/be69d4368ee7e86d/pipelines/88873d22-4fea-45c3-83f3-eb034aa3ee32 ### **Before** ### **After** ## **Pre-merge author checklist** - [ ] I’ve followed [MetaMask Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've clearly explained what problem this PR is solving and how it is solved. - [ ] I've linked related issues - [ ] I've included manual testing steps - [ ] I've included screenshots/recordings if applicable - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. - [ ] I’ve properly set the pull request status: - [ ] In case it's not yet "ready for review", I've set it to "draft". - [ ] In case it's "ready for review", I've changed it from "draft" to "non-draft". ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.## **Description** ## **Related issues** Fixes: ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** ### **Before** ### **After** ## **Pre-merge author checklist** - [ ] I’ve followed [MetaMask Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've clearly explained what problem this PR is solving and how it is solved. - [ ] I've linked related issues - [ ] I've included manual testing steps - [ ] I've included screenshots/recordings if applicable - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. - [ ] I’ve properly set the pull request status: - [ ] In case it's not yet "ready for review", I've set it to "draft". - [ ] In case it's "ready for review", I've changed it from "draft" to "non-draft". ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. Co-authored-by: MetaMask Bot <37885440+metamaskbot@users.noreply.github.com> --- locales/languages/de.json | 41 ++++++++++++++++++++++++++++++++--- locales/languages/el.json | 45 ++++++++++++++++++++++++++++++++++----- locales/languages/es.json | 45 ++++++++++++++++++++++++++++++++++----- locales/languages/fr.json | 45 ++++++++++++++++++++++++++++++++++----- locales/languages/hi.json | 45 ++++++++++++++++++++++++++++++++++----- locales/languages/id.json | 45 ++++++++++++++++++++++++++++++++++----- locales/languages/ja.json | 45 ++++++++++++++++++++++++++++++++++----- locales/languages/ko.json | 45 ++++++++++++++++++++++++++++++++++----- locales/languages/pt.json | 45 ++++++++++++++++++++++++++++++++++----- locales/languages/ru.json | 45 ++++++++++++++++++++++++++++++++++----- locales/languages/tl.json | 45 ++++++++++++++++++++++++++++++++++----- locales/languages/tr.json | 45 ++++++++++++++++++++++++++++++++++----- locales/languages/vi.json | 45 ++++++++++++++++++++++++++++++++++----- locales/languages/zh.json | 45 ++++++++++++++++++++++++++++++++++----- 14 files changed, 558 insertions(+), 68 deletions(-) diff --git a/locales/languages/de.json b/locales/languages/de.json index dd7fee2816e..fd338edd9e4 100644 --- a/locales/languages/de.json +++ b/locales/languages/de.json @@ -7,6 +7,8 @@ "deceptive_request_title": "Dies ist eine betrügerische Anfrage.", "failed_title": "Anfrage ist möglicherweise nicht sicher", "failed_description": "Aufgrund eines Fehlers wurde diese Anfrage vom Sicherheitsanbieter nicht überprüft. Gehen Sie mit Bedacht vor.", + "loading_title": "Suche nach Sicherheitsbenachrichtigungen ...", + "loading_complete_title": "No alerts received. Always do your own due diligence before approving requests.", "malicious_domain_description": "Sie haben es mit einer bösartigen Domain zu tun. Wenn Sie diese Anfrage genehmigen, könnten Sie Ihre Assets verlieren.", "other_description": "Wenn Sie diese Anfrage genehmigen, könnten Sie Ihre Assets verlieren.", "raw_signature_farming_description": "Wenn Sie diese Anfrage genehmigen, könnten Sie Ihre Assets verlieren.", @@ -375,6 +377,13 @@ "nfts_autodetection_title": "NFT-Erkennung", "nfts_autodetection_desc": "Erlauben Sie MetaMask, NFTs automatisch in OpenSea zu erkennen und in Ihrer MetaMask-Wallet anzuzeigen.", "network_details_check": "Überprüfung der Netzwerkangaben", + "network_with_chain_id": "Das Netzwerk mit Chain-ID", + "potential_scam": "Dies ist ein möglicher Betrug", + "network_not_matching": "Dieses Netzwerk passt nicht zu seiner zugehörigen Chain-ID oder seinem Namen. Viele beliebte Tokens verwenden diesen Namen,", + "target_scam_network": "was sie zu einem Ziel für Betrüger macht. Betrüger könnten Sie dazu verleiten, ihnen im Gegenzug wertvollere Währung zu senden. Überprüfen Sie alles, bevor Sie fortfahren.", + "use_the_currency_symbol": "verwendet das Währungssymbol", + "use_correct_symbol": "Vergewissern Sie sich, dass Sie das richtige Symbol verwenden, bevor Sie fortfahren.", + "chain_id_currently_used": "Diese Chain-ID wird derzeit verwendet von der", "network_check_validation_desc": "verringert die Wahrscheinlichkeit, dass Sie sich mit einem böswilligen oder falschen Netz verbinden.", "nfts_autodetection_cta": "Aktivieren Sie die NFT-Erkennung in den Einstellungen.", "learn_more": "Mehr erfahren", @@ -879,17 +888,39 @@ "transactions_subheading": "Transaktionen", "network_provider": "Netzwerkanbieter", "token_nft_ens_subheading": "Automatische Token-, NFT- und ENS-Erkennung", - "security_check_subheading": "Sicherheitsprüfungen" + "security_check_subheading": "Sicherheitsprüfungen", + "symbol_required": "Symbol ist erforderlich.", + "blockaid": "Blockaid", + "blockaid_desc": "Wahrung der Privatsphäre – keine Daten werden an Dritte weitergegeben. Verfügbar auf Arbitrum, Avalanche, BNB Chain, Ethereum Mainnet, Optimism und Polygon.", + "security_alerts": "Sicherheitsbenachrichtigungen", + "security_alerts_desc": "Diese Funktion warnt Sie vor bösartigen Aktivitäten, indem sie Ihre Transaktions- und Signaturanfragen lokal überprüft. Führen Sie immer Ihre eigene Prüfung durch, bevor Sie Anfragen genehmigen. Es gibt keine Garantie dafür, dass diese Funktion alle bösartigen Aktivitäten erkennt. Mit der Aktivierung dieser Funktion erklären Sie sich mit den Nutzungsbedingungen des Anbieters einverstanden." }, "sdk": { "disconnect_title": "Verbindung mit allen Seiten trennen?", "disconnect_all_info": "Wenn Sie Ihre Verbindungen mit allen Seiten trennen, müssen Sie die Genehmigung dazu erteilen, sich erneut zu verbinden.", "disconnect": "Trennen", "disconnect_all": "Alle trennen", + "disconnect_all_accounts": "Disconnect all Accounts", + "manage_connections": "Manage Connections", + "manage": "Manage", "cancel": "Stornieren", "loading": "Verbindung mit MetaMask wird hergestellt ...", "unkown_dapp": "DAPP-Name nicht verfügbar", - "no_connections": "Keine Verbindungen gefunden" + "no_connections": "No connections", + "no_connections_desc": "If you connect an account to a site or an app, you’ll see it here." + }, + "sdk_session_item": { + "connected_accounts": "{{accountsLength}} account(s) connected." + }, + "sdk_disconnect_modal": { + "disconnect_all": "Disconnect from all sites?", + "disconnect_all_desc": "If you disconnect your accounts from all sites, you'll need to give permissions to reconnect them.", + "disconnect_account": "Disconnect account?", + "disconnect_all_accounts": "Disconnect all Accounts", + "disconnect_all_accounts_desc": "If you disconnect all accounts from {{dapp}}, you will need to give permissions to reconnect them.", + "disconnect_account_desc": "If you disconnect {{account}} from {{dapp}}, you will need to give permissions to reconnect it.", + "disconnect_confirm": "Disconnect", + "cancel": "Cancel" }, "sdk_return_to_app_modal": { "title": "Zur App zurückkehren", @@ -1454,6 +1485,7 @@ "add": "Hinzufügen", "cancel": "Stornieren", "approve": "Genehmigen", + "edit_network_details": "Netzwerkdetails bearbeiten", "malicious_network_warning": "Ein betrügerischer Netzwerkanbieter kann bezüglich des Status der Blockchain täuschen und Ihre Netzwerkaktivitäten aufzeichnen. Fügen Sie nur vertrauenswürdige benutzerdefinierte Netzwerke hinzu.", "security_link": "https://metamask.zendesk.com/hc/en-us/articles/4404424659995", "network_warning_title": "Netzwerkinformationen", @@ -1473,7 +1505,9 @@ "add_network": "weitere Netzwerke manuell hinzufügen.", "select_network": "Netzwerk wählen", "show_test_networks": "Testnetzwerke anzeigen", - "deprecated_goerli": "Aufgrund der Protokolländerungen von Ethereum: Das Goerli-Testnetzwerk funktioniert möglicherweise nicht mehr so zuverlässig und wird demnächst abgeschaltet." + "deprecated_goerli": "Aufgrund der Protokolländerungen von Ethereum: Das Goerli-Testnetzwerk funktioniert möglicherweise nicht mehr so zuverlässig und wird demnächst abgeschaltet.", + "network_deprecated_title": "This network is deprecated", + "network_deprecated_description": "The network you're trying to connect to is no longer supported on Metamask." }, "select": { "cancel": "Stornieren", @@ -2028,6 +2062,7 @@ "get_new_quotes": "Neue Angebote einholen", "quotes_timeout": "Angebote-Timeout", "request_new_quotes": "Bitte fragen Sie neue Angebote an, um den besten Kurs zu bekommen.", + "terms_of_service": "Nutzungsbedingungen", "amount_to_buy": "Betrag zum Kauf", "amount_to_sell": "Betrag zum Verkauf", "want_to_buy": "Sie möchten kaufen", diff --git a/locales/languages/el.json b/locales/languages/el.json index be3cddb8e7a..1fc16ab6968 100644 --- a/locales/languages/el.json +++ b/locales/languages/el.json @@ -7,6 +7,8 @@ "deceptive_request_title": "Πρόκειται για παραπλανητικό αίτημα", "failed_title": "Το αίτημα μπορεί να μην είναι ασφαλές", "failed_description": "Λόγω σφάλματος, αυτό το αίτημα δεν επαληθεύτηκε από τον πάροχο ασφαλείας. Προχωρήστε με προσοχή.", + "loading_title": "Έλεγχος για ειδοποιήσεις ασφαλείας...", + "loading_complete_title": "No alerts received. Always do your own due diligence before approving requests.", "malicious_domain_description": "Αλληλεπιδράτε με έναν κακόβουλο τομέα. Εάν εγκρίνετε αυτό το αίτημα, ενδέχεται να χάσετε τα περιουσιακά σας στοιχεία.", "other_description": "Εάν εγκρίνετε αυτό το αίτημα, ενδέχεται να χάσετε τα περιουσιακά σας στοιχεία.", "raw_signature_farming_description": "Εάν εγκρίνετε αυτό το αίτημα, ενδέχεται να χάσετε τα περιουσιακά σας στοιχεία.", @@ -374,8 +376,15 @@ "no_nfts_yet": "Δεν έχετε ακόμη NFT", "nfts_autodetection_title": "Εντοπισμός NFT", "nfts_autodetection_desc": "Επιτρέψτε στο MetaMask να εντοπίζει αυτόματα NFT από το OpenSea και να τα εμφανίζει στο πορτοφόλι σας στο MetaMask.", - "network_details_check": "Network details check", - "network_check_validation_desc": "reduces your chances of connecting to a malicious or incorrect network.", + "network_details_check": "Ο έλεγχος λεπτομερειών δικτύου", + "network_with_chain_id": "Το δίκτυο με αναγνωριστικό αλυσίδας", + "potential_scam": "Πρόκειται για πιθανή απάτη", + "network_not_matching": "Αυτό το δίκτυο δεν ταιριάζει με το αναγνωριστικό ή το όνομα της σχετικής αλυσίδας. Πολλά δημοφιλή tokens χρησιμοποιούν το όνομα", + "target_scam_network": "καθιστώντας το στόχο για απάτες. Οι απατεώνες μπορεί να σας ξεγελάσουν για να τους στείλετε πιο πολύτιμα νομίσματα σε αντάλλαγμα. Επαληθεύστε τα πάντα προτού συνεχίσετε.", + "use_the_currency_symbol": "χρησιμοποιεί το σύμβολο νομίσματος", + "use_correct_symbol": "Βεβαιωθείτε ότι χρησιμοποιείτε το σωστό σύμβολο προτού συνεχίσετε", + "chain_id_currently_used": "Αυτό το αναγνωριστικό αλυσίδας χρησιμοποιείται προς το παρόν από το", + "network_check_validation_desc": "μειώνει τις πιθανότητες σύνδεσης σε κακόβουλο ή λανθασμένο δίκτυο.", "nfts_autodetection_cta": "Ενεργοποιήστε τον εντοπισμό NFT στις Ρυθμίσεις", "learn_more": "Μάθετε περισσότερα", "add_collectibles": "Εισαγωγή NFT", @@ -879,17 +888,39 @@ "transactions_subheading": "Συναλλαγές", "network_provider": "Network provider", "token_nft_ens_subheading": "Αυτόματος εντοπισμός Tokens, NFS και ENS", - "security_check_subheading": "Έλεγχοι ασφαλείας" + "security_check_subheading": "Έλεγχοι ασφαλείας", + "symbol_required": "Απαιτείται το σύμβολο.", + "blockaid": "Blockaid", + "blockaid_desc": "Διαφύλαξη της ιδιωτικής ζωής - δεν κοινοποιούνται δεδομενα σε τρίτους. Διατίθεται στα Arbitrum, Avalanche, BNB chain, Ethereum Mainnet, Optimism και Polygon.", + "security_alerts": "Ειδοποιήσεις ασφαλείας", + "security_alerts_desc": "Αυτή η λειτουργία σας προειδοποιεί για κακόβουλη δραστηριότητα, καθώς ελέγχει τοπικά τα αιτήματα συναλλαγών και υπογραφών σας. Πάντα να κάνετε τη δική σας επιμελή έρευνα προτού εγκρίνετε οποιαδήποτε αιτήματα. Δεν υπάρχει καμία εγγύηση ότι αυτή η λειτουργία θα εντοπίσει όλες τις κακόβουλες δραστηριότητες. Ενεργοποιώντας αυτή τη λειτουργία, συμφωνείτε με τους όρους χρήσης του παρόχου." }, "sdk": { "disconnect_title": "Αποσύνδεση όλων των ιστότοπων;", "disconnect_all_info": "Εάν αφαιρέσετε τις συνδέσεις σας σε όλους τους ιστότοπους, θα πρέπει να δώσετε άδεια για να συνδεθείτε ξανά.", "disconnect": "Αποσύνδεση", "disconnect_all": "Αποσύνδεση όλων", + "disconnect_all_accounts": "Disconnect all Accounts", + "manage_connections": "Manage Connections", + "manage": "Manage", "cancel": "Άκυρο", "loading": "Σύνδεση στο MetaMask...", "unkown_dapp": "Το όνομα DAPP δεν είναι διαθέσιμο", - "no_connections": "Δεν βρέθηκαν συνδέσεις" + "no_connections": "No connections", + "no_connections_desc": "If you connect an account to a site or an app, you’ll see it here." + }, + "sdk_session_item": { + "connected_accounts": "{{accountsLength}} account(s) connected." + }, + "sdk_disconnect_modal": { + "disconnect_all": "Disconnect from all sites?", + "disconnect_all_desc": "If you disconnect your accounts from all sites, you'll need to give permissions to reconnect them.", + "disconnect_account": "Disconnect account?", + "disconnect_all_accounts": "Disconnect all Accounts", + "disconnect_all_accounts_desc": "If you disconnect all accounts from {{dapp}}, you will need to give permissions to reconnect them.", + "disconnect_account_desc": "If you disconnect {{account}} from {{dapp}}, you will need to give permissions to reconnect it.", + "disconnect_confirm": "Disconnect", + "cancel": "Cancel" }, "sdk_return_to_app_modal": { "title": "Επιστροφή στην εφαρμογή", @@ -1454,6 +1485,7 @@ "add": "Προσθήκη", "cancel": "Άκυρο", "approve": "Έγκριση", + "edit_network_details": "Επεξεργασία λεπτομερειών δικτύου", "malicious_network_warning": "Ένας κακόβουλος πάροχος δικτύου μπορεί να πει ψέματα για την κατάσταση του blockchain και να καταγράψει τη δραστηριότητα του δικτύου σας. Να προσθέτετε μόνο προσαρμοσμένα δίκτυα που εμπιστεύεστε.", "security_link": "https://metamask.zendesk.com/hc/en-us/articles/4404424659995", "network_warning_title": "Πληροφορίες Δικτύου", @@ -1473,7 +1505,9 @@ "add_network": "να προσθέσετε περισσότερα δίκτυα χειροκίνητα.", "select_network": "Επιλέξτε ένα δίκτυο", "show_test_networks": "Εμφάνιση δοκιμαστικών δικτύων", - "deprecated_goerli": "Λόγω των αλλαγών στο πρωτόκολλο του δοκιμαστικού δίκτυου Ethereum: Goerli μπορεί να μην λειτουργεί τόσο αξιόπιστα και θα καταργηθεί σύντομα." + "deprecated_goerli": "Λόγω των αλλαγών στο πρωτόκολλο του δοκιμαστικού δίκτυου Ethereum: Goerli μπορεί να μην λειτουργεί τόσο αξιόπιστα και θα καταργηθεί σύντομα.", + "network_deprecated_title": "This network is deprecated", + "network_deprecated_description": "The network you're trying to connect to is no longer supported on Metamask." }, "select": { "cancel": "Άκυρο", @@ -2028,6 +2062,7 @@ "get_new_quotes": "Λάβετε νέες προσφορές", "quotes_timeout": "Λήξη προσφοράς", "request_new_quotes": "Ζητήστε νέες προσφορές για να πάρετε την πιο πρόσφατη καλύτερη τιμή.", + "terms_of_service": "Όροι Χρήσης", "amount_to_buy": "Ποσό προς αγορά", "amount_to_sell": "Ποσό προς πώληση", "want_to_buy": "Θέλετε να αγοράσετε", diff --git a/locales/languages/es.json b/locales/languages/es.json index 271a83d36ff..2a8b3ebac79 100644 --- a/locales/languages/es.json +++ b/locales/languages/es.json @@ -7,6 +7,8 @@ "deceptive_request_title": "Esta es una solicitud engañosa", "failed_title": "Es posible que la solicitud no sea segura", "failed_description": "Debido a un error, el proveedor de seguridad no verificó esta solicitud. Proceda con precaución.", + "loading_title": "Comprobando alertas de seguridad...", + "loading_complete_title": "No alerts received. Always do your own due diligence before approving requests.", "malicious_domain_description": "Está interactuando con un dominio malicioso. Si aprueba esta solicitud, podría perder sus activos.", "other_description": "Si aprueba esta solicitud, podría perder sus activos.", "raw_signature_farming_description": "Si aprueba esta solicitud, podría perder sus activos.", @@ -374,8 +376,15 @@ "no_nfts_yet": "No hay ningún NFT aún", "nfts_autodetection_title": "Detección de NFT", "nfts_autodetection_desc": "Permita que MetaMask detecte automáticamente los NFT de OpenSea y los muestre en su monedero MetaMask.", - "network_details_check": "Network details check", - "network_check_validation_desc": "reduces your chances of connecting to a malicious or incorrect network.", + "network_details_check": "Verificación de detalles de la red", + "network_with_chain_id": "La red con ID de cadena", + "potential_scam": "Esto es una estafa potencial", + "network_not_matching": "Esta red no coincide con su ID o nombre de cadena asociada. Muchos tokens populares usan el nombre", + "target_scam_network": "lo que los convierte en blanco de estafas. Los estafadores pueden engañarlo para que les envíe dinero más valioso a cambio. Verifique todo antes de continuar.", + "use_the_currency_symbol": "utiliza el símbolo de moneda", + "use_correct_symbol": "Asegúrese de estar utilizando el símbolo correcto antes de continuar", + "chain_id_currently_used": "Esta ID de cadena es utilizada actualmente por el", + "network_check_validation_desc": "reduce las posibilidades de conectarse a una red maliciosa o incorrecta.", "nfts_autodetection_cta": "Active la detección de NFT en Configuraciones", "learn_more": "Más información", "add_collectibles": "AGREGAR NFT", @@ -879,17 +888,39 @@ "transactions_subheading": "Transacciones", "network_provider": "Network provider", "token_nft_ens_subheading": "Detección automática de tokens, NFT y ENS", - "security_check_subheading": "Verificaciones de seguridad" + "security_check_subheading": "Verificaciones de seguridad", + "symbol_required": "Se requiere símbolo.", + "blockaid": "Blockaid", + "blockaid_desc": "Preservación de la privacidad: no se comparten datos con terceros. Disponible en Arbitrum, Avalanche, cadena BNB, Ethereum Mainnet, Optimism y Polygon.", + "security_alerts": "Alertas de seguridad", + "security_alerts_desc": "Esta función le alerta sobre actividad maliciosa al revisar localmente sus solicitudes de transacción y firma. Haga siempre su propia diligencia debida antes de aprobar cualquier solicitud. No hay garantía de que esta función detecte toda la actividad maliciosa. Al habilitar esta función, acepta los términos de uso del proveedor." }, "sdk": { "disconnect_title": "¿Desconectar de todos los sitios?", "disconnect_all_info": "Si elimina sus conexiones a todos los sitios, tendrá que dar permiso para volver a conectarse.", "disconnect": "Desconectar", "disconnect_all": "Desconectar todo", + "disconnect_all_accounts": "Disconnect all Accounts", + "manage_connections": "Manage Connections", + "manage": "Manage", "cancel": "Cancelar", "loading": "Conectándose a MetaMask...", "unkown_dapp": "Nombre de DAPP no disponible", - "no_connections": "No se encontraron conexiones" + "no_connections": "No connections", + "no_connections_desc": "If you connect an account to a site or an app, you’ll see it here." + }, + "sdk_session_item": { + "connected_accounts": "{{accountsLength}} account(s) connected." + }, + "sdk_disconnect_modal": { + "disconnect_all": "Disconnect from all sites?", + "disconnect_all_desc": "If you disconnect your accounts from all sites, you'll need to give permissions to reconnect them.", + "disconnect_account": "Disconnect account?", + "disconnect_all_accounts": "Disconnect all Accounts", + "disconnect_all_accounts_desc": "If you disconnect all accounts from {{dapp}}, you will need to give permissions to reconnect them.", + "disconnect_account_desc": "If you disconnect {{account}} from {{dapp}}, you will need to give permissions to reconnect it.", + "disconnect_confirm": "Disconnect", + "cancel": "Cancel" }, "sdk_return_to_app_modal": { "title": "Volver a la aplicación", @@ -1454,6 +1485,7 @@ "add": "Agregar", "cancel": "Cancelar", "approve": "Aprobar", + "edit_network_details": "Editar detalles de la red", "malicious_network_warning": "Un proveedor de red malintencionado puede mentir sobre el estado de la cadena de bloques y registrar su actividad de red. Agregue solo redes personalizadas de confianza.", "security_link": "https://metamask.zendesk.com/hc/en-us/articles/4404424659995", "network_warning_title": "Información de red", @@ -1473,7 +1505,9 @@ "add_network": "agregar más redes manualmente.", "select_network": "Seleccionar una red", "show_test_networks": "Mostrar redes de prueba", - "deprecated_goerli": "Debido a los cambios de protocolo de Ethereum: es posible que la red de prueba de Goerli no funcione de manera tan confiable y pronto quedará obsoleta." + "deprecated_goerli": "Debido a los cambios de protocolo de Ethereum: es posible que la red de prueba de Goerli no funcione de manera tan confiable y pronto quedará obsoleta.", + "network_deprecated_title": "This network is deprecated", + "network_deprecated_description": "The network you're trying to connect to is no longer supported on Metamask." }, "select": { "cancel": "Cancelar", @@ -2028,6 +2062,7 @@ "get_new_quotes": "Obtener cotizaciones nuevas", "quotes_timeout": "Cotizaciones vencidas", "request_new_quotes": "Por favor, solicite cotizaciones nuevas para tener los costos más recientes.", + "terms_of_service": "Términos de servicio", "amount_to_buy": "Monto para comprar", "amount_to_sell": "Monto para vender", "want_to_buy": "Quiere comprar", diff --git a/locales/languages/fr.json b/locales/languages/fr.json index c465f20a6f2..cb719b4f283 100644 --- a/locales/languages/fr.json +++ b/locales/languages/fr.json @@ -7,6 +7,8 @@ "deceptive_request_title": "Cette demande est trompeuse", "failed_title": "Cette demande peut présenter des risques", "failed_description": "À cause d’une erreur, cette demande n’a pas été vérifiée par le fournisseur de services de sécurité. Veuillez agir avec prudence.", + "loading_title": "En train de vérifier s’il y a des alertes de sécurité…", + "loading_complete_title": "No alerts received. Always do your own due diligence before approving requests.", "malicious_domain_description": "Vous interagissez avec un domaine malveillant. Si vous approuvez cette demande, vous risquez de perdre vos actifs.", "other_description": "Si vous approuvez cette demande, vous risquez de perdre vos actifs.", "raw_signature_farming_description": "Si vous approuvez cette demande, vous risquez de perdre vos actifs.", @@ -374,8 +376,15 @@ "no_nfts_yet": "Aucun NFT pour le moment", "nfts_autodetection_title": "Détection de NFT", "nfts_autodetection_desc": "Cela permet à MetaMask de détecter automatiquement les NFT d’OpenSea et de les afficher dans votre portefeuille MetaMask.", - "network_details_check": "Network details check", - "network_check_validation_desc": "reduces your chances of connecting to a malicious or incorrect network.", + "network_details_check": "Vérification des détails du réseau", + "network_with_chain_id": "Le réseau qui a un ID de chaîne", + "potential_scam": "Il pourrait s’agir d’une arnaque", + "network_not_matching": "L’ID ou le nom de la chaîne associée à ce réseau n’est pas correct. De nombreux jetons populaires utilisent le nom", + "target_scam_network": ", ce qui en fait une cible pour les escrocs. Vérifiez toutes les informations avant de continuer, car vous risquez de vous faire arnaquer.", + "use_the_currency_symbol": "utilise le symbole monétaire", + "use_correct_symbol": "Assurez-vous que vous utilisez le bon symbole avant de continuer", + "chain_id_currently_used": "Cet ID de chaîne est actuellement utilisé par le", + "network_check_validation_desc": "réduit les risques de connexion au mauvais réseau ou à un réseau malveillant.", "nfts_autodetection_cta": "Activez la détection de NFT dans les paramètres", "learn_more": "En savoir plus", "add_collectibles": "Importer des NFT", @@ -879,17 +888,39 @@ "transactions_subheading": "Transactions", "network_provider": "Network provider", "token_nft_ens_subheading": "Détection automatique des jetons, NFT et ENS", - "security_check_subheading": "Contrôles de sécurité" + "security_check_subheading": "Contrôles de sécurité", + "symbol_required": "Le symbole est requis.", + "blockaid": "Blockaid", + "blockaid_desc": "Protection de la vie privée : aucune donnée n’est partagée avec des tiers. Disponible sur Arbitrum, Avalanche, BNB chain, Optimism, Polygon et le réseau principal Ethereum.", + "security_alerts": "Alertes de sécurité", + "security_alerts_desc": "Cette fonctionnalité vous avertit de toute activité malveillante en examinant localement vos demandes de transaction et de signature. Vous devez faire preuve de diligence raisonnable avant d’approuver toute demande. Rien ne garantit que toutes les activités malveillantes seront détectées par cette fonctionnalité. En l’activant, vous acceptez les conditions d’utilisation du fournisseur." }, "sdk": { "disconnect_title": "Déconnecter tous les sites ?", "disconnect_all_info": "Si vous supprimez vos connexions à tous les sites, vous devrez autoriser la connexion à nouveau.", "disconnect": "Déconnecter", "disconnect_all": "Déconnecter tous", + "disconnect_all_accounts": "Disconnect all Accounts", + "manage_connections": "Manage Connections", + "manage": "Manage", "cancel": "Annuler", "loading": "Connexion à MetaMask...", "unkown_dapp": "Nom de DAPP non disponible", - "no_connections": "Aucune connexion trouvée" + "no_connections": "No connections", + "no_connections_desc": "If you connect an account to a site or an app, you’ll see it here." + }, + "sdk_session_item": { + "connected_accounts": "{{accountsLength}} account(s) connected." + }, + "sdk_disconnect_modal": { + "disconnect_all": "Disconnect from all sites?", + "disconnect_all_desc": "If you disconnect your accounts from all sites, you'll need to give permissions to reconnect them.", + "disconnect_account": "Disconnect account?", + "disconnect_all_accounts": "Disconnect all Accounts", + "disconnect_all_accounts_desc": "If you disconnect all accounts from {{dapp}}, you will need to give permissions to reconnect them.", + "disconnect_account_desc": "If you disconnect {{account}} from {{dapp}}, you will need to give permissions to reconnect it.", + "disconnect_confirm": "Disconnect", + "cancel": "Cancel" }, "sdk_return_to_app_modal": { "title": "Retourner à l’application", @@ -1454,6 +1485,7 @@ "add": "Ajouter", "cancel": "Annuler", "approve": "Approuver", + "edit_network_details": "Modifier les détails du réseau", "malicious_network_warning": "Un fournisseur de réseau malveillant peut mentir quant à l’état de la blockchain et enregistrer votre activité sur le réseau. N’ajoutez que des réseaux personnalisés auxquels vous faites confiance.", "security_link": "https://metamask.zendesk.com/hc/en-us/articles/4404424659995", "network_warning_title": "Informations sur le réseau", @@ -1473,7 +1505,9 @@ "add_network": "ajouter manuellement d’autres réseaux.", "select_network": "Sélectionner un réseau", "show_test_networks": "Afficher les réseaux de test", - "deprecated_goerli": "En raison des changements apportés au protocole d’Ethereum, le réseau de test Goerli pourra ne pas fonctionner d’une manière aussi fiable qu’auparavant et deviendra bientôt obsolète." + "deprecated_goerli": "En raison des changements apportés au protocole d’Ethereum, le réseau de test Goerli pourra ne pas fonctionner d’une manière aussi fiable qu’auparavant et deviendra bientôt obsolète.", + "network_deprecated_title": "This network is deprecated", + "network_deprecated_description": "The network you're trying to connect to is no longer supported on Metamask." }, "select": { "cancel": "Annuler", @@ -2028,6 +2062,7 @@ "get_new_quotes": "Obtenir de nouvelles cotations", "quotes_timeout": "Expiration des cotations", "request_new_quotes": "Veuillez demander de nouvelles cotations pour obtenir le meilleur taux actuellement disponible.", + "terms_of_service": "Conditions d’utilisation", "amount_to_buy": "Quantité à acheter", "amount_to_sell": "Quantité à vendre", "want_to_buy": "Vous voulez acheter", diff --git a/locales/languages/hi.json b/locales/languages/hi.json index c692297e3ea..12c3350c82a 100644 --- a/locales/languages/hi.json +++ b/locales/languages/hi.json @@ -7,6 +7,8 @@ "deceptive_request_title": "इस अनुरोध को धोखेबाजी के उद्देश्य से भेजा गया है", "failed_title": "हो सकता है कि अनुरोध सुरक्षित न हो", "failed_description": "कोई समस्या होने के कारण, इस अनुरोध को सिक्यूरिटी प्रोवाइडर द्वारा सत्यापित नहीं किया गया। सावधानी से आगे बढ़ें।", + "loading_title": "सुरक्षा अलर्ट की जाँच की जा रही है...", + "loading_complete_title": "No alerts received. Always do your own due diligence before approving requests.", "malicious_domain_description": "आप एक बुरी नीयत वाले डोमेन से इंटरैक्ट कर रहे हैं। यदि आप इस अनुरोध को स्वीकार करते हैं, तो आप अपने सारे एसेट गंवा सकते हैं।", "other_description": "यदि आप इस अनुरोध को स्वीकार करते हैं, तो आप अपने सारे एसेट गंवा सकते हैं।", "raw_signature_farming_description": "यदि आप इस अनुरोध को स्वीकार करते हैं, तो आप अपने सारे एसेट गंवा सकते हैं।", @@ -374,8 +376,15 @@ "no_nfts_yet": "अभी तक कोई NFT नहीं है", "nfts_autodetection_title": "NFT का पता लगाना", "nfts_autodetection_desc": "MetaMask को अनुमति दें ताकि OpenSea से NFT का अपनेआप पता लगा ले और आपके MetaMask वॉलेट में दिखे।", - "network_details_check": "Network details check", - "network_check_validation_desc": "reduces your chances of connecting to a malicious or incorrect network.", + "network_details_check": "नेटवर्क डिटेल्स की जांच", + "network_with_chain_id": "चेन ID के साथ वाला नेटवर्क", + "potential_scam": "यह एक बड़ा स्कैम है", + "network_not_matching": "यह नेटवर्क अपने साथ जुड़ी हुई चेन ID या नाम से मेल नहीं खाता है। कई लोकप्रिय टोकन नाम का उपयोग करते हैं,", + "target_scam_network": "जिससे इसमें स्कैम किया जा सकता है। स्कैम करने वाले आपको बदले में ज़्यादा कीमती करेंसी भेजने का झांसा दे सकते हैं। आगे बढ़ने से पहले सब कुछ वेरीफाई करें।", + "use_the_currency_symbol": "करेंसी सिंबल का उपयोग करता है", + "use_correct_symbol": "आगे बढ़ने से पहले यह पक्का कर लें कि आप सही सिंबल का उपयोग कर रहे हैं", + "chain_id_currently_used": "यह चेन ID वर्तमान में के द्वारा इस्तेमाल की जाती है", + "network_check_validation_desc": "किसी बुरी नीयत वाले या गलत नेटवर्क से जुड़ने की आपकी संभावना कम हो जाती है।", "nfts_autodetection_cta": "सेटिंग में NFT का पता लगाना चालू करें", "learn_more": "ज्यादा जानें।", "add_collectibles": "NFT इम्पोर्ट करें", @@ -879,17 +888,39 @@ "transactions_subheading": "ट्रांसेक्शन्स", "network_provider": "Network provider", "token_nft_ens_subheading": "टोकन, NFT और ENS ऑटो-डिटेक्शन", - "security_check_subheading": "सुरक्षा जाँचें" + "security_check_subheading": "सुरक्षा जाँचें", + "symbol_required": "सिंबल की ज़रूरत है।", + "blockaid": "Blockaid", + "blockaid_desc": "गोपनीयता को सुरक्षित रखना - कोई भी डेटा थर्ड पार्टी के साथ साझा नहीं किया जाता है। Arbitrum, Avalanche, BNB chain, Ethereum Mainnet, Linea, Optimism और Polygon पर उपलब्ध है।", + "security_alerts": "सुरक्षा एलर्ट", + "security_alerts_desc": "यह सुविधा स्थानीय रूप से आपके ट्रांसेक्शन और हस्ताक्षर अनुरोधों की समीक्षा करके आपको बुरी नीयत वाली गतिविधि के प्रति एलर्ट करती है। किसी भी अनुरोध को मंजूरी देने से पहले हमेशा पूरी जांच-पड़ताल ज़रूर करें। इस बात की कोई गारंटी नहीं है कि यह सुविधा सभी बुरी नीयत वाली गतिविधि का पता लगा लेगी। इस सुविधा को सक्षम करके आप प्रदाता की उपयोग की शर्तों से सहमत होते हैं।" }, "sdk": { "disconnect_title": "सभी साइटों को डिसकनेक्ट करें?", "disconnect_all_info": "यदि आप सभी साइटों के लिए अपने कनेक्शन्स हटाते हैं, तो फिर से कनेक्ट करने के लिए आपको अनुमति देनी होगी।", "disconnect": "डिसकनेक्ट करें", "disconnect_all": "सभी को डिस्कनेक्ट करें", + "disconnect_all_accounts": "Disconnect all Accounts", + "manage_connections": "Manage Connections", + "manage": "Manage", "cancel": "रद्द करें", "loading": "MetaMask से कनेक्ट हो रहा है...", "unkown_dapp": "DAPP नाम उपलब्ध नहीं है", - "no_connections": "कोई कनेक्शन नहीं मिला" + "no_connections": "No connections", + "no_connections_desc": "If you connect an account to a site or an app, you’ll see it here." + }, + "sdk_session_item": { + "connected_accounts": "{{accountsLength}} account(s) connected." + }, + "sdk_disconnect_modal": { + "disconnect_all": "Disconnect from all sites?", + "disconnect_all_desc": "If you disconnect your accounts from all sites, you'll need to give permissions to reconnect them.", + "disconnect_account": "Disconnect account?", + "disconnect_all_accounts": "Disconnect all Accounts", + "disconnect_all_accounts_desc": "If you disconnect all accounts from {{dapp}}, you will need to give permissions to reconnect them.", + "disconnect_account_desc": "If you disconnect {{account}} from {{dapp}}, you will need to give permissions to reconnect it.", + "disconnect_confirm": "Disconnect", + "cancel": "Cancel" }, "sdk_return_to_app_modal": { "title": "ऐप पर लौटें", @@ -1454,6 +1485,7 @@ "add": "जोड़ें", "cancel": "रद्द करें", "approve": "स्वीकृति दें", + "edit_network_details": "नेटवर्क का ब्यौरा बदलें", "malicious_network_warning": "एक दुर्भावनापूर्ण नेटवर्क प्रदाता ब्लॉकचेन की स्थिति के बारे में झूठ बोल सकता है और आपकी नेटवर्क गतिविधि को रिकॉर्ड कर सकता है। केवल ऐसे कस्टम नेटवर्क जोड़ें जिन पर आपको भरोसा हो।", "security_link": "https://metamask.zendesk.com/hc/en-us/articles/4404424659995", "network_warning_title": "नेटवर्क संबंधी सूचना", @@ -1473,7 +1505,9 @@ "add_network": "मैन्युअल रूप से अधिक नेटवर्क जोड़ें।", "select_network": "एक नेटवर्क चुनें", "show_test_networks": "परीक्षण नेटवर्क दिखाएं", - "deprecated_goerli": "Ethereum के प्रोटोकॉल परिवर्तनों के कारण: Goerli परीक्षण नेटवर्क विश्वसनीय रूप से काम नहीं कर सकता है और जल्द ही बंद हो जाएगा।" + "deprecated_goerli": "Ethereum के प्रोटोकॉल परिवर्तनों के कारण: Goerli परीक्षण नेटवर्क विश्वसनीय रूप से काम नहीं कर सकता है और जल्द ही बंद हो जाएगा।", + "network_deprecated_title": "This network is deprecated", + "network_deprecated_description": "The network you're trying to connect to is no longer supported on Metamask." }, "select": { "cancel": "रद्द करें", @@ -2028,6 +2062,7 @@ "get_new_quotes": "नए उद्धरण प्राप्त करें", "quotes_timeout": "उद्धरण समयबाह्य", "request_new_quotes": "नवीनतम सर्वोत्तम दर प्राप्त करने के लिए कृपया नए उद्धरणों का रिक्वेस्ट करें।", + "terms_of_service": "सेवा की शर्तें", "amount_to_buy": "खरीदने के लिए राशि", "amount_to_sell": "बेचने के लिए राशि", "want_to_buy": "आप खरीदना चाहते हैं", diff --git a/locales/languages/id.json b/locales/languages/id.json index 2357bf78f49..adb66770c8b 100644 --- a/locales/languages/id.json +++ b/locales/languages/id.json @@ -7,6 +7,8 @@ "deceptive_request_title": "Ini adalah permintaan tipuan", "failed_title": "Permintaan mungkin tidak aman", "failed_description": "Karena terjadi kesalahan, permintaan ini tidak diverifikasi oleh penyedia keamanan. Lanjutkan dengan hati-hati.", + "loading_title": "Memeriksa peringatan keamanan...", + "loading_complete_title": "No alerts received. Always do your own due diligence before approving requests.", "malicious_domain_description": "Anda berinteraksi dengan domain berbahaya. Jika Anda menyetujui permintaan ini, aset Anda kemungkinan akan hilang.", "other_description": "Jika Anda menyetujui permintaan ini, aset Anda kemungkinan akan hilang.", "raw_signature_farming_description": "Jika Anda menyetujui permintaan ini, aset Anda kemungkinan akan hilang.", @@ -374,8 +376,15 @@ "no_nfts_yet": "Belum ada NFT", "nfts_autodetection_title": "Deteksi NFT", "nfts_autodetection_desc": "Izinkan MetaMask untuk mendeteksi NFT dari OpenSea secara otomatis dan ditampilkan di dompet MetaMask Anda.", - "network_details_check": "Network details check", - "network_check_validation_desc": "reduces your chances of connecting to a malicious or incorrect network.", + "network_details_check": "Pemeriksaan detail jaringan", + "network_with_chain_id": "Jaringan dengan ID chain", + "potential_scam": "Ini merupakan potensi penipuan", + "network_not_matching": "Jaringan ini tidak cocok dengan ID chain atau nama yang terkait. Banyak token populer yang menggunakan nama tersebut", + "target_scam_network": "menjadikannya sebagai target penipuan. Penipu dapat mengelabui Anda agar mengirimkan mata uang yang lebih berharga sebagai gantinya. Pastikan untuk memverifikasi semuanya sebelum melanjutkan.", + "use_the_currency_symbol": "menggunakan simbol mata uang", + "use_correct_symbol": "Pastikan Anda menggunakan simbol yang benar sebelum melanjutkan", + "chain_id_currently_used": "ID chain ini saat ini digunakan oleh", + "network_check_validation_desc": "mengurangi peluang Anda untuk terhubung ke jaringan berbahaya atau salah.", "nfts_autodetection_cta": "Aktifkan deteksi NFT di Pengaturan", "learn_more": "Pelajari selengkapnya", "add_collectibles": "Impor NFT", @@ -879,17 +888,39 @@ "transactions_subheading": "Transaksi", "network_provider": "Network provider", "token_nft_ens_subheading": "Autodeteksi Token, NFT, dan ENS", - "security_check_subheading": "Pemeriksaan keamanan" + "security_check_subheading": "Pemeriksaan keamanan", + "symbol_required": "Simbol wajib diisi.", + "blockaid": "Blockaid", + "blockaid_desc": "Menjaga privasi - tidak ada data yang dibagikan kepada pihak ketiga. Tersedia di Arbitrum, Avalanche, BNB Chain, Mainnet Ethereum, Optimism, dan Polygon.", + "security_alerts": "Peringatan keamanan", + "security_alerts_desc": "Fitur ini memperingatkan Anda tentang aktivitas berbahaya dengan meninjau permintaan transaksi dan tanda tangan secara lokal. Selalu lakukan uji tuntas sendiri sebelum menyetujui permintaan. Tidak ada jaminan bahwa fitur ini akan mendeteksi semua aktivitas berbahaya. Dengan mengaktifkan fitur ini, Anda menyetujui persyaratan penggunaan penyedia." }, "sdk": { "disconnect_title": "Putuskan koneksi semua situs?", "disconnect_all_info": "Jika koneksi ke semua situs dihapus, Anda harus memberikan izin untuk menghubungkannya kembali.", "disconnect": "Putuskan koneksi", "disconnect_all": "Putuskan semua koneksi", + "disconnect_all_accounts": "Disconnect all Accounts", + "manage_connections": "Manage Connections", + "manage": "Manage", "cancel": "Batal", "loading": "Menghubungkan ke MetaMask...", "unkown_dapp": "Nama Aplikasi Terdesentralisasi (DAPP) tidak tersedia", - "no_connections": "Koneksi tidak ditemukan" + "no_connections": "No connections", + "no_connections_desc": "If you connect an account to a site or an app, you’ll see it here." + }, + "sdk_session_item": { + "connected_accounts": "{{accountsLength}} account(s) connected." + }, + "sdk_disconnect_modal": { + "disconnect_all": "Disconnect from all sites?", + "disconnect_all_desc": "If you disconnect your accounts from all sites, you'll need to give permissions to reconnect them.", + "disconnect_account": "Disconnect account?", + "disconnect_all_accounts": "Disconnect all Accounts", + "disconnect_all_accounts_desc": "If you disconnect all accounts from {{dapp}}, you will need to give permissions to reconnect them.", + "disconnect_account_desc": "If you disconnect {{account}} from {{dapp}}, you will need to give permissions to reconnect it.", + "disconnect_confirm": "Disconnect", + "cancel": "Cancel" }, "sdk_return_to_app_modal": { "title": "Kembali ke aplikasi", @@ -1454,6 +1485,7 @@ "add": "Tambahkan", "cancel": "Batal", "approve": "Setujui", + "edit_network_details": "Edit detail jaringan", "malicious_network_warning": "Penyedia jaringan jahat dapat berbohong tentang status blockchain dan merekam aktivitas jaringan Anda. Hanya tambahkan jaringan kustom yang Anda percayai.", "security_link": "https://metamask.zendesk.com/hc/en-us/articles/4404424659995", "network_warning_title": "Informasi Jaringan", @@ -1473,7 +1505,9 @@ "add_network": "menambahkan lebih banyak jaringan secara manual.", "select_network": "Pilih jaringan", "show_test_networks": "Tampilkan jaringan pengujian", - "deprecated_goerli": "Sehubungan dengan perubahan protokol Ethereum: Jaringan uji Goerli mungkin tidak dapat beroperasi dengan baik dan akan segera dihentikan." + "deprecated_goerli": "Sehubungan dengan perubahan protokol Ethereum: Jaringan uji Goerli mungkin tidak dapat beroperasi dengan baik dan akan segera dihentikan.", + "network_deprecated_title": "This network is deprecated", + "network_deprecated_description": "The network you're trying to connect to is no longer supported on Metamask." }, "select": { "cancel": "Batal", @@ -2028,6 +2062,7 @@ "get_new_quotes": "Dapatkan kuotasi baru", "quotes_timeout": "Waktu kuotasi habis", "request_new_quotes": "Minta kuotasi baru untuk mendapatkan tarif terbaik saat ini.", + "terms_of_service": "Ketentuan Layanan", "amount_to_buy": "Jumlah yang akan dibeli", "amount_to_sell": "Jumlah yang akan dijual", "want_to_buy": "Anda ingin membeli", diff --git a/locales/languages/ja.json b/locales/languages/ja.json index 96f3f809364..f4d25c7a867 100644 --- a/locales/languages/ja.json +++ b/locales/languages/ja.json @@ -7,6 +7,8 @@ "deceptive_request_title": "これは虚偽のリクエストです", "failed_title": "リクエストが安全でない可能性があります", "failed_description": "エラーが発生したため、このリクエストはセキュリティプロバイダーにより確認されませんでした。慎重に進めてください。", + "loading_title": "セキュリティアラートを確認中...", + "loading_complete_title": "No alerts received. Always do your own due diligence before approving requests.", "malicious_domain_description": "悪質なドメインとやり取りしています。このリクエストを承認すると、資産を失う可能性があります。", "other_description": "このリクエストを承認すると、資産を失う可能性があります。", "raw_signature_farming_description": "このリクエストを承認すると、資産を失う可能性があります。", @@ -374,8 +376,15 @@ "no_nfts_yet": "まだNFTがありません", "nfts_autodetection_title": "NFTの検出", "nfts_autodetection_desc": "MetaMaskがOpenSeaからNFTを自動検出し、MetaMaskウォレットに表示できるように許可してください。", - "network_details_check": "Network details check", - "network_check_validation_desc": "reduces your chances of connecting to a malicious or incorrect network.", + "network_details_check": "ネットワーク情報の確認", + "network_with_chain_id": "チェーンIDを持つネットワーク", + "potential_scam": "これは詐欺の可能性があります", + "network_not_matching": "このネットワークは、関連付けられたチェーンIDまたは名前と一致しません。人気のトークンの多くが「", + "target_scam_network": "」という名前を使用しているため、詐欺の標的となっています。詐欺師は、より価値の高い通貨を送り返すように仕向ける可能性があります。続ける前にすべてを確認してください。", + "use_the_currency_symbol": "通貨シンボルを使用", + "use_correct_symbol": "続ける前に、正しいシンボルを使用していることを確認してください", + "chain_id_currently_used": "このチェーンIDは現在次のネットワークで使用されています:", + "network_check_validation_desc": "悪質なネットワークや正しくないネットワークに接続してしまう可能性が減ります。", "nfts_autodetection_cta": "設定でNFTの検出をオンにしてください", "learn_more": "詳細", "add_collectibles": "NFTをインポート", @@ -879,17 +888,39 @@ "transactions_subheading": "トランザクション", "network_provider": "Network provider", "token_nft_ens_subheading": "トークン、NFT、ENSの自動検出", - "security_check_subheading": "セキュリティチェック" + "security_check_subheading": "セキュリティチェック", + "symbol_required": "シンボルが必要です", + "blockaid": "Blockaid", + "blockaid_desc": "プライバシーの保護 - サードパーティとデータが一切共有されません。Arbitrum、Avalanche、BNB Chain、イーサリアムメインネット、Optimism、Polygonで利用可能。", + "security_alerts": "セキュリティアラート", + "security_alerts_desc": "この機能は、トランザクションと署名要求をローカルで確認することで、悪質な行為に関するアラートを発します。要求を承認する前に、必ず独自のデューデリジェンスを行ってください。この機能がすべての悪質な行為を検出するという保証はありません。この機能を有効にすることで、プロバイダーの利用規約に同意したものとみなされます。" }, "sdk": { "disconnect_title": "すべてのサイトとの接続を解除しますか?", "disconnect_all_info": "すべてのサイトへの接続を削除した場合、再び接続するにはアクセス許可の付与が必要になります。", "disconnect": "接続解除", "disconnect_all": "すべて接続解除", + "disconnect_all_accounts": "Disconnect all Accounts", + "manage_connections": "Manage Connections", + "manage": "Manage", "cancel": "キャンセル", "loading": "MetaMaskに接続しています...", "unkown_dapp": "DApp名が利用できません", - "no_connections": "接続が見つかりません" + "no_connections": "No connections", + "no_connections_desc": "If you connect an account to a site or an app, you’ll see it here." + }, + "sdk_session_item": { + "connected_accounts": "{{accountsLength}} account(s) connected." + }, + "sdk_disconnect_modal": { + "disconnect_all": "Disconnect from all sites?", + "disconnect_all_desc": "If you disconnect your accounts from all sites, you'll need to give permissions to reconnect them.", + "disconnect_account": "Disconnect account?", + "disconnect_all_accounts": "Disconnect all Accounts", + "disconnect_all_accounts_desc": "If you disconnect all accounts from {{dapp}}, you will need to give permissions to reconnect them.", + "disconnect_account_desc": "If you disconnect {{account}} from {{dapp}}, you will need to give permissions to reconnect it.", + "disconnect_confirm": "Disconnect", + "cancel": "Cancel" }, "sdk_return_to_app_modal": { "title": "アプリに戻る", @@ -1454,6 +1485,7 @@ "add": "追加", "cancel": "キャンセル", "approve": "承認", + "edit_network_details": "ネットワークの詳細を編集", "malicious_network_warning": "悪意のあるネットワーク プロバイダーは、ブロックチェーンのステータスを偽り、ユーザーのネットワークアクティビティを記録することがあります。信頼するカスタムネットワークのみを追加してください。", "security_link": "https://metamask.zendesk.com/hc/en-us/articles/4404424659995", "network_warning_title": "ネットワーク情報", @@ -1473,7 +1505,9 @@ "add_network": "他のネットワークを手動で追加できます。", "select_network": "ネットワークを選択", "show_test_networks": "テストネットワークを表示", - "deprecated_goerli": "イーサリアムのプロトコルの変更により、Goerliテストネットワークは安定して動作しない可能性があり、近日中に非推奨になります。" + "deprecated_goerli": "イーサリアムのプロトコルの変更により、Goerliテストネットワークは安定して動作しない可能性があり、近日中に非推奨になります。", + "network_deprecated_title": "This network is deprecated", + "network_deprecated_description": "The network you're trying to connect to is no longer supported on Metamask." }, "select": { "cancel": "キャンセル", @@ -2028,6 +2062,7 @@ "get_new_quotes": "新しいクォートを入手", "quotes_timeout": "クォートのタイムアウト", "request_new_quotes": "最も有利な最新のレートを入手できるよう、新しいクォートをリクエストしてください", + "terms_of_service": "サービス規約", "amount_to_buy": "購入額", "amount_to_sell": "売却額", "want_to_buy": "購入希望", diff --git a/locales/languages/ko.json b/locales/languages/ko.json index fa715593acf..68155afa6a1 100644 --- a/locales/languages/ko.json +++ b/locales/languages/ko.json @@ -7,6 +7,8 @@ "deceptive_request_title": "사기성 요청입니다", "failed_title": "안전하지 않은 요청일 수 있습니다", "failed_description": "오류로 인해 보안업체에서 이 요청을 확인하지 못했습니다. 주의하여 진행하세요.", + "loading_title": "보안 경고 확인하는 중...", + "loading_complete_title": "No alerts received. Always do your own due diligence before approving requests.", "malicious_domain_description": "악성 도메인과 인터렉션하고 있습니다. 이 요청을 승인하면 본인의 자산을 잃을 수도 있습니다.", "other_description": "이 요청을 승인하면, 자산을 잃을 수 있습니다.", "raw_signature_farming_description": "이 요청을 승인하면, 자산을 잃을 수 있습니다.", @@ -374,8 +376,15 @@ "no_nfts_yet": "아직 NFT가 없습니다", "nfts_autodetection_title": "NFT 감지", "nfts_autodetection_desc": "MetaMask가 OpenSea에서 NFT를 자동으로 탐지하여 MetaMask 지갑에 표시할 수 있도록 하세요.", - "network_details_check": "Network details check", - "network_check_validation_desc": "reduces your chances of connecting to a malicious or incorrect network.", + "network_details_check": "네트워크 세부 정보 확인", + "network_with_chain_id": "체인 ID 포함 네트워크", + "potential_scam": "이는 사기일 수 있습니다", + "network_not_matching": "이 네트워크는 관련 체인 ID나 이름이 일치하지 않습니다. 많은 인기 토큰이 이 이름을 사용하기 때문에", + "target_scam_network": "사기의 표적이 되고 있습니다. 사기꾼은 더 가격이 높은 암호화폐를 주겠다고 속일 수 있습니다. 계속하기 전에 모든 사항을 확인하세요.", + "use_the_currency_symbol": "통화 심볼 사용", + "use_correct_symbol": "계속하기 전에 올바른 심볼을 사용하고 있는지 확인하세요", + "chain_id_currently_used": "이 체인 ID는 현재 다음에서 사용됩니다:", + "network_check_validation_desc": "악성 또는 잘못된 네트워크에 연결될 가능성이 줄어듭니다.", "nfts_autodetection_cta": "설정에서 NFT 감지를 켜세요", "learn_more": "더 알아보기", "add_collectibles": "NFT 가져오기", @@ -879,17 +888,39 @@ "transactions_subheading": "트랜잭션", "network_provider": "Network provider", "token_nft_ens_subheading": "토큰, NFT 및 ENS 자동 감지", - "security_check_subheading": "보안 점검" + "security_check_subheading": "보안 점검", + "symbol_required": "심볼은 필수입니다.", + "blockaid": "Blockaid", + "blockaid_desc": "개인정보 보호 - 제3자와 데이터를 공유하지 않습니다. Arbitrum, Avalanche, BNB Chain, 이더리움 메인넷, Optimism, Polygon에서 사용할 수 있습니다.", + "security_alerts": "보안 경고", + "security_alerts_desc": "이 기능은 트랜잭션 및 서명 요청을 로컬에서 검토하여 악의적인 활동이 있는 경우 경고합니다. 요청을 승인하기 전에 항상 직접 검토하세요. 이 기능이 모든 악성 활동을 탐지하는 것은 아닙니다. 이 기능을 활성화하면 제공 업체의 이용 약관에 동의하는 것이 됩니다." }, "sdk": { "disconnect_title": "모든 사이트를 연결 해제할까요?", "disconnect_all_info": "모든 사이트의 연결을 해제한 후 다시 연결하려면 허용 권한을 다시 부여해야 합니다.", "disconnect": "연결 해제", "disconnect_all": "모두 연결 해제", + "disconnect_all_accounts": "Disconnect all Accounts", + "manage_connections": "Manage Connections", + "manage": "Manage", "cancel": "취소", "loading": "MetaMask 연결 중...", "unkown_dapp": "디앱 이름을 사용할 수 없습니다", - "no_connections": "연결을 찾을 수 없습니다" + "no_connections": "No connections", + "no_connections_desc": "If you connect an account to a site or an app, you’ll see it here." + }, + "sdk_session_item": { + "connected_accounts": "{{accountsLength}} account(s) connected." + }, + "sdk_disconnect_modal": { + "disconnect_all": "Disconnect from all sites?", + "disconnect_all_desc": "If you disconnect your accounts from all sites, you'll need to give permissions to reconnect them.", + "disconnect_account": "Disconnect account?", + "disconnect_all_accounts": "Disconnect all Accounts", + "disconnect_all_accounts_desc": "If you disconnect all accounts from {{dapp}}, you will need to give permissions to reconnect them.", + "disconnect_account_desc": "If you disconnect {{account}} from {{dapp}}, you will need to give permissions to reconnect it.", + "disconnect_confirm": "Disconnect", + "cancel": "Cancel" }, "sdk_return_to_app_modal": { "title": "앱으로 돌아가기", @@ -1454,6 +1485,7 @@ "add": "추가", "cancel": "취소", "approve": "승인", + "edit_network_details": "네트워크 세부 정보 편집", "malicious_network_warning": "악성 네트워크 공급업체는 블록체인 상태를 거짓으로 보고하고 네트워크 활동을 기록할 수 있습니다. 신뢰하는 커스텀 네트워크만 추가하세요.", "security_link": "https://metamask.zendesk.com/hc/en-us/articles/4404424659995", "network_warning_title": "네트워크 정보", @@ -1473,7 +1505,9 @@ "add_network": "네트워크를 직접 추가할 수도 있습니다.", "select_network": "네트워크 선택", "show_test_networks": "테스트 네트워크 표시", - "deprecated_goerli": "이더리움의 프로토콜 변경으로 인해 Goerli 테스트 네트워크가 안정적으로 작동하지 않을 수 있으며, 곧 사용 중지될 예정입니다." + "deprecated_goerli": "이더리움의 프로토콜 변경으로 인해 Goerli 테스트 네트워크가 안정적으로 작동하지 않을 수 있으며, 곧 사용 중지될 예정입니다.", + "network_deprecated_title": "This network is deprecated", + "network_deprecated_description": "The network you're trying to connect to is no longer supported on Metamask." }, "select": { "cancel": "취소", @@ -2028,6 +2062,7 @@ "get_new_quotes": "새 견적 받기", "quotes_timeout": "견적 만료", "request_new_quotes": "새 견적을 신청하여 최신 요율을 확인하세요.", + "terms_of_service": "서비스 약관", "amount_to_buy": "매수 금액", "amount_to_sell": "매도 금액", "want_to_buy": "희망 구매량", diff --git a/locales/languages/pt.json b/locales/languages/pt.json index b24b8feefb6..0ecda0bf199 100644 --- a/locales/languages/pt.json +++ b/locales/languages/pt.json @@ -7,6 +7,8 @@ "deceptive_request_title": "Essa solicitação é enganosa", "failed_title": "A solicitação pode não ser segura", "failed_description": "Em razão de um erro, essa solicitação não foi confirmada pelo provedor de segurança. Prossiga com cautela.", + "loading_title": "Verificando se há alertas de segurança...", + "loading_complete_title": "No alerts received. Always do your own due diligence before approving requests.", "malicious_domain_description": "Você está interagindo com um domínio mal-intencionado. Se você aprovar essa solicitação, poderá perder seus ativos.", "other_description": "Se você aprovar essa solicitação, poderá perder seus ativos.", "raw_signature_farming_description": "Se você aprovar essa solicitação, poderá perder seus ativos.", @@ -374,8 +376,15 @@ "no_nfts_yet": "Nenhum NFT até agora", "nfts_autodetection_title": "Detecção de NFTs", "nfts_autodetection_desc": "Permita que a MetaMask detecte NFTs automaticamente da OpenSea e os exiba na sua carteira MetaMask.", - "network_details_check": "Network details check", - "network_check_validation_desc": "reduces your chances of connecting to a malicious or incorrect network.", + "network_details_check": "A verificação dos dados da rede", + "network_with_chain_id": "A rede com a ID de cadeia", + "potential_scam": "Isto é um possível golpe", + "network_not_matching": "Esta rede não corresponde ao nome ou ID de cadeia associados a ela. Muitos tokens populares usam o nome", + "target_scam_network": "o que o torna alvo de golpes. Os golpistas podem tentar enganar você para que envie a eles moedas mais valiosas em troca. Verifique tudo antes de continuar.", + "use_the_currency_symbol": "usa o símbolo de moeda", + "use_correct_symbol": "Certifique-se de usar o símbolo correto antes de continuar", + "chain_id_currently_used": "Esta ID de cadeia está sendo usada pela", + "network_check_validation_desc": "reduz suas chances de se conectar a uma rede mal-intencionada ou incorreta.", "nfts_autodetection_cta": "Ative a detecção de NFTs nas Configurações", "learn_more": "Saiba mais", "add_collectibles": "Importar NFTs", @@ -879,17 +888,39 @@ "transactions_subheading": "Transações", "network_provider": "Network provider", "token_nft_ens_subheading": "Detecção automática de tokens, NFTs e ENS", - "security_check_subheading": "Verificações de segurança" + "security_check_subheading": "Verificações de segurança", + "symbol_required": "O símbolo é obrigatório.", + "blockaid": "Blockaid", + "blockaid_desc": "Privacidade resguardada: nenhum dado é compartilhado com terceiros. Disponível na Arbitrum, Avalanche, BNB Chain, Mainnet da Ethereum, Optimism e Polygon.", + "security_alerts": "Alertas de segurança", + "security_alerts_desc": "Esse recurso alerta sobre atividades mal-intencionadas por meio da análise local de solicitações de transações e assinaturas. Sempre realize sua própria devida diligência antes de aprovar solicitações. Não há garantia de que esse recurso detectará toda e qualquer atividade mal-intencionada. Ao ativar esse recurso, você concorda com os termos de uso do provedor." }, "sdk": { "disconnect_title": "Desconectar todos os sites?", "disconnect_all_info": "Se você remover suas conexões com todos os sites, precisará dar permissão para se reconectar.", "disconnect": "Desconectar", "disconnect_all": "Desconectar todos", + "disconnect_all_accounts": "Disconnect all Accounts", + "manage_connections": "Manage Connections", + "manage": "Manage", "cancel": "Cancelar", "loading": "Conectando à MetaMask...", "unkown_dapp": "Nome do dapp indisponível", - "no_connections": "Nenhuma conexão encontrada" + "no_connections": "No connections", + "no_connections_desc": "If you connect an account to a site or an app, you’ll see it here." + }, + "sdk_session_item": { + "connected_accounts": "{{accountsLength}} account(s) connected." + }, + "sdk_disconnect_modal": { + "disconnect_all": "Disconnect from all sites?", + "disconnect_all_desc": "If you disconnect your accounts from all sites, you'll need to give permissions to reconnect them.", + "disconnect_account": "Disconnect account?", + "disconnect_all_accounts": "Disconnect all Accounts", + "disconnect_all_accounts_desc": "If you disconnect all accounts from {{dapp}}, you will need to give permissions to reconnect them.", + "disconnect_account_desc": "If you disconnect {{account}} from {{dapp}}, you will need to give permissions to reconnect it.", + "disconnect_confirm": "Disconnect", + "cancel": "Cancel" }, "sdk_return_to_app_modal": { "title": "Voltar ao app", @@ -1454,6 +1485,7 @@ "add": "Adicionar", "cancel": "Cancelar", "approve": "Aprovar", + "edit_network_details": "Editar os dados da rede", "malicious_network_warning": "Um provedor de rede mal-intencionado pode mentir sobre o estado da blockchain e registrar sua atividade na rede. Adicione apenas redes personalizadas em que você confia.", "security_link": "https://metamask.zendesk.com/hc/en-us/articles/4404424659995", "network_warning_title": "Informações da rede", @@ -1473,7 +1505,9 @@ "add_network": "adicionar mais redes manualmente.", "select_network": "Selecione uma rede", "show_test_networks": "Exibir redes de teste", - "deprecated_goerli": "Devido às alterações no protocolo Ethereum, a rede de teste Goerli pode não funcionar com a mesma confiabilidade e será descontinuada." + "deprecated_goerli": "Devido às alterações no protocolo Ethereum, a rede de teste Goerli pode não funcionar com a mesma confiabilidade e será descontinuada.", + "network_deprecated_title": "This network is deprecated", + "network_deprecated_description": "The network you're trying to connect to is no longer supported on Metamask." }, "select": { "cancel": "Cancelar", @@ -2028,6 +2062,7 @@ "get_new_quotes": "Obter novas cotações", "quotes_timeout": "Cotações expiradas", "request_new_quotes": "Solicite novas cotações para obter a melhor taxa mais recente.", + "terms_of_service": "Termos de Serviço", "amount_to_buy": "Valor a comprar", "amount_to_sell": "Valor a vender", "want_to_buy": "Você deseja comprar", diff --git a/locales/languages/ru.json b/locales/languages/ru.json index 493f33cfef4..474e399bdd9 100644 --- a/locales/languages/ru.json +++ b/locales/languages/ru.json @@ -7,6 +7,8 @@ "deceptive_request_title": "Это запрос с целью обмана", "failed_title": "Запрос может быть небезопасным", "failed_description": "Из-за ошибки этот запрос не был подтвержден поставщиком услуг безопасности. Действуйте осторожно.", + "loading_title": "Проверка оповещений безопасности...", + "loading_complete_title": "No alerts received. Always do your own due diligence before approving requests.", "malicious_domain_description": "Вы взаимодействуете с вредоносным доменом. Если вы одобрите этот запрос, вы можете потерять свои активы.", "other_description": "Если вы одобрите этот запрос, вы можете потерять свои активы.", "raw_signature_farming_description": "Если вы одобрите этот запрос, вы можете потерять свои активы.", @@ -374,8 +376,15 @@ "no_nfts_yet": "Пока нет NFT", "nfts_autodetection_title": "Определение NFT", "nfts_autodetection_desc": "Разрешите MetaMask автоопределять NFT из OpenSea и отображать их в кошельке MetaMask.", - "network_details_check": "Network details check", - "network_check_validation_desc": "reduces your chances of connecting to a malicious or incorrect network.", + "network_details_check": "Проверка сведений о сети", + "network_with_chain_id": "Сеть с ID блокчейна", + "potential_scam": "Это потенциальное мошенничество", + "network_not_matching": "Эта сеть не соответствует идентификатору или имени связанного с ним блокчейна. Многие популярные токены используют это название,", + "target_scam_network": "что делает его мишенью для мошенников. Мошенники могут обманом заставить вас отправить им взамен более ценную валюту. Проверьте все, прежде чем продолжить.", + "use_the_currency_symbol": "использует символ валюты", + "use_correct_symbol": "Прежде чем продолжить, убедитесь, что вы используете правильный символ", + "chain_id_currently_used": "Этот ID блокчейна в настоящее время используется", + "network_check_validation_desc": "снижает ваши шансы подключиться к вредоносной или неправильной сети.", "nfts_autodetection_cta": "Включите определение NFT в настройках", "learn_more": "Подробнее", "add_collectibles": "Импорт NFT", @@ -879,17 +888,39 @@ "transactions_subheading": "Транзакции", "network_provider": "Network provider", "token_nft_ens_subheading": "Автоопределение токенов, NFT и ENS", - "security_check_subheading": "Проверки безопасности" + "security_check_subheading": "Проверки безопасности", + "symbol_required": "Требуется символ.", + "blockaid": "Blockaid", + "blockaid_desc": "Сохранение конфиденциальности – никакие данные не передаются третьим сторонам. Доступно в Arbitrum, Avalanche, BNB Chain, Мейн-нете Ethereum, Optimism и Polygon.", + "security_alerts": "Оповещения безопасности", + "security_alerts_desc": "Эта функция предупреждает вас о вредоносной активности, проверяя запросы транзакций и подписей локально. Всегда проводите комплексную проверку перед утверждением каких-либо запросов. Нет никакой гарантии, что эта функция обнаружит всю вредоносную активность. Включая эту функцию, вы соглашаетесь с условиями использования поставщика." }, "sdk": { "disconnect_title": "Отключить все сайты?", "disconnect_all_info": "Если вы удалите свои подключения ко всем сайтам, вам потребуется снова предоставить разрешение на подключение.", "disconnect": "Отключить", "disconnect_all": "Отключить все", + "disconnect_all_accounts": "Disconnect all Accounts", + "manage_connections": "Manage Connections", + "manage": "Manage", "cancel": "Отмена", "loading": "Подключение к MetaMask...", "unkown_dapp": "Имя DAPP недоступно", - "no_connections": "Подключения не найдены" + "no_connections": "No connections", + "no_connections_desc": "If you connect an account to a site or an app, you’ll see it here." + }, + "sdk_session_item": { + "connected_accounts": "{{accountsLength}} account(s) connected." + }, + "sdk_disconnect_modal": { + "disconnect_all": "Disconnect from all sites?", + "disconnect_all_desc": "If you disconnect your accounts from all sites, you'll need to give permissions to reconnect them.", + "disconnect_account": "Disconnect account?", + "disconnect_all_accounts": "Disconnect all Accounts", + "disconnect_all_accounts_desc": "If you disconnect all accounts from {{dapp}}, you will need to give permissions to reconnect them.", + "disconnect_account_desc": "If you disconnect {{account}} from {{dapp}}, you will need to give permissions to reconnect it.", + "disconnect_confirm": "Disconnect", + "cancel": "Cancel" }, "sdk_return_to_app_modal": { "title": "Назад в приложение", @@ -1454,6 +1485,7 @@ "add": "Добавить", "cancel": "Отмена", "approve": "Одобрить", + "edit_network_details": "Изменить сведения о сети", "malicious_network_warning": "Вредоносный сетевой провайдер может дезинформировать о состоянии блокчейна и записывать ваши действия в сети. Добавляйте только те пользовательские сети, которым доверяете.", "security_link": "https://metamask.zendesk.com/hc/en-us/articles/4404424659995", "network_warning_title": "Информация о сети", @@ -1473,7 +1505,9 @@ "add_network": "добавить другие сети вручную.", "select_network": "Выбрать сеть", "show_test_networks": "Показать тестнеты", - "deprecated_goerli": "Из-за изменений протокола Ethereum: тестовая сеть Goerli может работать ненадежно и скоро будет выведена из эксплуатации." + "deprecated_goerli": "Из-за изменений протокола Ethereum: тестовая сеть Goerli может работать ненадежно и скоро будет выведена из эксплуатации.", + "network_deprecated_title": "This network is deprecated", + "network_deprecated_description": "The network you're trying to connect to is no longer supported on Metamask." }, "select": { "cancel": "Отмена", @@ -2028,6 +2062,7 @@ "get_new_quotes": "Получить новые котировки", "quotes_timeout": "Таймаут котировок", "request_new_quotes": "Запросите новые котировки, чтобы получить последний лучший курс.", + "terms_of_service": "Условия обслуживания", "amount_to_buy": "Сумма для покупки", "amount_to_sell": "Сумма для продажи", "want_to_buy": "Вы хотите купить", diff --git a/locales/languages/tl.json b/locales/languages/tl.json index 1d563e87b99..ca87894e10e 100644 --- a/locales/languages/tl.json +++ b/locales/languages/tl.json @@ -7,6 +7,8 @@ "deceptive_request_title": "Isa itong mapanlinlang na kahilingan", "failed_title": "Baka hindi ligtas ang kahilingan", "failed_description": "Dahil sa pagkakamali, ang kahilingang ito ay hindi na-verify ng tagapaglaan ng seguridad. Magpatuloy nang may pag-iingat.", + "loading_title": "Sinusuri ang mga alertong pangseguridad...", + "loading_complete_title": "No alerts received. Always do your own due diligence before approving requests.", "malicious_domain_description": "Nakikipag-ugnayan ka sa isang mapaminsalang domain. Kung aaprubahan mo ang kahilingang ito, posibleng mawala sa iyo ang mga asset mo.", "other_description": "Kung aaprubahan mo ang kahilingang ito, posibleng mawala sa iyo ang mga asset mo.", "raw_signature_farming_description": "Kung aaprubahan mo ang kahilingang ito, posibleng mawala sa iyo ang mga asset mo.", @@ -374,8 +376,15 @@ "no_nfts_yet": "Wala pang mga NFT", "nfts_autodetection_title": "Pagtuklas ng NFT", "nfts_autodetection_desc": "Payagan ang MetaMask na awtomatikong matuklasan ang mga NFT mula sa OpenSea at ipakita sa iyong wallet sa MetaMask.", - "network_details_check": "Network details check", - "network_check_validation_desc": "reduces your chances of connecting to a malicious or incorrect network.", + "network_details_check": "Pagsusuri ng detalye ng network", + "network_with_chain_id": "Ang network na may ID ng chain", + "potential_scam": "Isa itong potensyal na scam", + "network_not_matching": "Ang network na ito ay hindi tugma sa kaugnay nitong ID ng chain o pangalan. Maraming popular na token ay ginagamit ang pangalan", + "target_scam_network": "kaya ito ay isang target para sa mga scam. Maaari kang lokohin ng mga scammer na magpadala ka ng mas mahalagang salapi bilang kapalit. Beripikahin ang lahat bago magpatuloy.", + "use_the_currency_symbol": "ginagamit ang simbolo ng salapi", + "use_correct_symbol": "Tiyakin na ginagamit mo ang tamang simbolo bago magpatuloy", + "chain_id_currently_used": "Ang ID ng Chain na ito ay kasalukuyang ginagamit ng", + "network_check_validation_desc": "binabawasan ang iyong tiyansa na kumonekta sa isang malicious o maling network.", "nfts_autodetection_cta": "I-on ang pagtuklas ng NFT sa Mga Setting", "learn_more": "Matuto pa", "add_collectibles": "Mag-import ng mga NFT", @@ -879,17 +888,39 @@ "transactions_subheading": "Mga Transaksyon", "network_provider": "Network provider", "token_nft_ens_subheading": "Awtomatikong pagtuklas ng token, NFT at ENS", - "security_check_subheading": "Pagsusuring panseguridad" + "security_check_subheading": "Pagsusuring panseguridad", + "symbol_required": "Kailangan ang simbolo.", + "blockaid": "Blockaid", + "blockaid_desc": "Pagpapanatili ng pagkapribado - walang datos na ibinahagi sa mga third party. Available sa Arbitrum, Avalanche, BNB chain, Ethereum Mainnet, Linea, Optimism at Polygon.", + "security_alerts": "Mga alerto sa seguridad", + "security_alerts_desc": "Inaalertuhan ka ng tampok na ito sa mga aktibidad na may masamang hangarin sa pamamagitan ng lokal na pagsusuri sa iyong mga transaksyon at kahilingan sa paglagda. Palaging gumawa ng sarili mong pag-iingat bago aprubahan ang anumang mga kahilingan. Walang garantiya na made-detect ng tampok na ito ang lahat ng aktibidad na may masamang hangarin. Sa pagpapagana sa tampok na ito, sumasang-ayon ka sa mga tuntunin ng paggamit ng provider." }, "sdk": { "disconnect_title": "Idiskonekta ang lahat ng site?", "disconnect_all_info": "Kung aalisin mo ang iyong mga koneksyon sa lahat ng site, kakailanganin mong magbigay ng pahintulot na kumonekta muli.", "disconnect": "Idiskonekta", "disconnect_all": "Idiskonekta ang lahat", + "disconnect_all_accounts": "Disconnect all Accounts", + "manage_connections": "Manage Connections", + "manage": "Manage", "cancel": "Kanselahin", "loading": "Kumokonekta sa MetaMask...", "unkown_dapp": "Hindi available ang pangalan ng DAPP", - "no_connections": "Walang nakitang koneksyon" + "no_connections": "No connections", + "no_connections_desc": "If you connect an account to a site or an app, you’ll see it here." + }, + "sdk_session_item": { + "connected_accounts": "{{accountsLength}} account(s) connected." + }, + "sdk_disconnect_modal": { + "disconnect_all": "Disconnect from all sites?", + "disconnect_all_desc": "If you disconnect your accounts from all sites, you'll need to give permissions to reconnect them.", + "disconnect_account": "Disconnect account?", + "disconnect_all_accounts": "Disconnect all Accounts", + "disconnect_all_accounts_desc": "If you disconnect all accounts from {{dapp}}, you will need to give permissions to reconnect them.", + "disconnect_account_desc": "If you disconnect {{account}} from {{dapp}}, you will need to give permissions to reconnect it.", + "disconnect_confirm": "Disconnect", + "cancel": "Cancel" }, "sdk_return_to_app_modal": { "title": "Bumalik sa app", @@ -1454,6 +1485,7 @@ "add": "Idagdag", "cancel": "Kanselahin", "approve": "Aprubahan", + "edit_network_details": "I-edit ang mga detalye ng network", "malicious_network_warning": "Ang isang mapaminsalang network provider ay maaaring magsinungaling tungkol sa estado ng blockchain at itala ang iyong aktibidad sa network. Magdagdag lang ng mga custom na network na pinagkakatiwalaan mo.", "security_link": "https://metamask.zendesk.com/hc/en-us/articles/4404424659995", "network_warning_title": "Impormasyon ng Network", @@ -1473,7 +1505,9 @@ "add_network": "magdagdag pa ng mga network nang manu-mano.", "select_network": "Pumili ng network", "show_test_networks": "Ipakita ang mga test network", - "deprecated_goerli": "Dahil sa mga pagbabago sa protocol ng Ethereum: Ang Goerli test network ay maaaring hindi gumana tulad ng inaasahan at malapit nang ihinto ang paggamit." + "deprecated_goerli": "Dahil sa mga pagbabago sa protocol ng Ethereum: Ang Goerli test network ay maaaring hindi gumana tulad ng inaasahan at malapit nang ihinto ang paggamit.", + "network_deprecated_title": "This network is deprecated", + "network_deprecated_description": "The network you're trying to connect to is no longer supported on Metamask." }, "select": { "cancel": "Kanselahin", @@ -2028,6 +2062,7 @@ "get_new_quotes": "Kumuha ng mga bagong quote", "quotes_timeout": "Natapos na ang quote", "request_new_quotes": "Mangyaring humiling ng mga bagong quote para makuha ng pinakabagong pinakamahusay na rate.", + "terms_of_service": "Mga Tuntunin ng Serbisyo", "amount_to_buy": "Halagang bibilhin", "amount_to_sell": "Halagang ibebenta", "want_to_buy": "Gusto mong bilhin", diff --git a/locales/languages/tr.json b/locales/languages/tr.json index 2de9f9623b3..e36d5ebe17f 100644 --- a/locales/languages/tr.json +++ b/locales/languages/tr.json @@ -7,6 +7,8 @@ "deceptive_request_title": "Bu, aldatıcı bir taleptir", "failed_title": "Talep güvenli olmayabilir", "failed_description": "Bu talep bir hatadan dolayı güvenlik sağlayıcısı tarafından doğrulanmadı. Dikkatli bir şekilde ilerleyin.", + "loading_title": "Güvenlik uyarıları kontrol ediliyor...", + "loading_complete_title": "No alerts received. Always do your own due diligence before approving requests.", "malicious_domain_description": "Kötü niyetli bir alanla etkileşimde bulunuyorsunuz. Bu talebi onaylarsanız varlıklarınızı kaybedebilirsiniz.", "other_description": "Bu talebi onaylarsanız varlıklarınızı kaybedebilirsiniz.", "raw_signature_farming_description": "Bu talebi onaylarsanız varlıklarınızı kaybedebilirsiniz.", @@ -374,8 +376,15 @@ "no_nfts_yet": "Henüz NFT yok", "nfts_autodetection_title": "NFT algılama", "nfts_autodetection_desc": "MetaMask'ın OpenSea'den NFT'leri otomatik olarak algılayıp MetaMask cüzdanınızda göstermesine izin verin.", - "network_details_check": "Network details check", - "network_check_validation_desc": "reduces your chances of connecting to a malicious or incorrect network.", + "network_details_check": "Ağ bilgileri kontrolü", + "network_with_chain_id": "Zincir kimliği olan ağ", + "potential_scam": "Bu potansiyel bir dolandırıcılıktır", + "network_not_matching": "Bu ağ, ilişkili zincir kimliği veya isim ile uyumlu değil. Bu ismin pek çok popüler token tarafından kullanılması", + "target_scam_network": "dolandırıcılıkların hedefi haline gelmesine neden olmaktadır. Dolandırıcılar, karşılığında daha değerli bir para birimi göndereceğini belirterek sizi aldatabilir. Devam etmeden önce her şeyi doğrulayın.", + "use_the_currency_symbol": "para birimi sembolü kullanır", + "use_correct_symbol": "Devam etmeden önce doğru sembolü kullandığınızdan emin olun", + "chain_id_currently_used": "Bu Zincir Kimliği şu anda şunun tarafından kullanılıyor:", + "network_check_validation_desc": "kötü amaçlı veya yanlış bir ağa bağlanma ihtimalinizi azaltır.", "nfts_autodetection_cta": "Ayarlarda NFT algılamayı açın", "learn_more": "Daha fazlasını öğren", "add_collectibles": "NFT'leri içe aktar", @@ -879,17 +888,39 @@ "transactions_subheading": "İşlemler", "network_provider": "Network provider", "token_nft_ens_subheading": "Token, NFT ve ENS otomatik algılama", - "security_check_subheading": "Güvenlik kontrolleri" + "security_check_subheading": "Güvenlik kontrolleri", + "symbol_required": "Sembol gerekli.", + "blockaid": "Blockaid", + "blockaid_desc": "Gizlilik koruması - hiçbir veri üçüncü taraflarla paylaşılmaz. Arbitrum, Avalanche, BNB chain, Ethereum Ana Ağı, Optimism ve Polygon üzerinde kullanılabilir.", + "security_alerts": "Güvenlik uyarıları", + "security_alerts_desc": "Bu özellik, işlem ve imza taleplerinizi yerel olarak incelerken gizliliğinizi koruyarak Ethereum Ana Ağındaki kötü amaçlı aktivitelere karşı sizi uyarır. Talepleri onaylamadan önce her zaman gereken özeni kendiniz gösterin. Bu özelliğin tüm kötü amaçlı faaliyetleri algılayacağına dair herhangi bir garanti bulunmamaktadır. Bu özelliği etkinleştirerek sağlayıcının kullanım koşullarını kabul etmiş olursunuz." }, "sdk": { "disconnect_title": "Tüm sitelerin bağlantısı kesilsin mi?", "disconnect_all_info": "Tüm sitelerin bağlantılarını kaldırırsanız tekrar bağlanmak için izin vermeniz gerekecektir.", "disconnect": "Bağlantıyı kes", "disconnect_all": "Tümünün bağlantısını kes", + "disconnect_all_accounts": "Disconnect all Accounts", + "manage_connections": "Manage Connections", + "manage": "Manage", "cancel": "İptal", "loading": "MetaMask'a bağlanılıyor...", "unkown_dapp": "Merkeziyetsiz uygulama adı kullanılamıyor", - "no_connections": "Bağlantı bulunamadı" + "no_connections": "No connections", + "no_connections_desc": "If you connect an account to a site or an app, you’ll see it here." + }, + "sdk_session_item": { + "connected_accounts": "{{accountsLength}} account(s) connected." + }, + "sdk_disconnect_modal": { + "disconnect_all": "Disconnect from all sites?", + "disconnect_all_desc": "If you disconnect your accounts from all sites, you'll need to give permissions to reconnect them.", + "disconnect_account": "Disconnect account?", + "disconnect_all_accounts": "Disconnect all Accounts", + "disconnect_all_accounts_desc": "If you disconnect all accounts from {{dapp}}, you will need to give permissions to reconnect them.", + "disconnect_account_desc": "If you disconnect {{account}} from {{dapp}}, you will need to give permissions to reconnect it.", + "disconnect_confirm": "Disconnect", + "cancel": "Cancel" }, "sdk_return_to_app_modal": { "title": "Uygulamaya geri dön", @@ -1454,6 +1485,7 @@ "add": "Ekle", "cancel": "İptal et", "approve": "Onayla", + "edit_network_details": "Ağ bilgilerini düzenle", "malicious_network_warning": "Kötü amaçlı bir ağ sağlayıcı blokzincirinin durumu hakkında yalan söyleyebilir ve ağ aktivitenizi kaydedebilir. Sadece güvendiğiniz özel ağları ekleyin.", "security_link": "https://metamask.zendesk.com/hc/en-us/articles/4404424659995", "network_warning_title": "Ağ Bilgileri", @@ -1473,7 +1505,9 @@ "add_network": "manuel olarak daha fazla ekleyebilirsiniz.", "select_network": "Bir ağ seçin", "show_test_networks": "Test ağlarını göster", - "deprecated_goerli": "Ethereum'da yaşanan protokol değişikliklerinden dolayı: Goerli test ağı güvenilir bir şekilde çalışmayabilir ve yakında kullanım dışı olacak." + "deprecated_goerli": "Ethereum'da yaşanan protokol değişikliklerinden dolayı: Goerli test ağı güvenilir bir şekilde çalışmayabilir ve yakında kullanım dışı olacak.", + "network_deprecated_title": "This network is deprecated", + "network_deprecated_description": "The network you're trying to connect to is no longer supported on Metamask." }, "select": { "cancel": "İptal", @@ -2028,6 +2062,7 @@ "get_new_quotes": "Yeni teklifler al", "quotes_timeout": "Teklifler için zaman aşımı", "request_new_quotes": "En yeni en iyi oranı almak için lütfen yeni teklifler talep et.", + "terms_of_service": "Hizmet Şartları", "amount_to_buy": "Alınacak tutar", "amount_to_sell": "Satılacak tutar", "want_to_buy": "Şunu almak istiyorsun:", diff --git a/locales/languages/vi.json b/locales/languages/vi.json index 24e55e1a07f..a608a9c5800 100644 --- a/locales/languages/vi.json +++ b/locales/languages/vi.json @@ -7,6 +7,8 @@ "deceptive_request_title": "Đây là một yêu cầu lừa đảo", "failed_title": "Yêu cầu có thể không an toàn", "failed_description": "Do có lỗi, yêu cầu này đã không được nhà cung cấp dịch vụ bảo mật xác minh. Hãy thực hiện cẩn thận.", + "loading_title": "Đang kiểm tra cảnh báo bảo mật...", + "loading_complete_title": "No alerts received. Always do your own due diligence before approving requests.", "malicious_domain_description": "Bạn đang tương tác với một tên miền độc hại. Nếu bạn chấp thuận yêu cầu này, bạn có thể mất tài sản của mình.", "other_description": "Nếu bạn chấp thuận yêu cầu này, bạn có thể mất tài sản của mình.", "raw_signature_farming_description": "Nếu bạn chấp thuận yêu cầu này, bạn có thể mất tài sản của mình.", @@ -374,8 +376,15 @@ "no_nfts_yet": "Chưa có NFT", "nfts_autodetection_title": "Phát hiện NFT", "nfts_autodetection_desc": "Cho phép MetaMask tự động phát hiện NFT từ OpenSea và hiển thị trên ví MetaMask của bạn.", - "network_details_check": "Network details check", - "network_check_validation_desc": "reduces your chances of connecting to a malicious or incorrect network.", + "network_details_check": "Kiểm tra thông tin mạng", + "network_with_chain_id": "Mạng có ID chuỗi", + "potential_scam": "Đây có khả năng là một hành vi lừa đảo", + "network_not_matching": "Mạng này không trùng khớp với tên hoặc ID chuỗi đã liên kết của nó. Nhiều token phổ biến sử dụng tên", + "target_scam_network": "khiến nó trở thành mục tiêu để lừa đảo. Những kẻ lừa đảo có thể lừa bạn gửi lại cho họ những loại tiền tệ có giá trị hơn. Nhớ xác minh mọi thông tin trước khi tiếp tục.", + "use_the_currency_symbol": "sử dụng ký hiệu tiền tệ", + "use_correct_symbol": "Đảm bảo bạn đang sử dụng đúng ký hiệu trước khi tiếp tục", + "chain_id_currently_used": "ID chuỗi này hiện được sử dụng bởi", + "network_check_validation_desc": "giảm khả năng bạn kết nối với mạng độc hại hoặc mạng không chính xác.", "nfts_autodetection_cta": "Bật tính năng phát hiện NFT trong phần Cài đặt", "learn_more": "Tìm hiểu thêm", "add_collectibles": "Nhập NFT", @@ -879,17 +888,39 @@ "transactions_subheading": "Giao dịch", "network_provider": "Network provider", "token_nft_ens_subheading": "Tự động phát hiện Token, NFT và ENS", - "security_check_subheading": "Kiểm tra bảo mật" + "security_check_subheading": "Kiểm tra bảo mật", + "symbol_required": "Ký hiệu là bắt buộc.", + "blockaid": "Blockaid", + "blockaid_desc": "Bảo vệ quyền riêng tư – không chia sẻ dữ liệu với các bên thứ ba. Có sẵn trên Arbitrum, Avalanche, BNB Chain, Ethereum Mainnet, Optimism và Polygon.", + "security_alerts": "Cảnh báo bảo mật", + "security_alerts_desc": "Tính năng này sẽ cảnh báo bạn về hoạt động độc hại bằng cách xem xét cục bộ các yêu cầu giao dịch và chữ ký của bạn. Hãy luôn tự mình thực hiện quy trình thẩm định trước khi chấp thuận bất kỳ yêu cầu nào. Không có gì đảm bảo rằng tính năng này sẽ phát hiện được tất cả các hoạt động độc hại. Bằng cách bật tính năng này, bạn đồng ý với các điều khoản sử dụng của nhà cung cấp." }, "sdk": { "disconnect_title": "Ngắt kết nối tất cả các trang web?", "disconnect_all_info": "Nếu bạn xóa kết nối với tất cả các trang web, bạn sẽ cần cấp quyền để kết nối lại.", "disconnect": "Ngắt kết nối", "disconnect_all": "Ngắt kết nối tất cả", + "disconnect_all_accounts": "Disconnect all Accounts", + "manage_connections": "Manage Connections", + "manage": "Manage", "cancel": "Hủy", "loading": "Đang kết nối với MetaMask...", "unkown_dapp": "Tên DAPP không khả dụng", - "no_connections": "Không tìm thấy kết nối nào" + "no_connections": "No connections", + "no_connections_desc": "If you connect an account to a site or an app, you’ll see it here." + }, + "sdk_session_item": { + "connected_accounts": "{{accountsLength}} account(s) connected." + }, + "sdk_disconnect_modal": { + "disconnect_all": "Disconnect from all sites?", + "disconnect_all_desc": "If you disconnect your accounts from all sites, you'll need to give permissions to reconnect them.", + "disconnect_account": "Disconnect account?", + "disconnect_all_accounts": "Disconnect all Accounts", + "disconnect_all_accounts_desc": "If you disconnect all accounts from {{dapp}}, you will need to give permissions to reconnect them.", + "disconnect_account_desc": "If you disconnect {{account}} from {{dapp}}, you will need to give permissions to reconnect it.", + "disconnect_confirm": "Disconnect", + "cancel": "Cancel" }, "sdk_return_to_app_modal": { "title": "Quay lại ứng dụng", @@ -1454,6 +1485,7 @@ "add": "Thêm", "cancel": "Hủy", "approve": "Chấp thuận", + "edit_network_details": "Chỉnh sửa thông tin mạng", "malicious_network_warning": "Một nhà cung cấp mạng độc hại có thể nói dối về trạng thái của chuỗi khối và ghi lại hoạt động của bạn trên mạng. Chỉ thêm các mạng tùy chỉnh mà bạn tin tưởng.", "security_link": "https://metamask.zendesk.com/hc/en-us/articles/4404424659995", "network_warning_title": "Thông tin mạng", @@ -1473,7 +1505,9 @@ "add_network": "thêm thủ công các mạng khác.", "select_network": "Chọn mạng", "show_test_networks": "Hiển thị các mạng thử nghiệm", - "deprecated_goerli": "Do những thay đổi trong giao thức của Ethereum: Mạng thử nghiệm Goerli có thể không hoạt động đáng tin cậy và sẽ sớm bị ngừng sử dụng." + "deprecated_goerli": "Do những thay đổi trong giao thức của Ethereum: Mạng thử nghiệm Goerli có thể không hoạt động đáng tin cậy và sẽ sớm bị ngừng sử dụng.", + "network_deprecated_title": "This network is deprecated", + "network_deprecated_description": "The network you're trying to connect to is no longer supported on Metamask." }, "select": { "cancel": "Hủy", @@ -2028,6 +2062,7 @@ "get_new_quotes": "Nhận báo giá mới", "quotes_timeout": "Hết thời gian chờ báo giá", "request_new_quotes": "Vui lòng yêu cầu báo giá mới để nhận tỷ giá tốt nhất và mới nhất.", + "terms_of_service": "Điều khoản dịch vụ", "amount_to_buy": "Số tiền cần mua", "amount_to_sell": "Số tiền cần bán", "want_to_buy": "Bạn muốn mua", diff --git a/locales/languages/zh.json b/locales/languages/zh.json index a6ff1bba4ef..39fce0e0e72 100644 --- a/locales/languages/zh.json +++ b/locales/languages/zh.json @@ -7,6 +7,8 @@ "deceptive_request_title": "此请求属欺骗性质", "failed_title": "此请求可能不安全", "failed_description": "由于出现错误,安全服务提供商未验证此请求。请谨慎操作。", + "loading_title": "正在检查安全提醒......", + "loading_complete_title": "No alerts received. Always do your own due diligence before approving requests.", "malicious_domain_description": "您正在与恶意网域交互。如果您批准此请求,可能会遭受资产损失。", "other_description": "如果您批准此请求,可能会遭受资产损失。", "raw_signature_farming_description": "如果您批准此请求,可能会有资产损失。", @@ -374,8 +376,15 @@ "no_nfts_yet": "尚无 NFT", "nfts_autodetection_title": "NFT 检测", "nfts_autodetection_desc": "允许 MetaMask 自动检测 OpenSea 的 NFT,并显示在您的 MetaMask 钱包里。", - "network_details_check": "Network details check", - "network_check_validation_desc": "reduces your chances of connecting to a malicious or incorrect network.", + "network_details_check": "网络详情检查", + "network_with_chain_id": "网络及其链 ID", + "potential_scam": "这可能是欺诈", + "network_not_matching": "此网络与其关联的链 ID 或名称不匹配。很多热门代币均使用该名称,", + "target_scam_network": "这使其成为欺诈目标。骗子可能会诱骗您将更有价值的货币转给他们作为回报。在继续之前请先验证所有信息。", + "use_the_currency_symbol": "使用货币符号", + "use_correct_symbol": "确保您使用正确的符号才能继续", + "chain_id_currently_used": "此链 ID 目前的使用者是", + "network_check_validation_desc": "减少您连接到恶意或错误网络的机会。", "nfts_autodetection_cta": "在设置中打开 NFT 检测", "learn_more": "了解更多", "add_collectibles": "添加收藏品", @@ -879,17 +888,39 @@ "transactions_subheading": "交易", "network_provider": "Network provider", "token_nft_ens_subheading": "代币、NFT 和 ENS(Ethereum 域名服务)自动检测", - "security_check_subheading": "安全检查" + "security_check_subheading": "安全检查", + "symbol_required": "需要符号。", + "blockaid": "Blockaid", + "blockaid_desc": "隐私保护 - 不会与第三方共享任何数据。适用于 Arbitrum、Avalanche、BNB Chain、以太坊主网、Optimism 和 Polygon。", + "security_alerts": "安全提醒", + "security_alerts_desc": "此功能通过本地审查您的交易和签名请求来提醒您注意恶意活动。在批准任何请求之前,请务必自行进行审慎调查。无法保证此功能能够检测到所有恶意活动。启用此功能即表示您同意提供商的使用条款。" }, "sdk": { "disconnect_title": "要断开所有网站的连接吗?", "disconnect_all_info": "如果您移除了与所有网站的连接,需要授予权限才能重新连接。", "disconnect": "断开连接", "disconnect_all": "断开所有连接", + "disconnect_all_accounts": "Disconnect all Accounts", + "manage_connections": "Manage Connections", + "manage": "Manage", "cancel": "取消", "loading": "正在连接MetaMask…...", "unkown_dapp": "去中心化应用(DAPP)名称不可用", - "no_connections": "找不到连接" + "no_connections": "No connections", + "no_connections_desc": "If you connect an account to a site or an app, you’ll see it here." + }, + "sdk_session_item": { + "connected_accounts": "{{accountsLength}} account(s) connected." + }, + "sdk_disconnect_modal": { + "disconnect_all": "Disconnect from all sites?", + "disconnect_all_desc": "If you disconnect your accounts from all sites, you'll need to give permissions to reconnect them.", + "disconnect_account": "Disconnect account?", + "disconnect_all_accounts": "Disconnect all Accounts", + "disconnect_all_accounts_desc": "If you disconnect all accounts from {{dapp}}, you will need to give permissions to reconnect them.", + "disconnect_account_desc": "If you disconnect {{account}} from {{dapp}}, you will need to give permissions to reconnect it.", + "disconnect_confirm": "Disconnect", + "cancel": "Cancel" }, "sdk_return_to_app_modal": { "title": "返回应用程序", @@ -1454,6 +1485,7 @@ "add": "添加", "cancel": "取消", "approve": "批准", + "edit_network_details": "编辑网络详情", "malicious_network_warning": "恶意网络提供商可能会谎报区块链的状态,并记录您的网络活动。仅添加您信任的自定义网络。", "security_link": "https://metamask.zendesk.com/hc/en-us/articles/4404424659995", "network_warning_title": "网络信息", @@ -1473,7 +1505,9 @@ "add_network": "手动添加更多网络。", "select_network": "选择网络", "show_test_networks": "显示测试网络", - "deprecated_goerli": "由于以太坊协议的变化:Goerli 测试网络可能无法可靠工作,很快就会弃用。" + "deprecated_goerli": "由于以太坊协议的变化:Goerli 测试网络可能无法可靠工作,很快就会弃用。", + "network_deprecated_title": "This network is deprecated", + "network_deprecated_description": "The network you're trying to connect to is no longer supported on Metamask." }, "select": { "cancel": "取消", @@ -2028,6 +2062,7 @@ "get_new_quotes": "获取新报价", "quotes_timeout": "报价超时", "request_new_quotes": "请重新请求报价,以获得最新的最佳价格。", + "terms_of_service": "服务条款", "amount_to_buy": "要买入的金额", "amount_to_sell": "要卖出的金额", "want_to_buy": "您想购买", From e0b5f719de99915a3c9dca053dcc550302b2d767 Mon Sep 17 00:00:00 2001 From: Sylva Elendu Date: Thu, 29 Feb 2024 01:46:59 +0100 Subject: [PATCH 06/11] fix: cherry-pick (#8725) (#8767) Cherry-pick fix for https://github.com/MetaMask/metamask-mobile/pull/8725 on version 7.17.0. Co-authored-by: Jyoti Puri Co-authored-by: sethkfman <10342624+sethkfman@users.noreply.github.com> --- .../confirmations/components/BlockaidBanner/BlockaidBanner.tsx | 2 +- locales/languages/en.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/components/Views/confirmations/components/BlockaidBanner/BlockaidBanner.tsx b/app/components/Views/confirmations/components/BlockaidBanner/BlockaidBanner.tsx index 67335fc2422..a8f4252c150 100644 --- a/app/components/Views/confirmations/components/BlockaidBanner/BlockaidBanner.tsx +++ b/app/components/Views/confirmations/components/BlockaidBanner/BlockaidBanner.tsx @@ -166,7 +166,7 @@ const BlockaidBanner = (bannerProps: BlockaidBannerProps) => { return ( - + {strings('blockaid_banner.loading_complete_title')} diff --git a/locales/languages/en.json b/locales/languages/en.json index 2c8871d7917..cc2d97982bd 100644 --- a/locales/languages/en.json +++ b/locales/languages/en.json @@ -8,7 +8,7 @@ "failed_title": "Request may not be safe", "failed_description": "Because of an error, this request was not verified by the security provider. Proceed with caution.", "loading_title": "Checking for security alerts...", - "loading_complete_title": "No alerts received", + "loading_complete_title": "No alerts received. Always do your own due diligence before approving requests.", "malicious_domain_description": "You're interacting with a malicious domain. If you approve this request, you might lose your assets.", "other_description": "If you approve this request, you might lose your assets.", "raw_signature_farming_description": "If you approve this request, you might lose your assets.", From 9c11aacf73f5282c1fa6091a6a5356cb507bfb83 Mon Sep 17 00:00:00 2001 From: Sylva Elendu Date: Thu, 29 Feb 2024 01:48:06 +0100 Subject: [PATCH 07/11] fix: cherry-pick (#8742) (#8765) Cherry-pick fix for https://github.com/MetaMask/metamask-mobile/pull/8742 on version 7.17.0. --- app/components/Views/confirmations/SendFlow/Confirm/index.js | 2 +- app/core/TransactionTypes.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/components/Views/confirmations/SendFlow/Confirm/index.js b/app/components/Views/confirmations/SendFlow/Confirm/index.js index d02516c6bd5..4bd4d20cd4d 100644 --- a/app/components/Views/confirmations/SendFlow/Confirm/index.js +++ b/app/components/Views/confirmations/SendFlow/Confirm/index.js @@ -509,7 +509,7 @@ class Confirm extends PureComponent { id, jsonrpc: '2.0', method: 'eth_sendTransaction', - origin: TransactionTypes.MMM, + origin: TransactionTypes.MM, params: [ { from, diff --git a/app/core/TransactionTypes.js b/app/core/TransactionTypes.js index 10883e44a9a..0aa9bcd753d 100644 --- a/app/core/TransactionTypes.js +++ b/app/core/TransactionTypes.js @@ -12,4 +12,5 @@ export default { ERC1155: 'ERC1155', }, MMM: 'MetaMask Mobile', + MM: 'metamask', }; From 3f48fe2b0dcd031ff86cdf2fc166127c7024fc6d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 28 Feb 2024 17:50:54 -0700 Subject: [PATCH 08/11] chore: cherry-pick #8744 (#8757) This PR cherry-picks #8744 Co-authored-by: salimtb --- .../__snapshots__/index.test.tsx.snap | 27 +++++++++++-------- .../NetworkVerificationInfo.tsx | 24 ++++++++++++++--- .../NetworkVerificationInfo.test.tsx.snap | 27 +++++++++++-------- .../NetworkSwitcher.test.tsx.snap | 27 +++++++++++-------- app/core/RPCMethods/networkChecker.test.ts | 26 ++++++++++++++++++ app/core/RPCMethods/networkChecker.util.ts | 10 ++++++- 6 files changed, 103 insertions(+), 38 deletions(-) diff --git a/app/components/UI/NetworkModal/__snapshots__/index.test.tsx.snap b/app/components/UI/NetworkModal/__snapshots__/index.test.tsx.snap index 84e5c22fe23..648a484d48f 100644 --- a/app/components/UI/NetworkModal/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/NetworkModal/__snapshots__/index.test.tsx.snap @@ -234,27 +234,32 @@ exports[`NetworkDetails renders correctly 1`] = ` - + > + T + - https://localhost:8545 + https:/ setAlerts(alertsFromProps), [alertsFromProps]); + const networkImageSource = useMemo( + () => + //@ts-expect-error - The utils/network file is still JS and this function expects a networkType, and should be optional + getNetworkImageSource({ + chainId: customNetworkInformation.chainId, + }), + [customNetworkInformation], + ); + const renderNetworkInfo = () => ( {strings('add_custom_network.network_url')} - {customNetworkInformation.rpcUrl} + + {hideKeyFromUrl(customNetworkInformation.rpcUrl)} + { if (!safeChainsListValidationEnabled) return null; if (!alerts.length) return null; + return alerts.map( ( networkAlert: { @@ -229,7 +245,7 @@ const NetworkVerificationInfo = ({ - + > + T + - http://test.com + http:/ - + > + C + - https://evm.cronos.org + https:/ { ]); }); + it('should not return an error if the rpcUrl is not matched but its infura', async () => { + mockedAxios.get.mockImplementation(() => + Promise.resolve({ + data: [ + { + chainId: '137', + rpc: ['http://localhost:8545'], + name: 'Test', + nativeCurrency: { + symbol: 'MATIC', + decimals: 18, + }, + }, + ], + }), + ); + + const alerts = await checkSafeNetwork( + '137', + 'https://polygon-mainnet.infura.io/v3/test', + 'Test', + 'MATIC', + ); + expect(alerts).toEqual([]); + }); + it('should return a warning if the decimals is not matched', async () => { mockedAxios.get.mockImplementation(() => Promise.resolve({ diff --git a/app/core/RPCMethods/networkChecker.util.ts b/app/core/RPCMethods/networkChecker.util.ts index 17129a1cb91..8342d0d210a 100644 --- a/app/core/RPCMethods/networkChecker.util.ts +++ b/app/core/RPCMethods/networkChecker.util.ts @@ -1,6 +1,13 @@ import axios from 'axios'; import { BannerAlertSeverity } from '../../component-library/components/Banners/Banner'; import { strings } from '../../../locales/i18n'; +import PopularList from '../../util/networks/customNetworks'; + +const findPopularNetwork = (rpcUrl: string) => + PopularList.some((network) => { + const { origin } = new URL(network.rpcUrl); + return origin === rpcUrl; + }); const checkSafeNetwork = async ( chainIdDecimal: string, @@ -23,7 +30,8 @@ const checkSafeNetwork = async ( if ( !matchedChain.rpc ?.map((rpc: string) => new URL(rpc).origin) - .includes(origin) + .includes(origin) && + !findPopularNetwork(origin) ) { alerts.push({ alertError: strings('add_custom_network.invalid_rpc_url'), From bf433deeeefff44cde96f0e9f6e0262cb2993a8c Mon Sep 17 00:00:00 2001 From: Sylva Elendu Date: Thu, 29 Feb 2024 11:17:47 +0100 Subject: [PATCH 09/11] fix: cherry-pick (#8727) (#8766) Cherry-pick fix for https://github.com/MetaMask/metamask-mobile/pull/8727 on version 7.17.0. --- app/store/migrations/030.test.ts | 92 ++++++++++++++++++++++++++++++++ app/store/migrations/030.ts | 54 +++++++++++++++++++ app/store/migrations/index.ts | 2 + 3 files changed, 148 insertions(+) create mode 100644 app/store/migrations/030.test.ts create mode 100644 app/store/migrations/030.ts diff --git a/app/store/migrations/030.test.ts b/app/store/migrations/030.test.ts new file mode 100644 index 00000000000..8f404f0a8f6 --- /dev/null +++ b/app/store/migrations/030.test.ts @@ -0,0 +1,92 @@ +import migrate from './030'; +import { merge } from 'lodash'; +import { captureException } from '@sentry/react-native'; +import initialRootState from '../../util/test/initial-root-state'; + +const expectedState = { + engine: { + backgroundState: { + PreferencesController: { + securityAlertsEnabled: true, + }, + }, + }, +}; + +jest.mock('@sentry/react-native', () => ({ + captureException: jest.fn(), +})); +const mockedCaptureException = jest.mocked(captureException); + +describe('Migration #30', () => { + beforeEach(() => { + jest.restoreAllMocks(); + jest.resetAllMocks(); + }); + + const invalidStates = [ + { + state: null, + errorMessage: "Migration 30: Invalid root state: 'object'", + scenario: 'state is invalid', + }, + { + state: merge({}, initialRootState, { + engine: null, + }), + errorMessage: "Migration 30: Invalid root engine state: 'object'", + scenario: 'engine state is invalid', + }, + { + state: merge({}, initialRootState, { + engine: { + backgroundState: null, + }, + }), + errorMessage: + "Migration 30: Invalid root engine backgroundState: 'object'", + scenario: 'backgroundState is invalid', + }, + ]; + + for (const { errorMessage, scenario, state } of invalidStates) { + it(`should capture exception if ${scenario}`, () => { + const newState = migrate(state); + + expect(newState).toStrictEqual(state); + expect(mockedCaptureException).toHaveBeenCalledWith(expect.any(Error)); + expect(mockedCaptureException.mock.calls[0][0].message).toBe( + errorMessage, + ); + }); + } + + it('should not change anything if security alert is already enabled', () => { + const oldState = { + engine: { + backgroundState: { + PreferencesController: { + securityAlertsEnabled: true, + }, + }, + }, + }; + + const migratedState = migrate(oldState); + expect(migratedState).toStrictEqual(expectedState); + }); + + it('should enable security alert if it is not enabled', () => { + const oldState = { + engine: { + backgroundState: { + PreferencesController: { + securityAlertsEnabled: false, + }, + }, + }, + }; + const migratedState = migrate(oldState); + expect(migratedState).toStrictEqual(expectedState); + }); +}); diff --git a/app/store/migrations/030.ts b/app/store/migrations/030.ts new file mode 100644 index 00000000000..dab6dcd4c01 --- /dev/null +++ b/app/store/migrations/030.ts @@ -0,0 +1,54 @@ +import { PreferencesState } from '@metamask/preferences-controller'; +import { captureException } from '@sentry/react-native'; +import { isObject } from '@metamask/utils'; + +/** + * Enable security alerts by default. + * @param {any} state - Redux state. + * @returns Migrated Redux state. + */ +export default function migrate(state: unknown) { + if (!isObject(state)) { + captureException( + new Error(`Migration 30: Invalid root state: '${typeof state}'`), + ); + return state; + } + + if (!isObject(state.engine)) { + captureException( + new Error( + `Migration 30: Invalid root engine state: '${typeof state.engine}'`, + ), + ); + return state; + } + + if (!isObject(state.engine.backgroundState)) { + captureException( + new Error( + `Migration 30: Invalid root engine backgroundState: '${typeof state + .engine.backgroundState}'`, + ), + ); + return state; + } + + const preferencesControllerState = state.engine.backgroundState + .PreferencesController as PreferencesState; + + if (!isObject(preferencesControllerState)) { + captureException( + new Error( + `Migration 30: Invalid PreferencesController state: '${typeof preferencesControllerState}'`, + ), + ); + return state; + } + + if (!preferencesControllerState.securityAlertsEnabled) { + preferencesControllerState.securityAlertsEnabled = true; + } + + return state; +} diff --git a/app/store/migrations/index.ts b/app/store/migrations/index.ts index 9e599fa3e50..de194ea95db 100644 --- a/app/store/migrations/index.ts +++ b/app/store/migrations/index.ts @@ -30,6 +30,7 @@ import migration26 from './026'; import migration27 from './027'; import migration28 from './028'; import migration29 from './029'; +import migration30 from './030'; // We do not keep track of the old state // We create this type for better readability @@ -66,6 +67,7 @@ export const migrations: MigrationManifest = { 27: migration27, 28: migration28 as unknown as (state: PersistedState) => PersistedState, 29: migration29 as unknown as (state: OldState) => PersistedState, + 30: migration30 as unknown as (state: OldState) => PersistedState, }; // The latest (i.e. highest) version number. From 5e2d2280da76f18e65a291bb3707ed4a5d1999e8 Mon Sep 17 00:00:00 2001 From: Matthew Walsh Date: Thu, 29 Feb 2024 16:35:54 +0000 Subject: [PATCH 10/11] chore: cherry-pick #8708 (#8760) Cherry-pick fix for #8708 on version 7.17.0. --------- Co-authored-by: Sylva Elendu --- .../confirmations/SendFlow/Confirm/index.js | 111 +++++++++--------- 1 file changed, 57 insertions(+), 54 deletions(-) diff --git a/app/components/Views/confirmations/SendFlow/Confirm/index.js b/app/components/Views/confirmations/SendFlow/Confirm/index.js index 4bd4d20cd4d..92c768511cf 100644 --- a/app/components/Views/confirmations/SendFlow/Confirm/index.js +++ b/app/components/Views/confirmations/SendFlow/Confirm/index.js @@ -250,7 +250,6 @@ class Confirm extends PureComponent { multiLayerL1FeeTotal: '0x0', result: {}, transactionMeta: {}, - preparedTransaction: {}, }; originIsWalletConnect = this.props.transaction.origin?.startsWith( @@ -376,6 +375,13 @@ class Confirm extends PureComponent { isPaymentRequest, } = this.props; + const { + from, + transactionTo: to, + transactionValue: value, + data, + } = this.props.transaction; + this.updateNavBar(); this.getGasLimit(); @@ -399,9 +405,39 @@ class Confirm extends PureComponent { POLLING_INTERVAL_ESTIMATED_L1_FEE, ); } + // add transaction + const { TransactionController } = Engine.context; + const { result, transactionMeta } = + await TransactionController.addTransaction(this.props.transaction, { + deviceConfirmedOn: WalletDevice.MM_MOBILE, + origin: TransactionTypes.MMM, + }); + + this.setState({ result, transactionMeta }); + + if (isBlockaidFeatureEnabled()) { + // start validate ppom + const id = transactionMeta.id; + const reqObject = { + id, + jsonrpc: '2.0', + method: 'eth_sendTransaction', + origin: TransactionTypes.MM, + params: [ + { + from, + to, + value, + data, + }, + ], + }; + + ppomUtil.validateRequest(reqObject, id); + } }; - componentDidUpdate = async (prevProps, prevState) => { + componentDidUpdate = (prevProps, prevState) => { const { transactionState: { transactionTo, @@ -479,52 +515,6 @@ class Confirm extends PureComponent { this.parseTransactionDataHeader(); } } - - const { gasEstimationReady, preparedTransaction } = this.state; - - // only add transaction if gasEstimationReady and preparedTransaction has gas - if (gasEstimationReady && !preparedTransaction.gas) { - const { TransactionController } = Engine.context; - - const preparedTransaction = this.prepareTransactionToSend(); - - // update state only if preparedTransaction has gas - if (preparedTransaction.gas) { - const { from, to, value, data } = preparedTransaction; - - // eslint-disable-next-line react/no-did-update-set-state - this.setState({ preparedTransaction }, async () => { - const { result, transactionMeta } = - await TransactionController.addTransaction(preparedTransaction, { - deviceConfirmedOn: WalletDevice.MM_MOBILE, - origin: TransactionTypes.MMM, - }); - - this.setState({ result, transactionMeta }); - - if (isBlockaidFeatureEnabled()) { - // start validate ppom - const id = transactionMeta.id; - const reqObject = { - id, - jsonrpc: '2.0', - method: 'eth_sendTransaction', - origin: TransactionTypes.MM, - params: [ - { - from, - to, - value, - data, - }, - ], - }; - - ppomUtil.validateRequest(reqObject, id); - } - }); - } - } }; setScrollViewRef = (ref) => { @@ -798,11 +788,7 @@ class Confirm extends PureComponent { if (transactionConfirmed) return; this.setState({ transactionConfirmed: true, stopUpdateGas: true }); try { - const { - result, - transactionMeta, - preparedTransaction: transaction, - } = this.state; + const transaction = this.prepareTransactionToSend(); let error; if (gasEstimateType === GAS_ESTIMATE_TYPES.FEE_MARKET) { @@ -822,6 +808,8 @@ class Confirm extends PureComponent { return; } + const { result, transactionMeta } = this.state; + const isLedgerAccount = isHardwareAccount(transaction.from, [ ExtendedKeyringTypes.ledger, ]); @@ -851,6 +839,7 @@ class Confirm extends PureComponent { return; } + await this.persistTransactionParameters(transaction); await KeyringController.resetQRKeyringState(); await ApprovalController.accept(transactionMeta.id, undefined, { waitForResult: true, @@ -938,7 +927,6 @@ class Confirm extends PureComponent { updateTransactionStateWithUpdatedNonce = (nonceValue) => { this.props.setNonce(nonceValue); - this.setState({ preparedTransaction: {} }); }; renderCustomNonceModal = () => { @@ -1118,6 +1106,21 @@ class Confirm extends PureComponent { return confirmButtonStyle; } + async persistTransactionParameters(transactionParams) { + const { TransactionController } = Engine.context; + const { transactionMeta } = this.state; + const { id: transactionId } = transactionMeta; + + const controllerTransactionMeta = + TransactionController.state.transactions.find( + (tx) => tx.id === transactionId, + ); + + controllerTransactionMeta.transaction = transactionParams; + + await TransactionController.updateTransaction(controllerTransactionMeta); + } + render = () => { const { selectedAsset, paymentRequest } = this.props.transactionState; const { From 495c915f35f6748709f565b95892fd29c59e12cd Mon Sep 17 00:00:00 2001 From: sethkfman <10342624+sethkfman@users.noreply.github.com> Date: Thu, 29 Feb 2024 10:13:15 -0700 Subject: [PATCH 11/11] chore: bump version 1267 (#8779) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** Chore to bump release version ## **Related issues** Fixes: ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** ### **Before** ### **After** ## **Pre-merge author checklist** - [ ] I’ve followed [MetaMask Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've clearly explained what problem this PR is solving and how it is solved. - [ ] I've linked related issues - [ ] I've included manual testing steps - [ ] I've included screenshots/recordings if applicable - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. - [ ] I’ve properly set the pull request status: - [ ] In case it's not yet "ready for review", I've set it to "draft". - [ ] In case it's "ready for review", I've changed it from "draft" to "non-draft". ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- android/app/build.gradle | 2 +- bitrise.yml | 4 ++-- ios/MetaMask.xcodeproj/project.pbxproj | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 070ed973be6..884a391b87b 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -181,7 +181,7 @@ android { applicationId "io.metamask" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1266 + versionCode 1267 versionName "7.17.0" testBuildType System.getProperty('testBuildType', 'debug') missingDimensionStrategy 'react-native-camera', 'general' diff --git a/bitrise.yml b/bitrise.yml index 42b2cb838f2..a344255296c 100644 --- a/bitrise.yml +++ b/bitrise.yml @@ -1241,13 +1241,13 @@ app: VERSION_NAME: 7.17.0 - opts: is_expand: false - VERSION_NUMBER: 1266 + VERSION_NUMBER: 1267 - opts: is_expand: false FLASK_VERSION_NAME: 7.17.0 - opts: is_expand: false - FLASK_VERSION_NUMBER: 1266 + FLASK_VERSION_NUMBER: 1267 - opts: is_expand: false ANDROID_APK_LINK: '' diff --git a/ios/MetaMask.xcodeproj/project.pbxproj b/ios/MetaMask.xcodeproj/project.pbxproj index bb75711f5f9..db6ad0b3b67 100644 --- a/ios/MetaMask.xcodeproj/project.pbxproj +++ b/ios/MetaMask.xcodeproj/project.pbxproj @@ -1341,7 +1341,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1266; + CURRENT_PROJECT_VERSION = 1267; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -1405,7 +1405,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1266; + CURRENT_PROJECT_VERSION = 1267; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 48XVW22RCG; @@ -1470,7 +1470,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1266; + CURRENT_PROJECT_VERSION = 1267; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -1531,7 +1531,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1266; + CURRENT_PROJECT_VERSION = 1267; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 48XVW22RCG; @@ -1692,7 +1692,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1266; + CURRENT_PROJECT_VERSION = 1267; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -1760,7 +1760,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1266; + CURRENT_PROJECT_VERSION = 1267; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 48XVW22RCG;